diff options
Diffstat (limited to 'pkg/server/hook/hook.go')
| -rw-r--r-- | pkg/server/hook/hook.go | 126 |
1 files changed, 126 insertions, 0 deletions
diff --git a/pkg/server/hook/hook.go b/pkg/server/hook/hook.go new file mode 100644 index 0000000..b2970ac --- /dev/null +++ b/pkg/server/hook/hook.go @@ -0,0 +1,126 @@ +package hook + +import ( + "fmt" + "log" + "sort" + "strings" + "tunnel/pkg/server/env" + "tunnel/pkg/server/opts" + "tunnel/pkg/server/queue" +) + +type hookInitFunc func(opts.Opts, env.Env) (hook, error) + +var hooks = map[string]hookInitFunc{} + +type hook interface { + Open(env env.Env) (interface{}, error) +} + +type H interface { + hook + String() string +} + +type Sender interface { + Send(rq, wq queue.Q) error +} + +type Recver interface { + Recv(rq, wq queue.Q) error +} + +type Func func(rq, wq queue.Q) error + +func (f Func) Send(rq, wq queue.Q) error { + return f(rq, wq) +} + +func (f Func) Open(env env.Env) (interface{}, error) { + return f, nil +} + +type wrapper struct { + hook + name string + reverse bool +} + +func (w *wrapper) String() string { + return fmt.Sprintf("hook:%s", w.name) +} + +func Open(h H, env env.Env) (Func, Func, error) { + var send, recv Func + + w := h.(*wrapper) + + it, err := h.Open(env) + if err != nil { + return nil, nil, err + } + + if sender, ok := it.(Sender); ok { + send = sender.Send + } + + if recver, ok := it.(Recver); ok { + recv = recver.Recv + } + + if w.reverse { + send, recv = recv, send + } + + return send, recv, nil +} + +func New(desc string, env env.Env) (H, error) { + name, opts := opts.Parse(desc) + reverse := false + + if strings.HasPrefix(name, "-") { + name = name[1:] + reverse = true + } + + if f, ok := hooks[name]; !ok { + return nil, fmt.Errorf("unknown hook '%s'", name) + } else if h, err := f(opts, env); err != nil { + return nil, err + } else { + w := &wrapper{ + hook: h, + name: name, + reverse: reverse, + } + return w, nil + } +} + +func register(name string, f hookInitFunc) { + if _, ok := hooks[name]; ok { + log.Panicf("duplicate hook name '%s'", name) + } + + hooks[name] = f +} + +func registerFunc(name string, p Func) { + register(name, func(opts.Opts, env.Env) (hook, error) { + return p, nil + }) +} + +func GetList() []string { + var list []string + + for k := range hooks { + list = append(list, k) + } + + sort.Strings(list) + + return list +} |
