mirror of
https://github.com/melonDS-emu/melonDS.git
synced 2025-07-25 07:10:00 -06:00
start encapsulating LAN
This commit is contained in:
211
src/net/LAN.cpp
211
src/net/LAN.cpp
@ -45,14 +45,13 @@
|
|||||||
#define INVALID_SOCKET (socket_t)-1
|
#define INVALID_SOCKET (socket_t)-1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <enet/enet.h>
|
// REMOVEME REMOVEME REMOVEME
|
||||||
#include <SDL2/SDL.h>
|
#include <SDL2/SDL.h>
|
||||||
|
|
||||||
#include "LAN.h"
|
#include "LAN.h"
|
||||||
|
|
||||||
using namespace melonDS;
|
|
||||||
|
|
||||||
namespace LAN
|
namespace melonDS
|
||||||
{
|
{
|
||||||
|
|
||||||
const u32 kDiscoveryMagic = 0x444E414C; // LAND
|
const u32 kDiscoveryMagic = 0x444E414C; // LAND
|
||||||
@ -61,6 +60,8 @@ const u32 kPacketMagic = 0x4946494E; // NIFI
|
|||||||
|
|
||||||
const u32 kProtocolVersion = 1;
|
const u32 kProtocolVersion = 1;
|
||||||
|
|
||||||
|
const u32 kLocalhost = 0x0100007F;
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
Chan_Cmd = 0, // channel 0 -- control commands
|
Chan_Cmd = 0, // channel 0 -- control commands
|
||||||
@ -76,51 +77,14 @@ enum
|
|||||||
Cmd_PlayerDisconnect, // 05 -- both -- signal disconnected state (not receiving MP frames)
|
Cmd_PlayerDisconnect, // 05 -- both -- signal disconnected state (not receiving MP frames)
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MPPacketHeader
|
|
||||||
{
|
|
||||||
u32 Magic;
|
|
||||||
u32 SenderID;
|
|
||||||
u32 Type; // 0=regular 1=CMD 2=reply 3=ack
|
|
||||||
u32 Length;
|
|
||||||
u64 Timestamp;
|
|
||||||
};
|
|
||||||
|
|
||||||
const int kDiscoveryPort = 7063;
|
const int kDiscoveryPort = 7063;
|
||||||
const int kLANPort = 7064;
|
const int kLANPort = 7064;
|
||||||
|
|
||||||
socket_t DiscoverySocket;
|
|
||||||
u32 DiscoveryLastTick;
|
|
||||||
std::map<u32, DiscoveryData> DiscoveryList;
|
|
||||||
Platform::Mutex* DiscoveryMutex = nullptr;
|
|
||||||
|
|
||||||
bool Active;
|
LAN::LAN() noexcept : Inited(false)
|
||||||
bool IsHost;
|
|
||||||
|
|
||||||
ENetHost* Host;
|
|
||||||
ENetPeer* RemotePeers[16];
|
|
||||||
|
|
||||||
Player Players[16];
|
|
||||||
u32 PlayerPing[16];
|
|
||||||
int NumPlayers;
|
|
||||||
int MaxPlayers;
|
|
||||||
|
|
||||||
u16 ConnectedBitmask;
|
|
||||||
|
|
||||||
Player MyPlayer;
|
|
||||||
u32 HostAddress;
|
|
||||||
bool Lag;
|
|
||||||
|
|
||||||
int MPRecvTimeout;
|
|
||||||
int LastHostID;
|
|
||||||
ENetPeer* LastHostPeer;
|
|
||||||
std::queue<ENetPacket*> RXQueue;
|
|
||||||
|
|
||||||
u32 FrameCount;
|
|
||||||
|
|
||||||
|
|
||||||
bool Init()
|
|
||||||
{
|
{
|
||||||
DiscoveryMutex = Platform::Mutex_Create();
|
DiscoveryMutex = Platform::Mutex_Create();
|
||||||
|
PlayersMutex = Platform::Mutex_Create();
|
||||||
|
|
||||||
DiscoverySocket = INVALID_SOCKET;
|
DiscoverySocket = INVALID_SOCKET;
|
||||||
DiscoveryLastTick = 0;
|
DiscoveryLastTick = 0;
|
||||||
@ -128,7 +92,7 @@ bool Init()
|
|||||||
Active = false;
|
Active = false;
|
||||||
IsHost = false;
|
IsHost = false;
|
||||||
Host = nullptr;
|
Host = nullptr;
|
||||||
Lag = false;
|
//Lag = false;
|
||||||
|
|
||||||
memset(RemotePeers, 0, sizeof(RemotePeers));
|
memset(RemotePeers, 0, sizeof(RemotePeers));
|
||||||
memset(Players, 0, sizeof(Players));
|
memset(Players, 0, sizeof(Players));
|
||||||
@ -144,19 +108,18 @@ bool Init()
|
|||||||
|
|
||||||
FrameCount = 0;
|
FrameCount = 0;
|
||||||
|
|
||||||
// TODO we init enet here but also in Netplay
|
// TODO make this somewhat nicer
|
||||||
// that is redundant
|
|
||||||
if (enet_initialize() != 0)
|
if (enet_initialize() != 0)
|
||||||
{
|
{
|
||||||
printf("enet shat itself :(\n");
|
printf("enet shat itself :(\n");
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("enet init OK\n");
|
printf("enet init OK\n");
|
||||||
return true;
|
Inited = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeInit()
|
LAN::~LAN() noexcept
|
||||||
{
|
{
|
||||||
if (DiscoverySocket)
|
if (DiscoverySocket)
|
||||||
{
|
{
|
||||||
@ -187,12 +150,46 @@ void DeInit()
|
|||||||
enet_deinitialize();
|
enet_deinitialize();
|
||||||
|
|
||||||
Platform::Mutex_Free(DiscoveryMutex);
|
Platform::Mutex_Free(DiscoveryMutex);
|
||||||
DiscoveryMutex = nullptr;
|
Platform::Mutex_Free(PlayersMutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool StartDiscovery()
|
std::map<u32, LAN::DiscoveryData> LAN::GetDiscoveryList()
|
||||||
{
|
{
|
||||||
|
Platform::Mutex_Lock(DiscoveryMutex);
|
||||||
|
auto ret = DiscoveryList;
|
||||||
|
Platform::Mutex_Unlock(DiscoveryMutex);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<LAN::Player> LAN::GetPlayerList()
|
||||||
|
{
|
||||||
|
Platform::Mutex_Lock(PlayersMutex);
|
||||||
|
|
||||||
|
std::vector<Player> ret;
|
||||||
|
for (int i = 0; i < 16; i++)
|
||||||
|
{
|
||||||
|
if (Players[i].Status == Player_None) continue;
|
||||||
|
|
||||||
|
// make a copy of the player entry, fix up the address field
|
||||||
|
Player newp = Players[i];
|
||||||
|
if (newp.ID == MyPlayer.ID)
|
||||||
|
newp.Address = kLocalhost;
|
||||||
|
else if (newp.Status == Player_Host)
|
||||||
|
newp.Address = HostAddress;
|
||||||
|
|
||||||
|
ret.push_back(newp);
|
||||||
|
}
|
||||||
|
|
||||||
|
Platform::Mutex_Unlock(PlayersMutex);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool LAN::StartDiscovery()
|
||||||
|
{
|
||||||
|
if (!Inited) return false;
|
||||||
|
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
DiscoverySocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
DiscoverySocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||||
@ -231,8 +228,10 @@ bool StartDiscovery()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EndDiscovery()
|
void LAN::EndDiscovery()
|
||||||
{
|
{
|
||||||
|
if (!Inited) return;
|
||||||
|
|
||||||
if (DiscoverySocket != INVALID_SOCKET)
|
if (DiscoverySocket != INVALID_SOCKET)
|
||||||
{
|
{
|
||||||
closesocket(DiscoverySocket);
|
closesocket(DiscoverySocket);
|
||||||
@ -243,8 +242,11 @@ void EndDiscovery()
|
|||||||
Active = false;
|
Active = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StartHost(const char* playername, int numplayers)
|
bool LAN::StartHost(const char* playername, int numplayers)
|
||||||
{
|
{
|
||||||
|
if (!Inited) return false;
|
||||||
|
if (numplayers > 16) return false;
|
||||||
|
|
||||||
ENetAddress addr;
|
ENetAddress addr;
|
||||||
addr.host = ENET_HOST_ANY;
|
addr.host = ENET_HOST_ANY;
|
||||||
addr.port = kLANPort;
|
addr.port = kLANPort;
|
||||||
@ -255,17 +257,21 @@ bool StartHost(const char* playername, int numplayers)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Platform::Mutex_Lock(PlayersMutex);
|
||||||
|
|
||||||
Player* player = &Players[0];
|
Player* player = &Players[0];
|
||||||
memset(player, 0, sizeof(Player));
|
memset(player, 0, sizeof(Player));
|
||||||
player->ID = 0;
|
player->ID = 0;
|
||||||
strncpy(player->Name, playername, 31);
|
strncpy(player->Name, playername, 31);
|
||||||
player->Status = Player_Host;
|
player->Status = Player_Host;
|
||||||
player->Address = 0x0100007F;
|
player->Address = kLocalhost;
|
||||||
NumPlayers = 1;
|
NumPlayers = 1;
|
||||||
MaxPlayers = numplayers;
|
MaxPlayers = numplayers;
|
||||||
memcpy(&MyPlayer, player, sizeof(Player));
|
memcpy(&MyPlayer, player, sizeof(Player));
|
||||||
|
|
||||||
HostAddress = 0x0100007F;
|
Platform::Mutex_Unlock(PlayersMutex);
|
||||||
|
|
||||||
|
HostAddress = kLocalhost;
|
||||||
LastHostID = -1;
|
LastHostID = -1;
|
||||||
LastHostPeer = nullptr;
|
LastHostPeer = nullptr;
|
||||||
|
|
||||||
@ -279,8 +285,10 @@ bool StartHost(const char* playername, int numplayers)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StartClient(const char* playername, const char* host)
|
bool LAN::StartClient(const char* playername, const char* host)
|
||||||
{
|
{
|
||||||
|
if (!Inited) return false;
|
||||||
|
|
||||||
Host = enet_host_create(nullptr, 16, 2, 0, 0);
|
Host = enet_host_create(nullptr, 16, 2, 0, 0);
|
||||||
if (!Host)
|
if (!Host)
|
||||||
{
|
{
|
||||||
@ -298,12 +306,16 @@ bool StartClient(const char* playername, const char* host)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Platform::Mutex_Lock(PlayersMutex);
|
||||||
|
|
||||||
Player* player = &MyPlayer;
|
Player* player = &MyPlayer;
|
||||||
memset(player, 0, sizeof(Player));
|
memset(player, 0, sizeof(Player));
|
||||||
player->ID = 0;
|
player->ID = 0;
|
||||||
strncpy(player->Name, playername, 31);
|
strncpy(player->Name, playername, 31);
|
||||||
player->Status = Player_Connecting;
|
player->Status = Player_Connecting;
|
||||||
|
|
||||||
|
Platform::Mutex_Unlock(PlayersMutex);
|
||||||
|
|
||||||
ENetEvent event;
|
ENetEvent event;
|
||||||
int conn = 0;
|
int conn = 0;
|
||||||
u32 starttick = SDL_GetTicks();
|
u32 starttick = SDL_GetTicks();
|
||||||
@ -331,6 +343,7 @@ bool StartClient(const char* playername, const char* host)
|
|||||||
u32 version = data[5] | (data[6] << 8) | (data[7] << 16) | (data[8] << 24);
|
u32 version = data[5] | (data[6] << 8) | (data[7] << 16) | (data[8] << 24);
|
||||||
if (magic != kLANMagic) continue;
|
if (magic != kLANMagic) continue;
|
||||||
if (version != kProtocolVersion) continue;
|
if (version != kProtocolVersion) continue;
|
||||||
|
if (data[10] > 16) continue;
|
||||||
|
|
||||||
MaxPlayers = data[10];
|
MaxPlayers = data[10];
|
||||||
|
|
||||||
@ -383,7 +396,7 @@ bool StartClient(const char* playername, const char* host)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void ProcessDiscovery()
|
void LAN::ProcessDiscovery()
|
||||||
{
|
{
|
||||||
if (DiscoverySocket == INVALID_SOCKET)
|
if (DiscoverySocket == INVALID_SOCKET)
|
||||||
return;
|
return;
|
||||||
@ -473,15 +486,10 @@ void ProcessDiscovery()
|
|||||||
}
|
}
|
||||||
|
|
||||||
Platform::Mutex_Unlock(DiscoveryMutex);
|
Platform::Mutex_Unlock(DiscoveryMutex);
|
||||||
|
|
||||||
// update the list in the connect dialog if needed
|
|
||||||
|
|
||||||
//if (lanClientDlg)
|
|
||||||
// lanClientDlg->updateDiscoveryList();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void HostUpdatePlayerList()
|
void LAN::HostUpdatePlayerList()
|
||||||
{
|
{
|
||||||
u8 cmd[2+sizeof(Players)];
|
u8 cmd[2+sizeof(Players)];
|
||||||
cmd[0] = Cmd_PlayerList;
|
cmd[0] = Cmd_PlayerList;
|
||||||
@ -489,18 +497,13 @@ void HostUpdatePlayerList()
|
|||||||
memcpy(&cmd[2], Players, sizeof(Players));
|
memcpy(&cmd[2], Players, sizeof(Players));
|
||||||
ENetPacket* pkt = enet_packet_create(cmd, 2+sizeof(Players), ENET_PACKET_FLAG_RELIABLE);
|
ENetPacket* pkt = enet_packet_create(cmd, 2+sizeof(Players), ENET_PACKET_FLAG_RELIABLE);
|
||||||
enet_host_broadcast(Host, Chan_Cmd, pkt);
|
enet_host_broadcast(Host, Chan_Cmd, pkt);
|
||||||
|
|
||||||
//if (lanDlg)
|
|
||||||
// lanDlg->updatePlayerList();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClientUpdatePlayerList()
|
void LAN::ClientUpdatePlayerList()
|
||||||
{
|
{
|
||||||
//if (lanDlg)
|
|
||||||
// lanDlg->updatePlayerList();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProcessHostEvent(ENetEvent& event)
|
void LAN::ProcessHostEvent(ENetEvent& event)
|
||||||
{
|
{
|
||||||
switch (event.type)
|
switch (event.type)
|
||||||
{
|
{
|
||||||
@ -539,12 +542,16 @@ void ProcessHostEvent(ENetEvent& event)
|
|||||||
ENetPacket* pkt = enet_packet_create(cmd, 11, ENET_PACKET_FLAG_RELIABLE);
|
ENetPacket* pkt = enet_packet_create(cmd, 11, ENET_PACKET_FLAG_RELIABLE);
|
||||||
enet_peer_send(event.peer, Chan_Cmd, pkt);
|
enet_peer_send(event.peer, Chan_Cmd, pkt);
|
||||||
|
|
||||||
|
Platform::Mutex_Lock(PlayersMutex);
|
||||||
|
|
||||||
Players[id].ID = id;
|
Players[id].ID = id;
|
||||||
Players[id].Status = Player_Connecting;
|
Players[id].Status = Player_Connecting;
|
||||||
Players[id].Address = event.peer->address.host;
|
Players[id].Address = event.peer->address.host;
|
||||||
event.peer->data = &Players[id];
|
event.peer->data = &Players[id];
|
||||||
NumPlayers++;
|
NumPlayers++;
|
||||||
|
|
||||||
|
Platform::Mutex_Unlock(PlayersMutex);
|
||||||
|
|
||||||
RemotePeers[id] = event.peer;
|
RemotePeers[id] = event.peer;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -604,10 +611,14 @@ void ProcessHostEvent(ENetEvent& event)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Platform::Mutex_Lock(PlayersMutex);
|
||||||
|
|
||||||
player.Status = Player_Client;
|
player.Status = Player_Client;
|
||||||
player.Address = event.peer->address.host;
|
player.Address = event.peer->address.host;
|
||||||
memcpy(hostside, &player, sizeof(Player));
|
memcpy(hostside, &player, sizeof(Player));
|
||||||
|
|
||||||
|
Platform::Mutex_Unlock(PlayersMutex);
|
||||||
|
|
||||||
// broadcast updated player list
|
// broadcast updated player list
|
||||||
HostUpdatePlayerList();
|
HostUpdatePlayerList();
|
||||||
}
|
}
|
||||||
@ -642,7 +653,7 @@ void ProcessHostEvent(ENetEvent& event)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProcessClientEvent(ENetEvent& event)
|
void LAN::ProcessClientEvent(ENetEvent& event)
|
||||||
{
|
{
|
||||||
switch (event.type)
|
switch (event.type)
|
||||||
{
|
{
|
||||||
@ -685,7 +696,9 @@ void ProcessClientEvent(ENetEvent& event)
|
|||||||
int id = player->ID;
|
int id = player->ID;
|
||||||
RemotePeers[id] = nullptr;
|
RemotePeers[id] = nullptr;
|
||||||
|
|
||||||
|
Platform::Mutex_Lock(PlayersMutex);
|
||||||
player->Status = Player_Disconnected;
|
player->Status = Player_Disconnected;
|
||||||
|
Platform::Mutex_Unlock(PlayersMutex);
|
||||||
|
|
||||||
ClientUpdatePlayerList();
|
ClientUpdatePlayerList();
|
||||||
}
|
}
|
||||||
@ -703,6 +716,8 @@ void ProcessClientEvent(ENetEvent& event)
|
|||||||
if (event.packet->dataLength != (2+sizeof(Players))) break;
|
if (event.packet->dataLength != (2+sizeof(Players))) break;
|
||||||
if (data[1] > 16) break;
|
if (data[1] > 16) break;
|
||||||
|
|
||||||
|
Platform::Mutex_Lock(PlayersMutex);
|
||||||
|
|
||||||
NumPlayers = data[1];
|
NumPlayers = data[1];
|
||||||
memcpy(Players, &data[2], sizeof(Players));
|
memcpy(Players, &data[2], sizeof(Players));
|
||||||
for (int i = 0; i < 16; i++)
|
for (int i = 0; i < 16; i++)
|
||||||
@ -710,8 +725,7 @@ void ProcessClientEvent(ENetEvent& event)
|
|||||||
Players[i].Name[31] = '\0';
|
Players[i].Name[31] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
//if (lanDlg)
|
Platform::Mutex_Unlock(PlayersMutex);
|
||||||
// lanDlg->updatePlayerList();
|
|
||||||
|
|
||||||
// establish connections to any new clients
|
// establish connections to any new clients
|
||||||
for (int i = 0; i < 16; i++)
|
for (int i = 0; i < 16; i++)
|
||||||
@ -765,7 +779,7 @@ void ProcessClientEvent(ENetEvent& event)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProcessEvent(ENetEvent& event)
|
void LAN::ProcessEvent(ENetEvent& event)
|
||||||
{
|
{
|
||||||
if (IsHost)
|
if (IsHost)
|
||||||
ProcessHostEvent(event);
|
ProcessHostEvent(event);
|
||||||
@ -776,7 +790,7 @@ void ProcessEvent(ENetEvent& event)
|
|||||||
// 0 = per-frame processing of events and eventual misc. frame
|
// 0 = per-frame processing of events and eventual misc. frame
|
||||||
// 1 = checking if a misc. frame has arrived
|
// 1 = checking if a misc. frame has arrived
|
||||||
// 2 = waiting for a MP frame
|
// 2 = waiting for a MP frame
|
||||||
void Process(int type)
|
void LAN::ProcessLAN(int type)
|
||||||
{
|
{
|
||||||
if (!Host) return;
|
if (!Host) return;
|
||||||
//printf("Process(%d): %d %d\n", type, RXQueue.empty(), RXQueue.size());
|
//printf("Process(%d): %d %d\n", type, RXQueue.empty(), RXQueue.size());
|
||||||
@ -868,10 +882,12 @@ void Process(int type)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProcessFrame()
|
void LAN::Process()
|
||||||
{
|
{
|
||||||
|
if (!Active) return;
|
||||||
|
|
||||||
ProcessDiscovery();
|
ProcessDiscovery();
|
||||||
Process(0);
|
ProcessLAN(0);
|
||||||
|
|
||||||
FrameCount++;
|
FrameCount++;
|
||||||
if (FrameCount >= 60)
|
if (FrameCount >= 60)
|
||||||
@ -893,12 +909,7 @@ void ProcessFrame()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void SetMPRecvTimeout(int timeout)
|
void LAN::Begin(int inst)
|
||||||
{
|
|
||||||
MPRecvTimeout = timeout;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MPBegin()
|
|
||||||
{
|
{
|
||||||
if (!Host) return;
|
if (!Host) return;
|
||||||
|
|
||||||
@ -911,7 +922,7 @@ void MPBegin()
|
|||||||
enet_host_broadcast(Host, Chan_Cmd, pkt);
|
enet_host_broadcast(Host, Chan_Cmd, pkt);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MPEnd()
|
void LAN::End(int inst)
|
||||||
{
|
{
|
||||||
if (!Host) return;
|
if (!Host) return;
|
||||||
|
|
||||||
@ -923,7 +934,7 @@ void MPEnd()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int SendMPPacketGeneric(u32 type, u8* packet, int len, u64 timestamp)
|
int LAN::SendPacketGeneric(u32 type, u8* packet, int len, u64 timestamp)
|
||||||
{
|
{
|
||||||
if (!Host) return 0;
|
if (!Host) return 0;
|
||||||
|
|
||||||
@ -952,11 +963,11 @@ int SendMPPacketGeneric(u32 type, u8* packet, int len, u64 timestamp)
|
|||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
int RecvMPPacketGeneric(u8* packet, bool block, u64* timestamp)
|
int LAN::RecvPacketGeneric(u8* packet, bool block, u64* timestamp)
|
||||||
{
|
{
|
||||||
if (!Host) return 0;
|
if (!Host) return 0;
|
||||||
|
|
||||||
Process(block ? 2 : 1);
|
ProcessLAN(block ? 2 : 1);
|
||||||
if (RXQueue.empty()) return 0;
|
if (RXQueue.empty()) return 0;
|
||||||
|
|
||||||
ENetPacket* enetpacket = RXQueue.front();
|
ENetPacket* enetpacket = RXQueue.front();
|
||||||
@ -983,33 +994,33 @@ int RecvMPPacketGeneric(u8* packet, bool block, u64* timestamp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int SendMPPacket(u8* packet, int len, u64 timestamp)
|
int LAN::SendPacket(int inst, u8* packet, int len, u64 timestamp)
|
||||||
{
|
{
|
||||||
return SendMPPacketGeneric(0, packet, len, timestamp);
|
return SendPacketGeneric(0, packet, len, timestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
int RecvMPPacket(u8* packet, u64* timestamp)
|
int LAN::RecvPacket(int inst, u8* packet, u64* timestamp)
|
||||||
{
|
{
|
||||||
return RecvMPPacketGeneric(packet, false, timestamp);
|
return RecvPacketGeneric(packet, false, timestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int SendMPCmd(u8* packet, int len, u64 timestamp)
|
int LAN::SendCmd(int inst, u8* packet, int len, u64 timestamp)
|
||||||
{
|
{
|
||||||
return SendMPPacketGeneric(1, packet, len, timestamp);
|
return SendPacketGeneric(1, packet, len, timestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
int SendMPReply(u8* packet, int len, u64 timestamp, u16 aid)
|
int LAN::SendReply(int inst, u8* packet, int len, u64 timestamp, u16 aid)
|
||||||
{
|
{
|
||||||
return SendMPPacketGeneric(2 | (aid<<16), packet, len, timestamp);
|
return SendPacketGeneric(2 | (aid<<16), packet, len, timestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
int SendMPAck(u8* packet, int len, u64 timestamp)
|
int LAN::SendAck(int inst, u8* packet, int len, u64 timestamp)
|
||||||
{
|
{
|
||||||
return SendMPPacketGeneric(3, packet, len, timestamp);
|
return SendPacketGeneric(3, packet, len, timestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
int RecvMPHostPacket(u8* packet, u64* timestamp)
|
int LAN::RecvHostPacket(int inst, u8* packet, u64* timestamp)
|
||||||
{
|
{
|
||||||
if (LastHostID != -1)
|
if (LastHostID != -1)
|
||||||
{
|
{
|
||||||
@ -1019,10 +1030,10 @@ int RecvMPHostPacket(u8* packet, u64* timestamp)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return RecvMPPacketGeneric(packet, true, timestamp);
|
return RecvPacketGeneric(packet, true, timestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
u16 RecvMPReplies(u8* packets, u64 timestamp, u16 aidmask)
|
u16 LAN::RecvReplies(int inst, u8* packets, u64 timestamp, u16 aidmask)
|
||||||
{
|
{
|
||||||
if (!Host) return 0;
|
if (!Host) return 0;
|
||||||
|
|
||||||
@ -1034,7 +1045,7 @@ u16 RecvMPReplies(u8* packets, u64 timestamp, u16 aidmask)
|
|||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
Process(2);
|
ProcessLAN(2);
|
||||||
if (RXQueue.empty())
|
if (RXQueue.empty())
|
||||||
{
|
{
|
||||||
// no more replies available
|
// no more replies available
|
||||||
|
177
src/net/LAN.h
177
src/net/LAN.h
@ -22,77 +22,128 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
|
#include <enet/enet.h>
|
||||||
|
|
||||||
|
#ifndef socket_t
|
||||||
|
#ifdef __WIN32__
|
||||||
|
#include <winsock2.h>
|
||||||
|
#define socket_t SOCKET
|
||||||
|
#else
|
||||||
|
#define socket_t int
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "Platform.h"
|
#include "Platform.h"
|
||||||
|
#include "MPInterface.h"
|
||||||
|
|
||||||
namespace LAN
|
namespace melonDS
|
||||||
{
|
{
|
||||||
using namespace melonDS;
|
|
||||||
|
|
||||||
enum PlayerStatus
|
class LAN : public MPInterface
|
||||||
{
|
{
|
||||||
Player_None = 0, // no player in this entry
|
public:
|
||||||
Player_Client, // game client
|
LAN() noexcept;
|
||||||
Player_Host, // game host
|
LAN(const LAN&) = delete;
|
||||||
Player_Connecting, // player still connecting
|
LAN& operator=(const LAN&) = delete;
|
||||||
Player_Disconnected, // player disconnected
|
LAN(LAN&& other) = delete;
|
||||||
|
LAN& operator=(LAN&& other) = delete;
|
||||||
|
~LAN() noexcept;
|
||||||
|
|
||||||
|
enum PlayerStatus
|
||||||
|
{
|
||||||
|
Player_None = 0, // no player in this entry
|
||||||
|
Player_Client, // game client
|
||||||
|
Player_Host, // game host
|
||||||
|
Player_Connecting, // player still connecting
|
||||||
|
Player_Disconnected, // player disconnected
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Player
|
||||||
|
{
|
||||||
|
int ID;
|
||||||
|
char Name[32];
|
||||||
|
PlayerStatus Status;
|
||||||
|
u32 Address;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DiscoveryData
|
||||||
|
{
|
||||||
|
u32 Magic;
|
||||||
|
u32 Version;
|
||||||
|
u32 Tick;
|
||||||
|
char SessionName[64];
|
||||||
|
u8 NumPlayers;
|
||||||
|
u8 MaxPlayers;
|
||||||
|
u8 Status; // 0=idle 1=playing
|
||||||
|
};
|
||||||
|
|
||||||
|
bool StartDiscovery();
|
||||||
|
void EndDiscovery();
|
||||||
|
bool StartHost(const char* player, int numplayers);
|
||||||
|
bool StartClient(const char* player, const char* host);
|
||||||
|
|
||||||
|
std::map<u32, DiscoveryData> GetDiscoveryList();
|
||||||
|
std::vector<Player> GetPlayerList();
|
||||||
|
|
||||||
|
void Process() override;
|
||||||
|
|
||||||
|
void Begin(int inst) override;
|
||||||
|
void End(int inst) override;
|
||||||
|
|
||||||
|
int SendPacket(int inst, u8* data, int len, u64 timestamp) override;
|
||||||
|
int RecvPacket(int inst, u8* data, u64* timestamp) override;
|
||||||
|
int SendCmd(int inst, u8* data, int len, u64 timestamp) override;
|
||||||
|
int SendReply(int inst, u8* data, int len, u64 timestamp, u16 aid) override;
|
||||||
|
int SendAck(int inst, u8* data, int len, u64 timestamp) override;
|
||||||
|
int RecvHostPacket(int inst, u8* data, u64* timestamp) override;
|
||||||
|
u16 RecvReplies(int inst, u8* data, u64 timestamp, u16 aidmask) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool Inited;
|
||||||
|
bool Active;
|
||||||
|
bool IsHost;
|
||||||
|
|
||||||
|
ENetHost* Host;
|
||||||
|
ENetPeer* RemotePeers[16];
|
||||||
|
|
||||||
|
socket_t DiscoverySocket;
|
||||||
|
u32 DiscoveryLastTick;
|
||||||
|
std::map<u32, DiscoveryData> DiscoveryList;
|
||||||
|
Platform::Mutex* DiscoveryMutex;
|
||||||
|
|
||||||
|
Player Players[16];
|
||||||
|
u32 PlayerPing[16];
|
||||||
|
int NumPlayers;
|
||||||
|
int MaxPlayers;
|
||||||
|
Platform::Mutex* PlayersMutex;
|
||||||
|
|
||||||
|
Player MyPlayer;
|
||||||
|
u32 HostAddress;
|
||||||
|
|
||||||
|
u16 ConnectedBitmask;
|
||||||
|
|
||||||
|
int MPRecvTimeout;
|
||||||
|
int LastHostID;
|
||||||
|
ENetPeer* LastHostPeer;
|
||||||
|
std::queue<ENetPacket*> RXQueue;
|
||||||
|
|
||||||
|
u32 FrameCount;
|
||||||
|
|
||||||
|
void ProcessDiscovery();
|
||||||
|
|
||||||
|
void HostUpdatePlayerList();
|
||||||
|
void ClientUpdatePlayerList();
|
||||||
|
|
||||||
|
void ProcessHostEvent(ENetEvent& event);
|
||||||
|
void ProcessClientEvent(ENetEvent& event);
|
||||||
|
void ProcessEvent(ENetEvent& event);
|
||||||
|
void ProcessLAN(int type);
|
||||||
|
|
||||||
|
int SendPacketGeneric(u32 type, u8* packet, int len, u64 timestamp);
|
||||||
|
int RecvPacketGeneric(u8* packet, bool block, u64* timestamp);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Player
|
|
||||||
{
|
|
||||||
int ID;
|
|
||||||
char Name[32];
|
|
||||||
PlayerStatus Status;
|
|
||||||
u32 Address;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct DiscoveryData
|
|
||||||
{
|
|
||||||
u32 Magic;
|
|
||||||
u32 Version;
|
|
||||||
u32 Tick;
|
|
||||||
char SessionName[64];
|
|
||||||
u8 NumPlayers;
|
|
||||||
u8 MaxPlayers;
|
|
||||||
u8 Status; // 0=idle 1=playing
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
extern bool Active;
|
|
||||||
|
|
||||||
extern std::map<u32, DiscoveryData> DiscoveryList;
|
|
||||||
extern Platform::Mutex* DiscoveryMutex; // TODO: turn into Platform::Mutex or rework this to be nicer
|
|
||||||
|
|
||||||
extern Player Players[16];
|
|
||||||
extern u32 PlayerPing[16];
|
|
||||||
extern int NumPlayers;
|
|
||||||
extern int MaxPlayers;
|
|
||||||
|
|
||||||
extern Player MyPlayer;
|
|
||||||
extern u32 HostAddress;
|
|
||||||
|
|
||||||
bool Init();
|
|
||||||
void DeInit();
|
|
||||||
|
|
||||||
bool StartDiscovery();
|
|
||||||
void EndDiscovery();
|
|
||||||
bool StartHost(const char* player, int numplayers);
|
|
||||||
bool StartClient(const char* player, const char* host);
|
|
||||||
|
|
||||||
void ProcessFrame();
|
|
||||||
|
|
||||||
void SetMPRecvTimeout(int timeout);
|
|
||||||
void MPBegin();
|
|
||||||
void MPEnd();
|
|
||||||
|
|
||||||
int SendMPPacket(u8* data, int len, u64 timestamp);
|
|
||||||
int RecvMPPacket(u8* data, u64* timestamp);
|
|
||||||
int SendMPCmd(u8* data, int len, u64 timestamp);
|
|
||||||
int SendMPReply(u8* data, int len, u64 timestamp, u16 aid);
|
|
||||||
int SendMPAck(u8* data, int len, u64 timestamp);
|
|
||||||
int RecvMPHostPacket(u8* data, u64* timestamp);
|
|
||||||
u16 RecvMPReplies(u8* data, u64 timestamp, u16 aidmask);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // LAN_H
|
#endif // LAN_H
|
||||||
|
@ -34,15 +34,6 @@ struct MPStatusData
|
|||||||
u16 MPReplyBitmask; // bitmask of which clients replied in time
|
u16 MPReplyBitmask; // bitmask of which clients replied in time
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MPPacketHeader
|
|
||||||
{
|
|
||||||
u32 Magic;
|
|
||||||
u32 SenderID;
|
|
||||||
u32 Type; // 0=regular 1=CMD 2=reply 3=ack
|
|
||||||
u32 Length;
|
|
||||||
u64 Timestamp;
|
|
||||||
};
|
|
||||||
|
|
||||||
constexpr u32 kPacketQueueSize = 0x10000;
|
constexpr u32 kPacketQueueSize = 0x10000;
|
||||||
constexpr u32 kReplyQueueSize = 0x10000;
|
constexpr u32 kReplyQueueSize = 0x10000;
|
||||||
constexpr u32 kMaxFrameSize = 0x948;
|
constexpr u32 kMaxFrameSize = 0x948;
|
||||||
|
@ -34,6 +34,15 @@ enum MPInterfaceType
|
|||||||
MPInterface_Netplay,
|
MPInterface_Netplay,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct MPPacketHeader
|
||||||
|
{
|
||||||
|
u32 Magic;
|
||||||
|
u32 SenderID;
|
||||||
|
u32 Type; // 0=regular 1=CMD 2=reply 3=ack
|
||||||
|
u32 Length;
|
||||||
|
u64 Timestamp;
|
||||||
|
};
|
||||||
|
|
||||||
class MPInterface
|
class MPInterface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
Reference in New Issue
Block a user