summaryrefslogtreecommitdiff
path: root/pkg/server/module/tee.go
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/server/module/tee.go')
-rw-r--r--pkg/server/module/tee.go112
1 files changed, 112 insertions, 0 deletions
diff --git a/pkg/server/module/tee.go b/pkg/server/module/tee.go
new file mode 100644
index 0000000..7953247
--- /dev/null
+++ b/pkg/server/module/tee.go
@@ -0,0 +1,112 @@
+package module
+
+import (
+ "bytes"
+ "fmt"
+ "os"
+ "encoding/hex"
+ "sync"
+ "tunnel/pkg/server/env"
+ "tunnel/pkg/server/opts"
+ "tunnel/pkg/server/queue"
+)
+
+const teeDefaultPath = "/tmp/tunnel.dump"
+
+type tee struct {
+ f *os.File
+ mu sync.Mutex
+ wg sync.WaitGroup
+}
+
+type teeModule struct {
+ path string
+}
+
+func (t *tee) dump(s string, p []byte) error {
+ var out bytes.Buffer
+
+ fmt.Fprintln(&out, s, len(p))
+
+ w := hex.Dumper(&out)
+ w.Write(p)
+ w.Close()
+
+ if _, err := t.f.Write(out.Bytes()); err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func (t *tee) Send(rq, wq queue.Q) error {
+ defer t.wg.Done()
+
+ for b := range rq {
+ t.dump(">", b)
+ wq <- b
+ }
+
+ return nil
+}
+
+func (t *tee) Recv(rq, wq queue.Q) error {
+ defer t.wg.Done()
+
+ for b := range rq {
+ t.dump("<", b)
+ wq <- b
+ }
+
+ return nil
+}
+
+func (m *teeModule) where(env env.Env) string {
+ if m.path != "" {
+ return m.path
+ }
+
+ if v := env.Eval("@{tunnel.@{tunnel}.tee.path}"); v != "" {
+ return v
+ }
+
+ if v, ok := env.Find("module.tee.path"); ok {
+ return v
+ }
+
+ return teeDefaultPath
+}
+
+func (m *teeModule) Open(env env.Env) (interface{}, error) {
+ tid, sid := env.Get("tunnel"), env.Get("stream")
+ name := fmt.Sprintf("%s.%s.%s", m.where(env), tid, sid)
+
+ var t tee
+
+ if f, err := os.Create(name); err != nil {
+ return nil, err
+ } else {
+ t.f = f
+ }
+
+ t.wg.Add(2)
+
+ go func() {
+ t.wg.Wait()
+ t.f.Close()
+ }()
+
+ return &t, nil
+}
+
+func newTeeModule(opts opts.Opts, env env.Env) (module, error) {
+ m := &teeModule{}
+ if path, ok := opts["path"]; ok {
+ m.path = path
+ }
+ return m, nil
+}
+
+func init() {
+ register("tee", newTeeModule)
+}