From c786b0bd07fd016e41faf9bb7b31e93d69297add Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Wed, 8 Aug 2018 00:16:52 -0600 Subject: [PATCH] support pipes and stdin --- README.md | 16 +++++++++++++ sclient-cli.go | 59 +++++++++++++++++++++++++++------------------ sclient.go | 60 ++++++++++++++++++++++++++++++++++++++++++---- tests/get.bin | 5 ++++ tests/localhost.sh | 8 +++++++ tests/pipe.sh | 3 +++ tests/stdin.sh | 3 +++ 7 files changed, 126 insertions(+), 28 deletions(-) create mode 100644 tests/get.bin create mode 100755 tests/localhost.sh create mode 100755 tests/pipe.sh create mode 100755 tests/stdin.sh diff --git a/README.md b/README.md index af2d1df..7e1005f 100644 --- a/README.md +++ b/README.md @@ -96,3 +96,19 @@ Ignore a bad TLS/SSL/HTTPS certificate and connect anyway. ```bash sclient -k badtls.telebit.cloud:443 localhost:3000 ``` + +Reading from stdin + +```bash +sclient telebit.cloud:443 - +``` + +```bash +sclient telebit.cloud:443 - 0 even if there's an err - count, err := r.Read(buffer) //fmt.Fprintf(os.Stdout, "[debug] (%s) reading\n", t) + count, err := r.Read(buffer) if nil != err { //fmt.Fprintf(os.Stdout, "[debug] (%s:%d) error reading %s\n", t, count, err) if io.EOF != err { @@ -56,7 +86,7 @@ func pipe(r net.Conn, w net.Conn, t string) { } } -func handleConnection(remote string, conn net.Conn, opts *SclientOpts) { +func handleConnection(remote string, conn Rwc, opts *SclientOpts) { sclient, err := tls.Dial("tcp", remote, &tls.Config{InsecureSkipVerify: opts.InsecureSkipVerify}) @@ -66,8 +96,13 @@ func handleConnection(remote string, conn net.Conn, opts *SclientOpts) { return } - fmt.Fprintf(os.Stdout, "[connect] %s => %s:%d\n", - strings.Replace(conn.RemoteAddr().String(), "[::1]:", "localhost:", 1), opts.RemoteAddress, opts.RemotePort) + if "stdio" == conn.RemoteAddr().Network() { + fmt.Fprintf(os.Stdout, "(connected to %s:%d and reading from %s)\n", + opts.RemoteAddress, opts.RemotePort, conn.RemoteAddr().String()) + } else { + fmt.Fprintf(os.Stdout, "[connect] %s => %s:%d\n", + strings.Replace(conn.RemoteAddr().String(), "[::1]:", "localhost:", 1), opts.RemoteAddress, opts.RemotePort) + } go pipe(conn, sclient, "local") pipe(sclient, conn, "remote") @@ -84,6 +119,21 @@ func (*Sclient) DialAndListen(opts *SclientOpts) error { conn.Close() } + // use stdin/stdout + if "-" == opts.LocalAddress || "|" == opts.LocalAddress { + var name string + network := "stdio" + if "|" == opts.LocalAddress { + name = "pipe" + } else { + name = "stdin" + } + conn := &stdnet{os.Stdin, os.Stdout, &stdaddr{net.UnixAddr{name, network}}} + handleConnection(remote, conn, opts) + return nil + } + + // use net.Conn local := opts.LocalAddress + ":" + strconv.Itoa(opts.LocalPort) ln, err := net.Listen("tcp", local) if err != nil { diff --git a/tests/get.bin b/tests/get.bin new file mode 100644 index 0000000..6a7e3ce --- /dev/null +++ b/tests/get.bin @@ -0,0 +1,5 @@ +GET / HTTP/1.1 +Host: telebit.cloud +Connection: close + + diff --git a/tests/localhost.sh b/tests/localhost.sh new file mode 100755 index 0000000..4e16d8b --- /dev/null +++ b/tests/localhost.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +go run -race sclient*.go telebit.cloud:443 localhost:3000 & +my_pid=$! +sleep 5 + +netcat localhost 3000 < tests/get.bin +kill $my_pid diff --git a/tests/pipe.sh b/tests/pipe.sh new file mode 100755 index 0000000..b74d4ec --- /dev/null +++ b/tests/pipe.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +cat tests/get.bin | go run -race sclient*.go telebit.cloud:443 diff --git a/tests/stdin.sh b/tests/stdin.sh new file mode 100755 index 0000000..3f085ec --- /dev/null +++ b/tests/stdin.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +go run -race sclient*.go telebit.cloud:443 - < ./tests/get.bin