func RunMultiplexSOCKSServer(transport io.ReadWriteCloser) { ctx := make_icom_ctx(transport, true, false, 2048) for { thing, err := ctx.our_srv.Accept() if err != nil { return } go func() { defer thing.Close() addr, err := socks5.ReadRequest(thing) if err != nil { return } remote, err := net.DialTimeout("tcp", addr, time.Second*20) if err != nil { kilog.Debug("Connection to %s failed: %s", addr, err.Error()) e := err.(net.Error) if e.Timeout() { socks5.CompleteRequest(0x06, thing) } else { socks5.CompleteRequest(0x01, thing) } return } defer remote.Close() rlrem := remote err = socks5.CompleteRequest(0x00, thing) if err != nil { return } go func() { defer rlrem.Close() io.Copy(rlrem, thing) }() kilog.Debug("Opened connection to %s", addr) io.Copy(thing, rlrem) }() } }
func run_client_loop() { listener, err := net.Listen("tcp", MasterConfig.General.SocksAddr) if err != nil { panic(err) } circ_ch <- produce_circ() set_gui_progress(1.0) kilog.Info("Bootstrapping 100%%: client started!") go func() { var haha sync.WaitGroup haha.Add(5) for i := 0; i < 5; i++ { go func() { circ_ch <- produce_circ() haha.Done() }() } haha.Wait() }() for { nconn, err := listener.Accept() if err != nil { kilog.Warning("Problem while accepting client socket: %s", err.Error()) continue } go func() { defer func() { nconn.Close() }() addr, err := socks5.ReadRequest(nconn) if err != nil { kilog.Warning("Problem while reading SOCKS5 request") return } kilog.Debug("Attempting connection to %s...", addr) retry: newcirc := <-circ_ch remote, err := newcirc.SocksAccept(nconn) if err != nil { dirclient.RefreshDirectory() circ_ch <- produce_circ() goto retry } circ_ch <- newcirc defer remote.Close() lenbts := []byte{byte((len(addr) + 1) % 256), byte((len(addr) + 1) / 256)} _, err = remote.Write(lenbts) _, err = remote.Write([]byte(fmt.Sprintf("t%s", addr))) if err != nil { kilog.Debug("Failed to send tunnelling request to %s!", addr) socks5.CompleteRequest(0x03, nconn) return } kilog.Debug("Sent tunneling request") code := make([]byte, 4) _, err = io.ReadFull(remote, code) if err != nil { kilog.Debug("Failed to read response for %s! (%s)", addr, err) socks5.CompleteRequest(0x03, nconn) return } switch string(code) { case "OKAY": kilog.Debug("Successfully tunneled %s!", addr) socks5.CompleteRequest(0x00, nconn) go func() { defer remote.Close() io.Copy(remote, nconn) }() io.Copy(nconn, remote) case "TMOT": kilog.Debug("Tunnel to %s timed out!", addr) socks5.CompleteRequest(0x06, nconn) case "NOIM": kilog.Debug("Tunnel type for %s isn't implemented by server!", addr) socks5.CompleteRequest(0x07, nconn) case "FAIL": kilog.Debug("Tunnel to %s cannot be established!", addr) socks5.CompleteRequest(0x04, nconn) default: kilog.Debug("Protocol error on tunnel to %s! (%s)", addr, string(code)) socks5.CompleteRequest(0x01, nconn) return } }() } }