forked from cafeberry/cafeberry
update lcemp networking
This commit is contained in:
@@ -39,7 +39,7 @@ BYTE NetworkSocketLayer::s_nextSmallId = 1;
|
||||
CRITICAL_SECTION NetworkSocketLayer::s_sendLock;
|
||||
CRITICAL_SECTION NetworkSocketLayer::s_connectionsLock;
|
||||
|
||||
std::vector<RemoteConnection> NetworkSocketLayer::s_connections;
|
||||
RemoteConnection NetworkSocketLayer::s_connections[NETWORK_LAN_MAX_CLIENTS + 1];
|
||||
|
||||
C4JThread* NetworkSocketLayer::s_advertiseThread = NULL;
|
||||
volatile bool NetworkSocketLayer::s_advertising = false;
|
||||
@@ -55,6 +55,9 @@ std::vector<LANSession> NetworkSocketLayer::s_discoveredSessions;
|
||||
CRITICAL_SECTION NetworkSocketLayer::s_disconnectLock;
|
||||
std::vector<BYTE> NetworkSocketLayer::s_disconnectedSmallIds;
|
||||
|
||||
CRITICAL_SECTION NetworkSocketLayer::s_pendingJoinLock;
|
||||
std::vector<BYTE> NetworkSocketLayer::s_pendingJoinSmallIds;
|
||||
|
||||
CRITICAL_SECTION NetworkSocketLayer::s_freeSmallIdLock;
|
||||
std::vector<BYTE> NetworkSocketLayer::s_freeSmallIds;
|
||||
|
||||
@@ -83,7 +86,17 @@ bool NetworkSocketLayer::Initialize()
|
||||
InitializeCriticalSection(&s_advertiseLock);
|
||||
InitializeCriticalSection(&s_discoveryLock);
|
||||
InitializeCriticalSection(&s_disconnectLock);
|
||||
InitializeCriticalSection(&s_pendingJoinLock);
|
||||
InitializeCriticalSection(&s_freeSmallIdLock);
|
||||
|
||||
for (int i = 0; i < NETWORK_LAN_MAX_CLIENTS + 1; i++)
|
||||
{
|
||||
s_connections[i].tcpSocket = INVALID_SOCKET;
|
||||
s_connections[i].smallId = 0;
|
||||
s_connections[i].recvThread = NULL;
|
||||
s_connections[i].active = false;
|
||||
InitializeCriticalSection(&s_connections[i].sendLock);
|
||||
}
|
||||
s_locksCreated = true;
|
||||
}
|
||||
|
||||
@@ -167,7 +180,7 @@ void NetworkSocketLayer::Shutdown()
|
||||
|
||||
EnterCriticalSection(&s_connectionsLock);
|
||||
|
||||
for (size_t i = 0; i < s_connections.size(); i++)
|
||||
for (int i = 0; i < NETWORK_LAN_MAX_CLIENTS + 1; i++)
|
||||
{
|
||||
s_connections[i].active = false;
|
||||
#if defined _WINDOWS64 || defined _XBOX
|
||||
@@ -177,9 +190,16 @@ void NetworkSocketLayer::Shutdown()
|
||||
#endif
|
||||
{
|
||||
closesocket(s_connections[i].tcpSocket);
|
||||
s_connections[i].tcpSocket = INVALID_SOCKET;
|
||||
}
|
||||
if (s_connections[i].recvThread != NULL)
|
||||
{
|
||||
s_connections[i].recvThread->WaitForCompletion(2000);
|
||||
delete s_connections[i].recvThread;
|
||||
s_connections[i].recvThread = NULL;
|
||||
}
|
||||
DeleteCriticalSection(&s_connections[i].sendLock);
|
||||
}
|
||||
s_connections.clear();
|
||||
LeaveCriticalSection(&s_connectionsLock);
|
||||
|
||||
if (s_acceptThread != NULL)
|
||||
@@ -204,6 +224,8 @@ void NetworkSocketLayer::Shutdown()
|
||||
DeleteCriticalSection(&s_discoveryLock);
|
||||
DeleteCriticalSection(&s_disconnectLock);
|
||||
s_disconnectedSmallIds.clear();
|
||||
DeleteCriticalSection(&s_pendingJoinLock);
|
||||
s_pendingJoinSmallIds.clear();
|
||||
DeleteCriticalSection(&s_freeSmallIdLock);
|
||||
s_freeSmallIds.clear();
|
||||
s_locksCreated = false;
|
||||
@@ -219,6 +241,14 @@ bool NetworkSocketLayer::HostGame(int port)
|
||||
s_isHost = true;
|
||||
s_localSmallId = 0;
|
||||
s_hostSmallId = 0;
|
||||
s_connected = false;
|
||||
s_active = false;
|
||||
|
||||
if (s_hostConnectionSocket != INVALID_SOCKET)
|
||||
{
|
||||
closesocket(s_hostConnectionSocket);
|
||||
s_hostConnectionSocket = INVALID_SOCKET;
|
||||
}
|
||||
s_nextSmallId = 1;
|
||||
s_hostGamePort = port;
|
||||
|
||||
@@ -786,9 +816,9 @@ bool NetworkSocketLayer::JoinGame(const char *ip, int port)
|
||||
bool NetworkSocketLayer::SendOnSocket(SOCKET sock, const void *data, int dataSize)
|
||||
{
|
||||
#if defined _WINDOWS64 || defined _XBOX
|
||||
if (sock == INVALID_SOCKET || dataSize <= 0) return false;
|
||||
if (sock == INVALID_SOCKET || dataSize <= 0 || dataSize > NETWORK_LAN_MAX_PACKET_SIZE) return false;
|
||||
#elif defined __PS3__ || defined __ORBIS__ || defined __PSVITA__
|
||||
if (sock < 0 || dataSize <= 0) return false;
|
||||
if (sock < 0 || dataSize <= 0 || dataSize > NETWORK_LAN_MAX_PACKET_SIZE) return false;
|
||||
#endif
|
||||
|
||||
EnterCriticalSection(&s_sendLock);
|
||||
@@ -809,10 +839,7 @@ bool NetworkSocketLayer::SendOnSocket(SOCKET sock, const void *data, int dataSiz
|
||||
#elif defined __PS3__ || defined __ORBIS__ || defined __PSVITA__
|
||||
if (sent < 0 || sent == 0)
|
||||
#endif
|
||||
{
|
||||
LeaveCriticalSection(&s_sendLock);
|
||||
return false;
|
||||
}
|
||||
totalSent += sent;
|
||||
}
|
||||
|
||||
@@ -826,14 +853,10 @@ bool NetworkSocketLayer::SendOnSocket(SOCKET sock, const void *data, int dataSiz
|
||||
#elif defined __PS3__ || defined __ORBIS__ || defined __PSVITA__
|
||||
if (sent < 0 || sent == 0)
|
||||
#endif
|
||||
{
|
||||
LeaveCriticalSection(&s_sendLock);
|
||||
return false;
|
||||
}
|
||||
totalSent += sent;
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&s_sendLock);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -843,31 +866,38 @@ bool NetworkSocketLayer::SendToSmallId(BYTE targetSmallId, const void *data, int
|
||||
|
||||
if (s_isHost)
|
||||
{
|
||||
SOCKET sock = GetSocketForSmallId(targetSmallId);
|
||||
#if defined _WINDOWS64 || defined _XBOX
|
||||
if (sock == INVALID_SOCKET) return false;
|
||||
#elif defined __PS3__ || defined __ORBIS__ || defined __PSVITA__
|
||||
if (sock < 0) return false;
|
||||
#endif
|
||||
return SendOnSocket(sock, data, dataSize);
|
||||
EnterCriticalSection(&s_connectionsLock);
|
||||
if (targetSmallId >= NETWORK_LAN_MAX_CLIENTS + 1 || !s_connections[targetSmallId].active)
|
||||
{
|
||||
LeaveCriticalSection(&s_connectionsLock);
|
||||
return false;
|
||||
}
|
||||
SOCKET sock = s_connections[targetSmallId].tcpSocket;
|
||||
CRITICAL_SECTION *pLock = &s_connections[targetSmallId].sendLock;
|
||||
LeaveCriticalSection(&s_connectionsLock);
|
||||
|
||||
EnterCriticalSection(pLock);
|
||||
bool result = SendOnSocket(sock, data, dataSize);
|
||||
LeaveCriticalSection(pLock);
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
return SendOnSocket(s_hostConnectionSocket, data, dataSize);
|
||||
EnterCriticalSection(&s_sendLock);
|
||||
bool result = SendOnSocket(s_hostConnectionSocket, data, dataSize);
|
||||
LeaveCriticalSection(&s_sendLock);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
SOCKET NetworkSocketLayer::GetSocketForSmallId(BYTE smallId)
|
||||
{
|
||||
EnterCriticalSection(&s_connectionsLock);
|
||||
for (size_t i = 0; i < s_connections.size(); i++)
|
||||
if (smallId < NETWORK_LAN_MAX_CLIENTS + 1 && s_connections[smallId].active)
|
||||
{
|
||||
if (s_connections[i].smallId == smallId && s_connections[i].active)
|
||||
{
|
||||
SOCKET sock = s_connections[i].tcpSocket;
|
||||
LeaveCriticalSection(&s_connectionsLock);
|
||||
return sock;
|
||||
}
|
||||
SOCKET sock = s_connections[smallId].tcpSocket;
|
||||
LeaveCriticalSection(&s_connectionsLock);
|
||||
return sock;
|
||||
}
|
||||
LeaveCriticalSection(&s_connectionsLock);
|
||||
#if defined _WINDOWS64 || defined _XBOX
|
||||
@@ -981,15 +1011,19 @@ int NetworkSocketLayer::AcceptThreadProc(LPVOID param)
|
||||
continue;
|
||||
}
|
||||
|
||||
RemoteConnection conn;
|
||||
RemoteConnection &conn = s_connections[assignedSmallId];
|
||||
|
||||
EnterCriticalSection(&s_connectionsLock);
|
||||
|
||||
if (conn.recvThread != NULL)
|
||||
{
|
||||
conn.recvThread->WaitForCompletion(2000);
|
||||
delete conn.recvThread;
|
||||
conn.recvThread = NULL;
|
||||
}
|
||||
conn.tcpSocket = clientSocket;
|
||||
conn.smallId = assignedSmallId;
|
||||
conn.active = true;
|
||||
conn.recvThread = NULL;
|
||||
|
||||
EnterCriticalSection(&s_connectionsLock);
|
||||
s_connections.push_back(conn);
|
||||
int connIdx = (int)s_connections.size() - 1;
|
||||
LeaveCriticalSection(&s_connectionsLock);
|
||||
|
||||
app.DebugPrintf("Win64 LAN: Client connected, assigned smallId=%d\n", assignedSmallId);
|
||||
@@ -999,17 +1033,17 @@ int NetworkSocketLayer::AcceptThreadProc(LPVOID param)
|
||||
extern void Win64_SetupRemoteQNetPlayer(IQNetPlayer *player, BYTE smallId, bool isHost, bool isLocal);
|
||||
Win64_SetupRemoteQNetPlayer(qnetPlayer, assignedSmallId, false, false);
|
||||
|
||||
extern CPlatformNetworkManagerStub *g_pPlatformNetworkManager;
|
||||
g_pPlatformNetworkManager->NotifyPlayerJoined(qnetPlayer);
|
||||
EnterCriticalSection(&s_pendingJoinLock);
|
||||
s_pendingJoinSmallIds.push_back(assignedSmallId);
|
||||
LeaveCriticalSection(&s_pendingJoinLock);
|
||||
|
||||
DWORD *threadParam = new DWORD;
|
||||
*threadParam = connIdx;
|
||||
*threadParam = assignedSmallId;
|
||||
C4JThread* hThread = new C4JThread(RecvThreadProc, threadParam, "RecvThreadProc");
|
||||
hThread->Run();
|
||||
|
||||
EnterCriticalSection(&s_connectionsLock);
|
||||
if (connIdx < (int)s_connections.size())
|
||||
s_connections[connIdx].recvThread = hThread;
|
||||
s_connections[assignedSmallId].recvThread = hThread;
|
||||
LeaveCriticalSection(&s_connectionsLock);
|
||||
}
|
||||
return 0;
|
||||
@@ -1017,17 +1051,16 @@ int NetworkSocketLayer::AcceptThreadProc(LPVOID param)
|
||||
|
||||
int NetworkSocketLayer::RecvThreadProc(LPVOID param)
|
||||
{
|
||||
DWORD connIdx = *(DWORD *)param;
|
||||
BYTE clientSmallId = (BYTE)*(DWORD *)param;
|
||||
delete (DWORD *)param;
|
||||
|
||||
EnterCriticalSection(&s_connectionsLock);
|
||||
if (connIdx >= (DWORD)s_connections.size())
|
||||
if (clientSmallId >= NETWORK_LAN_MAX_CLIENTS + 1 || !s_connections[clientSmallId].active)
|
||||
{
|
||||
LeaveCriticalSection(&s_connectionsLock);
|
||||
return 0;
|
||||
}
|
||||
SOCKET sock = s_connections[connIdx].tcpSocket;
|
||||
BYTE clientSmallId = s_connections[connIdx].smallId;
|
||||
SOCKET sock = s_connections[clientSmallId].tcpSocket;
|
||||
LeaveCriticalSection(&s_connectionsLock);
|
||||
|
||||
std::vector<BYTE> recvBuf;
|
||||
@@ -1048,7 +1081,7 @@ int NetworkSocketLayer::RecvThreadProc(LPVOID param)
|
||||
((uint32_t)header[2] << 8) |
|
||||
((uint32_t)header[3]);
|
||||
|
||||
if (packetSize <= 0 || packetSize > NETWORK_LAN_MAX_PACKET_SIZE)
|
||||
if (packetSize <= 0 || (unsigned int)packetSize > NETWORK_LAN_MAX_PACKET_SIZE)
|
||||
{
|
||||
app.DebugPrintf("LAN: Invalid packet size %d from client smallId=%d (max=%d)\n",
|
||||
packetSize,
|
||||
@@ -1073,18 +1106,11 @@ int NetworkSocketLayer::RecvThreadProc(LPVOID param)
|
||||
}
|
||||
|
||||
EnterCriticalSection(&s_connectionsLock);
|
||||
for (size_t i = 0; i < s_connections.size(); i++)
|
||||
s_connections[clientSmallId].active = false;
|
||||
if (s_connections[clientSmallId].tcpSocket != INVALID_SOCKET)
|
||||
{
|
||||
if (s_connections[i].smallId == clientSmallId)
|
||||
{
|
||||
s_connections[i].active = false;
|
||||
if (s_connections[i].tcpSocket != INVALID_SOCKET)
|
||||
{
|
||||
closesocket(s_connections[i].tcpSocket);
|
||||
s_connections[i].tcpSocket = INVALID_SOCKET;
|
||||
}
|
||||
break;
|
||||
}
|
||||
closesocket(s_connections[clientSmallId].tcpSocket);
|
||||
s_connections[clientSmallId].tcpSocket = INVALID_SOCKET;
|
||||
}
|
||||
LeaveCriticalSection(&s_connectionsLock);
|
||||
|
||||
@@ -1116,18 +1142,34 @@ void NetworkSocketLayer::PushFreeSmallId(BYTE smallId)
|
||||
LeaveCriticalSection(&s_freeSmallIdLock);
|
||||
}
|
||||
|
||||
bool NetworkSocketLayer::PopPendingJoinSmallId(BYTE *outSmallId)
|
||||
{
|
||||
bool found = false;
|
||||
EnterCriticalSection(&s_pendingJoinLock);
|
||||
if (!s_pendingJoinSmallIds.empty())
|
||||
{
|
||||
*outSmallId = s_pendingJoinSmallIds.back();
|
||||
s_pendingJoinSmallIds.pop_back();
|
||||
found = true;
|
||||
}
|
||||
LeaveCriticalSection(&s_pendingJoinLock);
|
||||
return found;
|
||||
}
|
||||
|
||||
bool NetworkSocketLayer::IsSmallIdConnected(BYTE smallId)
|
||||
{
|
||||
if (smallId >= NETWORK_LAN_MAX_CLIENTS + 1) return false;
|
||||
return s_connections[smallId].active;
|
||||
}
|
||||
|
||||
void NetworkSocketLayer::CloseConnectionBySmallId(BYTE smallId)
|
||||
{
|
||||
EnterCriticalSection(&s_connectionsLock);
|
||||
for (size_t i = 0; i < s_connections.size(); i++)
|
||||
if (smallId < NETWORK_LAN_MAX_CLIENTS + 1 && s_connections[smallId].active && s_connections[smallId].tcpSocket != INVALID_SOCKET)
|
||||
{
|
||||
if (s_connections[i].smallId == smallId && s_connections[i].active && s_connections[i].tcpSocket != INVALID_SOCKET)
|
||||
{
|
||||
closesocket(s_connections[i].tcpSocket);
|
||||
s_connections[i].tcpSocket = INVALID_SOCKET;
|
||||
app.DebugPrintf("Win64 LAN: Force-closed TCP connection for smallId=%d\n", smallId);
|
||||
break;
|
||||
}
|
||||
closesocket(s_connections[smallId].tcpSocket);
|
||||
s_connections[smallId].tcpSocket = INVALID_SOCKET;
|
||||
app.DebugPrintf("Win64 LAN: Force-closed TCP connection for smallId=%d\n", smallId);
|
||||
}
|
||||
LeaveCriticalSection(&s_connectionsLock);
|
||||
}
|
||||
@@ -1150,9 +1192,9 @@ int NetworkSocketLayer::ClientRecvThreadProc(LPVOID param)
|
||||
break;
|
||||
}
|
||||
|
||||
int packetSize = (header[0] << 24) | (header[1] << 16) | (header[2] << 8) | header[3];
|
||||
int packetSize = ((uint32_t)header[0] << 24) | ((uint32_t)header[1] << 16) | ((uint32_t)header[2] << 8) | (uint32_t)header[3];
|
||||
|
||||
if (packetSize <= 0 || packetSize > NETWORK_LAN_MAX_PACKET_SIZE)
|
||||
if (packetSize <= 0 || (unsigned int)packetSize > NETWORK_LAN_MAX_PACKET_SIZE)
|
||||
{
|
||||
app.DebugPrintf("LAN: Invalid packet size %d from host\n", packetSize);
|
||||
break;
|
||||
@@ -1161,7 +1203,6 @@ int NetworkSocketLayer::ClientRecvThreadProc(LPVOID param)
|
||||
if ((int)recvBuf.size() < packetSize)
|
||||
{
|
||||
recvBuf.resize(packetSize);
|
||||
app.DebugPrintf("LAN: Resized client recv buffer to %d bytes\n", packetSize);
|
||||
}
|
||||
|
||||
if (!RecvExact(s_hostConnectionSocket, &recvBuf[0], packetSize))
|
||||
@@ -1494,8 +1535,8 @@ std::vector<LANSession> NetworkSocketLayer::GetDiscoveredSessions()
|
||||
|
||||
int NetworkSocketLayer::DiscoveryThreadProc(LPVOID param)
|
||||
{
|
||||
app.DebugPrintf("Discovery thread started\n");
|
||||
char recvBuf[1024];
|
||||
const size_t MAX_DISCOVERED_SESSIONS = 64;
|
||||
|
||||
while (s_discovering)
|
||||
{
|
||||
@@ -1544,6 +1585,11 @@ int NetworkSocketLayer::DiscoveryThreadProc(LPVOID param)
|
||||
if (broadcast->magic != NETWORK_LAN_BROADCAST_MAGIC)
|
||||
continue;
|
||||
|
||||
broadcast->hostName[31] = L'\0';
|
||||
|
||||
for (int pn = 0; pn < 8; pn++)
|
||||
broadcast->playerNames[pn][XUSER_NAME_SIZE - 1] = '\0';
|
||||
|
||||
char senderIP[64];
|
||||
#if defined _XBOX
|
||||
unsigned char *ipBytes = (unsigned char *)&senderAddr.sin_addr;
|
||||
@@ -1586,6 +1632,12 @@ int NetworkSocketLayer::DiscoveryThreadProc(LPVOID param)
|
||||
|
||||
if (!found)
|
||||
{
|
||||
if (s_discoveredSessions.size() >= MAX_DISCOVERED_SESSIONS)
|
||||
{
|
||||
LeaveCriticalSection(&s_discoveryLock);
|
||||
continue;
|
||||
}
|
||||
|
||||
LANSession session;
|
||||
memset(&session, 0, sizeof(session));
|
||||
strncpy(session.hostIP, senderIP, sizeof(session.hostIP) - 1);
|
||||
|
||||
Reference in New Issue
Block a user