package module import ( "fmt" "log" "strings" "tunnel/pkg/server/env" "tunnel/pkg/server/opts" "tunnel/pkg/server/queue" ) type moduleInitFunc func(opts.Opts, env.Env) (module, error) var modules = map[string]moduleInitFunc{} type module interface { Open(env env.Env) (interface{}, error) } type M interface { module 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 { module name string reverse bool } func (w *wrapper) String() string { return fmt.Sprintf("module:%s", w.name) } func Open(m M, env env.Env) (Func, Func, error) { var send, recv Func w := m.(*wrapper) it, err := m.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) (M, error) { name, opts := opts.Parse(desc) reverse := false if strings.HasPrefix(name, "-") { name = name[1:] reverse = true } if f, ok := modules[name]; !ok { return nil, fmt.Errorf("unknown module '%s'", name) } else if m, err := f(opts, env); err != nil { return nil, err } else { w := &wrapper{ module: m, name: name, reverse: reverse, } return w, nil } } func register(name string, f moduleInitFunc) { if _, ok := modules[name]; ok { log.Panicf("duplicate module name '%s'", name) } modules[name] = f } func registerFunc(name string, p Func) { register(name, func(opts.Opts, env.Env) (module, error) { return p, nil }) }