//写入文件 func (s *server) dump(db *bolt.DB, changes map[uint64]bool) { //写入已经更改的id for k := range changes { //读取message ep := s.read_ep(k) if ep == nil { log.Errorf("canot find endpoint %v", k) continue } //序列化数据 bin, err := msgpack.Marshal(ep.Read()) if err != nil { log.Critical("canot marshal:", err) continue } //更新表 db.Update(func(tx *bolt.Tx) error { //拿到表句柄 b := tx.Bucket([]byte(BOLTDB_BUCKET)) //存入数据, k-v形式 err := b.Put([]byte(fmt.Sprint(k)), bin) return err }) } }
//订阅消息, 通过Chat_Id func (s *server) Subscribe(p *Chat_Id, stream ChatService_SubscribeServer) error { die := make(chan bool) //包装消息 f := pubsub.NewWrap(func(msg *Chat_Message) { //发送message if err := stream.Send(msg); err != nil { // 出错时, 取消订阅 close(die) } }) log.Tracef("new subscriber: %p", f) //读取消息盒子 ep := s.read_ep(p.Id) if ep == nil { log.Errorf("canot find endpoint %v", p) return ERROR_NOT_EXISTS } //订阅消息 ep.ps.Sub(f) defer func() { ep.ps.Leave(f) }() <-die return nil }
func PrintPanicStack(extras ...interface{}) { if x := recover(); x != nil { log.Error(x) i := 0 funcName, file, line, ok := runtime.Caller(i) for ok { log.Errorf("frame %v:[func:%v,file:%v,line:%v]\n", i, runtime.FuncForPC(funcName).Name(), file, line) i++ funcName, file, line, ok = runtime.Caller(i) } for k := range extras { log.Errorf("EXRAS#%v DATA:%v\n", k, spew.Sdump(extras[k])) } } }
//注册消息通道 func (s *server) Reg(ctx context.Context, p *Chat_Id) (*Chat_Nil, error) { s.Lock() defer s.Unlock() //通过id读取消息盒子 ep := s.eps[p.Id] //判断是否已注册 if ep != nil { log.Errorf("id already exists:%v", p.Id) return nil, ERROR_ALREADY_EXISTS } //一个消息id绑定一个endpoint s.eps[p.Id] = NewEndPoint() //标记要保存的id s.pending <- p.Id return OK, nil }
//通过Chat_Id读取消息 func (s *server) Read(p *Chat_Id, stream ChatService_ReadServer) error { ep := s.read_ep(p.Id) if ep == nil { log.Errorf("canot find endpoint %v", p) return ERROR_NOT_EXISTS } //如果读到消息 msgs := ep.Read() for k := range msgs { //发送消息 if err := stream.Send(&msgs[k]); err != nil { return err } } return nil }
// client protocol handle proxy func proxy_user_request(sess *Session, p []byte) []byte { start := time.Now() defer utils.PrintPanicStack() //解密 if sess.Flag&SESS_ENCRYPT != 0 { //使用2组密钥匙, 增加破解难度 sess.Decoder.XORKeyStream(p, p) } //封装成reader reader := packet.Reader(p) // 读客户端数据包序列号(1,2,3...) // 可避免重放攻击-REPLAY-ATTACK //数据包的前4个字节存放的是客户端的发包数量 //客户端每次发包要包含第几次发包信息 seq_id, err := reader.ReadU32() if err != nil { log.Error("read client timestamp failed:", err) sess.Flag |= SESS_KICKED_OUT return nil } // 数据包个数验证 if seq_id != sess.PacketCount { //数据包真实长度是,总长度-4个字节的包个数长度-2个字节的协议号长度 log.Errorf("illegal packet sequeue id:%v should be:%v size:%v", seq_id, sess.PacketCount, len(p)-6) sess.Flag |= SESS_KICKED_OUT return nil } // 读协议号 b, err := reader.ReadS16() if err != nil { log.Error("read protocol number failed.") sess.Flag |= SESS_KICKED_OUT return nil } //根据协议号段 做服务划分 var ret []byte if b > MAX_PROTO_NUM { //去除4字节发包个数,将其余的向前传递 if err := forward(sess, p[4:]); err != nil { log.Errorf("service id:%v execute failed, error:%v", b, err) sess.Flag |= SESS_KICKED_OUT return nil } } else { if h := client_handler.Handlers[b]; h != nil { ret = h(sess, reader) } else { log.Errorf("service id:%v not bind", b) sess.Flag |= SESS_KICKED_OUT return nil } } // 统计处理时间 elasped := time.Now().Sub(start) if b != 0 { //排除心跳包日志 log.Trace("[REQ]", client_handler.RCode[b]) _statter.Timing(1.0, fmt.Sprintf("%v%v", STATSD_PREFIX, client_handler.RCode[b]), elasped) } return ret }