// NewClient returns a new Client instance connected to an IMAP server via conn. // The function waits for the server to send a greeting message, and then // requests server capabilities if they weren't included in the greeting. An // error is returned if either operation fails or does not complete before the // timeout, which must be positive to have any effect. If an error is returned, // it is the caller's responsibility to close the connection. func NewClient(conn net.Conn, host string, timeout time.Duration) (c *Client, err error) { log := newDebugLog(DefaultLogger, DefaultLogMask) cch := make(chan chan<- *response, 1) c = &Client{ Caps: make(map[string]bool), CommandConfig: defaultCommands(), host: host, state: unknown, tag: *newTagGen(0), cmds: make(map[string]*Command), t: newTransport(conn, log), debugLog: log, } c.r = newReader(c.t, MemoryReader{}, string(c.tag.id)) c.Logf(LogConn, "Connected to %v (Tag=%s)", conn.RemoteAddr(), c.tag.id) if err = c.greeting(timeout); err != nil { c.Logln(LogConn, "Greeting error:", err) return nil, err } c.cch = cch go c.receiver(cch) runtime.Gosched() return }
// handleRawConn is run in its own goroutine and handles a just-accepted // connection that has not had any I/O performed on it yet. func (s *Server) handleRawConn(rawConn net.Conn) { conn, authInfo, err := s.useTransportAuthenticator(rawConn) if err != nil { s.mu.Lock() s.errorf("ServerHandshake(%q) failed: %v", rawConn.RemoteAddr(), err) s.mu.Unlock() grpclog.Printf("grpc: Server.Serve failed to complete security handshake from %q: %v", rawConn.RemoteAddr(), err) rawConn.Close() return } s.mu.Lock() if s.conns == nil { s.mu.Unlock() conn.Close() return } s.mu.Unlock() if s.opts.useHandlerImpl { s.serveUsingHandler(conn) } else { s.serveNewHTTP2Transport(conn, authInfo) } }
func (s *Server) onConn(c net.Conn) { conn := s.newClientConn(c) //新建一个conn defer func() { err := recover() if err != nil { const size = 4096 buf := make([]byte, size) buf = buf[:runtime.Stack(buf, false)] //获得当前goroutine的stacktrace golog.Error("server", "onConn", "error", 0, "remoteAddr", c.RemoteAddr().String(), "stack", string(buf), ) } conn.Close() }() if allowConnect := conn.IsAllowConnect(); allowConnect == false { err := mysql.NewError(mysql.ER_ACCESS_DENIED_ERROR, "ip address access denied by kingshard.") conn.writeError(err) conn.Close() return } if err := conn.Handshake(); err != nil { golog.Error("server", "onConn", err.Error(), 0) c.Close() return } conn.Run() }
func (p *Peer) Accept(conn net.Conn) (_err error) { defer conn.Close() p.logFields(SERVE, log.Fields{ "remoteAddr": conn.RemoteAddr(), }).Debug("accepted connection") defer func() { if _err != nil { p.logErr(SERVE, _err).Error() } }() var failResp string if p.readAcquire() { defer p.wg.Done() } else { failResp = "sync not available, currently mutating" } remoteConfig, err := p.handleConfig(conn, SERVE, failResp) if err != nil { return errgo.Mask(err) } if failResp == "" { return p.interactWithClient(conn, remoteConfig, cf.NewBitstring(0)) } return nil }
// The core of the file: read any input from the connection and outputs it into // the server connection func proxyConnection(conn net.Conn, done chan bool) { dec := json.NewDecoder(conn) nerr := 0 for { m := SingleMeasure{} // Receive data if err := dec.Decode(&m); err != nil { if err == io.EOF { break } log.Lvl1("Error receiving data from", conn.RemoteAddr().String(), ":", err) nerr++ if nerr > 1 { log.Lvl1("Too many errors from", conn.RemoteAddr().String(), ": Abort connection") break } } log.Lvl3("Proxy received", m) // Proxy data back to monitor if err := serverEnc.Encode(m); err != nil { log.Lvl2("Error proxying data :", err) break } if m.Name == "end" { // the end log.Lvl2("Proxy detected end of measurement. Closing connection.") break } } if err := conn.Close(); err != nil { log.Error("Couldn't close connection:", err) } done <- true }
func handleClient(conn net.Conn) { common.Conn2ClientInfo[conn] = &common.ClientInfo{Conn: conn, ClientMap: make(map[net.Conn]*common.Session), Id2Session: make(map[string]*common.Session), IsServer: false, Quit: make(chan bool), ResponseTime: time.Now().Unix()} log.Println("client linked success", conn.RemoteAddr().String()) common.Conn2ClientInfo[conn].Loop() common.Read(conn, handleResponse) client, bHave := common.Conn2ClientInfo[conn] if bHave { close(client.Quit) if client.IsServer { for conn, session := range client.ClientMap { conn.Close() common.RmId(client.ServerName, session.Id) } delete(common.ServerName2Conn, client.ServerName) log.Println("unregister service Name", client.ServerName) if bUseDB { user, _ := auth.GetUser(client.UserName) if user != nil { user.OnLogout() } } } else { common.GetServerInfoByConn(conn, func(server *common.ClientInfo) { id := server.DelClient(conn) log.Println("send quit") common.Write(server.Conn, id, "clientquit", "") }, func() {}) } delete(common.Conn2ClientInfo, conn) } conn.Close() log.Println("client disconnected", conn.RemoteAddr().String()) }
func handleConn(conn net.Conn) { defer conn.Close() log.Println("connected from:", conn.RemoteAddr()) dst, err := dialer.Dial("tcp", *dstAddr) if err != nil { log.Println(err) return } defer dst.Close() wg := &sync.WaitGroup{} wg.Add(2) go func(wg *sync.WaitGroup) { buf := bufferPool.Get() _, err = io.CopyBuffer(conn, dst, buf.([]byte)) if err != nil { log.Println(err) } bufferPool.Put(buf) wg.Done() }(wg) go func(wg *sync.WaitGroup) { buf := bufferPool.Get() _, err = io.CopyBuffer(dst, conn, buf.([]byte)) if err != nil { log.Println(err) } bufferPool.Put(buf) wg.Done() }(wg) wg.Wait() }
func storage_upload_file(header *Header, conn net.Conn) bool { buff := make([]byte, header.pkg_len) n, err := io.ReadFull(conn, buff) if err != nil || n != int(header.pkg_len) { return false } req := &UploadFileRequest{} err = req.Unmarshal(buff) if err != nil { return false } file_ext := storage_format_ext_name(req.file_ext) crc32 := crc32.ChecksumIEEE(req.file_data) now := time.Now() // log.Println(req.store_path_index, req.file_length, len(req.file_data), file_ext, crc32) addr, _ := conn.RemoteAddr().(*net.TCPAddr) file_name, full_name := storage_get_filename(addr.IP.String(), int(req.store_path_index), int(now.Unix()), req.file_length, int(crc32), file_ext) file, err := os.OpenFile(full_name, os.O_WRONLY|os.O_EXCL|os.O_CREATE, 0644) if err != nil { log.Print(err) return send_result(errno(err), conn) } n, err = file.Write(req.file_data) if err != nil || n != len(req.file_data) { panic("write") } file_name = fmt.Sprintf("M00/%s", file_name) storage_binlog_write(int(now.Unix()), STORAGE_OP_TYPE_SOURCE_CREATE_FILE, file_name) resp := &UploadFileResponse{"group1", file_name} return send_response(resp, conn) }
func handleResponse(conn net.Conn, request *protocol.VMessRequest, output chan<- *alloc.Buffer, finish *sync.Mutex, isUDP bool) { defer finish.Unlock() defer close(output) responseKey := md5.Sum(request.RequestKey[:]) responseIV := md5.Sum(request.RequestIV[:]) decryptResponseReader, err := v2io.NewAesDecryptReader(responseKey[:], responseIV[:], conn) if err != nil { log.Error("VMessOut: Failed to create decrypt reader: %v", err) return } buffer, err := v2net.ReadFrom(decryptResponseReader, nil) if err != nil { log.Error("VMessOut: Failed to read VMess response (%d bytes): %v", buffer.Len(), err) return } if buffer.Len() < 4 || !bytes.Equal(buffer.Value[:4], request.ResponseHeader[:]) { log.Warning("VMessOut: unexepcted response header. The connection is probably hijacked.") return } log.Info("VMessOut received %d bytes from %s", buffer.Len()-4, conn.RemoteAddr().String()) buffer.SliceFrom(4) output <- buffer if !isUDP { v2net.ReaderToChan(output, decryptResponseReader) } return }
// hanleTCPConn handle a long live tcp connection. func handleTCPConn(conn net.Conn, rc chan *bufio.Reader) { addr := conn.RemoteAddr().String() log.Debug("<%s> handleTcpConn routine start", addr) rd := newBufioReader(rc, conn) if args, err := parseCmd(rd); err == nil { // return buffer bufio.Reader putBufioReader(rc, rd) switch args[0] { case "sub": SubscribeTCPHandle(conn, args[1:]) break default: conn.Write(ParamReply) log.Warn("<%s> unknown cmd \"%s\"", addr, args[0]) break } } else { // return buffer bufio.Reader putBufioReader(rc, rd) log.Error("<%s> parseCmd() error(%v)", addr, err) } // close the connection if err := conn.Close(); err != nil { log.Error("<%s> conn.Close() error(%v)", addr, err) } log.Debug("<%s> handleTcpConn routine stop", addr) return }
func tunnel(conn net.Conn) { defer conn.Close() // We start with a JSON header, currenly only has the dest addr. hdrdec := json.NewDecoder(conn) var hdr header err := hdrdec.Decode(&hdr) if err != nil { log.Printf("Couldn't parse tunnelled connection header: %v", err) return } destc, err := net.Dial("tcp", hdr.Destaddr) if err != nil { log.Printf("Couldn't dial destination $v: %v", hdr.Destaddr, err) return } defer destc.Close() log.Printf("Now tunnelling %v to %v", conn.RemoteAddr(), destc.RemoteAddr()) done := make(chan struct{}) go func() { io.Copy(destc, io.MultiReader(hdrdec.Buffered(), conn)) done <- struct{}{} }() io.Copy(conn, destc) <-done }
func handleConn(cid int, usConn net.Conn) { defer usConn.Close() log.Println(cid, "Handling new connection from", usConn.RemoteAddr()) log.Println(cid, "Making downstream connection...") dsConn, err := makeDownstreamConnection() defer dsConn.Close() if err != nil { log.Println(cid, "Failed upstream", err) return } hp, err := ReadHandshakePacket(usConn) if err != nil { log.Println(cid, "Failed RHP", err) return } hp2 := MangleHandshakePacket(hp) err = WriteHandshakePacket(dsConn, hp2) if err != nil { log.Println(cid, "Failed WHP", err) return } go io.Copy(usConn, dsConn) io.Copy(dsConn, usConn) }
func roundtrip(ctx *ClientContext, conn net.Conn, requestSize, requestBytes []byte) ([]byte, error) { deadline, ok := ctx.Deadline() if !ok { deadline = time.Time{} } var err error if err = conn.SetDeadline(deadline); err != nil { return nil, makeClientErr(err.Error()) } if _, err = conn.Write(requestSize); err != nil { return nil, makeClientErrf("Failed to write 4 bytes for request size: %s", err) } if _, err = conn.Write(requestBytes); err != nil { return nil, makeClientErrf("Failed to write %d bytes for request: %s", err) } buf := bytes.NewBuffer(make([]byte, 0, 4)) if _, err = io.CopyN(buf, conn, 4); err != nil { return nil, makeClientErrf( "Failed to read 4 bytes for response size from '%s': %s", conn.RemoteAddr().String(), err) } responseSize := binary.BigEndian.Uint32(buf.Bytes()) if _, err = io.CopyN(buf, conn, int64(responseSize)); err != nil { return nil, makeClientErrf( "Failed to read %d bytes for response from '%s': %s", conn.RemoteAddr().String(), err) } return buf.Bytes(), nil }
func newClientRESP(conn net.Conn, app *App) { c := new(respClient) c.client = newClient(app) c.conn = conn c.activeQuit = false if tcpConn, ok := conn.(*net.TCPConn); ok { tcpConn.SetReadBuffer(app.cfg.ConnReadBufferSize) tcpConn.SetWriteBuffer(app.cfg.ConnWriteBufferSize) } br := bufio.NewReaderSize(conn, app.cfg.ConnReadBufferSize) c.respReader = goredis.NewRespReader(br) c.resp = newWriterRESP(conn, app.cfg.ConnWriteBufferSize) c.remoteAddr = conn.RemoteAddr().String() app.connWait.Add(1) app.addRespClient(c) go c.run() }
func (s *Server) onConn(c net.Conn) { conn := s.newClientConn(c) defer func() { err := recover() if err != nil { const size = 4096 buf := make([]byte, size) buf = buf[:runtime.Stack(buf, false)] log.Printf("Error server.onConn remoteAddr:%s, stack:%s", c.RemoteAddr().String(), string(buf)) } conn.Close() }() if allowConnect := conn.IsAllowConnect(); allowConnect == false { err := mysql.NewError(mysql.ER_ACCESS_DENIED_ERROR, "ip address access denied by mysqlproxy.") conn.writeError(err) conn.Close() return } if err := conn.Handshake(); err != nil { log.Printf("Error server.onConn %s", err.Error()) c.Close() return } conn.Run() }
//////////////////////////////////////////////////////// // //服务器端接收数据线程 //参数: // 数据连接 conn //////////////////////////////////////////////////////// func Handler(conn net.Conn) { //获取访问者IP端口 siteno := "0" ipstr := conn.RemoteAddr().String() fmt.Println("connected from", ipstr) buf := make([]byte, 1024) for { lenght, err := conn.Read(buf) if checkError(err, "Readerr: Close"+ipstr) == false { conn.Close() delete(conns, ipstr) delete(sitetelnoreply, siteiptotel[ipstr]) delete(siteiptotel, ipstr) break } if lenght > 0 { buf[lenght] = 0 } if siteno == "0" && lenght > 20 { siteno = string(buf[4:15]) siteiptotel[ipstr] = siteno } //fmt.Println("Rec[", ipstr, "] Say :", string(buf[0:lenght])) reciveStr := string(buf[0:lenght]) if lenght > 20 && crcok(buf) { //用于记录 站点有多少次 没有回复指令累计10次就断开链接 sitetelnoreply[siteno] = 0 setFiles(reciveStr, siteno) //这个站点累计0次没有回复 } } }
func handleClient(conn net.Conn, hello, goodbye chan<- client, toBroadcast chan<- string) { // Lifecycle management. toClient := make(chan string) hello <- toClient defer func() { goodbye <- toClient }() // Announce the presence of a new chatter. handle := conn.RemoteAddr().String() toBroadcast <- fmt.Sprintf("%s has joined the chat", handle) defer func() { toBroadcast <- fmt.Sprintf("%s has left the chat", handle) }() // Messages from the chat server to the conn. // We range over the toClient channel and exit when it's closed. // (It's closed after it's processed by the goodbye handler.) go func() { for message := range toClient { fmt.Fprintf(conn, message+"\n") } }() // Messages from the conn to the chat server. // When the client disconnects, the scanner stops scanning. // We close the conn, and signal our goodbye via the defer. s := bufio.NewScanner(conn) for s.Scan() { toBroadcast <- "<" + handle + "> " + s.Text() } }
func handleConnection(local net.Conn) error { defer local.Close() handlerChan <- 1 defer func() { handlerChan <- -1 }() var remote net.Conn err := socks.AwaitSocks4aConnect(local.(*net.TCPConn), func(dest string) (*net.TCPAddr, error) { var err error // set remote in outer function environment remote, err = net.Dial("tcp", dest) if err != nil { return nil, err } return remote.RemoteAddr().(*net.TCPAddr), nil }) if err != nil { return err } defer remote.Close() copyLoop(local, remote) return nil }
func (s *Server) handleConnection(conn net.Conn) { defer func() { conn.Close() s.Logger.Printf("connection from %s closed", conn.RemoteAddr()) }() s.Logger.Printf("new connection from %s", conn.RemoteAddr()) reader := bufio.NewReader(conn) for { b, err := reader.ReadString('\n') if err != nil { conn.Close() return } else { query := strings.Trim(b, "\r\n") if query == "" { continue } s.Logger.Printf("executing query '%s'", query) c, err := s.searcher.Search(query) if err != nil { conn.Write([]byte(err.Error())) } else { for s := range c { conn.Write([]byte(s + "\n")) } } // Send two newlines to indicate end-of-results. conn.Write([]byte("\n\n")) } } }
func (p *Proxy) handleLoop(conn net.Conn) { p.conns.Add(1) defer p.conns.Done() defer conn.Close() s, err := newSession() if err != nil { log.Errorf("martian: failed to create session: %v", err) return } ctx, err := withSession(s) if err != nil { log.Errorf("martian: failed to create context: %v", err) return } brw := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn)) for { deadline := time.Now().Add(p.timeout) conn.SetDeadline(deadline) if err := p.handle(ctx, conn, brw); isCloseable(err) { log.Debugf("martian: closing connection: %v", conn.RemoteAddr()) return } } }
func HandleIncomingSSHConn(nConn net.Conn, config *ssh.ServerConfig) { DoneCh := make(chan bool) go TimeoutConnection(DoneCh, nConn) _, chans, reqs, err := ssh.NewServerConn(nConn, config) if err == nil { DoneCh <- true } // Right now that we are out of annoying people land. defer nConn.Close() go HandleSSHrequests(reqs) for newChannel := range chans { if newChannel.ChannelType() != "session" { newChannel.Reject(ssh.UnknownChannelType, "unknown channel type") log.Printf("WARNING - Rejecting %s Because they asked for a chan type %s that I don't have", nConn.RemoteAddr().String(), newChannel.ChannelType()) continue } channel, requests, err := newChannel.Accept() if err != nil { log.Printf("WARNING - Was unable to Accept channel with %s", nConn.RemoteAddr().String()) return } go HandleSSHrequests(requests) go ServeDOSTerm(channel) } }
// newClientConn wraps the provided connections and enables secured // duplex communication between the client and the server. func newClientConn(conn net.Conn) (*clientConn, error) { pub, priv, err := box.GenerateKey(rand.Reader) if err != nil { return nil, err } privK, pubK := (*key)(priv), (*key)(pub) v(2).Printf("client: generated private key %v, public key %v", privK, pubK) peersPub, err := exchange(conn, pubK) if err != nil { return nil, fmt.Errorf("key exchange failed with server %v: %v", conn.RemoteAddr(), err) } v(2).Printf("client: peer's public key is %v", peersPub) cc := &clientConn{ NewSecureReader(conn, privK, peersPub), NewSecureWriter(conn, privK, peersPub), conn, } return cc, nil }
func (f *forwarder) connect() { if f.c != nil { return } rate := time.Tick(200 * time.Millisecond) for { var c net.Conn var err error if f.Config.TlsConfig != nil { c, err = tls.Dial("tcp", f.Config.ForwardDest, f.Config.TlsConfig) } else { c, err = net.DialTimeout("tcp", f.Config.ForwardDest, f.Config.ForwardDestConnectTimeout) } if err != nil { f.cErrors.Inc(1) log.WithFields(log.Fields{"id": f.ID, "message": err}).Error("Forwarder Connection Error") f.disconnect() } else { f.cSuccesses.Inc(1) log.WithFields(log.Fields{"id": f.ID, "remote_addr": c.RemoteAddr().String()}).Info("Forwarder Connection Success") f.c = c return } <-rate } }
func serverHandler(f base.ServerFactory, conn net.Conn, info *pt.ServerInfo) { defer conn.Close() termMon.onHandlerStart() defer termMon.onHandlerFinish() name := f.Transport().Name() addrStr := log.ElideAddr(conn.RemoteAddr().String()) log.Infof("%s(%s) - new connection", name, addrStr) // Instantiate the server transport method and handshake. remote, err := f.WrapConn(conn) if err != nil { log.Warnf("%s(%s) - handshake failed: %s", name, addrStr, log.ElideError(err)) return } // Connect to the orport. orConn, err := pt.DialOr(info, conn.RemoteAddr().String(), name) if err != nil { log.Errorf("%s(%s) - failed to connect to ORPort: %s", name, addrStr, log.ElideError(err)) return } defer orConn.Close() if err = copyLoop(orConn, remote); err != nil { log.Warnf("%s(%s) - closed connection: %s", name, addrStr, log.ElideError(err)) } else { log.Infof("%s(%s) - closed connection", name, addrStr) } return }
func NewClientV2(conn net.Conn) *ClientV2 { var identifier string if conn != nil { identifier, _, _ = net.SplitHostPort(conn.RemoteAddr().String()) } return &ClientV2{ Conn: conn, // ReadyStateChan has a buffer of 1 to guarantee that in the event // there is a race the state update is not lost ReadyStateChan: make(chan int, 1), ExitChan: make(chan int), ConnectTime: time.Now(), ShortIdentifier: identifier, LongIdentifier: identifier, Reader: bufio.NewReaderSize(conn, 16*1024), Writer: bufio.NewWriterSize(conn, 16*1024), State: nsq.StateInit, SubEventChan: make(chan *Channel, 1), // heartbeats are client configurable but default to 30s HeartbeatInterval: nsqd.options.clientTimeout / 2, HeartbeatUpdateChan: make(chan time.Duration, 1), } }
// handle a new connection: // Steps: // 1. Read input from connection line by line. // 2. Parse each line into a metric. // 3. Validate the metric // 4. Process the metric. func (d *Detector) handle(conn net.Conn) { addr := conn.RemoteAddr() health.IncrNumClients(1) defer health.DecrNumClients(1) log.Infof("conn %s established", addr) scanner := bufio.NewScanner(conn) for scanner.Scan() { // Read line by line. if err := scanner.Err(); err != nil { // Close on read error. log.Errorf("read error: %v, closing conn..", err) break } line := scanner.Text() m, err := parseMetric(line) // Parse if err != nil { log.Errorf("parse error: %v, skipping..", err) continue } if err = m.Validate(); err != nil { log.Errorf("invalid metric: %v, skipping..", err) return } d.process(m, true) } conn.Close() log.Infof("conn %s disconnected", addr) }
func (sup *Supervisor) acceptAgent(cc net.Conn) { sup.mu.Lock() defer sup.mu.Unlock() raddr := addressFromNet(cc.RemoteAddr()) ll := log.KV("raddr", raddr) if _, ok := sup.agents[raddr]; ok { ll.Info("agent already joined") _ = cc.Close() return } ll.Info("new agent joined") agent := &agent{ ll: ll, addr: raddr, client: rpc.RepresentAgent(cc, sup.provider), cc: cc, setState: make(chan stack), } sup.agents[raddr] = agent if s, ok := sup.dfn.Machines[raddr]; !ok { ll.Info("no stack defined for this agent") } else { go agent.enforceState(s) } }
// handleRawConn is run in its own goroutine and handles a just-accepted // connection that has not had any I/O performed on it yet. func (s *Server) handleRawConn(rawConn net.Conn) { // Server在每一个Connection上都都做啥了 // 1. 获取经过 TLS 封装的 Conn/AuthInfo等 conn, authInfo, err := s.useTransportAuthenticator(rawConn) // HandShake Failed if err != nil { s.mu.Lock() s.errorf("ServerHandshake(%q) failed: %v", rawConn.RemoteAddr(), err) s.mu.Unlock() grpclog.Printf("grpc: Server.Serve failed to complete security handshake from %q: %v", rawConn.RemoteAddr(), err) rawConn.Close() return } // 服务关闭 s.mu.Lock() if s.conns == nil { s.mu.Unlock() conn.Close() return } s.mu.Unlock() // 2. 对外提供服务 if s.opts.useHandlerImpl { s.serveUsingHandler(conn) } else { s.serveNewHTTP2Transport(conn, authInfo) } }
func (self *ProtobufServer) handleConnection(conn net.Conn) { log.Info("ProtobufServer: client connected: %s", conn.RemoteAddr().String()) message := make([]byte, 0, MAX_REQUEST_SIZE) buff := bytes.NewBuffer(message) var messageSizeU uint32 for { err := binary.Read(conn, binary.LittleEndian, &messageSizeU) if err != nil { log.Error("Error reading from connection (%s): %s", conn.RemoteAddr().String(), err) self.connectionMapLock.Lock() delete(self.connectionMap, conn) self.connectionMapLock.Unlock() conn.Close() return } messageSize := int64(messageSizeU) if messageSize > MAX_REQUEST_SIZE { err = self.handleRequestTooLarge(conn, messageSize, buff) } else { err = self.handleRequest(conn, messageSize, buff) } if err != nil { log.Error("Error, closing connection: %s", err) self.connectionMapLock.Lock() delete(self.connectionMap, conn) self.connectionMapLock.Unlock() conn.Close() return } buff.Reset() } }
// ServeConn takes an inbound conn and proxies it to a backend. func (p *ReverseProxy) ServeConn(ctx context.Context, dconn net.Conn) { transport := p.transport if transport == nil { panic("router: nil transport for proxy") } defer dconn.Close() clientGone := dconn.(http.CloseNotifier).CloseNotify() ctx, cancel := context.WithCancel(ctx) defer cancel() // finish cancellation goroutine go func() { select { case <-clientGone: cancel() // client went away, cancel request case <-ctx.Done(): } }() l := p.Logger.New("client_addr", dconn.RemoteAddr(), "host_addr", dconn.LocalAddr(), "proxy", "tcp") uconn, err := transport.Connect(ctx, l) if err != nil { return } defer uconn.Close() joinConns(uconn, dconn) }