diff options
Diffstat (limited to 'pkg/server/server.go')
| -rw-r--r-- | pkg/server/server.go | 55 |
1 files changed, 42 insertions, 13 deletions
diff --git a/pkg/server/server.go b/pkg/server/server.go index 1248b1d..e2515cb 100644 --- a/pkg/server/server.go +++ b/pkg/server/server.go @@ -2,6 +2,7 @@ package server import ( "tunnel/pkg/config" + "tunnel/pkg/netstring" "strings" "bytes" "sync" @@ -46,6 +47,8 @@ type request struct { argc int args []string + failed bool + out *bytes.Buffer } @@ -183,7 +186,7 @@ func (c *client) newRequest() *request { r := &request{ c: c, id: c.nextRid, - out: bytes.NewBuffer(nil), + out: new(bytes.Buffer), } c.nextRid++ @@ -209,9 +212,7 @@ func (c *client) handle() { r := c.newRequest() - if r.parse(query) { - r.run() - } + r.run(query) if r.out.Len() == 0 { r.out.Write([]byte("\n")) @@ -225,30 +226,58 @@ func (c *client) handle() { } } -func (r *request) parse(query string) bool { - c, args := getCmd(strings.Split(query, " ")) +func (r *request) decode(query string) []string { + dec := netstring.NewDecoder(bytes.NewReader([]byte(query))) + var t []string + + for { + if s, err := dec.Decode(); err == nil { + t = append(t, s) + } else { + if err == io.EOF { + break + } + + r.Fatal("failed to parse request") + } + } + + return t +} +func (r *request) parse(query string) { + c, args := getCmd(r.decode(query)) if c == nil { - r.Print("command not found") - return false + r.Fatal("command not found") + } + + for n, s := range args { + if strings.HasPrefix(s, "%") { + if v, ok := r.c.s.env.get(s[1:]); ok { + args[n] = v + } else { + r.Fatal("unbound variable ", s) + } + } } r.args = args r.argc = len(args) r.cmd = c - - return true } -func (r *request) run() { - log.Printf("%s %s run [%s] '%s'", r.c, r, r.cmd.name, strings.Join(r.args, " ")) - +func (r *request) run(query string) { defer func () { if e := recover(); e != nil { + r.failed = true r.Print(e) } }() + r.parse(query) + + log.Printf("%s %s run [%s] '%s'", r.c, r, r.cmd.name, strings.Join(r.args, " ")) + r.cmd.f(r) } |
