#include "net/connection/WowConnectionNet.hpp" #include "net/connection/WowConnection.hpp" #include #include #include #include #include #include #include #include #include int32_t s_workerPipe[2]; void WowConnectionNet::PlatformAdd(WowConnection* connection) { uint32_t on = 1; setsockopt(connection->m_sock, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)); char buf = '\1'; write(s_workerPipe[1], &buf, sizeof(buf)); } void WowConnectionNet::PlatformChangeState(WowConnection* connection, WOW_CONN_STATE state) { char buf = '\1'; write(s_workerPipe[1], &buf, sizeof(buf)); } void WowConnectionNet::PlatformInit(bool useEngine) { // TODO } void WowConnectionNet::PlatformRemove(WowConnection* connection) { char buf = '\1'; write(s_workerPipe[1], &buf, sizeof(buf)); } void WowConnectionNet::PlatformRun() { pipe(s_workerPipe); if (fcntl(s_workerPipe[0], F_SETFL, O_NONBLOCK) < 0) { perror("fcntl(worker pipe)"); } TSGrowableArray connections; char buf[25]; while (!this->m_stop) { timeval timeout = { 30, 0 }; fd_set readFds; FD_ZERO(&readFds); fd_set writeFds; FD_ZERO(&writeFds); fd_set errorFds; FD_ZERO(&errorFds); FD_SET(s_workerPipe[0], &readFds); auto fdCount = s_workerPipe[0]; this->m_connectionsLock.Enter(); uint32_t connectionCount = 0; uint32_t disconnectionCount = 0; for (auto connection = this->m_connections.Head(); connection; connection = this->m_connections.Link(connection)->Next()) { if (connection->m_serviceCount) { continue; } switch (connection->m_connState) { case WOWC_CONNECTING: { FD_SET(connection->m_sock, &writeFds); FD_SET(connection->m_sock, &errorFds); connections.GrowToFit(connectionCount, 0); connections[connectionCount] = connection; connection->AddRef(); fdCount = std::max(fdCount, connection->m_sock); break; } case WOWC_LISTENING: { FD_SET(connection->m_sock, &readFds); connections.GrowToFit(connectionCount, 0); connections[connectionCount] = connection; connection->AddRef(); fdCount = std::max(fdCount, connection->m_sock); break; } case WOWC_CONNECTED: { FD_SET(connection->m_sock, &readFds); FD_SET(connection->m_sock, &errorFds); // TODO connections.GrowToFit(connectionCount, 0); connections[connectionCount] = connection; connection->AddRef(); fdCount = std::max(fdCount, connection->m_sock); break; } case WOWC_DISCONNECTING: { // TODO disconnectionCount++; connections.GrowToFit(connectionCount, 0); connections[connectionCount] = connection; connection->AddRef(); break; } default: { break; } } connectionCount++; } this->m_connectionsLock.Leave(); if (disconnectionCount > 0) { timeout = { 0, 0 }; } if (connectionCount > 0) { // TODO } select(fdCount + 1, &readFds, &writeFds, &errorFds, &timeout); auto v1 = s_workerPipe[0]; if (FD_ISSET(s_workerPipe[0], &readFds)) { while (read(v1, buf, 1u) > 0) { v1 = s_workerPipe[0]; } } for (int32_t i = 0; i < connectionCount; i++) { auto connection = connections[i]; uint32_t signalFlags = 0x0; if (!(connection->m_sock & 0x80000000)) { if (FD_ISSET(connection->m_sock, &writeFds)) { signalFlags |= 0x1; } if (FD_ISSET(connection->m_sock, &readFds)) { signalFlags |= 0x2; } if (FD_ISSET(connection->m_sock, &errorFds)) { signalFlags |= 0x4; } } if (connection->m_connState == WOWC_DISCONNECTING) { signalFlags |= 0x8; } // TODO // auto v15 = connection->dword10C; // if (!(v15 & 1) && v15) { // signalFlags |= 0x2; // } if (signalFlags) { this->SignalWorker(connection, signalFlags); } connection->Release(); } } } void WowConnectionNet::PlatformWorkerReady() { char buf = '\1'; write(s_workerPipe[1], &buf, sizeof(buf)); }