veyron/lib/modules: add wspr module and a tool to start all services
Change-Id: I2684c5b270417f61bb298d2e4d2b61b242fec930
diff --git a/lib/flags/doc.go b/lib/flags/doc.go
index 49a7360..b752f0a 100644
--- a/lib/flags/doc.go
+++ b/lib/flags/doc.go
@@ -1,17 +1,18 @@
-// Package flags provides definitions for commonly used flags and where
-// appropriate, implementations of the flag.Value interface for those flags
-// to ensure that only valid values of those flags are supplied. Some of these
-// flags may also be specified using environment variables directly for
-// are documented accordingly; in these cases the command line value takes
+// Package flags provides definitions for commonly used flags and, where
+// appropriate, implementations of the flag.Value interface for those flags to
+// ensure that only valid values of those flags are supplied. Some of these
+// flags may also be specified using environment variables directly and are
+// documented accordingly; in these cases the command line value takes
// precedence over the environment variable.
-// Flags are defined as 'groups' of related flags so that caller may choose
-// which ones to use without having to be burdened with the full set. The
-// groups may be used directly or via the Flags type that aggregates multiple
-// groups. In all cases, the flags are registered with a supplied
-// flag.FlagSet and hence are not forced onto the command line
-// unless the caller passes in flag.CommandLine as the flag.FlagSet to use.
//
-// In general, this package will be used by veyron profiles and the
-// runtime implementations, but can also be used by any application
-// that wants access to the flags and environment variables it supports.
+// Flags are defined as 'groups' of related flags so that the caller may choose
+// which ones to use without having to be burdened with the full set. The groups
+// may be used directly or via the Flags type that aggregates multiple
+// groups. In all cases, the flags are registered with a supplied flag.FlagSet
+// and hence are not forced onto the command line unless the caller passes in
+// flag.CommandLine as the flag.FlagSet to use.
+//
+// In general, this package will be used by veyron profiles and the runtime
+// implementations, but can also be used by any application that wants access to
+// the flags and environment variables it supports.
package flags
diff --git a/lib/modules/core/core.go b/lib/modules/core/core.go
index bf4e6d4..add670f 100644
--- a/lib/modules/core/core.go
+++ b/lib/modules/core/core.go
@@ -67,6 +67,7 @@
MTCommand = "mt"
LSExternalCommand = "lse"
ProxyServerCommand = "proxyd"
+ WSPRCommand = "wsprd"
ShellCommand = "sh"
)
@@ -93,7 +94,11 @@
run a glob command as an external subprocess`)
shell.AddSubprocess(ProxyServerCommand, `<name>...
run a proxy server mounted at the specified names`)
- // shell.AddSubprocess(ShellCommand, subshell, "")
+ // TODO(sadovsky): It's unfortunate that we must duplicate help strings
+ // between RegisterChild and AddSubprocess. Will be fixed by my proposed
+ // refactoring.
+ shell.AddSubprocess(WSPRCommand, usageWSPR())
+ //shell.AddSubprocess(ShellCommand, subshell, "")
shell.AddFunction(LSCommand, ls, `<glob>...
issues glob requests using the current processes namespace library`)
diff --git a/lib/modules/core/echo.go b/lib/modules/core/echo.go
index 3f6ff42..f3adb9f 100644
--- a/lib/modules/core/echo.go
+++ b/lib/modules/core/echo.go
@@ -40,7 +40,7 @@
func echoServer(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
fl, args, err := parseListenFlags(args)
if err != nil {
- return fmt.Errorf("failed parsing args: %s", err)
+ return fmt.Errorf("failed to parse args: %s", err)
}
if err := checkArgs(args, 2, "<message> <name>"); err != nil {
return err
diff --git a/lib/modules/core/mounttable.go b/lib/modules/core/mounttable.go
index 9c4fec0..9326030 100644
--- a/lib/modules/core/mounttable.go
+++ b/lib/modules/core/mounttable.go
@@ -36,9 +36,8 @@
r := rt.R()
fl, args, err := parseListenFlags(args)
if err != nil {
- return fmt.Errorf("failed parsing args: %s", err)
+ return fmt.Errorf("failed to parse args: %s", err)
}
- // args = fl.Args()
lspec := initListenSpec(fl)
server, err := r.NewServer(options.ServesMountTable(true))
if err != nil {
@@ -72,7 +71,7 @@
func ls(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
details := false
- args = args[1:] // skip over comamnd name
+ args = args[1:] // skip over command name
if len(args) > 0 && args[0] == "-l" {
details = true
args = args[1:]
diff --git a/lib/modules/core/proxy.go b/lib/modules/core/proxy.go
index 7290543..3cc63ea 100644
--- a/lib/modules/core/proxy.go
+++ b/lib/modules/core/proxy.go
@@ -20,8 +20,10 @@
func proxyServer(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
fl, args, err := parseListenFlags(args)
if err != nil {
- return fmt.Errorf("failed parsing args: %s", err)
- } // args = fl.Args()
+ return fmt.Errorf("failed to parse args: %s", err)
+ }
+ // TODO(sadovsky): Why does this require >=1 arg? Seems 0 should be fine.
+ // Also note, we have no way to specify ">=0".
if err := checkArgs(args, -1, ""); err != nil {
return err
}
@@ -63,7 +65,6 @@
for _, p := range pub.Published() {
fmt.Fprintf(stdout, "PUBLISHED_PROXY_NAME=%s\n", p)
}
- fmt.Fprintf(stdout, "READY")
modules.WaitForEOF(stdin)
return nil
}
diff --git a/lib/modules/core/util.go b/lib/modules/core/util.go
index 81b6101..a429651 100644
--- a/lib/modules/core/util.go
+++ b/lib/modules/core/util.go
@@ -9,13 +9,19 @@
"veyron.io/veyron/veyron/lib/flags"
)
+func parseFlags(fl *flags.Flags, args []string) error {
+ if len(args) == 0 {
+ return nil
+ }
+ return fl.Parse(args[1:])
+}
+
+// parseListenFlags parses the given args using just the flags and env vars
+// defined in the veyron/lib/flags package.
func parseListenFlags(args []string) (*flags.Flags, []string, error) {
fs := flag.NewFlagSet("modules/core", flag.ContinueOnError)
fl := flags.CreateAndRegister(fs, flags.Listen)
- if len(args) == 0 {
- return fl, []string{}, nil
- }
- err := fl.Parse(args[1:])
+ err := parseFlags(fl, args)
return fl, fl.Args(), err
}
@@ -28,7 +34,7 @@
}
}
-// checkArgs checks for the expected number of args in args. A -ve
+// checkArgs checks for the expected number of args in args. A negative
// value means at least that number of args are expected.
func checkArgs(args []string, expected int, usage string) error {
got := len(args)
diff --git a/lib/modules/core/wspr.go b/lib/modules/core/wspr.go
new file mode 100644
index 0000000..2c242e8
--- /dev/null
+++ b/lib/modules/core/wspr.go
@@ -0,0 +1,72 @@
+package core
+
+import (
+ "flag"
+ "fmt"
+ "io"
+ "strings"
+
+ "veyron.io/veyron/veyron2"
+ "veyron.io/veyron/veyron2/options"
+
+ "veyron.io/veyron/veyron/lib/flags"
+ "veyron.io/veyron/veyron/lib/modules"
+ "veyron.io/wspr/veyron/services/wsprd/wspr"
+)
+
+var (
+ // TODO(sadovsky): We should restructure things so that we can avoid
+ // duplicating code between subprocess command impls and actual main()'s.
+ fs *flag.FlagSet = flag.NewFlagSet("wspr", flag.ContinueOnError)
+
+ port *int = fs.Int("port", 0, "Port to listen on.")
+ identd *string = fs.String("identd", "", "identd server name. Must be set.")
+ // TODO(ataly, ashankar, bjornick): Remove this flag once the old security
+ // model is killed.
+ newSecurityModel *bool = fs.Bool("new_security_model", false, "Use the new security model.")
+
+ fl *flags.Flags = flags.CreateAndRegister(fs, flags.Listen)
+)
+
+func usageWSPR() string {
+ res := []string{}
+ fs.VisitAll(func(f *flag.Flag) {
+ format := " -%s=%s: %s"
+ if getter, ok := f.Value.(flag.Getter); ok {
+ if _, ok := getter.Get().(string); ok {
+ // put quotes on the value
+ format = " -%s=%q: %s"
+ }
+ }
+ res = append(res, fmt.Sprintf(format, f.Name, f.DefValue, f.Usage))
+ })
+ return strings.Join(res, "\n") + "\n"
+}
+
+func init() {
+ modules.RegisterChild(WSPRCommand, usageWSPR(), startWSPR)
+}
+
+func startWSPR(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
+ if err := parseFlags(fl, args); err != nil {
+ return fmt.Errorf("failed to parse args: %s", err)
+ }
+ args = fl.Args()
+
+ var opts []veyron2.ROpt
+ if *newSecurityModel {
+ opts = append(opts, options.ForceNewSecurityModel{})
+ }
+
+ proxy := wspr.NewWSPR(*port, initListenSpec(fl), *identd)
+ defer proxy.Shutdown()
+
+ addr := proxy.Listen()
+ go func() {
+ proxy.Serve()
+ }()
+
+ fmt.Fprintf(stdout, "WSPR_ADDR=%s\n", addr.String())
+ modules.WaitForEOF(stdin)
+ return nil
+}