diff --git a/beam/examples/beamsh/beamsh.go b/beam/examples/beamsh/beamsh.go index c363372..60a13c7 100644 --- a/beam/examples/beamsh/beamsh.go +++ b/beam/examples/beamsh/beamsh.go @@ -304,6 +304,55 @@ func GetHandler(name string) Handler { beam.Send(out, data.Empty().Set("type", "socket").Set("remoteaddr", conn.RemoteAddr().String()).Bytes(), f) } } + } else if name == "connect" { + return func(args []string, in *net.UnixConn, out *net.UnixConn) { + if len(args) != 2 { + beam.Send(out, data.Empty().Set("status", "1").Set("message", "wrong number of arguments").Bytes(), nil) + return + } + u, err := url.Parse(args[1]) + if err != nil { + beam.Send(out, data.Empty().Set("status", "1").Set("message", err.Error()).Bytes(), nil) + return + } + var tasks sync.WaitGroup + for { + _, attachment, err := beam.Receive(in) + if err != nil { + break + } + if attachment == nil { + continue + } + Logf("connecting to %s/%s\n", u.Scheme, u.Host) + conn, err := net.Dial(u.Scheme, u.Host) + if err != nil { + beam.Send(out, data.Empty().Set("cmd", "msg", "connect error: " + err.Error()).Bytes(), nil) + return + } + beam.Send(out, data.Empty().Set("cmd", "msg", "connection established").Bytes(), nil) + tasks.Add(1) + go func(attachment *os.File, conn net.Conn) { + defer tasks.Done() + // even when successful, conn.File() returns a duplicate, + // so we must close the original + var iotasks sync.WaitGroup + iotasks.Add(2) + go func(attachment *os.File, conn net.Conn) { + defer iotasks.Done() + io.Copy(attachment, conn) + }(attachment, conn) + go func(attachment *os.File, conn net.Conn) { + defer iotasks.Done() + io.Copy(conn, attachment) + }(attachment, conn) + iotasks.Wait() + conn.Close() + attachment.Close() + }(attachment, conn) + } + tasks.Wait() + } } else if name == "openfile" { return func(args []string, in *net.UnixConn, out *net.UnixConn) { for _, name := range args {