diff options
Diffstat (limited to 'pkg/server/hook')
| -rw-r--r-- | pkg/server/hook/aes.go | 16 | ||||
| -rw-r--r-- | pkg/server/hook/auth.go | 18 | ||||
| -rw-r--r-- | pkg/server/hook/b64.go | 19 | ||||
| -rw-r--r-- | pkg/server/hook/b85.go | 19 | ||||
| -rw-r--r-- | pkg/server/hook/dump.go | 30 | ||||
| -rw-r--r-- | pkg/server/hook/hex.go | 19 | ||||
| -rw-r--r-- | pkg/server/hook/hook.go | 77 | ||||
| -rw-r--r-- | pkg/server/hook/info-http.go | 10 | ||||
| -rw-r--r-- | pkg/server/hook/proxy.go | 28 | ||||
| -rw-r--r-- | pkg/server/hook/split.go | 37 | ||||
| -rw-r--r-- | pkg/server/hook/zip.go | 19 |
11 files changed, 120 insertions, 172 deletions
diff --git a/pkg/server/hook/aes.go b/pkg/server/hook/aes.go index e437651..dc48f49 100644 --- a/pkg/server/hook/aes.go +++ b/pkg/server/hook/aes.go @@ -6,8 +6,8 @@ import ( "crypto/md5" "crypto/rand" "io" + "tunnel/pkg/server/env" - "tunnel/pkg/server/opts" "tunnel/pkg/server/queue" ) @@ -64,24 +64,16 @@ func (a *aesPipe) Recv(rq, wq queue.Q) error { return queue.IoCopy(reader, wq.Writer()) } -func newAes(env env.Env) *aesPipe { +func (aesHook) New(env env.Env) (interface{}, error) { s := env.Value("secret") h := md5.Sum([]byte(s)) a := &aesPipe{key: make([]byte, 16)} copy(a.key, h[:]) - return a -} - -func (aesHook) Open(env env.Env) (interface{}, error) { - return newAes(env), nil -} - -func newAesHook(opts.Opts) (hook, error) { - return aesHook{}, nil + return a, nil } func init() { - register("aes", newAesHook) + register("aes", aesHook{}) } diff --git a/pkg/server/hook/auth.go b/pkg/server/hook/auth.go index 5910b56..dbfc9bc 100644 --- a/pkg/server/hook/auth.go +++ b/pkg/server/hook/auth.go @@ -7,8 +7,8 @@ import ( "io" "sync" "time" + "tunnel/pkg/server/env" - "tunnel/pkg/server/opts" "tunnel/pkg/server/queue" ) @@ -17,6 +17,10 @@ const authTimeout = 5 * time.Second const saltSize = 16 const hashSize = md5.Size +type authHook struct { + m sync.Map +} + type auth struct { h *authHook @@ -42,10 +46,6 @@ var errDupSalt = errors.New("peer repeats salt") var errAuthFail = errors.New("peer auth fail") var errTimeout = errors.New("timeout") -type authHook struct { - m sync.Map -} - func (a *auth) Init() error { b := make([]byte, saltSize) if _, err := rand.Read(b); err != nil { @@ -149,7 +149,7 @@ func (a *auth) Close() { a.h.m.Delete(a.salt.self) } -func (h *authHook) Open(env env.Env) (interface{}, error) { +func (h *authHook) New(env env.Env) (interface{}, error) { a := &auth{ h: h, secret: env.Value("secret"), @@ -169,10 +169,6 @@ func (h *authHook) Open(env env.Env) (interface{}, error) { return a, nil } -func newAuthHook(opts.Opts) (hook, error) { - return &authHook{}, nil -} - func init() { - register("auth", newAuthHook) + register("auth", authHook{}) } diff --git a/pkg/server/hook/b64.go b/pkg/server/hook/b64.go index fce42a0..c6637e5 100644 --- a/pkg/server/hook/b64.go +++ b/pkg/server/hook/b64.go @@ -2,17 +2,16 @@ package hook import ( "encoding/base64" + "tunnel/pkg/netstring" - "tunnel/pkg/server/env" - "tunnel/pkg/server/opts" "tunnel/pkg/server/queue" ) var b64Enc = base64.RawStdEncoding -type b64Hook struct{} +type b64Pipe struct{} -func (b64Hook) Send(rq, wq queue.Q) error { +func (b64Pipe) Send(rq, wq queue.Q) error { e := netstring.NewEncoder(wq.Writer()) for b := range rq { @@ -22,7 +21,7 @@ func (b64Hook) Send(rq, wq queue.Q) error { return nil } -func (b64Hook) Recv(rq, wq queue.Q) error { +func (b64Pipe) Recv(rq, wq queue.Q) error { d := netstring.NewDecoder(rq.Reader()) for { @@ -39,14 +38,6 @@ func (b64Hook) Recv(rq, wq queue.Q) error { } } -func (h b64Hook) Open(env.Env) (interface{}, error) { - return h, nil -} - -func newB64Hook(opts.Opts) (hook, error) { - return b64Hook{}, nil -} - func init() { - register("b64", newB64Hook) + registerPipe("b64", b64Pipe{}) } diff --git a/pkg/server/hook/b85.go b/pkg/server/hook/b85.go index bf36b56..d90a1c4 100644 --- a/pkg/server/hook/b85.go +++ b/pkg/server/hook/b85.go @@ -3,15 +3,14 @@ package hook import ( "encoding/ascii85" "errors" + "tunnel/pkg/netstring" - "tunnel/pkg/server/env" - "tunnel/pkg/server/opts" "tunnel/pkg/server/queue" ) -type b85Hook struct{} +type b85Pipe struct{} -func (b85Hook) Send(rq, wq queue.Q) error { +func (b85Pipe) Send(rq, wq queue.Q) error { e := netstring.NewEncoder(wq.Writer()) for b := range rq { @@ -23,7 +22,7 @@ func (b85Hook) Send(rq, wq queue.Q) error { return nil } -func (b85Hook) Recv(rq, wq queue.Q) error { +func (b85Pipe) Recv(rq, wq queue.Q) error { d := netstring.NewDecoder(rq.Reader()) for { @@ -44,14 +43,6 @@ func (b85Hook) Recv(rq, wq queue.Q) error { } } -func (h b85Hook) Open(env.Env) (interface{}, error) { - return h, nil -} - -func newB85Hook(opts.Opts) (hook, error) { - return b85Hook{}, nil -} - func init() { - register("b85", newB85Hook) + registerPipe("b85", b85Pipe{}) } diff --git a/pkg/server/hook/dump.go b/pkg/server/hook/dump.go index 864443b..d871d63 100644 --- a/pkg/server/hook/dump.go +++ b/pkg/server/hook/dump.go @@ -7,28 +7,28 @@ import ( "os" "path" "time" + "tunnel/pkg/config" "tunnel/pkg/server/env" - "tunnel/pkg/server/opts" "tunnel/pkg/server/queue" ) const dumpDefaultFile = "/tmp/tunnel/dump" +type dumpHook struct { + File string + Time bool +} + type dump struct { f *os.File h *dumpHook } -type dumpHook struct { - file string - time bool -} - func (t *dump) write(s string, p []byte) error { var out bytes.Buffer - if t.h.time { + if t.h.Time { now := time.Now().Format(config.TimeMsFormat) fmt.Fprintln(&out, now, s, len(p)) } else { @@ -69,8 +69,8 @@ func (t *dump) Close() { } func (h *dumpHook) where(env env.Env) string { - if h.file != "" { - return h.file + if h.File != "" { + return h.File } if v := env.Value("dump.file"); v != "" { @@ -80,7 +80,7 @@ func (h *dumpHook) where(env env.Env) string { return dumpDefaultFile } -func (h *dumpHook) Open(env env.Env) (interface{}, error) { +func (h *dumpHook) New(env env.Env) (interface{}, error) { file := h.where(env) dir := path.Dir(file) @@ -102,14 +102,6 @@ func (h *dumpHook) Open(env env.Env) (interface{}, error) { return t, nil } -func newDumpHook(opts opts.Opts) (hook, error) { - h := &dumpHook{ - file: opts["file"], - time: opts.Bool("time"), - } - return h, nil -} - func init() { - register("dump", newDumpHook) + register("dump", dumpHook{}) } diff --git a/pkg/server/hook/hex.go b/pkg/server/hook/hex.go index bc71bf2..362dbd4 100644 --- a/pkg/server/hook/hex.go +++ b/pkg/server/hook/hex.go @@ -2,14 +2,13 @@ package hook import ( "encoding/hex" - "tunnel/pkg/server/env" - "tunnel/pkg/server/opts" + "tunnel/pkg/server/queue" ) -type hexHook struct{} +type hexPipe struct{} -func (hexHook) Send(rq, wq queue.Q) error { +func (hexPipe) Send(rq, wq queue.Q) error { enc := hex.NewEncoder(wq.Writer()) for b := range rq { @@ -19,19 +18,11 @@ func (hexHook) Send(rq, wq queue.Q) error { return nil } -func (hexHook) Recv(rq, wq queue.Q) error { +func (hexPipe) Recv(rq, wq queue.Q) error { r := hex.NewDecoder(rq.Reader()) return queue.IoCopy(r, wq.Writer()) } -func (h hexHook) Open(env.Env) (interface{}, error) { - return h, nil -} - -func newHexHook(opts.Opts) (hook, error) { - return hexHook{}, nil -} - func init() { - register("hex", newHexHook) + registerPipe("hex", hexPipe{}) } diff --git a/pkg/server/hook/hook.go b/pkg/server/hook/hook.go index 69aa237..36b01d4 100644 --- a/pkg/server/hook/hook.go +++ b/pkg/server/hook/hook.go @@ -3,16 +3,16 @@ package hook import ( "fmt" "log" + "reflect" "sort" "strings" + "tunnel/pkg/server/env" "tunnel/pkg/server/opts" "tunnel/pkg/server/queue" ) -type hookInitFunc func(opts.Opts) (hook, error) - -var hooks = map[string]hookInitFunc{} +var hooks = map[string]interface{}{} type Pipe struct { priv interface{} @@ -21,13 +21,12 @@ type Pipe struct { Recv Func } -type hook interface { - Open(env env.Env) (interface{}, error) +type Hooker interface { + New(env env.Env) (interface{}, error) } type H interface { - Open(env env.Env) (*Pipe, error) - String() string + New(env env.Env) (*Pipe, error) } type Sender interface { @@ -44,12 +43,12 @@ func (f Func) Send(rq, wq queue.Q) error { return f(rq, wq) } -func (f Func) Open(env env.Env) (interface{}, error) { +func (f Func) New(env env.Env) (interface{}, error) { return f, nil } type wrapper struct { - hook + hook Hooker name string reverse bool } @@ -58,8 +57,8 @@ func (w *wrapper) String() string { return fmt.Sprintf("hook:%s", w.name) } -func (w *wrapper) Open(env env.Env) (*Pipe, error) { - it, err := w.hook.Open(env) +func (w *wrapper) New(env env.Env) (*Pipe, error) { + it, err := w.hook.New(env) if err != nil { return nil, err } @@ -87,6 +86,23 @@ func (p *Pipe) Close() { } } +func initHook(i interface{}, opts opts.Opts) (Hooker, error) { + if f, ok := i.(Func); ok { + return f, nil + } + + if p, ok := i.(pipeHolder); ok { + return p, nil + } + + h := reflect.New(reflect.TypeOf(i)).Interface() + if err := opts.Configure(h); err != nil { + return nil, err + } + + return h.(Hooker), nil +} + func New(desc string) (H, error) { name, opts := opts.Parse(desc) reverse := false @@ -96,9 +112,9 @@ func New(desc string) (H, error) { reverse = true } - if f, ok := hooks[name]; !ok { + if i, ok := hooks[name]; !ok { return nil, fmt.Errorf("unknown hook '%s'", name) - } else if h, err := f(opts); err != nil { + } else if h, err := initHook(i, opts); err != nil { return nil, fmt.Errorf("%s: %w", name, err) } else { w := &wrapper{ @@ -110,18 +126,41 @@ func New(desc string) (H, error) { } } -func register(name string, f hookInitFunc) { +func register(name string, i interface{}) { + switch t := reflect.TypeOf(i); t.Kind() { + case reflect.Struct: + if _, ok := reflect.New(t).Interface().(Hooker); !ok { + log.Panicf("uncompatible hook type '%s'", t.String()) + } + case reflect.Func: + if _, ok := i.(Func); !ok { + log.Panicf("uncompatible func type '%s'", t.String()) + } + default: + log.Panicf("non-struct and non-func type '%s'", t.String()) + } + if _, ok := hooks[name]; ok { log.Panicf("duplicate hook name '%s'", name) } - hooks[name] = f + hooks[name] = i } -func registerFunc(name string, p Func) { - register(name, func(opts.Opts) (hook, error) { - return p, nil - }) +func registerFunc(name string, f Func) { + register(name, f) +} + +type pipeHolder struct { + i interface{} +} + +func (p pipeHolder) New(env.Env) (interface{}, error) { + return p.i, nil +} + +func registerPipe(name string, i interface{}) { + register(name, pipeHolder{i}) } func GetList() []string { diff --git a/pkg/server/hook/info-http.go b/pkg/server/hook/info-http.go index 73480ff..ec56f87 100644 --- a/pkg/server/hook/info-http.go +++ b/pkg/server/hook/info-http.go @@ -2,9 +2,9 @@ package hook import ( "bufio" + "tunnel/pkg/http" "tunnel/pkg/server/env" - "tunnel/pkg/server/opts" "tunnel/pkg/server/queue" ) @@ -42,14 +42,10 @@ func (info *infoHttp) Recv(rq, wq queue.Q) error { return queue.Copy(rq, wq) } -func (infoHttpHook) Open(env env.Env) (interface{}, error) { +func (infoHttpHook) New(env env.Env) (interface{}, error) { return &infoHttp{env: env}, nil } -func newInfoHttpHook(opts.Opts) (hook, error) { - return infoHttpHook{}, nil -} - func init() { - register("info-http", newInfoHttpHook) + register("info-http", infoHttpHook{}) } diff --git a/pkg/server/hook/proxy.go b/pkg/server/hook/proxy.go index bc6da18..4276d9a 100644 --- a/pkg/server/hook/proxy.go +++ b/pkg/server/hook/proxy.go @@ -3,12 +3,11 @@ package hook import ( "bufio" "bytes" - "errors" "fmt" "regexp" + "tunnel/pkg/http" "tunnel/pkg/server/env" - "tunnel/pkg/server/opts" "tunnel/pkg/server/queue" ) @@ -16,8 +15,8 @@ var addrPattern = "^([0-9a-zA-Z-.]+|\\[[0-9a-fA-F:]*\\]):[0-9]+$" var isGoodAddr = regexp.MustCompile(addrPattern).MatchString type proxyHook struct { - addr string - auth string + Addr string `opts:"required"` + Auth string } type proxy struct { @@ -67,15 +66,15 @@ func (p *proxy) Recv(rq, wq queue.Q) error { return queue.IoCopy(r, wq.Writer()) } -func (h *proxyHook) Open(env env.Env) (interface{}, error) { - addr := env.Expand(h.addr) +func (h *proxyHook) New(env env.Env) (interface{}, error) { + addr := env.Expand(h.Addr) if !isGoodAddr(addr) { return nil, fmt.Errorf("invalid addr '%s'", addr) } p := &proxy{ addr: addr, - auth: h.auth, + auth: h.Auth, c: make(chan bool), env: env, } @@ -87,19 +86,6 @@ func (h *proxyHook) Open(env env.Env) (interface{}, error) { return p, nil } -func newProxyHook(opts opts.Opts) (hook, error) { - h := &proxyHook{ - addr: opts["addr"], - auth: opts["auth"], - } - - if h.addr == "" { - return nil, errors.New("expected addr") - } - - return h, nil -} - func init() { - register("proxy", newProxyHook) + register("proxy", proxyHook{}) } diff --git a/pkg/server/hook/split.go b/pkg/server/hook/split.go index 6a2c4ca..59c8055 100644 --- a/pkg/server/hook/split.go +++ b/pkg/server/hook/split.go @@ -1,27 +1,24 @@ package hook import ( - "errors" - "strconv" "tunnel/pkg/server/env" - "tunnel/pkg/server/opts" "tunnel/pkg/server/queue" ) -const splitDefaultSize = 1024 - -var errBadSize = errors.New("bad size value") - type splitHook struct { - size int + Size int `opts:"positive,default:1024"` +} + +type splitPipe struct { + h *splitHook } -func (h *splitHook) Send(rq, wq queue.Q) error { +func (p splitPipe) Send(rq, wq queue.Q) error { for b := range rq { var upto int for n := 0; n < len(b); n = upto { - upto += h.size + upto += p.h.Size if upto > len(b) { upto = len(b) @@ -34,24 +31,10 @@ func (h *splitHook) Send(rq, wq queue.Q) error { return nil } -func (h *splitHook) Open(env.Env) (interface{}, error) { - return h, nil -} - -func newSplitHook(opts opts.Opts) (hook, error) { - size := splitDefaultSize - - if s, ok := opts["size"]; ok { - var err error - - if size, err = strconv.Atoi(s); err != nil || size <= 0 { - return nil, errBadSize - } - } - - return &splitHook{size: size}, nil +func (h *splitHook) New(env.Env) (interface{}, error) { + return &splitPipe{h}, nil } func init() { - register("split", newSplitHook) + register("split", splitHook{}) } diff --git a/pkg/server/hook/zip.go b/pkg/server/hook/zip.go index bde4957..615b50d 100644 --- a/pkg/server/hook/zip.go +++ b/pkg/server/hook/zip.go @@ -3,14 +3,13 @@ package hook import ( "compress/flate" "io" - "tunnel/pkg/server/env" - "tunnel/pkg/server/opts" + "tunnel/pkg/server/queue" ) -type zipHook struct{} +type zipPipe struct{} -func (zipHook) Send(rq, wq queue.Q) error { +func (zipPipe) Send(rq, wq queue.Q) error { w, err := flate.NewWriter(wq.Writer(), flate.BestCompression) if err != nil { return err @@ -28,7 +27,7 @@ func (zipHook) Send(rq, wq queue.Q) error { return w.Close() } -func (zipHook) Recv(rq, wq queue.Q) error { +func (zipPipe) Recv(rq, wq queue.Q) error { r := flate.NewReader(rq.Reader()) // FIXME: not received ending due to ultimate conn.Close @@ -42,14 +41,6 @@ func (zipHook) Recv(rq, wq queue.Q) error { return r.Close() } -func (h zipHook) Open(env.Env) (interface{}, error) { - return h, nil -} - -func newZipHook(opts.Opts) (hook, error) { - return zipHook{}, nil -} - func init() { - register("zip", newZipHook) + registerPipe("zip", zipPipe{}) } |
