diff --git a/port/include/net/net.h b/port/include/net/net.h index 6880dd84d..e99179f63 100644 --- a/port/include/net/net.h +++ b/port/include/net/net.h @@ -5,7 +5,7 @@ #include "constants.h" #include "net/netbuf.h" -#define NET_PROTOCOL_VER 1 +#define NET_PROTOCOL_VER 2 #define NET_MAX_CLIENTS MAX_PLAYERS #define NET_MAX_NAME MAX_PLAYERNAME @@ -30,6 +30,7 @@ #define DISCONNECT_TIMEOUT 5 #define DISCONNECT_FULL 6 #define DISCONNECT_LATE 7 +#define DISCONNECT_FILES 8 #define CLSTATE_DISCONNECTED 0 #define CLSTATE_CONNECTING 1 @@ -132,6 +133,7 @@ void netChat(const char *text); void netServerStageStart(void); void netServerStageEnd(void); +void netServerKick(struct netclient *cl, const u32 reason); void netPlayersAllocate(void); void netSyncIdsAllocate(void); diff --git a/port/include/romdata.h b/port/include/romdata.h index d1d411f1e..4f7fdabff 100644 --- a/port/include/romdata.h +++ b/port/include/romdata.h @@ -5,6 +5,7 @@ extern u8 *g_RomFile; extern u32 g_RomFileSize; +extern const char *g_RomName; s32 romdataInit(void); diff --git a/port/src/net/net.c b/port/src/net/net.c index 65ec8e3a2..446483d86 100644 --- a/port/src/net/net.c +++ b/port/src/net/net.c @@ -239,6 +239,25 @@ static inline void netFlushSendBuffers(void) } } +static inline const char *netGetDisconnectReason(const u32 reason) +{ + static const char *msgs[] = { + "Unknown", + "Server is shutting down", + "Protocol or version mismatch", + "Kicked by console", + "You are banned on this server", + "Connection timed out", + "Server is full", + "The game is already in progress", + "Your files differ from the server's" + }; + if (reason < (u32)ARRAYCOUNT(msgs)) { + return msgs[reason]; + } + return msgs[0]; +} + void netInit(void) { if (enet_initialize() < 0) { @@ -319,6 +338,19 @@ void netServerStageEnd(void) netSend(NULL, &g_NetMsgRel, true, NETCHAN_CONTROL); } +void netServerKick(struct netclient *cl, const u32 reason) +{ + if (g_NetMode != NETMODE_SERVER) { + return; + } + + if (!cl || !cl->state || !cl->peer) { + return; + } + + enet_peer_disconnect(cl->peer, reason); +} + s32 netStartClient(const char *addr) { if (g_NetMode || !g_NetInit) { @@ -405,7 +437,7 @@ s32 netDisconnect(void) g_NetHost = NULL; g_NetMode = NETMODE_NONE; - sysLogPrintf(LOG_NOTE, "NET: disconnected"); + sysLogPrintf(LOG_CHAT, "NET: disconnected"); if (wasingame) { mainEndStage(); @@ -465,7 +497,11 @@ static void netServerEvDisconnect(struct netclient *cl) enet_peer_reset(cl->peer); } - sysLogPrintf(LOG_CHAT, "NET: %s (client %u) disconnected", cl->settings.name, cl->id); + if (cl->settings.name) { + sysLogPrintf(LOG_CHAT, "NET: %s (%u) disconnected", cl->settings.name, cl->id); + } else { + sysLogPrintf(LOG_CHAT, "NET: client %u disconnected", cl->id); + } netClientReset(cl); @@ -509,10 +545,8 @@ static void netClientEvConnect(const u32 data) static void netClientEvDisconnect(const u32 reason) { - sysLogPrintf(LOG_NOTE, "NET: kicked from server, reason: %u", reason); + sysLogPrintf(LOG_CHAT, "NET: disconnected from server: %s (%u)", netGetDisconnectReason(reason), reason); netDisconnect(); - - sysLogPrintf(LOG_CHAT, "NET: disconnected from server"); } static void netClientEvReceive(struct netclient *cl) diff --git a/port/src/net/netmsg.c b/port/src/net/netmsg.c index 029b9ac59..028e3f6b4 100644 --- a/port/src/net/netmsg.c +++ b/port/src/net/netmsg.c @@ -22,6 +22,8 @@ #include "game/modelmgr.h" #include "game/propsnd.h" #include "system.h" +#include "romdata.h" +#include "fs.h" #include "console.h" #include "net/net.h" #include "net/netbuf.h" @@ -141,11 +143,19 @@ static inline s32 propRoomsEqual(const RoomNum *ra, const RoomNum *rb) u32 netmsgClcAuthWrite(struct netbuf *dst) { + const char *modDir = fsGetModDir(); + if (!modDir) { + modDir = ""; + } + netbufWriteU8(dst, CLC_AUTH); + netbufWriteStr(dst, g_RomName); // TODO: use a CRC or something + netbufWriteStr(dst, modDir); netbufWriteU8(dst, 1); // TODO: number of local players netbufWriteU8(dst, g_NetLocalClient->settings.bodynum); netbufWriteU8(dst, g_NetLocalClient->settings.headnum); netbufWriteStr(dst, g_NetLocalClient->settings.name); + return dst->error; } @@ -156,15 +166,35 @@ u32 netmsgClcAuthRead(struct netbuf *src, struct netclient *srccl) return 1; } + const char *romName = netbufReadStr(src); + const char *modDir = netbufReadStr(src); const u8 players = netbufReadU8(src); const u8 bodynum = netbufReadU8(src); const u8 headnum = netbufReadU8(src); char *name = netbufReadStr(src); if (src->error) { sysLogPrintf(LOG_WARNING, "NET: malformed CLC_AUTH from %s", netFormatClientAddr(srccl)); + netServerKick(srccl, DISCONNECT_KICKED); return 1; } + if (strcasecmp(romName, g_RomName) != 0) { + sysLogPrintf(LOG_WARNING, "NET: CLC_AUTH: %s has the wrong ROM, disconnecting", netFormatClientAddr(srccl)); + netServerKick(srccl, DISCONNECT_FILES); + return src->error; + } + + if (modDir[0] == '\0') { + modDir = NULL; + } + + const char *myModDir = fsGetModDir(); + if ((!myModDir != !modDir) || (myModDir && modDir && strcasecmp(modDir, myModDir) != 0)) { + sysLogPrintf(LOG_WARNING, "NET: CLC_AUTH: %s has the wrong mod, disconnecting", netFormatClientAddr(srccl)); + netServerKick(srccl, DISCONNECT_FILES); + return src->error; + } + strncpy(srccl->settings.name, name, sizeof(srccl->settings.name) - 1); srccl->settings.bodynum = bodynum; srccl->settings.headnum = headnum; @@ -176,7 +206,7 @@ u32 netmsgClcAuthRead(struct netbuf *src, struct netclient *srccl) netmsgSvcAuthWrite(&srccl->out, srccl); netSend(srccl, NULL, true, NETCHAN_CONTROL); - sysLogPrintf(LOG_CHAT, "NET: %s (client %u) joined", srccl->settings.name, srccl->id); + sysLogPrintf(LOG_CHAT, "NET: %s (%u) joined", srccl->settings.name, srccl->id); return 0; } diff --git a/port/src/romdata.c b/port/src/romdata.c index effc67e65..d31db357f 100644 --- a/port/src/romdata.c +++ b/port/src/romdata.c @@ -53,10 +53,10 @@ u8 *g_RomFile; u32 g_RomFileSize; +const char *g_RomName = ROMDATA_ROM_NAME; static u8 *romDataSeg; static u32 romDataSegSize; -static const char *romName = ROMDATA_ROM_NAME; enum loadsource { SRC_UNLOADED = 0, @@ -188,12 +188,12 @@ static inline void romdataWrongRomError(const char *fmt, ...) static inline void romdataLoadRom(void) { - sysLogPrintf(LOG_NOTE, "ROM file: %s", romName); + sysLogPrintf(LOG_NOTE, "ROM file: %s", g_RomName); - g_RomFile = fsFileLoad(romName, &g_RomFileSize); + g_RomFile = fsFileLoad(g_RomName, &g_RomFileSize); if (!g_RomFile) { - sysFatalError("Could not open ROM file %s.\nEnsure that it is in the %s directory.", romName, fsFullPath("")); + sysFatalError("Could not open ROM file %s.\nEnsure that it is in the %s directory.", g_RomName, fsFullPath("")); } // zips are not guaranteed to start with PK, but might as well at least try @@ -368,7 +368,7 @@ s32 romdataInit(void) { const char *altRomName = sysArgGetString("--rom-file"); if (altRomName) { - romName = altRomName; + g_RomName = altRomName; } romdataLoadRom();