summaryrefslogtreecommitdiff
path: root/pkg/server/hook
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/server/hook')
-rw-r--r--pkg/server/hook/aes.go16
-rw-r--r--pkg/server/hook/auth.go18
-rw-r--r--pkg/server/hook/b64.go19
-rw-r--r--pkg/server/hook/b85.go19
-rw-r--r--pkg/server/hook/dump.go30
-rw-r--r--pkg/server/hook/hex.go19
-rw-r--r--pkg/server/hook/hook.go77
-rw-r--r--pkg/server/hook/info-http.go10
-rw-r--r--pkg/server/hook/proxy.go28
-rw-r--r--pkg/server/hook/split.go37
-rw-r--r--pkg/server/hook/zip.go19
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{})
}