func (self *Client) dochgCLOSED(isRmManager bool) { fun := "Client.dochgCLOSED" self.state_lock.Lock() defer self.state_lock.Unlock() if self.state == State_CLOSED { slog.Warnf("%s client:%s is already:%s", fun, self, State_CLOSED) return } if isRmManager && self.state == State_ESTABLISHED { self.manager.delClient(self.client_id, self.remoteaddr) } if err := self.conn.Close(); err != nil { slog.Warnf("%s client:%s Close net.Conn err: %s", fun, self, err) } for k, v := range self.bussmsg { select { case v <- false: default: slog.Warnf("%s client:%s msgid:%d no wait notify", fun, self, k) } } old_state := self.state self.state = State_CLOSED slog.Infof("%s change client:%s %s:%s", fun, self, old_state, self.state) }
func (self *ConnectionManager) delClient(client_id string, addr string) { fun := "ConnectionManager.delClient" if v, ok := self.clients[client_id]; ok { if v.remoteaddr == addr { delete(self.clients, client_id) slog.Infof("%s Remove %s %d", fun, v, len(self.clients)) } else { slog.Warnf("%s delete client %s not same %s", fun, v, addr) } } else { slog.Warnf("%s delete client_id %s not fond", fun, client_id) } }
func (self *Client) chgESTABLISHED(pb *pushproto.Talk) { fun := "Client.chgESTABLISHED" self.state_lock.Lock() defer self.state_lock.Unlock() if self.state == State_ESTABLISHED { // 已经建立了连接,当前状态是ESTABLISHED,可能是客户端没有收到synack // 重新回执synack slog.Warnf("%s client:%s is already:%s", fun, self, State_ESTABLISHED) self.sendSYNACK(self.client_id) return } appid := pb.GetAppid() installid := pb.GetInstallid() sec := "9b0319bc5c05055283cee2533abab270" h := sha1.Sum([]byte(appid + installid + sec)) self.client_id = fmt.Sprintf("%x", h) old_state := self.state self.state = State_ESTABLISHED slog.Infof("%s change client:%s %s:%s", fun, self, old_state, self.state) self.sendSYNACK(self.client_id) self.manager.addClient(self) }
func (self *ConnectionManager) Loop(addr string) { fun := "ConnectionManager.Loop" tcpAddr, error := net.ResolveTCPAddr("tcp", addr) if error != nil { slog.Fatalf("%s Error: Could not resolve address %s", fun, error) panic("resolve address") } netListen, error := net.Listen(tcpAddr.Network(), tcpAddr.String()) if error != nil { slog.Fatalf("%s Error: Could not Listen %s", fun, error) panic("listen address") } defer netListen.Close() //go self.req() //go self.trans() for { slog.Infof("%s Waiting for clients", fun) connection, error := netListen.Accept() if error != nil { slog.Warnf("%s Client error: ", fun, error) } else { NewClient(self, connection) } } }
func (self *Client) proto(data []byte) { fun := "Client.proto" pb := &pushproto.Talk{} err := proto.Unmarshal(data, pb) if err != nil { slog.Warnf("%s unmarshaling error: %s", fun, err) self.errNotifyCLOSED("package unmarshaling error") return } slog.Debugf("%s recv proto: %s", fun, pb) pb_type := pb.GetType() if pb_type == pushproto.Talk_SYN { self.recvSYN(pb) } else if pb_type == pushproto.Talk_ECHO { self.Send(util.Packdata(data)) } else if pb_type == pushproto.Talk_HEART { self.sendHEART() } else if pb_type == pushproto.Talk_ACK { self.recvACK(pb) } }
func (self *Client) recvACK(pb *pushproto.Talk) { fun := "Client.recvACK" msgid := pb.GetAckmsgid() c := self.getBussmsg(msgid) if c != nil { select { case c <- true: slog.Debugf("%s client:%s msgid:%d notify", fun, self, msgid) default: slog.Warnf("%s client:%s msgid:%d no wait notify", fun, self, msgid) } } else { slog.Warnf("%s client:%s msgid:%d not found", fun, self, msgid) } }
func (self *ConnectionManager) Send(client_id string, ziptype int32, datatype int32, data []byte) (uint64, string) { fun := "ConnectionManager.Send" if v, ok := self.clients[client_id]; ok { return v.SendBussiness(ziptype, datatype, data) } else { slog.Warnf("%s client_id %s not fond", fun, client_id) return 0, "" } }
func (self *ConnectionManager) addClient(cli *Client) { fun := "ConnectionManager.addClient" client_id := cli.client_id if v, ok := self.clients[client_id]; ok { v.errNotifyCLOSED("dup client add client") delete(self.clients, client_id) slog.Warnf("%s dup client add client_id %s", fun, client_id) } self.clients[client_id] = cli slog.Infof("%s Add %s %d", fun, cli, len(self.clients)) }
// goroutine func (self *Client) sendData(s []byte, isclose bool) { fun := "Client.sendData" //slog.Debug("sendData %s %d", s, isclose) self.send_lock.Lock() defer self.send_lock.Unlock() self.conn.SetWriteDeadline(time.Now().Add(time.Duration(5) * time.Second)) a, err := self.conn.Write(s) slog.Infof("%s client:%s Send Write rv %d", fun, self, a) if err != nil { slog.Warnf("%s client:%s write error:%s ", fun, self, err) self.chgCLOSED() return } if isclose { self.chgCLOSED() } }
func (self *Client) chgCLOSED2TCP_READY(c net.Conn) { fun := "Client.chgCLOSED2TCP_READY" self.state_lock.Lock() defer self.state_lock.Unlock() if self.state == State_TCP_READY { slog.Warnf("%s client:%s is already:%s", fun, self, State_TCP_READY) return } self.client_id = "NULL" self.conn = c self.remoteaddr = c.RemoteAddr().String() self.bussmsg = make(map[uint64]chan bool) old_state := self.state self.state = State_TCP_READY slog.Infof("%s change client:%s %s:%s", fun, self, old_state, self.state) go self.Recv() }
// goroutine func (self *Client) Recv() { fun := "Client.Recv" buffer := make([]byte, 2048) packBuff := make([]byte, 0) var bufLen uint64 = 0 conn := self.conn errmsg := "" defer self.deferErrNotifyCLOSED(&errmsg) for { conn.SetReadDeadline(time.Now().Add(time.Duration(60*10) * time.Second)) bytesRead, error := conn.Read(buffer) if error != nil { slog.Infof("%s client:%s conn error: %s", fun, self, error) return } packBuff = append(packBuff, buffer[:bytesRead]...) bufLen += uint64(bytesRead) slog.Infof("%s client:%s Recv: %d %d %d", fun, self, bytesRead, packBuff, bufLen) for { if bufLen > 0 { pacLen, sz := binary.Uvarint(packBuff[:bufLen]) if sz < 0 { slog.Warnf("%s client:%s package head error:%s", fun, self, packBuff[:bufLen]) return } else if sz == 0 { break } slog.Debugf("%s pacLen %d", fun, pacLen) // must < 5K if pacLen > 1024*5 { slog.Warnf("%s client:%s package too long error:%s", fun, self, packBuff[:bufLen]) errmsg = "package too long" return } else if pacLen == 0 { errmsg = "package len 0" return } apacLen := uint64(sz) + pacLen + 1 if bufLen >= apacLen { pad := packBuff[apacLen-1] if pad != 0 { slog.Warnf("%s client:%s package pad error:%s", fun, self, packBuff[:bufLen]) errmsg = "package pad error" return } self.proto(packBuff[sz : apacLen-1]) packBuff = packBuff[apacLen:] bufLen -= apacLen } else { break } } else { break } } } }