// dispatch accepts connections on the listener and serves requests // for each incoming connection. dispatch blocks; the caller typically // invokes it in a go statement. func (server *Server) dispatchTCP(key string, conn *net.TCPConn, wr *bufio.Writer, wp *bytes.Pool, wb *bytes.Buffer, ch *Channel) { var ( p *Proto err error ) if Debug { log.Debug("key: %s start dispatch tcp goroutine", key) } for { if !ch.Ready() { if Debug { log.Debug("key: %s wakeup exit dispatch goroutine", key) } break } // fetch message from svrbox(server send) for { if p, err = ch.SvrProto.Get(); err != nil { // must be empty error err = nil break } // just forward the message if err = server.writeTCPResponse(wr, p); err != nil { goto failed } p.Body = nil // avoid memory leak ch.SvrProto.GetAdv() } // only hungry flush response if err = wr.Flush(); err != nil { break } } failed: log.Error("key: %s dispatch tcp error(%v)", key, err) conn.Close() wp.Put(wb) if Debug { log.Debug("key: %s dispatch goroutine exit", key) } return }
// auth for goim handshake with client, use rsa & aes. func (server *Server) authTCP(rr *bufio.Reader, wr *bufio.Writer, p *Proto) (key string, rid int32, heartbeat time.Duration, err error) { if err = server.readTCPRequest(rr, p); err != nil { return } if p.Operation != define.OP_AUTH { log.Warn("auth operation not valid: %d", p.Operation) err = ErrOperation return } if key, rid, heartbeat, err = server.operator.Connect(p); err != nil { return } p.Body = nil p.Operation = define.OP_AUTH_REPLY if err = server.writeTCPResponse(wr, p); err != nil { return } err = wr.Flush() return }
// sendResponse send resp to client, sendResponse must be goroutine safe. func (server *Server) writeTCPResponse(wr *bufio.Writer, p *Proto) (err error) { var ( buf []byte packLen int32 ) packLen = RawHeaderSize + int32(len(p.Body)) p.HeaderLen = RawHeaderSize if buf, err = wr.Peek(RawHeaderSize); err != nil { return } binary.BigEndian.PutInt32(buf[PackOffset:], packLen) binary.BigEndian.PutInt16(buf[HeaderOffset:], p.HeaderLen) binary.BigEndian.PutInt16(buf[VerOffset:], p.Ver) binary.BigEndian.PutInt32(buf[OperationOffset:], p.Operation) binary.BigEndian.PutInt32(buf[SeqIdOffset:], p.SeqId) if p.Body != nil { _, err = wr.Write(p.Body) } if Debug { log.Debug("write proto: %v", p) } return }