From 00fa94162c41f6b873b8c9078394dcd87078f223 Mon Sep 17 00:00:00 2001 From: CPunch Date: Fri, 10 Mar 2023 23:59:13 -0600 Subject: [PATCH] server: refactoring; start support for variadic packets --- server/login.go | 53 +++++++++++++++++-------------- server/loginserver.go | 2 +- server/peer.go | 74 ++++++++++++++++++++++++------------------- 3 files changed, 71 insertions(+), 58 deletions(-) diff --git a/server/login.go b/server/login.go index 7ace2f3..1e2f8df 100644 --- a/server/login.go +++ b/server/login.go @@ -35,7 +35,7 @@ func (server *LoginServer) AcceptLogin(peer *Peer, SzID string, IClientVerC int3 UiSvrTime: uint64(time.Now().Unix()), } - if err := peer.Send(resp, protocol.P_LS2CL_REP_LOGIN_SUCC); err != nil { + if err := peer.Send(protocol.P_LS2CL_REP_LOGIN_SUCC, resp); err != nil { return err } @@ -53,7 +53,7 @@ func (server *LoginServer) AcceptLogin(peer *Peer, SzID string, IClientVerC int3 // send characters (if any) for i := 0; i < len(data); i++ { - if err := peer.Send(&data[i], protocol.P_LS2CL_REP_CHAR_INFO); err != nil { + if err := peer.Send(protocol.P_LS2CL_REP_CHAR_INFO, &data[i]); err != nil { return err } } @@ -66,10 +66,10 @@ func (server *LoginServer) Login(peer *Peer, pkt protocol.Packet) error { pkt.Decode(&loginPkt) SendError := func(e int32) { - peer.Send(&protocol.SP_LS2CL_REP_LOGIN_FAIL{ + peer.Send(protocol.P_LS2CL_REP_LOGIN_FAIL, &protocol.SP_LS2CL_REP_LOGIN_FAIL{ IErrorCode: e, SzID: loginPkt.SzID, - }, protocol.P_LS2CL_REP_LOGIN_FAIL) + }) } // client is resending a login packet?? @@ -137,10 +137,10 @@ func (server *LoginServer) CheckCharacterName(peer *Peer, pkt protocol.Packet) e pkt.Decode(&charPkt) // just auto accept, client resends this data later - return peer.Send(&protocol.SP_LS2CL_REP_CHECK_CHAR_NAME_SUCC{ + return peer.Send(protocol.P_LS2CL_REP_CHECK_CHAR_NAME_SUCC, &protocol.SP_LS2CL_REP_CHECK_CHAR_NAME_SUCC{ SzFirstName: charPkt.SzFirstName, SzLastName: charPkt.SzLastName, - }, protocol.P_LS2CL_REP_CHECK_CHAR_NAME_SUCC) + }) } func (server *LoginServer) SaveCharacterName(peer *Peer, pkt protocol.Packet) error { @@ -148,24 +148,24 @@ func (server *LoginServer) SaveCharacterName(peer *Peer, pkt protocol.Packet) er pkt.Decode(&charPkt) if peer.AccountID == -1 { - peer.Send(&protocol.SP_LS2CL_REP_SAVE_CHAR_NAME_FAIL{}, protocol.P_LS2CL_REP_SAVE_CHAR_NAME_FAIL) + peer.Send(protocol.P_LS2CL_REP_SAVE_CHAR_NAME_FAIL, &protocol.SP_LS2CL_REP_SAVE_CHAR_NAME_FAIL{}) return fmt.Errorf("Out of order P_LS2CL_REP_SAVE_CHAR_NAME_FAIL!") } // TODO: sanity check SzFirstName && SzLastName PlayerID, err := db.DefaultDB.NewPlayer(peer.AccountID, charPkt.SzFirstName, charPkt.SzLastName, int(charPkt.ISlotNum)) if err != nil { - peer.Send(&protocol.SP_LS2CL_REP_SAVE_CHAR_NAME_FAIL{}, protocol.P_LS2CL_REP_SAVE_CHAR_NAME_FAIL) + peer.Send(protocol.P_LS2CL_REP_SAVE_CHAR_NAME_FAIL, &protocol.SP_LS2CL_REP_SAVE_CHAR_NAME_FAIL{}) return err } - return peer.Send(&protocol.SP_LS2CL_REP_SAVE_CHAR_NAME_SUCC{ + return peer.Send(protocol.P_LS2CL_REP_SAVE_CHAR_NAME_SUCC, &protocol.SP_LS2CL_REP_SAVE_CHAR_NAME_SUCC{ IPC_UID: int64(PlayerID), ISlotNum: charPkt.ISlotNum, IGender: charPkt.IGender, SzFirstName: charPkt.SzFirstName, SzLastName: charPkt.SzLastName, - }, protocol.P_LS2CL_REP_SAVE_CHAR_NAME_SUCC) + }) } func validateCharacterCreation(character *protocol.SP_CL2LS_REQ_CHAR_CREATE) bool { @@ -194,33 +194,40 @@ func validateCharacterCreation(character *protocol.SP_CL2LS_REQ_CHAR_CREATE) boo return true } +func SendFail(peer *Peer) error { + if err := peer.Send(protocol.P_LS2CL_REP_SHARD_SELECT_FAIL, &protocol.SP_LS2CL_REP_SHARD_SELECT_FAIL{ + IErrorCode: 2, + }); err != nil { + return err + } + + return nil +} + func (server *LoginServer) CharacterCreate(peer *Peer, pkt protocol.Packet) error { var charPkt protocol.SP_CL2LS_REQ_CHAR_CREATE pkt.Decode(&charPkt) if !validateCharacterCreation(&charPkt) { - peer.Send(&protocol.SP_LS2CL_REP_SHARD_SELECT_FAIL{IErrorCode: 2}, protocol.P_LS2CL_REP_SHARD_SELECT_FAIL) - return fmt.Errorf("invalid SP_CL2LS_REQ_CHAR_CREATE!") + return SendFail(peer) } if err := db.DefaultDB.FinishPlayer(&charPkt, peer.AccountID); err != nil { - peer.Send(&protocol.SP_LS2CL_REP_SHARD_SELECT_FAIL{IErrorCode: 2}, protocol.P_LS2CL_REP_SHARD_SELECT_FAIL) - return err + return SendFail(peer) } plr, err := db.DefaultDB.GetPlayer(int(charPkt.PCStyle.IPC_UID)) if err != nil { - peer.Send(&protocol.SP_LS2CL_REP_SHARD_SELECT_FAIL{IErrorCode: 2}, protocol.P_LS2CL_REP_SHARD_SELECT_FAIL) - return err + return SendFail(peer) } PCStyle, PCStyle2 := util.Player2PCStyle(plr) - return peer.Send(&protocol.SP_LS2CL_REP_CHAR_CREATE_SUCC{ + return peer.Send(protocol.P_LS2CL_REP_CHAR_CREATE_SUCC, &protocol.SP_LS2CL_REP_CHAR_CREATE_SUCC{ ILevel: int16(plr.Level), SPC_Style: PCStyle, SPC_Style2: PCStyle2, SOn_Item: charPkt.SOn_Item, // if items were faked, we don't really care since the db only stores the sanitized fields - }, protocol.P_LS2CL_REP_CHAR_CREATE_SUCC) + }) } func (server *LoginServer) CharacterDelete(peer *Peer, pkt protocol.Packet) error { @@ -229,13 +236,12 @@ func (server *LoginServer) CharacterDelete(peer *Peer, pkt protocol.Packet) erro slot, err := db.DefaultDB.DeletePlayer(int(charPkt.IPC_UID), peer.AccountID) if err != nil { - peer.Send(&protocol.SP_LS2CL_REP_SHARD_SELECT_FAIL{IErrorCode: 2}, protocol.P_LS2CL_REP_SHARD_SELECT_FAIL) - return err + return SendFail(peer) } - return peer.Send(&protocol.SP_LS2CL_REP_CHAR_DELETE_SUCC{ + return peer.Send(protocol.P_LS2CL_REP_CHAR_DELETE_SUCC, &protocol.SP_LS2CL_REP_CHAR_DELETE_SUCC{ ISlotNum: int8(slot), - }, protocol.P_LS2CL_REP_CHAR_DELETE_SUCC) + }) } func (server *LoginServer) FinishTutorial(peer *Peer, pkt protocol.Packet) error { @@ -243,8 +249,7 @@ func (server *LoginServer) FinishTutorial(peer *Peer, pkt protocol.Packet) error pkt.Decode(&charPkt) if err := db.DefaultDB.FinishTutorial(int(charPkt.IPC_UID), peer.AccountID); err != nil { - peer.Send(&protocol.SP_LS2CL_REP_SHARD_SELECT_FAIL{IErrorCode: 2}, protocol.P_LS2CL_REP_SHARD_SELECT_FAIL) - return err + return SendFail(peer) } // no response diff --git a/server/loginserver.go b/server/loginserver.go index f72ba2c..7e88a1b 100644 --- a/server/loginserver.go +++ b/server/loginserver.go @@ -63,7 +63,7 @@ func (server *LoginServer) Start() { client := NewPeer(server, conn) server.Connect(client) - go client.ClientHandler() + go client.Handler() } } diff --git a/server/peer.go b/server/peer.go index 248c994..1936245 100644 --- a/server/peer.go +++ b/server/peer.go @@ -49,56 +49,64 @@ func NewPeer(handler PeerHandler, conn net.Conn) *Peer { } } -func (client *Peer) Send(data interface{}, typeID uint32) error { +func (peer *Peer) Send(typeID uint32, data ...interface{}) error { buf := pool.Get() - defer func() { // always return the buffer to the pool - pool.Put(buf) - }() + defer pool.Put(buf) // always return the buffer to the pool - // encode + // body start pkt := protocol.NewPacket(buf) - // write the typeID and packet body - pkt.Encode(uint32(typeID)) - pkt.Encode(data) - - // write the packet size - binary.Write(client.conn, binary.LittleEndian, uint32(buf.Len())) - - // encrypt typeID & body - switch client.whichKey { - case USE_E: - protocol.EncryptData(buf.Bytes(), client.E_key) - case USE_FE: - protocol.EncryptData(buf.Bytes(), client.FE_key) + // encode type id + if err := pkt.Encode(uint32(typeID)); err != nil { + return err } - // write packet type && packet body + // encode data + for _, trailer := range data { + if err := pkt.Encode(trailer); err != nil { + return err + } + } + + // encrypt body + switch peer.whichKey { + case USE_E: + protocol.EncryptData(buf.Bytes(), peer.E_key) + case USE_FE: + protocol.EncryptData(buf.Bytes(), peer.FE_key) + } + + // write packet size + if err := binary.Write(peer.conn, binary.LittleEndian, uint32(buf.Len())); err != nil { + return err + } + + // write packet body log.Printf("Sending %#v, sizeof: %d", data, buf.Len()) - if _, err := client.conn.Write(buf.Bytes()); err != nil { + if _, err := peer.conn.Write(buf.Bytes()); err != nil { return fmt.Errorf("[FATAL] failed to write packet body! %v", err) } return nil } -func (client *Peer) Kill() { - if !client.alive { +func (peer *Peer) Kill() { + if !peer.alive { return } - client.alive = false - client.conn.Close() - client.handler.Disconnect(client) + peer.alive = false + peer.conn.Close() + peer.handler.Disconnect(peer) } -func (client *Peer) ClientHandler() { - defer client.Kill() +func (peer *Peer) Handler() { + defer peer.Kill() for { - // read packet size + // read packet size, the goroutine spends most of it's time parked here var sz uint32 - if err := binary.Read(client.conn, binary.LittleEndian, &sz); err != nil { + if err := binary.Read(peer.conn, binary.LittleEndian, &sz); err != nil { log.Printf("[FATAL] failed to read packet size! %v\n", err) return } @@ -111,17 +119,17 @@ func (client *Peer) ClientHandler() { // read packet body buf := pool.Get() - if _, err := buf.ReadFrom(io.LimitReader(client.conn, int64(sz))); err != nil { + if _, err := buf.ReadFrom(io.LimitReader(peer.conn, int64(sz))); err != nil { log.Printf("[FATAL] failed to read packet body! %v", err) return } // decrypt - protocol.DecryptData(buf.Bytes(), client.E_key) + protocol.DecryptData(buf.Bytes(), peer.E_key) + pkt := protocol.NewPacket(buf) // create packet && read typeID var typeID uint32 - pkt := protocol.NewPacket(buf) if err := pkt.Decode(&typeID); err != nil { log.Printf("[FATAL] failed to read packet type! %v", err) return @@ -129,7 +137,7 @@ func (client *Peer) ClientHandler() { // dispatch packet log.Printf("Got packet ID: %x, with a sizeof: %d\n", typeID, sz) - if err := client.handler.HandlePacket(client, typeID, pkt); err != nil { + if err := peer.handler.HandlePacket(peer, typeID, pkt); err != nil { log.Printf("[FATAL] %v", err) return }