require (
bazil.org/fuse v0.0.0-20180421153158-65cc252bf669
github.com/RoaringBitmap/roaring v0.4.18 // indirect
+ github.com/alexflint/go-arg v1.1.0
github.com/anacrolix/dht/v2 v2.0.1
github.com/anacrolix/envpprof v0.0.0-20180404065416-323002cec2fa
github.com/anacrolix/go-libutp v1.0.2
github.com/RoaringBitmap/roaring v0.4.7/go.mod h1:8khRDP4HmeXns4xIj9oGrKSz7XTQiJx2zgh7AcNke4w=
github.com/RoaringBitmap/roaring v0.4.18 h1:nh8Ngxctxt5QAoMLuR7MHJe4jEqpn+EnsdgDWPryQWo=
github.com/RoaringBitmap/roaring v0.4.18/go.mod h1:D3qVegWTmfCaX4Bl5CrBE9hfrSrrXIr8KVNvRsDi1NI=
+github.com/alexflint/go-arg v1.1.0 h1:92ADei0d3TP0mGBdJ/FNcF54X6uFY7BQfhqkrQt3CCE=
+github.com/alexflint/go-arg v1.1.0/go.mod h1:3Rj4baqzWaGGmZA2+bVTV8zQOZEjBQAPBnL5xLT+ftY=
+github.com/alexflint/go-scalar v1.0.0 h1:NGupf1XV/Xb04wXskDFzS0KWOLH632W/EO4fAFi+A70=
+github.com/alexflint/go-scalar v1.0.0/go.mod h1:GpHzbCOZXEKMEcygYQ5n/aa4Aq84zbxjy3MxYW0gjYw=
github.com/anacrolix/dht v0.0.0-20180412060941-24cbf25b72a4 h1:0yHJvFiGQhJ1gSHJOR8xzmnx45orEt7uiIB6guf0+zc=
github.com/anacrolix/dht v0.0.0-20180412060941-24cbf25b72a4/go.mod h1:hQfX2BrtuQsLQMYQwsypFAab/GvHg8qxwVi4OJdR1WI=
github.com/anacrolix/dht/v2 v2.0.1 h1:gOHJ+OKqJ4Eb48OYStZm4AlWr1/nSA2TWlzb/+t36SA=
--- /dev/null
+package main
+
+import (
+ "io"
+ "log"
+ "net"
+ "os"
+ "sync"
+
+ "github.com/alexflint/go-arg"
+ "golang.org/x/xerrors"
+
+ "github.com/anacrolix/torrent/mse"
+)
+
+func main() {
+ err := mainErr()
+ if err != nil {
+ log.Fatalf("fatal error: %v", err)
+ }
+}
+
+func mainErr() error {
+ var args = struct {
+ CryptoMethod mse.CryptoMethod
+ Dial *struct {
+ Network string `arg:"positional"`
+ Address string `arg:"positional"`
+ SecretKey string `arg:"positional"`
+ InitialPayload []byte
+ } `arg:"subcommand""`
+ Listen *struct {
+ Network string `arg:"positional"`
+ Address string `arg:"positional"`
+ SecretKeys []string `arg:"positional"`
+ } `arg:"subcommand""`
+ }{
+ CryptoMethod: mse.AllSupportedCrypto,
+ }
+ arg.MustParse(&args)
+ if args.Dial != nil {
+ cn, err := net.Dial(args.Dial.Network, args.Dial.Address)
+ if err != nil {
+ return xerrors.Errorf("dialing: %w", err)
+ }
+ defer cn.Close()
+ rw, _, err := mse.InitiateHandshake(cn, []byte(args.Dial.SecretKey), args.Dial.InitialPayload, args.CryptoMethod)
+ if err != nil {
+ return xerrors.Errorf("initiating handshake: %w", err)
+ }
+ doStreaming(rw)
+ }
+ if args.Listen != nil {
+ l, err := net.Listen(args.Listen.Network, args.Listen.Address)
+ if err != nil {
+ return xerrors.Errorf("listening: %w", err)
+ }
+ defer l.Close()
+ cn, err := l.Accept()
+ l.Close()
+ if err != nil {
+ return xerrors.Errorf("accepting: %w", err)
+ }
+ defer cn.Close()
+ rw, _, err := mse.ReceiveHandshake(cn, func(f func([]byte) bool) {
+ for _, sk := range args.Listen.SecretKeys {
+ f([]byte(sk))
+ }
+ }, mse.DefaultCryptoSelector)
+ if err != nil {
+ log.Fatalf("error receiving: %v", err)
+ }
+ doStreaming(rw)
+ }
+ return nil
+}
+
+func doStreaming(rw io.ReadWriter) {
+ var wg sync.WaitGroup
+ wg.Add(2)
+ go func() {
+ defer wg.Done()
+ log.Println(io.Copy(rw, os.Stdin))
+ }()
+ go func() {
+ defer wg.Done()
+ log.Println(io.Copy(os.Stdout, rw))
+ }()
+ wg.Wait()
+}