Beispiel #1
0
//加载数据
func (s *server) restore() {
	db := s.open_db()
	defer db.Close()
	count := 0
	//查询
	db.View(func(tx *bolt.Tx) error {
		b := tx.Bucket([]byte(BOLTDB_BUCKET))
		b.ForEach(func(k, v []byte) error {
			//查询每个用户对应消息记录集合,将其反序列化成ChatMessage[]对象
			var msg []Chat_Message
			err := msgpack.Unmarshal(v, &msg)
			if err != nil {
				log.Critical("chat data corrupted:", err)
				os.Exit(-1)
			}
			//id转成uint64
			id, err := strconv.ParseUint(string(k), 0, 64)
			if err != nil {
				log.Critical("chat data corrupted:", err)
				os.Exit(-1)
			}
			//用NewEndPoint包装msg
			ep := NewEndPoint()
			ep.inbox = msg
			//用过eps包装ep
			s.eps[id] = ep
			count++
			return nil
		})
		return nil
	})
	log.Infof("restored %v chats", count)
}
Beispiel #2
0
// 密钥交换
func P_get_seed_req(sess *Session, reader *packet.Packet) []byte {
	// 读取4字节的send_seed 和 4字节的receive_seed
	tbl, _ := PKT_seed_info(reader)

	//同客户端约定, 交换两组公钥, 一组用于
	// KEY1
	X1, E1 := dh.DHExchange()
	KEY1 := dh.DHKey(X1, big.NewInt(int64(tbl.F_client_send_seed)))

	// KEY2
	X2, E2 := dh.DHExchange()
	KEY2 := dh.DHKey(X2, big.NewInt(int64(tbl.F_client_receive_seed)))

	ret := seed_info{int32(E1.Int64()), int32(E2.Int64())}
	//服务器加密种子是客户端解密种子                         加点盐
	encoder, err := rc4.NewCipher([]byte(fmt.Sprintf("%v%v", SALT, KEY2)))
	if err != nil {
		log.Critical(err)
		return nil
	}
	decoder, err := rc4.NewCipher([]byte(fmt.Sprintf("%v%v", SALT, KEY1)))
	if err != nil {
		log.Critical(err)
		return nil
	}

	sess.Encoder = encoder
	sess.Decoder = decoder
	sess.Flag |= SESS_KEYEXCG
	return packet.Pack(Code["get_seed_ack"], ret, nil)
}
Beispiel #3
0
// 玩家登陆过程
func P_user_login_req(sess *Session, reader *packet.Packet) []byte {
	// TODO: 登录鉴权
	sess.UserId = 1

	// TODO: 选择登录服务器
	sess.GSID = DEFAULT_GSID

	// 选服
	cli, err := sp.GetServiceWithId(sp.SERVICE_GAME, sess.GSID)
	if err != nil {
		log.Critical(err)
		return nil
	}

	// type assertion
	service, ok := cli.(spp.GameServiceClient)
	if !ok {
		log.Critical("canot do type assertion on: %v", sess.GSID)
		return nil
	}

	//开启到游戏服的流
	// TODO: 处理context, 设置超时
	stream, err := service.Stream(context.Background())
	if err != nil {
		log.Critical(err)
		return nil
	}
	sess.Stream = stream

	//在game注册
	// TODO: 新用户的创建由game处理
	sess.Stream.Send(&spp.Game_Frame{Type: spp.Game_Register, UserId: sess.UserId})

	// 读取GAME返回的消息
	fetcher_task := func(sess *Session) {
		for {
			in, err := sess.Stream.Recv()
			if err == io.EOF { //流关闭
				log.Trace(err)
				return
			}
			if err != nil {
				log.Error(err)
				return
			}
			sess.MQ <- *in
		}
	}
	go fetcher_task(sess)
	return packet.Pack(Code["user_login_ack"], user_snapshot{F_uid: sess.UserId}, nil)
}
Beispiel #4
0
//写入文件
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
		})
	}
}
Beispiel #5
0
func (s *server) init() {
	// snappy
	if env := os.Getenv(ENV_SNAPPY); env != "" {
		s.enable_snappy = true
	}

	// read redis host
	redis_host := DEFAULT_REDIS_HOST
	if env := os.Getenv(ENV_REDIS_HOST); env != "" {
		redis_host = env
	}

	// start connection to redis cluster
	client, err := cluster.NewCluster(redis_host)
	if err != nil {
		log.Critical(err)
		os.Exit(-1)
	}

	//存放redis client 句柄
	s.redis_client = client

	// read mongodb host
	mongodb_url := DEFAULT_MONGODB_URL
	if env := os.Getenv(ENV_MONGODB_URL); env != "" {
		mongodb_url = env
	}

	// start connection to mongodb
	sess, err := mgo.Dial(mongodb_url)
	if err != nil {
		log.Critical(err)
		os.Exit(-1)
	}

	s.db = sess.DB("")

	// wait chan
	s.wait = make(chan string, BUFSIZ)
	go s.loader_task()
}
Beispiel #6
0
func init() {
	addr := DEFAULT_STATSD_HOST
	if env := os.Getenv(ENV_STATSD); env != "" {
		addr = env
	}

	s, err := g2s.Dial("udp", addr)
	if err != nil {
		log.Critical(err)
		os.Exit(-1)
	}
	_statter = s

}
Beispiel #7
0
func main() {
	log.SetPrefix(SERVICE)

	lis, err := net.Listen("tcp", _port)
	if err != nil {
		log.Critical(err)
		os.Exit(-1)
	}
	log.Info("listenin on ", lis.Addr())

	s := grpc.NewServer()
	ins := &server{}
	ins.init()
	pb.RegisterChatServiceServer(s, ins)

	s.Serve(lis)
}
Beispiel #8
0
//打开数据库
func (s *server) open_db() *bolt.DB {
	db, err := bolt.Open(BOLTDB_FILE, 0600, nil)
	if err != nil {
		log.Critical(err)
		os.Exit(-1)
	}

	//创建表
	db.Update(func(tx *bolt.Tx) error {
		_, err := tx.CreateBucketIfNotExists([]byte(BOLTDB_BUCKET))
		if err != nil {
			log.Criticalf("create bucket: %s", err)
			os.Exit(-1)
		}
		return nil
	})
	return db
}
Beispiel #9
0
func (s *server) dump(dirty map[string]bool) {
	//遍历dirty, 取出key
	for k := range dirty {
		raw, err := s.redis_client.Cmd("GET", k).Bytes()
		if err != nil {
			log.Critical(err)
			continue
		}

		// 解压缩
		if s.enable_snappy {
			if dec, err := snappy.Decode(nil, raw); err == nil {
				raw = dec
			} else {
				log.Critical(err)
				continue
			}
		}

		var record map[string]interface{}
		//反序列化
		err = msgpack.Unmarshal(raw, &record)
		if err != nil {
			log.Critical(err)
			continue
		}

		//分隔拿到key和value
		strs := strings.Split(k, ":")
		if len(strs) != 2 {
			log.Critical("canot split key", k)
			continue
		}

		tblname, id_str := strs[0], strs[1]

		id, err := strconv.Atoi(id_str)
		if err != nil {
			log.Critical(err)
			continue
		}

		// save data to mongodb
		_, err = s.db.C(tblname).Upsert(bson.M{"Id": id}, record)
		if err != nil {
			log.Critical(err)
			continue
		}
	}
}
Beispiel #10
0
func checkError(err error) {
	if err != nil {
		log.Critical(err)
		os.Exit(-1)
	}
}