func (context *bootContext) startServer() { defer func() { ex.CatchException(advice(recover())) sigChan <- t.Bye }() conf, err := t.Parse_d5s_file(context.config) if err != nil { log.Fatalln(advice(err)) } context.setLogVerbose(conf.Verbose) log.Infoln(versionString()) log.Infoln("Server is listening on", conf.ListenAddr) ln, err := net.ListenTCP("tcp", conf.ListenAddr) if err != nil { log.Fatalln(err) } defer ln.Close() dhKey, _ := c.NewDHKey(DH_METHOD) server := t.NewServer(conf, dhKey) context.components = append(context.components, server) context.closeable = append(context.closeable, ln) for { conn, err := ln.AcceptTCP() if err == nil { go server.TunnelServe(conn) } else { t.SafeClose(conn) } } }
func (context *bootContext) startClient() { defer func() { ex.CatchException(warning(recover())) sigChan <- t.Bye }() var conf = t.Parse_d5cFile(context.config) context.setLogVerbose(conf.Verbose) log.Infoln(versionString()) log.Infoln("Socks5/Http is working at", conf.ListenAddr) mgr := NewClientMgr(conf) context.statser = mgr ln, err := net.ListenTCP("tcp", conf.ListenAddr) if err != nil { log.Fatalln(err) } defer ln.Close() for { conn, err := ln.Accept() if err == nil { go mgr.selectClientServ(conn) } else { t.SafeClose(conn) } } }
func (context *bootContext) startServer() { defer func() { ex.CatchException(warning(recover())) sigChan <- t.Bye }() var conf = t.Parse_d5sFile(context.config) context.setLogVerbose(conf.Verbose) log.Infoln(versionString()) log.Infoln("Server is listening on", conf.ListenAddr) ln, err := net.ListenTCP("tcp", conf.ListenAddr) if err != nil { log.Fatalln(err) } defer ln.Close() dhKeys := t.GenerateDHKeyPairs() server := t.NewServer(conf, dhKeys) context.statser = server for { conn, err := ln.AcceptTCP() if err == nil { go server.TunnelServe(conn) } else { t.SafeClose(conn) } } }
func (t *Session) DataTunServe(fconn *Conn, buf []byte) { defer func() { var offline bool if atomic.AddInt32(&t.activeCnt, -1) <= 0 { offline = true t.mgr.clearTokens(t) t.mux.destroy() } var err = recover() if log.V(1) { log.Infof("Tun=%s was disconnected. %v\n", fconn.identifier, nvl(err, NULL)) if offline { log.Infof("Client=%s was offline\n", t.cid) } } if DEBUG { ex.CatchException(err) } }() atomic.AddInt32(&t.activeCnt, 1) if buf != nil { token := buf[:TKSZ] fconn.cipher = t.cipherFactory.NewCipher(token) buf = nil } else { // first negotiation had initialized cipher, the buf will be null log.Infof("Client=%s is online\n", t.cid) } if log.V(1) { log.Infof("Tun=%s is established\n", fconn.identifier) } t.mux.Listen(fconn, t.eventHandler, DT_PING_INTERVAL) }
func (p *multiplexer) connectToDest(frm *frame, key string, tun *Conn) { defer func() { ex.CatchException(recover()) }() var ( dstConn net.Conn err error target = string(frm.data) ) dstConn, err = net.DialTimeout("tcp", target, GENERAL_SO_TIMEOUT) frm.length = 0 if err != nil { p.router.removePreRegistered(key) log.Errorf("Cannot connect to [%s] for %s error: %s\n", target, key, err) frm.action = FRAME_ACTION_OPEN_N tunWrite2(tun, frm) } else { if log.V(1) { log.Infoln("OPEN", target, "for", key) } dstConn.SetReadDeadline(ZERO_TIME) edge := p.router.register(key, target, tun, dstConn, false) // write edge frm.action = FRAME_ACTION_OPEN_Y if tunWrite2(tun, frm) == nil { p.relay(edge, tun, frm.sid) // read edge } else { // send open_y failed SafeClose(tun) } } }
func (t *Session) DataTunServe(fconn *Conn, isNewSession bool) { atomic.AddInt32(&t.activeCnt, 1) defer func() { var ( offline bool err = recover() ) if atomic.AddInt32(&t.activeCnt, -1) <= 0 { offline = true t.mgr.clearTokens(t) t.mux.destroy() } if log.V(1) { log.Infof("Tun=%s was disconnected. %v\n", fconn.identifier, nvl(err, NULL)) if offline { log.Infof("Client=%s was offline\n", t.cid) } } if DEBUG { ex.CatchException(err) } }() if isNewSession { log.Infof("Client=%s is online\n", t.cid) } if log.V(1) { log.Infof("Tun=%s is established\n", fconn.identifier) } t.mux.Listen(fconn, t.eventHandler, DT_PING_INTERVAL) }
func (r *egressRouter) clean() { defer func() { ex.CatchException(recover()) }() r.lock.Lock() defer r.lock.Unlock() for k, e := range r.registry { // call conn.LocalAddr will give rise to checking fd. if e == nil || e.closed_gte(TCP_CLOSED) || e.conn.LocalAddr() == nil { delete(r.registry, k) } } }
// destroy each listener of all pooled tun, and destroy egress queues func (p *multiplexer) destroy() { if atomic.LoadInt32(&p.status) < 0 { return } defer func() { if !ex.CatchException(recover()) { atomic.StoreInt32(&p.status, MUX_CLOSED) } }() atomic.StoreInt32(&p.status, MUX_PENDING_CLOSE) p.router.destroy() // destroy queue p.pool.destroy() p.router = nil p.pool = nil }
// destroy each listener of all pooled tun, and destroy egress queues func (p *multiplexer) destroy() { if p.status < 0 { return } defer func() { if !ex.CatchException(recover()) { p.status = MUX_CLOSED } }() // will not send evt_dt_closed while pending_close was indicated p.status = MUX_PENDING_CLOSE p.router.destroy() // destroy queue p.pool.destroy() p.router = nil p.pool = nil }
func (t *Server) TunnelServe(conn *net.TCPConn) { fconn := NewConnWithHash(conn) defer func() { fconn.FreeHash() ex.CatchException(recover()) }() nego := &d5SNegotiation{Server: t} session, err := nego.negotiate(fconn) if err == nil || err == DATATUN_SESSION { // dataTunnel go session.DataTunServe(fconn.Conn, nego.tokenBuf) } else { log.Warningln("Close abnormal connection from", conn.RemoteAddr(), err) SafeClose(conn) if session != nil { t.sessionMgr.clearTokens(session) } } }
func (p *multiplexer) connectToDest(frm *frame, key string, tun *Conn) { defer func() { ex.CatchException(recover()) }() var ( dstConn net.Conn err error target = string(frm.data) denied = false ) if p.filter != nil { denied = p.filter.Filter(target) } if !denied { dstConn, err = net.DialTimeout("tcp", target, GENERAL_SO_TIMEOUT) } if err != nil || denied { p.router.removePreRegistered(key) if denied { frm.action = FRAME_ACTION_OPEN_DENIED log.Warningf("Denied request [%s] for %s\n", target, key) } else { frm.action = FRAME_ACTION_OPEN_N log.Warningf("Cannot connect to [%s] for %s error: %s\n", target, key, err) } frameWriteHead(tun, frm) } else { edge := p.router.register(key, target, tun, dstConn, false) // write edge if log.V(1) { log.Infoln("OPEN", target, "for", key) } dstConn.SetReadDeadline(ZERO_TIME) frm.action = FRAME_ACTION_OPEN_Y if frameWriteHead(tun, frm) == nil { p.relay(edge, tun, frm.sid) // read edge } else { // send open_y failed SafeClose(tun) } } }
func (context *bootContext) startClient() { defer func() { ex.CatchException(advice(recover())) sigChan <- t.Bye }() conf, err := t.Parse_d5c_file(context.config) if err != nil { log.Fatalln(advice(err)) } context.setLogVerbose(conf.Verbose) log.Infoln(versionString()) log.Infoln("Socks5/Http is working at", conf.ListenAddr) ln, err := net.ListenTCP("tcp", conf.ListenAddr) if err != nil { log.Fatalln(err) } defer ln.Close() dhKey, _ := c.NewDHKey(DH_METHOD) client := t.NewClient(conf, dhKey) context.components = append(context.components, client) context.closeable = append(context.closeable, ln) go client.StartTun(true) for { conn, err := ln.Accept() if err == nil { if client.IsReady() { go client.ClientServe(conn) continue } else { log.Errorf("No available tunnels for servicing new request") time.Sleep(time.Second) } } t.SafeClose(conn) } }
func (t *Server) TunnelServe(raw *net.TCPConn) { hConn, conn := newHashedConn(raw) defer func() { ex.CatchException(recover()) }() nego := &dbcSerNego{ Server: t, clientAddr: raw.RemoteAddr(), } // read atomically tcPool := *(*[]uint64)(atomic.LoadPointer(&t.tcPool)) session, err := nego.negotiate(hConn, tcPool) if err == nil { go session.DataTunServe(conn, nego.isNewSession) } else { SafeClose(raw) if session != nil { t.sessionMgr.clearTokens(session) } } }
func (c *Client) StartTun(mustRestart bool) { var ( wait bool tun *Conn rn = atomic.LoadInt32(&c.round) ) for { if wait { time.Sleep(RETRY_INTERVAL) } if rn < atomic.LoadInt32(&c.round) { return } if mustRestart { mustRestart = false if atomic.SwapInt32(&c.State, CLT_PENDING) >= CLT_WORKING { tun, rn = c.restart() if tun == nil { return } } else { return } } if atomic.LoadInt32(&c.State) == CLT_WORKING { // negotiation conn executed here firstly will not be null // otherwise must be null then create new one. if tun == nil { var err error tun, err = c.createDataTun() if err != nil { if DEBUG { ex.CatchException(err) } log.Errorf("Failed to connect %s. Reconnect after %s\n", err, RETRY_INTERVAL) wait = true continue } } if log.V(1) { log.Infof("Tun=%s is established\n", tun.sign()) } atomic.AddInt32(&c.dtCnt, 1) c.mux.Listen(tun, c.eventHandler, c.tp.pingInterval) dtcnt := atomic.AddInt32(&c.dtCnt, -1) log.Errorf("Tun=%s was disconnected, Reconnect after %s\n", tun.sign(), RETRY_INTERVAL) if atomic.LoadInt32(&c.mux.pingCnt) <= 0 { // dirty tokens: used abandoned tokens c.clearTokens() } if dtcnt <= 0 { // restart: all connections were disconnected log.Errorf("Connections %s were lost\n", tun.identifier) go c.StartTun(true) return } else { // reconnect // waiting and don't use old tun wait = true tun = nil } } else { // can't create tun and waiting for release if !c.pendingConn.acquire(RETRY_INTERVAL) { return } } } }