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
This commit is contained in:
Justin T 2021-09-10 01:07:38 -05:00 committed by GitHub
parent e32a74c9e1
commit f6856b3b42
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 155 additions and 112 deletions

View File

@ -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()
}

View File

@ -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
}

View File

@ -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()

View File

@ -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

View File

@ -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))
}

69
habbgo/server/router.go Normal file
View File

@ -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
}

View File

@ -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)
}
}
}

View File

@ -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
}

View File

@ -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

View File

@ -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")
}