diff options
| author | Mikhail Osipov <mike.osipov@gmail.com> | 2020-02-20 19:34:58 +0300 |
|---|---|---|
| committer | Mikhail Osipov <mike.osipov@gmail.com> | 2020-02-21 05:54:58 +0300 |
| commit | 6a25466ac3a8b94b08a3114c9e5cc721ed620d49 (patch) | |
| tree | 568012861f7c331359b5b946175dfcd2322af8d0 /pkg/server | |
| parent | 9e04a8bee8492cb662ebc8b7fd50a23c48c7d03f (diff) | |
tunnel del,rename commands
Diffstat (limited to 'pkg/server')
| -rw-r--r-- | pkg/server/automap.go | 31 | ||||
| -rw-r--r-- | pkg/server/tunnel.go | 118 |
2 files changed, 135 insertions, 14 deletions
diff --git a/pkg/server/automap.go b/pkg/server/automap.go index 15cafe4..cf4de7d 100644 --- a/pkg/server/automap.go +++ b/pkg/server/automap.go @@ -1,12 +1,37 @@ package server -type automap map[int]interface{} +import ( + "errors" + "fmt" +) -func (m automap) add(v interface{}) int { - for k := 0;; k++ { +type automap map[string]interface{} + +var errExists = errors.New("already exists") +var errNotFound = errors.New("no such entry") + +func (m automap) add(v interface{}) string { + for n := 1;; n++ { + k := fmt.Sprintf("%d", n) if _, ok := m[k]; !ok { m[k] = v return k } } } + +func (m automap) rename(old string, new string) (interface{}, error) { + if _, ok := m[old]; !ok { + return nil, errNotFound + } + + if _, ok := m[new]; ok { + return nil, errExists + } + + v := m[old] + m[new] = v + + delete(m, old) + return v, nil +} diff --git a/pkg/server/tunnel.go b/pkg/server/tunnel.go index b1c3fe8..04f838b 100644 --- a/pkg/server/tunnel.go +++ b/pkg/server/tunnel.go @@ -23,7 +23,7 @@ type stream struct { } type tunnel struct { - id int + id string args string streams map[int]*stream @@ -32,6 +32,9 @@ type tunnel struct { nextSid int + quit chan struct{} + done chan struct{} + in, out socket.S m []module.M } @@ -41,24 +44,54 @@ func (s *stream) String() string { } func (t *tunnel) String() string { - return fmt.Sprintf("tunnel(%d)", t.id) + return fmt.Sprintf("tunnel(%s)", t.id) } +/* FIXME close streams also */ func (t *tunnel) Close() { + close(t.quit) t.in.Close() t.out.Close() + <-t.done + + log.Println(t, "delete") +} + +func (t *tunnel) isQuit() bool { + select { + case <-t.quit: + return true + default: + return false + } } -func (t *tunnel) run() { +func (t *tunnel) serve() { + var wg sync.WaitGroup + for { if in, err := t.in.Open(); err != nil { + if t.isQuit() { + break + } + log.Println(t, err) time.Sleep(5 * time.Second) } else { log.Println(t, "open", in) - go t.run2(in) + + wg.Add(1) + + go func () { + t.handle(in) + wg.Done() + }() } } + + wg.Wait() + + close(t.done) } func (t *tunnel) newStream(in, out socket.Channel) *stream { @@ -123,7 +156,9 @@ func (s *stream) watchPipe(rq, wq queue.Q, f func (rq, wq queue.Q) error) { }() } -func (t *tunnel) run2(in socket.Channel) { +func (t *tunnel) handle(in socket.Channel) { + log.Println(t, "handle") + out, err := t.out.Open() if err != nil { log.Println(t, err) @@ -178,6 +213,8 @@ func newTunnel(args []string) (*tunnel, error) { t := &tunnel{ args: strings.Join(args, " "), + quit: make(chan struct{}), + done: make(chan struct{}), in: in, out: out, streams: make(map[int]*stream), @@ -216,34 +253,89 @@ func newTunnel(args []string) (*tunnel, error) { return nil, fmt.Errorf("bad '-' usage") } - go t.run() + go t.serve() return t, nil } +func isOkTunnelName(s string) bool { + return s != "" +} + func tunnelAdd(r *request) { - if r.argc < 2 { + args := r.args + name := "" + + if len(args) >= 2 { + if args[0] == "name" { + name = args[1] + if !isOkTunnelName(name) { + r.Fatal("bad name") + } + + if _, ok := r.c.s.tunnels[name]; ok { + r.Fatal("already exists") + } + + args = args[2:] + } + } + + if len(args) < 2 { r.Fatal("not enough args") } - t, err := newTunnel(r.args) + t, err := newTunnel(args) if err != nil { r.Fatal(err) } + if name == "" { + t.id = r.c.s.tunnels.add(t) + } else { + t.id = name + r.c.s.tunnels[t.id] = t + } + log.Println(r.c, r, t, "create") +} - t.id = r.c.s.tunnels.add(t) +func tunnelDel(r *request) { + r.expect(1) + + id := r.args[0] + + if t, ok := r.c.s.tunnels[id]; !ok { + r.Fatal("no such entry") + } else { + t.(*tunnel).Close() + delete(r.c.s.tunnels, id) + } +} + +func tunnelRename(r *request) { + r.expect(2) + + old, new := r.args[0], r.args[1] + if !isOkTunnelName(new) { + r.Fatal("bad name") + } + + if t, err := r.c.s.tunnels.rename(old, new); err != nil { + r.Fatal(err) + } else { + t.(*tunnel).id = new + } } func foreachTunnel(m automap, f func (t *tunnel)) { - var keys []int + var keys []string for k := range m { keys = append(keys, k) } - sort.Ints(keys) + sort.Strings(keys) for _, k := range keys { f(m[k].(*tunnel)) @@ -289,6 +381,10 @@ func streamShow(r *request) { func init() { newCmd(tunnelAdd, "add") + newCmd(tunnelDel, "del") + + newCmd(tunnelRename, "rename") + newCmd(tunnelShow, "show") newCmd(streamShow, "stream show") } |
