feat(net): finish basic networking support for windows

This commit is contained in:
fallenoak 2023-03-21 16:39:15 -05:00 committed by GitHub
parent b537c34990
commit 497520e672
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 163 additions and 9 deletions

View File

@ -590,6 +590,8 @@ void WowConnection::Init(WowConnectionResponse* response, void (*func)(void)) {
this->m_readBytes = 0;
this->m_readBufferSize = 0;
this->m_event = nullptr;
// TODO
this->SetState(WOWC_INITIALIZED);
@ -635,7 +637,20 @@ WC_SEND_RESULT WowConnection::SendRaw(uint8_t* data, int32_t len, bool a4) {
STORM_ASSERT(this->m_sock >= 0);
#if defined (WHOA_SYSTEM_WIN)
// TODO
if (this->m_sendList.Head()) {
// TODO
} else {
auto written = send(this->m_sock, reinterpret_cast<char*>(data), len, 0x0);
if (written == len) {
this->m_lock.Leave();
return WC_SEND_SENT;
}
if (written < 0) {
// TODO
}
}
#elif defined(WHOA_SYSTEM_MAC) || defined(WHOA_SYSTEM_LINUX)
if (this->m_sendList.Head()) {
// TODO
@ -697,11 +712,15 @@ void WowConnection::StartConnect() {
return;
}
#if defined(WHOA_SYSTEM_MAC)
#if defined(WHOA_SYSTEM_WIN)
u_long argp = 1;
ioctlsocket(this->m_sock, FIONBIO, &argp);
#elif defined(WHOA_SYSTEM_MAC)
fcntl(this->m_sock, F_SETFL, O_NONBLOCK);
uint32_t opt = 1;
setsockopt(this->m_sock, SOL_SOCKET, 4130, &opt, sizeof(opt));
#endif
sockaddr_in addr;
addr.sin_family = AF_INET;
@ -720,11 +739,19 @@ void WowConnection::StartConnect() {
return;
}
#if defined(WHOA_SYSTEM_WIN)
if (WSAGetLastError() == WSAEWOULDBLOCK) {
this->m_lock.Leave();
return;
}
#elif defined(WHOA_SYSTEM_MAC)
if (errno == EAGAIN || errno == EINTR || errno == EINPROGRESS) {
this->m_lock.Leave();
return;
}
#endif
WowConnection::s_network->Remove(this);
this->CloseSocket(this->m_sock);
@ -733,5 +760,4 @@ void WowConnection::StartConnect() {
this->SetState(WOWC_ERROR);
this->m_lock.Leave();
#endif
}

View File

@ -58,6 +58,7 @@ class WowConnection {
TSLink<WowConnection> m_netlink;
SCritSect m_lock;
ATOMIC32 m_serviceCount;
void* m_event;
WOWC_TYPE m_type;
// Member functions

View File

@ -29,6 +29,7 @@ class WowConnectionNet {
STORM_EXPLICIT_LIST(WowConnection, m_netlink) m_connections;
SSemaphore m_workerSem;
void (*m_threadinit)();
void* event8E8;
// Member functions
WowConnectionNet(uint32_t numThreads, void (*threadinit)())

View File

@ -1,25 +1,151 @@
#include "net/connection/WowConnectionNet.hpp"
#include <winsock2.h>
#include <ws2tcpip.h>
void WowConnectionNet::PlatformAdd(WowConnection* connection) {
// TODO
if (!connection->m_event) {
connection->m_event = WSACreateEvent();
}
uint32_t on = 1;
setsockopt(connection->m_sock, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast<char*>(&on), sizeof(on));
SetEvent(this->event8E8);
}
void WowConnectionNet::PlatformChangeState(WowConnection* connection, WOW_CONN_STATE state) {
// TODO
uint32_t networkEvents = 0x0;
switch (connection->GetState()) {
case WOWC_CONNECTING: {
networkEvents = FD_CLOSE | FD_CONNECT | FD_WRITE;
}
case WOWC_LISTENING: {
networkEvents = FD_ACCEPT;
}
case WOWC_CONNECTED: {
// TODO conditional network event
networkEvents = FD_CLOSE | FD_READ;
}
}
if (connection->m_event && connection->m_sock >= 0) {
WSAEventSelect(connection->m_sock, connection->m_event, networkEvents);
}
SetEvent(this->event8E8);
}
void WowConnectionNet::PlatformInit(bool useEngine) {
// TODO
WSADATA wsaData;
auto err = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (err || wsaData.wVersion != MAKEWORD(2, 2)) {
return;
}
this->event8E8 = CreateEvent(nullptr, true, false, nullptr);
}
void WowConnectionNet::PlatformRemove(WowConnection* connection) {
// TODO
SetEvent(this->event8E8);
}
void WowConnectionNet::PlatformRun() {
// TODO
uint32_t timeout = 500;
WowConnection* connections[64];
HANDLE connectionEvents[64];
while (!this->m_stop) {
this->m_connectionsLock.Enter();
uint32_t connectionCount = 0;
connections[connectionCount] = nullptr;
connectionEvents[connectionCount] = this->event8E8;
connectionCount++;
for (auto connection = this->m_connections.Head(); connection; connection = this->m_connections.Next(connection)) {
if (connection->m_serviceCount) {
continue;
}
switch (connection->GetState()) {
case WOWC_CONNECTING: {
WSAEventSelect(connection->m_sock, connection->m_event, FD_CONNECT | FD_CLOSE);
break;
}
case WOWC_LISTENING: {
WSAEventSelect(connection->m_sock, connection->m_event, FD_ACCEPT);
break;
}
case WOWC_CONNECTED: {
// TODO conditional network event
WSAEventSelect(connection->m_sock, connection->m_event, FD_CONNECT | FD_READ);
break;
}
case WOWC_DISCONNECTED: {
timeout = 0;
break;
}
default: {
break;
}
}
if (connectionCount < 64) {
connection->AddRef();
connections[connectionCount] = connection;
connectionEvents[connectionCount] = connection->m_event;
connectionCount++;
// TODO
}
}
this->m_connectionsLock.Leave();
auto waitIndex = WaitForMultipleObjects(connectionCount, connectionEvents, false, timeout);
if (waitIndex == 0) {
ResetEvent(connectionEvents[0]);
} else {
for (uint32_t i = 1; i < connectionCount; i++) {
WSANETWORKEVENTS networkEvents;
WSAEnumNetworkEvents(connections[i]->m_sock, connectionEvents[i], &networkEvents);
uint32_t signalFlags = 0x0;
if (networkEvents.lNetworkEvents & (FD_CLOSE | FD_ACCEPT | FD_READ)) {
signalFlags |= 0x2;
}
if (networkEvents.lNetworkEvents & (FD_CLOSE | FD_CONNECT | FD_WRITE)) {
signalFlags |= 0x1;
}
if (connections[i]->m_connState == WOWC_DISCONNECTING) {
signalFlags |= 0x8;
}
// TODO timeout manipulation
if (signalFlags) {
this->SignalWorker(connections[i], signalFlags);
}
}
}
for (uint32_t i = 1; i < connectionCount; i++) {
connections[i]->Release();
}
}
}
void WowConnectionNet::PlatformWorkerReady() {
// TODO
SetEvent(this->event8E8);
}