//------------------------------------------------ IPC send should be seqential func _call(data []byte) (ret []byte) { seq_id := atomic.AddUint64(&_seq_id, 1) _seq_lock.Lock() headwriter := packet.Writer() headwriter.WriteU16(uint16(len(data)) + 8) // data + seq id headwriter.WriteU64(seq_id) _, err := _conn.Write(headwriter.Data()) if err != nil { log.Println("Error send packet header:", err.Error()) return nil } _, err = _conn.Write(data) if err != nil { log.Println("Error send packet data:", err.Error()) return nil } _seq_lock.Unlock() // wait ack ACK := make(chan []byte) _wait_ack_lock.Lock() _wait_ack[seq_id] = ACK _wait_ack_lock.Unlock() select { case msg := <-ACK: return msg case _ = <-time.After(10 * time.Second): } return nil }
func P_rank_list_req(sess *Session, reader *packet.Packet) (ret []byte, err error) { ids, scores, err := ipc.GetList(1, -1) if err != nil { return nil, err } out := rank_list{} out.F_items = make([]rank_list_item, len(ids)) for k, v := range ids { info, _ := ipc.GetInfo(v) out.F_items[k].F_id = v out.F_items[k].F_name = info.Name out.F_items[k].F_rank = scores[k] out.F_items[k].F_state = info.State t := int32(info.ProtectTime - time.Now().Unix()) if t > 0 { out.F_items[k].F_protect_time = int32(t) } else { out.F_items[k].F_protect_time = 0 } } writer := packet.Writer() return packet.Pack(Code["rank_list_ack"], out, writer), nil }
func SendChan(seqid uint64, data []byte, output chan []byte) { writer := packet.Writer() writer.WriteU16(uint16(len(data)) + 8) writer.WriteU64(seqid) // piggyback seq id writer.WriteRawBytes(data) output <- writer.Data() }
func BenchmarkAgent(b *testing.B) { fmt.Println("Benchmark", b.N) for i := 0; i < b.N; i++ { addr, err := net.ResolveTCPAddr("tcp", "0.0.0.0:8888") if err != nil { fmt.Println(err) os.Exit(-1) } conn, err := net.DialTCP("tcp", nil, addr) if err != nil { fmt.Println(err) os.Exit(-1) } U := user_login_info{} U.F_user_name = fmt.Sprintf("test%v", i) U.F_mac_addr = fmt.Sprintf("mac%v", i) pkt := packet.Pack(Code["user_login_req"], &U, nil) writer := packet.Writer() writer.WriteU16(uint16(len(pkt) + 4)) writer.WriteU32(0) writer.WriteRawBytes(pkt) ret := make([]byte, 100) conn.Write(writer.Data()) conn.Read(ret) } }
//------------------------------------------------ call remote function func _call(data []byte) (ret []byte) { seq_id := atomic.AddUint64(&_seq_id, 1) writer := packet.Writer() writer.WriteU16(uint16(len(data)) + 8) // data + seq id writer.WriteU64(seq_id) writer.WriteRawBytes(data) // wait ack ACK := make(chan []byte) _wait_ack_lock.Lock() _wait_ack[seq_id] = ACK _wait_ack_lock.Unlock() // send the packet _, err := _conn.Write(writer.Data()) if err != nil { log.Println("Error send packet to Event Server:", err) _wait_ack_lock.Lock() delete(_wait_ack, seq_id) _wait_ack_lock.Unlock() return nil } select { case msg := <-ACK: return msg case <-time.After(10 * time.Second): log.Println("EventServer is not responding...") } return nil }
func TestAgent(t *testing.T) { log.Println("Connecting to GS") addr, err := net.ResolveTCPAddr("tcp", "0.0.0.0:8888") if err != nil { fmt.Println(err) os.Exit(-1) } conn, err := net.DialTCP("tcp", nil, addr) if err != nil { fmt.Println(err) os.Exit(-1) } U := &user_login_info{} U.F_user_name = "test1" U.F_mac_addr = "mac1" pkt := packet.Pack(Code["user_login_req"], U, nil) writer := packet.Writer() writer.WriteU16(uint16(len(pkt) + 4)) writer.WriteU32(0) writer.WriteRawBytes(pkt) conn.Write(writer.Data()) ret := make([]byte, 100) n, _ := conn.Read(ret) fmt.Printf("%q\n", ret[:n]) // talk msg := &talk{} msg.F_user = "******" msg.F_msg = "hello world" pkt = packet.Pack(Code["talk_req"], msg, nil) writer = packet.Writer() writer.WriteU16(uint16(len(pkt) + 4)) writer.WriteU32(0) writer.WriteRawBytes(pkt) conn.Write(writer.Data()) n, _ = conn.Read(ret) fmt.Printf("%q\n", ret[:n]) }
func send_proto(conn net.Conn, p int16, info interface{}) { seqid++ payload := packet.Pack(p, info, nil) writer := packet.Writer() writer.WriteU16(uint16(len(payload)) + 4) writer.WriteU32(seqid) writer.WriteRawBytes(payload) conn.Write(writer.Data()) time.Sleep(time.Second) }
func send_proto(conn net.Conn, p int16, info interface{}) (reader *packet.Packet) { seqid++ payload := packet.Packet(p, info, nil) writer := packet.Writer() writer.WriteU16(uint16(len(payload)) + 4) w := packet.Writer() w.WriteU32(seqid) w.WriteRawBytes(payload) data := w.Data() if KEY_EXCHANGE { encoder.XORKeyStream(data, data) } writer.WriteRawBytes(data) conn.Write(writer.Data()) log.Printf("send : %#v", writer.Data()) time.Sleep(time.Second) //read header := make([]byte, 2) io.ReadFull(conn, header) size := binary.BigEndian.Uint16(header) log.Printf("read header: %v \n", size) r := make([]byte, size) _, err := io.ReadFull(conn, r) if err != nil { log.Println(err) } if KEY_EXCHANGE { decoder.XORKeyStream(r, r) } reader = packet.Reader(r) b, err := reader.ReadS16() if err != nil { log.Println(err) } if _, ok := RCode[b]; !ok { log.Println("unknown proto ", b) } return }
func P_atk_monster_req(sess *Session, reader *packet.Packet) (ret []byte, err error) { tbl, _ := PKT_command_id_pack(reader) writer := packet.Writer() payload := command_result_pack{} // println(tbl.F_id) ret = packet.Pack(Code["atk_monster_ack"], payload, writer) return }
//------------------------------------------------ send packet online func (buf *Buffer) raw_send(data []byte) { writer := packet.Writer() writer.WriteU16(uint16(len(data))) writer.WriteRawBytes(data) _, err := buf.conn.Write(writer.Data()) if err != nil { log.Println("Error send reply :", err) return } }
//---------------------------------------------------------- send response func _send(seqid uint32, data []byte, conn net.Conn) { writer := packet.Writer() writer.WriteU16(uint16(len(data)) + 4) writer.WriteU32(seqid) // piggyback seq id writer.WriteRawBytes(data) n, err := conn.Write(writer.Data()) // write operation is assumed to be atomic if err != nil { log.Println("Error send reply to GS, bytes:", n, "reason:", err) } }
//------------------------------------------------ packet online func (buf *Buffer) raw_send(data []byte) { writer := packet.Writer() writer.WriteU16(uint16(len(data))) writer.WriteRawBytes(data) //nr := int16(data[0])<<8 | int16(data[1]) //log.Printf("\033[37;44m[ACK] %v\t%v\tSIZE:%v\033[0m\n", nr, proto.RCode[nr], len(data)) n, err := buf.conn.Write(writer.Data()) if err != nil { ERR("Error send reply, bytes:", n, "reason:", err) return } }
func (sender *Sender) rawSend(data []byte) error { if len(data) > 0xffff { fmt.Printf("Send data overflow size:", len(data)) return errors.New("send data overflow") } writer := packet.Writer() writer.WriteU16(uint16(len(data))) writer.WriteRawBytes(data) _, err := sender.conn.Write(writer.Data()) if err != nil { fmt.Printf("Error send reply :", err) return err } return nil }
//--------------------------------------------------------- send to Game Server func _send(seqid uint64, data []byte, conn net.Conn) { headwriter := packet.Writer() headwriter.WriteU16(uint16(len(data)) + 8) headwriter.WriteU64(seqid) // piggyback seq id _, err := conn.Write(headwriter.Data()) if err != nil { log.Println("Error send reply header:", err.Error()) return } _, err = conn.Write(data) if err != nil { log.Println("Error send reply msg:", err.Error()) return } }
func P_user_login_req(sess *Session, reader *packet.Packet) (ret []byte, err error) { tbl, _ := PKT_user_login_info(reader) writer := packet.Writer() failed := command_result_pack{F_rst: 0} success := user_snapshot{} //------------------------------------------------ config := cfg.Get() version, _ := strconv.Atoi(config["version"]) if tbl.F_client_version != int32(version) { ret = packet.Pack(Code["user_login_faild_ack"], failed, writer) return } if tbl.F_new_user == 0 { if user_tbl.LoginMAC(sess.User.Mac, &sess.User) { ipc.Register(sess, sess.User.Id) _fill_user_snapshot(&sess.User, &success) ret = packet.Pack(Code["user_login_succeed_ack"], success, writer) return } else { ret = packet.Pack(Code["user_login_faild_ack"], failed, writer) return } } else { // register to db & online user sess.User.Name = tbl.F_user_name sess.User.Mac = tbl.F_mac_addr sess.User.CreatedAt = time.Now() if user_tbl.New(&sess.User) { ipc.Register(sess, sess.User.Id) // TODO: add user //ranklist.AddUser(&sess.User) _fill_user_snapshot(&sess.User, &success) ret = packet.Pack(Code["user_login_succeed_ack"], success, writer) return } else { ret = packet.Pack(Code["user_login_faild_ack"], failed, writer) return } } return }
//------------------------------------------------ send packet online func (buf *Buffer) raw_send(pkt *_RawPacket) { headwriter := packet.Writer() headwriter.WriteU16(uint16(len(pkt.data))) _, err := buf.conn.Write(headwriter.Data()) if err != nil { log.Println("Error send reply header:", err.Error()) return } _, err = buf.conn.Write(pkt.data) if err != nil { log.Println("Error send reply msg:", err.Error()) return } return }
func P_atk_player_req(sess *Session, reader *packet.Packet) (ret []byte, err error) { tbl, _ := PKT_command_id_pack(reader) writer := packet.Writer() success := user_snapshot{} failed := command_result_pack{} if ipc.Raid(tbl.F_id) { opponent, e := user_tbl.Load(tbl.F_id) if e == nil { _fill_user_snapshot(&opponent, &success) ret = packet.Pack(Code["atk_player_succeed_ack"], success, writer) return } } // info, err := ipc.GetInfo(tbl.F_id) failed.F_rst = info.Id ret = packet.Pack(Code["atk_player_faild_ack"], failed, writer) return }
func _caller_routine() { // waiting ACK queue. wait_ack := make(map[uint32]chan []byte) var seq_id uint32 for { select { case req := <-_caller: seq_id++ if seq_id == 0 { seq_id++ } wait_ack[seq_id] = req.ack writer := packet.Writer() writer.WriteU16(uint16(len(req.data)) + 4) // data + seq id writer.WriteU32(seq_id) writer.WriteRawBytes(req.data) // send the packet n, err := _conn.Write(writer.Data()) if err != nil { ERR("Error send packet to HUB, bytes:", n, "reason:", err) // reconnect DialHub() } case resp := <-_callee: // callee ack, ok := wait_ack[resp.seq_id] if !ok { ERR("Illegal(or expired) packet seqid:", resp.seq_id, "from HUB", resp.data) continue } ack <- resp.data close(ack) delete(wait_ack, resp.seq_id) } } }