mirror of
https://github.com/WiiLink24/wfc-server.git
synced 2026-03-21 17:44:58 -05:00
168 lines
3.5 KiB
Go
168 lines
3.5 KiB
Go
package serverbrowser
|
|
|
|
import (
|
|
"encoding/binary"
|
|
"encoding/gob"
|
|
"os"
|
|
"wwfc/common"
|
|
"wwfc/logging"
|
|
|
|
"github.com/linkdata/deadlock"
|
|
"github.com/logrusorgru/aurora/v3"
|
|
)
|
|
|
|
var ServerName = "serverbrowser"
|
|
|
|
const (
|
|
// Requests sent from the client
|
|
ServerListRequest = 0x00
|
|
ServerInfoRequest = 0x01
|
|
SendMessageRequest = 0x02
|
|
KeepaliveReply = 0x03
|
|
MapLoopRequest = 0x04
|
|
PlayerSearchRequest = 0x05
|
|
|
|
// Requests sent from the server to the client
|
|
PushKeysMessage = 0x01
|
|
PushServerMessage = 0x02
|
|
KeepaliveMessage = 0x03
|
|
DeleteServerMessage = 0x04
|
|
MapLoopMessage = 0x05
|
|
PlayerSearchMessage = 0x06
|
|
)
|
|
|
|
var (
|
|
connBuffers = map[uint64]*[]byte{}
|
|
mutex = deadlock.RWMutex{}
|
|
)
|
|
|
|
func StartServer(reload bool) {
|
|
if !reload {
|
|
return
|
|
}
|
|
|
|
// Load connection state
|
|
file, err := os.Open("state/sb_connections.gob")
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
decoder := gob.NewDecoder(file)
|
|
|
|
err = decoder.Decode(&connBuffers)
|
|
file.Close()
|
|
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
logging.Notice("SB", "Loaded", aurora.Cyan(len(connBuffers)), "connections")
|
|
}
|
|
|
|
func Shutdown() {
|
|
// Save connection state
|
|
file, err := os.OpenFile("state/sb_connections.gob", os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
encoder := gob.NewEncoder(file)
|
|
|
|
err = encoder.Encode(connBuffers)
|
|
file.Close()
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
logging.Notice("SB", "Saved", aurora.Cyan(len(connBuffers)), "connections")
|
|
}
|
|
|
|
func NewConnection(index uint64, address string) {
|
|
}
|
|
|
|
func CloseConnection(index uint64) {
|
|
mutex.Lock()
|
|
delete(connBuffers, index)
|
|
mutex.Unlock()
|
|
}
|
|
|
|
func HandlePacket(index uint64, data []byte, address string) {
|
|
moduleName := "SB:" + address
|
|
|
|
mutex.RLock()
|
|
buffer := connBuffers[index]
|
|
mutex.RUnlock()
|
|
|
|
if buffer == nil {
|
|
buffer = &[]byte{}
|
|
defer func() {
|
|
if buffer == nil {
|
|
return
|
|
}
|
|
|
|
mutex.Lock()
|
|
connBuffers[index] = buffer
|
|
mutex.Unlock()
|
|
}()
|
|
}
|
|
|
|
if len(*buffer)+len(data) > 0x1000 {
|
|
logging.Error(moduleName, "Buffer overflow")
|
|
common.CloseConnection(ServerName, index)
|
|
buffer = nil
|
|
return
|
|
}
|
|
|
|
*buffer = append(*buffer, data...)
|
|
|
|
// Packets can be sent in fragments, so we need to check if we have a full packet
|
|
// The first two bytes signify the packet size
|
|
if len(*buffer) < 2 {
|
|
return
|
|
}
|
|
|
|
packetSize := binary.BigEndian.Uint16((*buffer)[:2])
|
|
if packetSize < 3 || packetSize > 0x1000 {
|
|
logging.Error(moduleName, "Invalid packet size - terminating")
|
|
common.CloseConnection(ServerName, index)
|
|
buffer = nil
|
|
return
|
|
}
|
|
|
|
if len(*buffer) < int(packetSize) {
|
|
return
|
|
}
|
|
|
|
switch (*buffer)[2] {
|
|
case ServerListRequest:
|
|
// logging.Info(moduleName, "Command:", aurora.Yellow("SERVER_LIST_REQUEST"))
|
|
handleServerListRequest(moduleName, index, address, (*buffer)[:packetSize])
|
|
|
|
case ServerInfoRequest:
|
|
logging.Info(moduleName, "Command:", aurora.Yellow("SERVER_INFO_REQUEST"))
|
|
|
|
case SendMessageRequest:
|
|
// logging.Info(moduleName, "Command:", aurora.Yellow("SEND_MESSAGE_REQUEST"))
|
|
handleSendMessageRequest(moduleName, index, address, (*buffer)[:packetSize])
|
|
|
|
case KeepaliveReply:
|
|
logging.Info(moduleName, "Command:", aurora.Yellow("KEEPALIVE_REPLY"))
|
|
|
|
case MapLoopRequest:
|
|
logging.Info(moduleName, "Command:", aurora.Yellow("MAPLOOP_REQUEST"))
|
|
|
|
case PlayerSearchRequest:
|
|
logging.Info(moduleName, "Command:", aurora.Yellow("PLAYER_SEARCH_REQUEST"))
|
|
|
|
default:
|
|
logging.Error(moduleName, "Unknown command:", aurora.Cyan((*buffer)[2]))
|
|
}
|
|
|
|
if len(*buffer) > int(packetSize) {
|
|
*buffer = (*buffer)[packetSize:]
|
|
} else {
|
|
*buffer = []byte{}
|
|
buffer = nil
|
|
}
|
|
}
|