From f6856b3b42a3a7d4dc10b264625b12347b49cc4b Mon Sep 17 00:00:00 2001 From: Justin T <37750742+jtieri@users.noreply.github.com> Date: Fri, 10 Sep 2021 01:07:38 -0500 Subject: [PATCH] Merge PR #4: Packet Handling Refactor * more detailed logging of packets * rename handlers to be less redundant * straggler file * packet handling refactor * get config ref --- habbgo/game/player/player.go | 2 + habbgo/log/logger.go | 23 +++-- .../protocol/handlers/handshake_handlers.go | 13 +-- .../protocol/handlers/navigator_handlers.go | 2 +- habbgo/protocol/handlers/player_handlers.go | 10 +-- habbgo/server/router.go | 69 ++++++++++++++ habbgo/server/scheduler.go | 89 +++---------------- habbgo/server/server.go | 16 ++-- habbgo/server/session.go | 35 +++++--- habbweb/controller/client.go | 8 ++ 10 files changed, 155 insertions(+), 112 deletions(-) create mode 100644 habbgo/server/router.go create mode 100644 habbweb/controller/client.go diff --git a/habbgo/game/player/player.go b/habbgo/game/player/player.go index b736c92..ad8489b 100644 --- a/habbgo/game/player/player.go +++ b/habbgo/game/player/player.go @@ -34,6 +34,8 @@ type Session interface { Queue(packet *packets.OutgoingPacket) Flush(packet *packets.OutgoingPacket) Database() *sql.DB + Address() string + GetPacketHandler(headerId int) (func(*Player, *packets.IncomingPacket), bool) Close() } diff --git a/habbgo/log/logger.go b/habbgo/log/logger.go index d54e84a..4fd10ae 100644 --- a/habbgo/log/logger.go +++ b/habbgo/log/logger.go @@ -1,18 +1,29 @@ package log import ( + "github.com/jtieri/HabbGo/habbgo/game/player" "github.com/jtieri/HabbGo/habbgo/protocol/packets" "log" + "reflect" + "runtime" + "strings" ) -func PrintOutgoingPacket(p *packets.OutgoingPacket) { - +func PrintOutgoingPacket(playerAddr string, p *packets.OutgoingPacket) { + log.Printf("[%v] [OUTGOING] [%v - %v] contents: %v ", playerAddr, p.Header, p.HeaderId, p.Payload.String()) } -func PrintIncomingPacket(p *packets.IncomingPacket) { - log.Printf("Received packet [%v - %v] with contents: %v ", p.Header, p.HeaderId, p.Payload.String()) +func PrintIncomingPacket(playerAddr string, handler func(*player.Player, *packets.IncomingPacket), p *packets.IncomingPacket) { + hName := getHandlerName(runtime.FuncForPC(reflect.ValueOf(handler).Pointer()).Name()) + log.Printf("[%v] [INCOMING] [%v - %v|%v] contents: %v ", playerAddr, hName, p.Header, p.HeaderId, p.Payload.String()) } -func PrintUnkownPacket(p *packets.IncomingPacket) { - +func PrintUnkownPacket(playerAddr string, p *packets.IncomingPacket) { + log.Printf("[%v] [UNK] [%v - %v] contents: %v ", playerAddr, p.Header, p.HeaderId, p.Payload.String()) +} + +func getHandlerName(handler string) string { + sp := strings.Split(handler, "/") // e.g. github.com/jtieri/HabbGo/habbgo/protocol/handlers.GenerateKey + s2 := sp[len(sp)-1] // e.g. handlers.GenerateKey + return strings.Split(s2, ".")[1] // e.g. GenerateKey } diff --git a/habbgo/protocol/handlers/handshake_handlers.go b/habbgo/protocol/handlers/handshake_handlers.go index 16374ec..3509678 100644 --- a/habbgo/protocol/handlers/handshake_handlers.go +++ b/habbgo/protocol/handlers/handshake_handlers.go @@ -1,24 +1,27 @@ package handlers +/* + + */ import ( "github.com/jtieri/HabbGo/habbgo/game/player" "github.com/jtieri/HabbGo/habbgo/protocol/composers" "github.com/jtieri/HabbGo/habbgo/protocol/packets" ) -func HandleInitCrypto(player *player.Player, packet *packets.IncomingPacket) { +func InitCrypto(player *player.Player, packet *packets.IncomingPacket) { player.Session.Send(composers.ComposeCryptoParams()) } -func HandleGenerateKey(player *player.Player, packet *packets.IncomingPacket) { +func GenerateKey(player *player.Player, packet *packets.IncomingPacket) { player.Session.Send(composers.ComposeEndCrypto()) } -func HandleGetSessionParams(player *player.Player, packet *packets.IncomingPacket) { +func GetSessionParams(player *player.Player, packet *packets.IncomingPacket) { player.Session.Send(composers.ComposeSessionParams()) } -func HandleSSO(p *player.Player, packet *packets.IncomingPacket) { +func SSO(p *player.Player, packet *packets.IncomingPacket) { token := packet.ReadString() // TODO if p login with token is success login, otherwise send LOCALISED ERROR & disconnect from server @@ -29,7 +32,7 @@ func HandleSSO(p *player.Player, packet *packets.IncomingPacket) { } } -func HandleTryLogin(p *player.Player, packet *packets.IncomingPacket) { +func TryLogin(p *player.Player, packet *packets.IncomingPacket) { username := packet.ReadString() password := packet.ReadString() diff --git a/habbgo/protocol/handlers/navigator_handlers.go b/habbgo/protocol/handlers/navigator_handlers.go index b9830af..a362c83 100644 --- a/habbgo/protocol/handlers/navigator_handlers.go +++ b/habbgo/protocol/handlers/navigator_handlers.go @@ -8,7 +8,7 @@ import ( "github.com/jtieri/HabbGo/habbgo/protocol/packets" ) -func HandleNavigate(player *player.Player, packet *packets.IncomingPacket) { +func Navigate(player *player.Player, packet *packets.IncomingPacket) { roomService := room.RoomService() nodeMask := packet.ReadInt() == 1 diff --git a/habbgo/protocol/handlers/player_handlers.go b/habbgo/protocol/handlers/player_handlers.go index c5ae77c..455bb96 100644 --- a/habbgo/protocol/handlers/player_handlers.go +++ b/habbgo/protocol/handlers/player_handlers.go @@ -6,23 +6,23 @@ import ( "github.com/jtieri/HabbGo/habbgo/protocol/packets" ) -func HandleGetInfo(player *player.Player, packet *packets.IncomingPacket) { +func GetInfo(player *player.Player, packet *packets.IncomingPacket) { player.Session.Send(composers.ComposeUserObj(player)) } -func HandleGetCredits(player *player.Player, packet *packets.IncomingPacket) { +func GetCredits(player *player.Player, packet *packets.IncomingPacket) { player.Session.Send(composers.ComposeCreditBalance(player.Details.Credits)) } -func HandleGetAvailableBadges(player *player.Player, packet *packets.IncomingPacket) { +func GetAvailableBadges(player *player.Player, packet *packets.IncomingPacket) { player.Session.Send(composers.ComposeAvailableBadges(player)) } -func HandleGetSoundSetting(player *player.Player, packet *packets.IncomingPacket) { +func GetSoundSetting(player *player.Player, packet *packets.IncomingPacket) { player.Session.Send(composers.ComposeSoundSetting(player.Details.SoundEnabled)) } -func HandleTestLatency(player *player.Player, packet *packets.IncomingPacket) { +func TestLatency(player *player.Player, packet *packets.IncomingPacket) { l := packet.ReadInt() player.Session.Send(composers.ComposeLatency(l)) } diff --git a/habbgo/server/router.go b/habbgo/server/router.go new file mode 100644 index 0000000..8eeaba9 --- /dev/null +++ b/habbgo/server/router.go @@ -0,0 +1,69 @@ +package server + +import ( + "github.com/jtieri/HabbGo/habbgo/game/player" + "github.com/jtieri/HabbGo/habbgo/protocol/handlers" + "github.com/jtieri/HabbGo/habbgo/protocol/packets" +) + +type Router struct { + RegisteredPackets map[int]func(*player.Player, *packets.IncomingPacket) +} + +func (r *Router) GetHandler(headerId int) (func(*player.Player, *packets.IncomingPacket), bool) { + h, found := r.RegisteredPackets[headerId] + return h, found +} + +func RegisterHandlers() (r *Router) { + r = &Router{RegisteredPackets: make(map[int]func(p *player.Player, packet *packets.IncomingPacket))} + + r.RegisterHandshakeHandlers() + r.RegisterPlayerHandlers() + r.RegisterNavigatorHandlers() + + return +} + +func (r *Router) RegisterHandshakeHandlers() { + r.RegisteredPackets[206] = handlers.InitCrypto + r.RegisteredPackets[202] = handlers.GenerateKey // older clients + r.RegisteredPackets[2002] = handlers.GenerateKey // newer clients + // 207 - SECRETKEY + // 5 - VERSIONCHECK in older clients + // 1170 - VERSIONCHECK in later clients? v26+? + // TODO figure out exact client revisions when these packet headers change + // 6 - UNIQUEID + r.RegisteredPackets[181] = handlers.GetSessionParams + r.RegisteredPackets[204] = handlers.SSO + r.RegisteredPackets[4] = handlers.TryLogin +} + +func (r *Router) RegisterPlayerHandlers() { + r.RegisteredPackets[7] = handlers.GetInfo + r.RegisteredPackets[8] = handlers.GetCredits + r.RegisteredPackets[157] = handlers.GetAvailableBadges + r.RegisteredPackets[228] = handlers.GetSoundSetting + r.RegisteredPackets[315] = handlers.TestLatency +} + +func (r *Router) RegisterNavigatorHandlers() { + r.RegisteredPackets[150] = handlers.Navigate + // 151: GETUSERFLATCATS + // 21: GETFLATINFO + // 23: DELETEFLAT + // 24: UPDATEFLAT + // 25: SETFLATINFO + // 13: SBUSYF + // 152: GETFLATCAT + // 153: SETFLATCAT + // 155: REMOVEALLRIGHTS + // 156: GETPARENTCHAIN + // 16: SUSERF + // 264: GET_RECOMMENDED_ROOMS + // 17: SRCHF + // 154: GETSPACENODEUSERS + // 18: GETFVRF + // 19: ADD_FAVORITE_ROOM + // 20: DEL_FAVORITE_ROOM +} diff --git a/habbgo/server/scheduler.go b/habbgo/server/scheduler.go index 73335fa..13534e3 100644 --- a/habbgo/server/scheduler.go +++ b/habbgo/server/scheduler.go @@ -2,85 +2,22 @@ package server import ( "github.com/jtieri/HabbGo/habbgo/game/player" - "github.com/jtieri/HabbGo/habbgo/protocol/handlers" + logger "github.com/jtieri/HabbGo/habbgo/log" "github.com/jtieri/HabbGo/habbgo/protocol/packets" - "log" ) -func Handle(player *player.Player, packet *packets.IncomingPacket) { - switch packet.HeaderId { - // Handshake Packets ---------------------------------------------------------------------------------------------- - case 206: // INIT_CRYPTO - handlers.HandleInitCrypto(player, packet) - case 202: // GENERATEKEY - handlers.HandleGenerateKey(player, packet) - case 2002: - handlers.HandleGenerateKey(player, packet) - case 207: // SECRETKEY +func Handle(p *player.Player, packet *packets.IncomingPacket) { + handler, found := p.Session.GetPacketHandler(packet.HeaderId) - case 5: // VERSIONCHECK - - case 6: // UNIQUEID - - case 181: // GET_SESSION_PARAMETERS - handlers.HandleGetSessionParams(player, packet) - case 204: // SSO - handlers.HandleSSO(player, packet) - case 4: // TRY LOGIN - used when SSO is disabled - handlers.HandleTryLogin(player, packet) - - // Player Packets ------------------------------------------------------------------------------------------------- - case 7: // GET_INFO - handlers.HandleGetInfo(player, packet) - case 8: // GET_CREDITS - handlers.HandleGetCredits(player, packet) - case 157: // GETAVAILABLEBADGES - handlers.HandleGetAvailableBadges(player, packet) - case 228: // GET_SOUND_SETTING - handlers.HandleGetSoundSetting(player, packet) - case 315: // TEST_LATENCY ---> Init Latency Test - handlers.HandleTestLatency(player, packet) - - // Navigator Packets ---------------------------------------------------------------------------------------------- - case 150: // NAVIGATE - //handlers.HandleNavigate(player, packet) - case 151: // GETUSERFLATCATS - - case 21: // GETFLATINFO - - case 23: // DELETEFLAT - - case 24: // UPDATEFLAT - - case 25: // SETFLATINFO - - case 13: // SBUSYF - - case 152: // GETFLATCAT - - case 153: // SETFLATCAT - - case 155: // REMOVEALLRIGHTS - - case 156: // GETPARENTCHAIN - - case 16: // SUSERF - - case 264: // GET_RECOMMENDED_ROOMS - - case 17: //SRCHF - - case 154: // GETSPACENODEUSERS - - case 18: // GETFVRF - - case 19: // ADD_FAVORITE_ROOM - - case 20: // DEL_FAVORITE_ROOM - - // ---------------------------------------------------------------------------------------------------------------- - default: - log.Printf("No registered handler for packet [%v - %v], it's payload contained %v ", - packet.Header, packet.HeaderId, packet.Payload.String()) + if found { + if GetConfig().Server.Debug { + logger.PrintIncomingPacket(p.Session.Address(), handler, packet) + } + handler(p, packet) + } else { + if GetConfig().Server.Debug { + logger.PrintUnkownPacket(p.Session.Address(), packet) + } } + } diff --git a/habbgo/server/server.go b/habbgo/server/server.go index f429484..918273b 100644 --- a/habbgo/server/server.go +++ b/habbgo/server/server.go @@ -10,25 +10,27 @@ import ( "sync" ) +var Config *config.Config + type Server struct { - Config *config.Config Database *sql.DB activeSessions []*Session } // New returns a pointer to a newly allocated server struct. func New(config *config.Config, db *sql.DB) *Server { + Config = config + return &Server{ - Config: config, Database: db, } } // Start will setup the game server, start listening for incoming connections, and handle connections appropriately. func (server *Server) Start() { - listener, err := net.Listen("tcp", server.Config.Server.Host+":"+strconv.Itoa(server.Config.Server.Port)) + listener, err := net.Listen("tcp", Config.Server.Host+":"+strconv.Itoa(Config.Server.Port)) if err != nil { - log.Fatalf("There was an issue starting the game server on port %v.", server.Config.Server.Port) // TODO properly handle errors + log.Fatalf("There was an issue starting the game server on port %v.", Config.Server.Port) // TODO properly handle errors } log.Printf("Successfully started the game server at %v", listener.Addr().String()) defer listener.Close() @@ -44,7 +46,7 @@ func (server *Server) Start() { // Check that there aren't multiple sessions for a given IP address // TODO kick a session to make room for the new one - if server.sessionsFromSameAddr(conn) < server.Config.Server.MaxConns { + if server.sessionsFromSameAddr(conn) < Config.Server.MaxConns { session := NewSession(conn, server) log.Printf("New session created for address: %v", conn.LocalAddr().String()) @@ -94,3 +96,7 @@ func (server *Server) sessionsFromSameAddr(conn net.Conn) int { return count } + +func GetConfig() *config.Config { + return Config +} diff --git a/habbgo/server/session.go b/habbgo/server/session.go index 07175fa..04d9613 100644 --- a/habbgo/server/session.go +++ b/habbgo/server/session.go @@ -4,8 +4,10 @@ import ( "bufio" "bytes" "database/sql" + logger "github.com/jtieri/HabbGo/habbgo/log" "log" "net" + "strings" "sync" "github.com/jtieri/HabbGo/habbgo/game/player" @@ -20,6 +22,7 @@ type Session struct { buffer *buffer active bool server *Server + router *Router } type buffer struct { @@ -35,6 +38,7 @@ func NewSession(conn net.Conn, server *Server) *Session { buffer: &buffer{mux: sync.Mutex{}, buff: bufio.NewWriter(conn)}, active: true, server: server, + router: RegisterHandlers(), } } @@ -78,11 +82,6 @@ func (session *Session) Listen() { packet := packets.NewIncoming(rawHeader, payload) - if session.server.Config.Server.Debug { - log.Printf("Received packet [%v - %v] with contents: %v ", - packet.Header, packet.HeaderId, packet.Payload.String()) - } - go Handle(p, packet) // Handle packets coming in from p's Session } } @@ -95,16 +94,16 @@ func (session *Session) Send(packet *packets.OutgoingPacket) { _, err := session.buffer.buff.Write(packet.Payload.Bytes()) if err != nil { - log.Printf("Error sending packet %v to session %v \n %v ", packet.Header, session.connection.LocalAddr(), err) + log.Printf("Error sending packet %v to session %v \n %v ", packet.Header, session.Address(), err) } err = session.buffer.buff.Flush() if err != nil { - log.Printf("Error sending packet %v to session %v \n %v ", packet.Header, session.connection.LocalAddr(), err) + log.Printf("Error sending packet %v to session %v \n %v ", packet.Header, session.Address(), err) } - if session.server.Config.Server.Debug { - log.Printf("Sent packet [%v - %v] with contents: %v ", packet.Header, packet.HeaderId, packet.String()) + if Config.Server.Debug { + logger.PrintOutgoingPacket(session.Address(), packet) } } @@ -116,7 +115,7 @@ func (session *Session) Queue(packet *packets.OutgoingPacket) { _, err := session.buffer.buff.Write(packet.Payload.Bytes()) if err != nil { - log.Printf("Error sending packet %v to session %v \n %v ", packet.Header, session.connection.LocalAddr(), err) + log.Printf("Error sending packet %v to session %v \n %v ", packet.Header, session.Address(), err) } } @@ -127,11 +126,11 @@ func (session *Session) Flush(packet *packets.OutgoingPacket) { err := session.buffer.buff.Flush() if err != nil { - log.Printf("Error sending packet %v to session %v \n %v ", packet.Header, session.connection.LocalAddr(), err) + log.Printf("Error sending packet %v to session %v \n %v ", packet.Header, session.Address(), err) } - if session.server.Config.Server.Debug { - log.Printf("Sent packet [%v - %v] with contents: %v ", packet.Header, packet.HeaderId, packet.String()) + if Config.Server.Debug { + logger.PrintOutgoingPacket(session.Address(), packet) } } @@ -140,9 +139,17 @@ func (session *Session) Database() *sql.DB { return session.database } +func (session *Session) GetPacketHandler(headerId int) (func(*player.Player, *packets.IncomingPacket), bool) { + return session.router.GetHandler(headerId) +} + +func (session *Session) Address() string { + return strings.Split(session.connection.RemoteAddr().String(), ":")[0] // split ip:port at : and return ip part +} + // Close disconnects a Session from the server. func (session *Session) Close() { - log.Printf("Closing session for address: %v ", session.connection.LocalAddr()) + log.Printf("Closing session for address: %v ", session.Address()) session.server.RemoveSession(session) session.server = nil session.buffer = nil diff --git a/habbweb/controller/client.go b/habbweb/controller/client.go new file mode 100644 index 0000000..56571d5 --- /dev/null +++ b/habbweb/controller/client.go @@ -0,0 +1,8 @@ +package controller + +import "github.com/gin-gonic/gin" + +func GetClient(c *gin.Context) { + //fmt.Println("Inside GetIndex() .....") + c.File("./client/client.html") +}