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) errNotifyCLOSED(errmsg string) { fun := "Client.errNotifyCLOSED" //slog.Debug("errmsg:%s", errmsg) errpb := &pushproto.Talk{ Type: pushproto.Talk_ERR.Enum(), Extdata: []byte(errmsg), } slog.Debugf("%s errmsg:%s", fun, errpb) data, _ := proto.Marshal(errpb) self.SendClose(util.Packdata(data)) }
// Method: POST // Uri: /push/CLIENT_ID/ZIPTYPE/DATATYPE // Data: push data func push(w http.ResponseWriter, r *http.Request) { fun := "rest.push" //debug_show_request(r) if r.Method != "POST" { writeRestErr(w, "method err") return } slog.Infof("%s %s", fun, r.URL.Path) path := strings.Split(r.URL.Path, "/") //slog.Info("%q", path) if len(path) != 5 { writeRestErr(w, "uri err") return } // path[0] "", path[1] push clientid := path[2] ziptype, err := strconv.Atoi(path[3]) if err != nil { writeRestErr(w, "ziptype err") return } datatype, err := strconv.Atoi(path[4]) if err != nil { writeRestErr(w, "datatype err") return } data, err := ioutil.ReadAll(r.Body) if err != nil { writeRestErr(w, "data err") return } if len(data) == 0 { writeRestErr(w, "data empty") return } msgid, link := connman.Send(clientid, int32(ziptype), int32(datatype), data) slog.Debugf("%s msgid:%d link:%s", fun, msgid, link) js, _ := json.Marshal(&RestReturn{Code: 0, Msgid: msgid, Link: link}) fmt.Fprintf(w, "%s", js) }
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) } }
// 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 } } } }