commit c4ef06f097354214460d45207a0297eec79d3bbe
Author: Ximin Luo <[email protected]>
Date:   Sun May 18 13:47:26 2014 +0100

    disambiguate binary names to avoid potential name clashes
---
 Makefile                                   |   22 +-
 pt-websocket-client/pt-websocket-client.go |  263 ++++++++++++++++++++++++
 pt-websocket-server/pt-websocket-server.go |  299 ++++++++++++++++++++++++++++
 websocket-client/websocket-client.go       |  263 ------------------------
 websocket-server/websocket-server.go       |  299 ----------------------------
 5 files changed, 573 insertions(+), 573 deletions(-)

diff --git a/Makefile b/Makefile
index b723c86..4882798 100644
--- a/Makefile
+++ b/Makefile
@@ -9,26 +9,26 @@ GOBUILDFLAGS =
 #   apt-get install gccgo-multilib
 # GOBUILDFLAGS = -compiler gccgo -gccgoflags "-O3 -m32 -static-libgo"
 
-all: websocket-server/websocket-server
+all: pt-websocket-server/pt-websocket-server
 
-websocket-server/websocket-server: websocket-server/*.go websocket/*.go
-       cd websocket-server && go build $(GOBUILDFLAGS)
+pt-websocket-server/pt-websocket-server: pt-websocket-server/*.go 
websocket/*.go
+       cd pt-websocket-server && go build $(GOBUILDFLAGS)
 
-websocket-client/websocket-client: websocket-client/*.go
-       cd websocket-client && go build $(GOBUILDFLAGS)
+pt-websocket-client/pt-websocket-client: pt-websocket-client/*.go
+       cd pt-websocket-client && go build $(GOBUILDFLAGS)
 
-doc/websocket-server.1: websocket-server/websocket-server
+doc/pt-websocket-server.1: pt-websocket-server/pt-websocket-server
        help2man --no-info --name "WebSocket server pluggable transport" 
--version-string "$(VERSION)" -o "$@" "$<"
 
-install: websocket-server/websocket-server
+install: pt-websocket-server/pt-websocket-server
        mkdir -p "$(DESTDIR)$(BINDIR)"
-       cp -f websocket-server/websocket-server "$(DESTDIR)$(BINDIR)"
+       cp -f "$<" "$(DESTDIR)$(BINDIR)"
 
 clean:
-       rm -f websocket-server/websocket-server 
websocket-client/websocket-client
-       rm -f doc/websocket-server.1
+       rm -f pt-websocket-server/pt-websocket-server 
pt-websocket-client/pt-websocket-client
+       rm -f doc/pt-websocket-server.1
 
 fmt:
-       go fmt ./websocket-server ./websocket-client ./websocket
+       go fmt ./pt-websocket-server ./pt-websocket-client ./websocket
 
 .PHONY: all install clean fmt
diff --git a/pt-websocket-client/pt-websocket-client.go 
b/pt-websocket-client/pt-websocket-client.go
new file mode 100644
index 0000000..fe38c9d
--- /dev/null
+++ b/pt-websocket-client/pt-websocket-client.go
@@ -0,0 +1,263 @@
+// Tor websocket client transport plugin.
+//
+// Usage in torrc:
+//     UseBridges 1
+//     Bridge websocket X.X.X.X:YYYY
+//     ClientTransportPlugin websocket exec ./websocket-client
+package main
+
+import (
+       "code.google.com/p/go.net/websocket"
+       "flag"
+       "fmt"
+       "io"
+       "net"
+       "net/url"
+       "os"
+       "os/signal"
+       "sync"
+       "syscall"
+       "time"
+)
+
+import "git.torproject.org/pluggable-transports/goptlib.git"
+
+var ptInfo pt.ClientInfo
+
+const ptMethodName = "websocket"
+const bufSiz = 1500
+
+var logFile = os.Stderr
+
+// When a connection handler starts, +1 is written to this channel; when it
+// ends, -1 is written.
+var handlerChan = make(chan int)
+
+var logMutex sync.Mutex
+
+func usage() {
+       fmt.Printf("Usage: %s [OPTIONS]\n", os.Args[0])
+       fmt.Printf("WebSocket client pluggable transport for Tor.\n")
+       fmt.Printf("Works only as a managed proxy.\n")
+       fmt.Printf("\n")
+       fmt.Printf("  -h, --help    show this help.\n")
+       fmt.Printf("  --log FILE    log messages to FILE (default stderr).\n")
+       fmt.Printf("  --socks ADDR  listen for SOCKS on ADDR.\n")
+}
+
+func log(format string, v ...interface{}) {
+       dateStr := time.Now().Format("2006-01-02 15:04:05")
+       logMutex.Lock()
+       defer logMutex.Unlock()
+       msg := fmt.Sprintf(format, v...)
+       fmt.Fprintf(logFile, "%s %s\n", dateStr, msg)
+}
+
+func proxy(local *net.TCPConn, ws *websocket.Conn) {
+       var wg sync.WaitGroup
+
+       wg.Add(2)
+
+       // Local-to-WebSocket read loop.
+       go func() {
+               buf := make([]byte, bufSiz)
+               var err error
+               for {
+                       n, er := local.Read(buf[:])
+                       if n > 0 {
+                               ew := websocket.Message.Send(ws, buf[:n])
+                               if ew != nil {
+                                       err = ew
+                                       break
+                               }
+                       }
+                       if er != nil {
+                               err = er
+                               break
+                       }
+               }
+               if err != nil && err != io.EOF {
+                       log("%s", err)
+               }
+               local.CloseRead()
+               ws.Close()
+
+               wg.Done()
+       }()
+
+       // WebSocket-to-local read loop.
+       go func() {
+               var buf []byte
+               var err error
+               for {
+                       er := websocket.Message.Receive(ws, &buf)
+                       if er != nil {
+                               err = er
+                               break
+                       }
+                       n, ew := local.Write(buf)
+                       if ew != nil {
+                               err = ew
+                               break
+                       }
+                       if n != len(buf) {
+                               err = io.ErrShortWrite
+                               break
+                       }
+               }
+               if err != nil && err != io.EOF {
+                       log("%s", err)
+               }
+               local.CloseWrite()
+               ws.Close()
+
+               wg.Done()
+       }()
+
+       wg.Wait()
+}
+
+func handleConnection(conn *pt.SocksConn) error {
+       defer conn.Close()
+
+       handlerChan <- 1
+       defer func() {
+               handlerChan <- -1
+       }()
+
+       var ws *websocket.Conn
+
+       log("SOCKS request for %s", conn.Req.Target)
+       destAddr, err := net.ResolveTCPAddr("tcp", conn.Req.Target)
+       if err != nil {
+               conn.Reject()
+               return err
+       }
+       wsUrl := url.URL{Scheme: "ws", Host: conn.Req.Target}
+       ws, err = websocket.Dial(wsUrl.String(), "", wsUrl.String())
+       if err != nil {
+               err = conn.Reject()
+               return err
+       }
+       log("WebSocket connection to %s", ws.Config().Location.String())
+       defer ws.Close()
+       err = conn.Grant(destAddr)
+       if err != nil {
+               return err
+       }
+
+       proxy(conn.Conn.(*net.TCPConn), ws)
+
+       return nil
+}
+
+func socksAcceptLoop(ln *pt.SocksListener) error {
+       defer ln.Close()
+       for {
+               socks, err := ln.AcceptSocks()
+               if err != nil {
+                       if e, ok := err.(*net.OpError); ok && !e.Temporary() {
+                               return err
+                       }
+                       continue
+               }
+               go func() {
+                       err := handleConnection(socks)
+                       if err != nil {
+                               log("SOCKS from %s: %s", socks.RemoteAddr(), 
err)
+                       }
+               }()
+       }
+       return nil
+}
+
+func startListener(addrStr string) (*pt.SocksListener, error) {
+       ln, err := pt.ListenSocks("tcp", addrStr)
+       if err != nil {
+               return nil, err
+       }
+       go func() {
+               err := socksAcceptLoop(ln)
+               if err != nil {
+                       log("accept: %s", err)
+               }
+       }()
+       return ln, nil
+}
+
+func main() {
+       var logFilename string
+       var socksAddrStr string
+       var err error
+
+       flag.Usage = usage
+       flag.StringVar(&logFilename, "log", "", "log file to write to")
+       flag.StringVar(&socksAddrStr, "socks", "127.0.0.1:0", "address on which 
to listen for SOCKS connections")
+       flag.Parse()
+
+       if logFilename != "" {
+               f, err := os.OpenFile(logFilename, 
os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0600)
+               if err != nil {
+                       fmt.Fprintf(os.Stderr, "Can't open log file %q: %s.\n", 
logFilename, err.Error())
+                       os.Exit(1)
+               }
+               logFile = f
+       }
+
+       log("starting")
+       ptInfo, err = pt.ClientSetup([]string{ptMethodName})
+       if err != nil {
+               log("error in setup: %s", err)
+               os.Exit(1)
+       }
+
+       listeners := make([]net.Listener, 0)
+       for _, methodName := range ptInfo.MethodNames {
+               switch methodName {
+               case ptMethodName:
+                       ln, err := startListener(socksAddrStr)
+                       if err != nil {
+                               pt.CmethodError(ptMethodName, err.Error())
+                               break
+                       }
+                       pt.Cmethod(ptMethodName, ln.Version(), ln.Addr())
+                       log("listening on %s", ln.Addr().String())
+                       listeners = append(listeners, ln)
+               default:
+                       pt.CmethodError(methodName, "no such method")
+               }
+       }
+       pt.CmethodsDone()
+
+       var numHandlers int = 0
+       var sig os.Signal
+       sigChan := make(chan os.Signal, 1)
+       signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
+
+       // wait for first signal
+       sig = nil
+       for sig == nil {
+               select {
+               case n := <-handlerChan:
+                       numHandlers += n
+               case sig = <-sigChan:
+               }
+       }
+       for _, ln := range listeners {
+               ln.Close()
+       }
+
+       if sig == syscall.SIGTERM {
+               return
+       }
+
+       // wait for second signal or no more handlers
+       sig = nil
+       for sig == nil && numHandlers != 0 {
+               select {
+               case n := <-handlerChan:
+                       numHandlers += n
+               case sig = <-sigChan:
+               }
+       }
+}
diff --git a/pt-websocket-server/pt-websocket-server.go 
b/pt-websocket-server/pt-websocket-server.go
new file mode 100644
index 0000000..4120df8
--- /dev/null
+++ b/pt-websocket-server/pt-websocket-server.go
@@ -0,0 +1,299 @@
+// Tor websocket server transport plugin.
+//
+// Usage in torrc:
+//     ExtORPort 6669
+//     ServerTransportPlugin websocket exec ./websocket-server --port 9901
+package main
+
+import (
+       "encoding/base64"
+       "errors"
+       "flag"
+       "fmt"
+       "io"
+       "net"
+       "net/http"
+       "os"
+       "os/signal"
+       "sync"
+       "syscall"
+       "time"
+)
+
+import "../websocket"
+
+import "git.torproject.org/pluggable-transports/goptlib.git"
+
+const ptMethodName = "websocket"
+const requestTimeout = 10 * time.Second
+
+// "4/3+1" accounts for possible base64 encoding.
+const maxMessageSize = 64*1024*4/3 + 1
+
+var logFile = os.Stderr
+
+var ptInfo pt.ServerInfo
+
+// When a connection handler starts, +1 is written to this channel; when it
+// ends, -1 is written.
+var handlerChan = make(chan int)
+
+func usage() {
+       fmt.Printf("Usage: %s [OPTIONS]\n", os.Args[0])
+       fmt.Printf("WebSocket server pluggable transport for Tor.\n")
+       fmt.Printf("Works only as a managed proxy.\n")
+       fmt.Printf("\n")
+       fmt.Printf("  -h, --help   show this help.\n")
+       fmt.Printf("  --log FILE   log messages to FILE (default stderr).\n")
+       fmt.Printf("  --port PORT  listen on PORT (overrides Tor's requested 
port).\n")
+}
+
+var logMutex sync.Mutex
+
+func log(format string, v ...interface{}) {
+       dateStr := time.Now().Format("2006-01-02 15:04:05")
+       logMutex.Lock()
+       defer logMutex.Unlock()
+       msg := fmt.Sprintf(format, v...)
+       fmt.Fprintf(logFile, "%s %s\n", dateStr, msg)
+}
+
+// An abstraction that makes an underlying WebSocket connection look like an
+// io.ReadWriteCloser. It internally takes care of things like base64 encoding
+// and decoding.
+type webSocketConn struct {
+       Ws         *websocket.WebSocket
+       Base64     bool
+       messageBuf []byte
+}
+
+// Implements io.Reader.
+func (conn *webSocketConn) Read(b []byte) (n int, err error) {
+       for len(conn.messageBuf) == 0 {
+               var m websocket.Message
+               m, err = conn.Ws.ReadMessage()
+               if err != nil {
+                       return
+               }
+               if m.Opcode == 8 {
+                       err = io.EOF
+                       return
+               }
+               if conn.Base64 {
+                       if m.Opcode != 1 {
+                               err = errors.New(fmt.Sprintf("got non-text 
opcode %d with the base64 subprotocol", m.Opcode))
+                               return
+                       }
+                       conn.messageBuf = make([]byte, 
base64.StdEncoding.DecodedLen(len(m.Payload)))
+                       var num int
+                       num, err = base64.StdEncoding.Decode(conn.messageBuf, 
m.Payload)
+                       if err != nil {
+                               return
+                       }
+                       conn.messageBuf = conn.messageBuf[:num]
+               } else {
+                       if m.Opcode != 2 {
+                               err = errors.New(fmt.Sprintf("got non-binary 
opcode %d with no subprotocol", m.Opcode))
+                               return
+                       }
+                       conn.messageBuf = m.Payload
+               }
+       }
+
+       n = copy(b, conn.messageBuf)
+       conn.messageBuf = conn.messageBuf[n:]
+
+       return
+}
+
+// Implements io.Writer.
+func (conn *webSocketConn) Write(b []byte) (n int, err error) {
+       if conn.Base64 {
+               buf := make([]byte, base64.StdEncoding.EncodedLen(len(b)))
+               base64.StdEncoding.Encode(buf, b)
+               err = conn.Ws.WriteMessage(1, buf)
+               if err != nil {
+                       return
+               }
+               n = len(b)
+       } else {
+               err = conn.Ws.WriteMessage(2, b)
+               n = len(b)
+       }
+       return
+}
+
+// Implements io.Closer.
+func (conn *webSocketConn) Close() error {
+       // Ignore any error in trying to write a Close frame.
+       _ = conn.Ws.WriteFrame(8, nil)
+       return conn.Ws.Conn.Close()
+}
+
+// Create a new webSocketConn.
+func newWebSocketConn(ws *websocket.WebSocket) webSocketConn {
+       var conn webSocketConn
+       conn.Ws = ws
+       conn.Base64 = (ws.Subprotocol == "base64")
+       return conn
+}
+
+// Copy from WebSocket to socket and vice versa.
+func proxy(local *net.TCPConn, conn *webSocketConn) {
+       var wg sync.WaitGroup
+       wg.Add(2)
+
+       go func() {
+               _, err := io.Copy(conn, local)
+               if err != nil {
+                       log("error copying ORPort to WebSocket")
+               }
+               local.CloseRead()
+               conn.Close()
+               wg.Done()
+       }()
+       go func() {
+               _, err := io.Copy(local, conn)
+               if err != nil {
+                       log("error copying WebSocket to ORPort")
+               }
+               local.CloseWrite()
+               conn.Close()
+               wg.Done()
+       }()
+
+       wg.Wait()
+}
+
+func webSocketHandler(ws *websocket.WebSocket) {
+       // Undo timeouts on HTTP request handling.
+       ws.Conn.SetDeadline(time.Time{})
+       conn := newWebSocketConn(ws)
+       defer conn.Close()
+
+       handlerChan <- 1
+       defer func() {
+               handlerChan <- -1
+       }()
+
+       or, err := pt.DialOr(&ptInfo, ws.Conn.RemoteAddr().String(), 
ptMethodName)
+       if err != nil {
+               log("Failed to connect to ORPort: " + err.Error())
+               return
+       }
+       defer or.Close()
+
+       proxy(or, &conn)
+}
+
+func startListener(addr *net.TCPAddr) (*net.TCPListener, error) {
+       ln, err := net.ListenTCP("tcp", addr)
+       if err != nil {
+               return nil, err
+       }
+       go func() {
+               defer ln.Close()
+               var config websocket.Config
+               config.Subprotocols = []string{"base64"}
+               config.MaxMessageSize = maxMessageSize
+               s := &http.Server{
+                       Handler:     config.Handler(webSocketHandler),
+                       ReadTimeout: requestTimeout,
+               }
+               err = s.Serve(ln)
+               if err != nil {
+                       log("http.Serve: " + err.Error())
+               }
+       }()
+       return ln, nil
+}
+
+func main() {
+       var logFilename string
+       var port int
+
+       flag.Usage = usage
+       flag.StringVar(&logFilename, "log", "", "log file to write to")
+       flag.IntVar(&port, "port", 0, "port to listen on if unspecified by Tor")
+       flag.Parse()
+
+       if logFilename != "" {
+               f, err := os.OpenFile(logFilename, 
os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0600)
+               if err != nil {
+                       fmt.Fprintf(os.Stderr, "Can't open log file %q: %s.\n", 
logFilename, err.Error())
+                       os.Exit(1)
+               }
+               logFile = f
+       }
+
+       log("starting")
+       var err error
+       ptInfo, err = pt.ServerSetup([]string{ptMethodName})
+       if err != nil {
+               log("error in setup: %s", err)
+               os.Exit(1)
+       }
+
+       listeners := make([]*net.TCPListener, 0)
+       for _, bindaddr := range ptInfo.Bindaddrs {
+               // Override tor's requested port (which is 0 if this transport
+               // has not been run before) with the one requested by the --port
+               // option.
+               if port != 0 {
+                       bindaddr.Addr.Port = port
+               }
+
+               switch bindaddr.MethodName {
+               case ptMethodName:
+                       ln, err := startListener(bindaddr.Addr)
+                       if err != nil {
+                               pt.SmethodError(bindaddr.MethodName, 
err.Error())
+                               break
+                       }
+                       pt.Smethod(bindaddr.MethodName, ln.Addr())
+                       log("listening on %s", ln.Addr().String())
+                       listeners = append(listeners, ln)
+               default:
+                       pt.SmethodError(bindaddr.MethodName, "no such method")
+               }
+       }
+       pt.SmethodsDone()
+
+       var numHandlers int = 0
+       var sig os.Signal
+       sigChan := make(chan os.Signal, 1)
+       signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
+
+       // wait for first signal
+       sig = nil
+       for sig == nil {
+               select {
+               case n := <-handlerChan:
+                       numHandlers += n
+               case sig = <-sigChan:
+               }
+       }
+       log("Got first signal %q with %d running handlers.", sig, numHandlers)
+       for _, ln := range listeners {
+               ln.Close()
+       }
+
+       if sig == syscall.SIGTERM {
+               log("Caught signal %q, exiting.", sig)
+               return
+       }
+
+       // wait for second signal or no more handlers
+       sig = nil
+       for sig == nil && numHandlers != 0 {
+               select {
+               case n := <-handlerChan:
+                       numHandlers += n
+                       log("%d remaining handlers.", numHandlers)
+               case sig = <-sigChan:
+               }
+       }
+       if sig != nil {
+               log("Got second signal %q with %d running handlers.", sig, 
numHandlers)
+       }
+}
diff --git a/websocket-client/websocket-client.go 
b/websocket-client/websocket-client.go
deleted file mode 100644
index fe38c9d..0000000
--- a/websocket-client/websocket-client.go
+++ /dev/null
@@ -1,263 +0,0 @@
-// Tor websocket client transport plugin.
-//
-// Usage in torrc:
-//     UseBridges 1
-//     Bridge websocket X.X.X.X:YYYY
-//     ClientTransportPlugin websocket exec ./websocket-client
-package main
-
-import (
-       "code.google.com/p/go.net/websocket"
-       "flag"
-       "fmt"
-       "io"
-       "net"
-       "net/url"
-       "os"
-       "os/signal"
-       "sync"
-       "syscall"
-       "time"
-)
-
-import "git.torproject.org/pluggable-transports/goptlib.git"
-
-var ptInfo pt.ClientInfo
-
-const ptMethodName = "websocket"
-const bufSiz = 1500
-
-var logFile = os.Stderr
-
-// When a connection handler starts, +1 is written to this channel; when it
-// ends, -1 is written.
-var handlerChan = make(chan int)
-
-var logMutex sync.Mutex
-
-func usage() {
-       fmt.Printf("Usage: %s [OPTIONS]\n", os.Args[0])
-       fmt.Printf("WebSocket client pluggable transport for Tor.\n")
-       fmt.Printf("Works only as a managed proxy.\n")
-       fmt.Printf("\n")
-       fmt.Printf("  -h, --help    show this help.\n")
-       fmt.Printf("  --log FILE    log messages to FILE (default stderr).\n")
-       fmt.Printf("  --socks ADDR  listen for SOCKS on ADDR.\n")
-}
-
-func log(format string, v ...interface{}) {
-       dateStr := time.Now().Format("2006-01-02 15:04:05")
-       logMutex.Lock()
-       defer logMutex.Unlock()
-       msg := fmt.Sprintf(format, v...)
-       fmt.Fprintf(logFile, "%s %s\n", dateStr, msg)
-}
-
-func proxy(local *net.TCPConn, ws *websocket.Conn) {
-       var wg sync.WaitGroup
-
-       wg.Add(2)
-
-       // Local-to-WebSocket read loop.
-       go func() {
-               buf := make([]byte, bufSiz)
-               var err error
-               for {
-                       n, er := local.Read(buf[:])
-                       if n > 0 {
-                               ew := websocket.Message.Send(ws, buf[:n])
-                               if ew != nil {
-                                       err = ew
-                                       break
-                               }
-                       }
-                       if er != nil {
-                               err = er
-                               break
-                       }
-               }
-               if err != nil && err != io.EOF {
-                       log("%s", err)
-               }
-               local.CloseRead()
-               ws.Close()
-
-               wg.Done()
-       }()
-
-       // WebSocket-to-local read loop.
-       go func() {
-               var buf []byte
-               var err error
-               for {
-                       er := websocket.Message.Receive(ws, &buf)
-                       if er != nil {
-                               err = er
-                               break
-                       }
-                       n, ew := local.Write(buf)
-                       if ew != nil {
-                               err = ew
-                               break
-                       }
-                       if n != len(buf) {
-                               err = io.ErrShortWrite
-                               break
-                       }
-               }
-               if err != nil && err != io.EOF {
-                       log("%s", err)
-               }
-               local.CloseWrite()
-               ws.Close()
-
-               wg.Done()
-       }()
-
-       wg.Wait()
-}
-
-func handleConnection(conn *pt.SocksConn) error {
-       defer conn.Close()
-
-       handlerChan <- 1
-       defer func() {
-               handlerChan <- -1
-       }()
-
-       var ws *websocket.Conn
-
-       log("SOCKS request for %s", conn.Req.Target)
-       destAddr, err := net.ResolveTCPAddr("tcp", conn.Req.Target)
-       if err != nil {
-               conn.Reject()
-               return err
-       }
-       wsUrl := url.URL{Scheme: "ws", Host: conn.Req.Target}
-       ws, err = websocket.Dial(wsUrl.String(), "", wsUrl.String())
-       if err != nil {
-               err = conn.Reject()
-               return err
-       }
-       log("WebSocket connection to %s", ws.Config().Location.String())
-       defer ws.Close()
-       err = conn.Grant(destAddr)
-       if err != nil {
-               return err
-       }
-
-       proxy(conn.Conn.(*net.TCPConn), ws)
-
-       return nil
-}
-
-func socksAcceptLoop(ln *pt.SocksListener) error {
-       defer ln.Close()
-       for {
-               socks, err := ln.AcceptSocks()
-               if err != nil {
-                       if e, ok := err.(*net.OpError); ok && !e.Temporary() {
-                               return err
-                       }
-                       continue
-               }
-               go func() {
-                       err := handleConnection(socks)
-                       if err != nil {
-                               log("SOCKS from %s: %s", socks.RemoteAddr(), 
err)
-                       }
-               }()
-       }
-       return nil
-}
-
-func startListener(addrStr string) (*pt.SocksListener, error) {
-       ln, err := pt.ListenSocks("tcp", addrStr)
-       if err != nil {
-               return nil, err
-       }
-       go func() {
-               err := socksAcceptLoop(ln)
-               if err != nil {
-                       log("accept: %s", err)
-               }
-       }()
-       return ln, nil
-}
-
-func main() {
-       var logFilename string
-       var socksAddrStr string
-       var err error
-
-       flag.Usage = usage
-       flag.StringVar(&logFilename, "log", "", "log file to write to")
-       flag.StringVar(&socksAddrStr, "socks", "127.0.0.1:0", "address on which 
to listen for SOCKS connections")
-       flag.Parse()
-
-       if logFilename != "" {
-               f, err := os.OpenFile(logFilename, 
os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0600)
-               if err != nil {
-                       fmt.Fprintf(os.Stderr, "Can't open log file %q: %s.\n", 
logFilename, err.Error())
-                       os.Exit(1)
-               }
-               logFile = f
-       }
-
-       log("starting")
-       ptInfo, err = pt.ClientSetup([]string{ptMethodName})
-       if err != nil {
-               log("error in setup: %s", err)
-               os.Exit(1)
-       }
-
-       listeners := make([]net.Listener, 0)
-       for _, methodName := range ptInfo.MethodNames {
-               switch methodName {
-               case ptMethodName:
-                       ln, err := startListener(socksAddrStr)
-                       if err != nil {
-                               pt.CmethodError(ptMethodName, err.Error())
-                               break
-                       }
-                       pt.Cmethod(ptMethodName, ln.Version(), ln.Addr())
-                       log("listening on %s", ln.Addr().String())
-                       listeners = append(listeners, ln)
-               default:
-                       pt.CmethodError(methodName, "no such method")
-               }
-       }
-       pt.CmethodsDone()
-
-       var numHandlers int = 0
-       var sig os.Signal
-       sigChan := make(chan os.Signal, 1)
-       signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
-
-       // wait for first signal
-       sig = nil
-       for sig == nil {
-               select {
-               case n := <-handlerChan:
-                       numHandlers += n
-               case sig = <-sigChan:
-               }
-       }
-       for _, ln := range listeners {
-               ln.Close()
-       }
-
-       if sig == syscall.SIGTERM {
-               return
-       }
-
-       // wait for second signal or no more handlers
-       sig = nil
-       for sig == nil && numHandlers != 0 {
-               select {
-               case n := <-handlerChan:
-                       numHandlers += n
-               case sig = <-sigChan:
-               }
-       }
-}
diff --git a/websocket-server/websocket-server.go 
b/websocket-server/websocket-server.go
deleted file mode 100644
index 4120df8..0000000
--- a/websocket-server/websocket-server.go
+++ /dev/null
@@ -1,299 +0,0 @@
-// Tor websocket server transport plugin.
-//
-// Usage in torrc:
-//     ExtORPort 6669
-//     ServerTransportPlugin websocket exec ./websocket-server --port 9901
-package main
-
-import (
-       "encoding/base64"
-       "errors"
-       "flag"
-       "fmt"
-       "io"
-       "net"
-       "net/http"
-       "os"
-       "os/signal"
-       "sync"
-       "syscall"
-       "time"
-)
-
-import "../websocket"
-
-import "git.torproject.org/pluggable-transports/goptlib.git"
-
-const ptMethodName = "websocket"
-const requestTimeout = 10 * time.Second
-
-// "4/3+1" accounts for possible base64 encoding.
-const maxMessageSize = 64*1024*4/3 + 1
-
-var logFile = os.Stderr
-
-var ptInfo pt.ServerInfo
-
-// When a connection handler starts, +1 is written to this channel; when it
-// ends, -1 is written.
-var handlerChan = make(chan int)
-
-func usage() {
-       fmt.Printf("Usage: %s [OPTIONS]\n", os.Args[0])
-       fmt.Printf("WebSocket server pluggable transport for Tor.\n")
-       fmt.Printf("Works only as a managed proxy.\n")
-       fmt.Printf("\n")
-       fmt.Printf("  -h, --help   show this help.\n")
-       fmt.Printf("  --log FILE   log messages to FILE (default stderr).\n")
-       fmt.Printf("  --port PORT  listen on PORT (overrides Tor's requested 
port).\n")
-}
-
-var logMutex sync.Mutex
-
-func log(format string, v ...interface{}) {
-       dateStr := time.Now().Format("2006-01-02 15:04:05")
-       logMutex.Lock()
-       defer logMutex.Unlock()
-       msg := fmt.Sprintf(format, v...)
-       fmt.Fprintf(logFile, "%s %s\n", dateStr, msg)
-}
-
-// An abstraction that makes an underlying WebSocket connection look like an
-// io.ReadWriteCloser. It internally takes care of things like base64 encoding
-// and decoding.
-type webSocketConn struct {
-       Ws         *websocket.WebSocket
-       Base64     bool
-       messageBuf []byte
-}
-
-// Implements io.Reader.
-func (conn *webSocketConn) Read(b []byte) (n int, err error) {
-       for len(conn.messageBuf) == 0 {
-               var m websocket.Message
-               m, err = conn.Ws.ReadMessage()
-               if err != nil {
-                       return
-               }
-               if m.Opcode == 8 {
-                       err = io.EOF
-                       return
-               }
-               if conn.Base64 {
-                       if m.Opcode != 1 {
-                               err = errors.New(fmt.Sprintf("got non-text 
opcode %d with the base64 subprotocol", m.Opcode))
-                               return
-                       }
-                       conn.messageBuf = make([]byte, 
base64.StdEncoding.DecodedLen(len(m.Payload)))
-                       var num int
-                       num, err = base64.StdEncoding.Decode(conn.messageBuf, 
m.Payload)
-                       if err != nil {
-                               return
-                       }
-                       conn.messageBuf = conn.messageBuf[:num]
-               } else {
-                       if m.Opcode != 2 {
-                               err = errors.New(fmt.Sprintf("got non-binary 
opcode %d with no subprotocol", m.Opcode))
-                               return
-                       }
-                       conn.messageBuf = m.Payload
-               }
-       }
-
-       n = copy(b, conn.messageBuf)
-       conn.messageBuf = conn.messageBuf[n:]
-
-       return
-}
-
-// Implements io.Writer.
-func (conn *webSocketConn) Write(b []byte) (n int, err error) {
-       if conn.Base64 {
-               buf := make([]byte, base64.StdEncoding.EncodedLen(len(b)))
-               base64.StdEncoding.Encode(buf, b)
-               err = conn.Ws.WriteMessage(1, buf)
-               if err != nil {
-                       return
-               }
-               n = len(b)
-       } else {
-               err = conn.Ws.WriteMessage(2, b)
-               n = len(b)
-       }
-       return
-}
-
-// Implements io.Closer.
-func (conn *webSocketConn) Close() error {
-       // Ignore any error in trying to write a Close frame.
-       _ = conn.Ws.WriteFrame(8, nil)
-       return conn.Ws.Conn.Close()
-}
-
-// Create a new webSocketConn.
-func newWebSocketConn(ws *websocket.WebSocket) webSocketConn {
-       var conn webSocketConn
-       conn.Ws = ws
-       conn.Base64 = (ws.Subprotocol == "base64")
-       return conn
-}
-
-// Copy from WebSocket to socket and vice versa.
-func proxy(local *net.TCPConn, conn *webSocketConn) {
-       var wg sync.WaitGroup
-       wg.Add(2)
-
-       go func() {
-               _, err := io.Copy(conn, local)
-               if err != nil {
-                       log("error copying ORPort to WebSocket")
-               }
-               local.CloseRead()
-               conn.Close()
-               wg.Done()
-       }()
-       go func() {
-               _, err := io.Copy(local, conn)
-               if err != nil {
-                       log("error copying WebSocket to ORPort")
-               }
-               local.CloseWrite()
-               conn.Close()
-               wg.Done()
-       }()
-
-       wg.Wait()
-}
-
-func webSocketHandler(ws *websocket.WebSocket) {
-       // Undo timeouts on HTTP request handling.
-       ws.Conn.SetDeadline(time.Time{})
-       conn := newWebSocketConn(ws)
-       defer conn.Close()
-
-       handlerChan <- 1
-       defer func() {
-               handlerChan <- -1
-       }()
-
-       or, err := pt.DialOr(&ptInfo, ws.Conn.RemoteAddr().String(), 
ptMethodName)
-       if err != nil {
-               log("Failed to connect to ORPort: " + err.Error())
-               return
-       }
-       defer or.Close()
-
-       proxy(or, &conn)
-}
-
-func startListener(addr *net.TCPAddr) (*net.TCPListener, error) {
-       ln, err := net.ListenTCP("tcp", addr)
-       if err != nil {
-               return nil, err
-       }
-       go func() {
-               defer ln.Close()
-               var config websocket.Config
-               config.Subprotocols = []string{"base64"}
-               config.MaxMessageSize = maxMessageSize
-               s := &http.Server{
-                       Handler:     config.Handler(webSocketHandler),
-                       ReadTimeout: requestTimeout,
-               }
-               err = s.Serve(ln)
-               if err != nil {
-                       log("http.Serve: " + err.Error())
-               }
-       }()
-       return ln, nil
-}
-
-func main() {
-       var logFilename string
-       var port int
-
-       flag.Usage = usage
-       flag.StringVar(&logFilename, "log", "", "log file to write to")
-       flag.IntVar(&port, "port", 0, "port to listen on if unspecified by Tor")
-       flag.Parse()
-
-       if logFilename != "" {
-               f, err := os.OpenFile(logFilename, 
os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0600)
-               if err != nil {
-                       fmt.Fprintf(os.Stderr, "Can't open log file %q: %s.\n", 
logFilename, err.Error())
-                       os.Exit(1)
-               }
-               logFile = f
-       }
-
-       log("starting")
-       var err error
-       ptInfo, err = pt.ServerSetup([]string{ptMethodName})
-       if err != nil {
-               log("error in setup: %s", err)
-               os.Exit(1)
-       }
-
-       listeners := make([]*net.TCPListener, 0)
-       for _, bindaddr := range ptInfo.Bindaddrs {
-               // Override tor's requested port (which is 0 if this transport
-               // has not been run before) with the one requested by the --port
-               // option.
-               if port != 0 {
-                       bindaddr.Addr.Port = port
-               }
-
-               switch bindaddr.MethodName {
-               case ptMethodName:
-                       ln, err := startListener(bindaddr.Addr)
-                       if err != nil {
-                               pt.SmethodError(bindaddr.MethodName, 
err.Error())
-                               break
-                       }
-                       pt.Smethod(bindaddr.MethodName, ln.Addr())
-                       log("listening on %s", ln.Addr().String())
-                       listeners = append(listeners, ln)
-               default:
-                       pt.SmethodError(bindaddr.MethodName, "no such method")
-               }
-       }
-       pt.SmethodsDone()
-
-       var numHandlers int = 0
-       var sig os.Signal
-       sigChan := make(chan os.Signal, 1)
-       signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
-
-       // wait for first signal
-       sig = nil
-       for sig == nil {
-               select {
-               case n := <-handlerChan:
-                       numHandlers += n
-               case sig = <-sigChan:
-               }
-       }
-       log("Got first signal %q with %d running handlers.", sig, numHandlers)
-       for _, ln := range listeners {
-               ln.Close()
-       }
-
-       if sig == syscall.SIGTERM {
-               log("Caught signal %q, exiting.", sig)
-               return
-       }
-
-       // wait for second signal or no more handlers
-       sig = nil
-       for sig == nil && numHandlers != 0 {
-               select {
-               case n := <-handlerChan:
-                       numHandlers += n
-                       log("%d remaining handlers.", numHandlers)
-               case sig = <-sigChan:
-               }
-       }
-       if sig != nil {
-               log("Got second signal %q with %d running handlers.", sig, 
numHandlers)
-       }
-}



_______________________________________________
tor-commits mailing list
[email protected]
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits

Reply via email to