12 #define network_cleanup() WSACleanup()
13 #define network_return int
15 #define network_return ssize_t
16 #include <sys/types.h>
17 #include <sys/socket.h>
18 #include <sys/ioctl.h>
22 #include <netinet/in.h>
23 #include <netinet/tcp.h>
24 #include <sys/socket.h>
28 #define closesocket close
29 #define INVALID_SOCKET -1
30 #define network_cleanup()
43 inline Network::Network(uint16_t port,
const std::string& hostname) :
44 _port(port), _hostname(hostname), _socketFD(INVALID_SOCKET), _time(0L) {
46 FD_ZERO(&_writeFDSet);
49 inline Network::~Network() {
50 closesocket(_socketFD);
54 inline bool Network::start() {
57 const int wsaResult = WSAStartup(MAKEWORD(2,2), &wsaData);
58 if (wsaResult != NO_ERROR) {
62 signal(SIGPIPE, SIG_IGN);
66 FD_ZERO(&_writeFDSet);
68 _socketFD = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
69 if (_socketFD == INVALID_SOCKET) {
73 struct sockaddr_in sin;
74 memset(&sin, 0,
sizeof(sin));
75 sin.sin_family = AF_INET;
76 sin.sin_addr.s_addr = INADDR_ANY;
77 sin.sin_port = htons(_port);
81 if (setsockopt(_socketFD, SOL_SOCKET, SO_REUSEADDR, (
char*) &t,
sizeof(t)) != 0) {
83 if (setsockopt(_socketFD, SOL_SOCKET, SO_REUSEADDR, &t,
sizeof(t)) != 0) {
85 closesocket(_socketFD);
89 if (bind(_socketFD, (
struct sockaddr *) &sin,
sizeof(sin)) < 0) {
92 FD_CLR(_socketFD, &_readFDSet);
93 FD_CLR(_socketFD, &_writeFDSet);
94 closesocket(_socketFD);
95 _socketFD = INVALID_SOCKET;
99 if (listen(_socketFD, 5) < 0) {
102 closesocket(_socketFD);
103 _socketFD = INVALID_SOCKET;
108 fcntl(_socketFD, F_SETFL, O_NONBLOCK);
111 unsigned long mode = 1;
112 ioctlsocket(_socketFD, FIONBIO, &mode);
115 FD_SET(_socketFD, &_readFDSet);
120 inline Network::ClientSocketsIter Network::closeClient(ClientSocketsIter& iter) {
121 Client& client = *iter;
122 const SOCKET clientSocket = client.socket;
123 FD_CLR(clientSocket, &_readFDSet);
124 FD_CLR(clientSocket, &_writeFDSet);
125 closesocket(clientSocket);
126 client.socket = INVALID_SOCKET;
127 for (INetworkListener* listener : _listeners) {
128 listener->onDisconnect(&client);
130 return _clientSockets.erase(iter);
133 inline bool Network::sendMessage(Client& client) {
134 if (client.out.empty()) {
138 std::array<uint8_t, 16384> buf;
139 while (!client.out.empty()) {
140 const size_t len = std::min(buf.size(), client.out.size());
141 std::copy_n(client.out.begin(), len, buf.begin());
142 const SOCKET clientSocket = client.socket;
143 const network_return sent = send(clientSocket, (
const char*)&buf[0], len, 0);
151 client.out.erase(client.out.begin(), std::next(client.out.begin(), sent));
156 inline void Network::update(int64_t deltaTime) {
166 memcpy(&readFDsOut, &_readFDSet,
sizeof(readFDsOut));
167 memcpy(&writeFDsOut, &_writeFDSet,
sizeof(writeFDsOut));
172 const int ready = select(FD_SETSIZE, &readFDsOut, &writeFDsOut,
nullptr, &tv);
176 if (_socketFD != INVALID_SOCKET && FD_ISSET(_socketFD, &readFDsOut)) {
177 const SOCKET clientSocket = accept(_socketFD,
nullptr,
nullptr);
178 if (clientSocket != INVALID_SOCKET) {
179 FD_SET(clientSocket, &_readFDSet);
180 const Client c(clientSocket);
181 _clientSockets.push_back(c);
182 for (INetworkListener* listener : _listeners) {
183 listener->onConnect(&_clientSockets.back());
188 ClientId clientId = 0;
189 for (ClientSocketsIter i = _clientSockets.begin(); i != _clientSockets.end(); ++clientId) {
191 const SOCKET clientSocket = client.socket;
192 if (clientSocket == INVALID_SOCKET) {
197 if (FD_ISSET(clientSocket, &writeFDsOut)) {
198 if (!sendMessage(client) || client.finished) {
204 if (FD_ISSET(clientSocket, &readFDsOut)) {
205 std::array<uint8_t, 16384> buf;
206 const network_return len = recv(clientSocket, (
char*)&buf[0], buf.size(), 0);
211 std::copy_n(buf.begin(), len, std::back_inserter(client.in));
214 ProtocolMessageFactory& factory = ProtocolMessageFactory::get();
215 if (factory.isNewMessageAvailable(client.in)) {
216 IProtocolMessage* msg = factory.create(client.in);
221 IProtocolHandler* handler = ProtocolHandlerRegistry::get().getHandler(*msg);
223 handler->execute(clientId, *msg);
231 if (_clientSockets.empty()) {
237 for (ClientSocketsIter i = _clientSockets.begin(); i != _clientSockets.end(); ++i) {
239 if (client.socket == INVALID_SOCKET) {
244 IProtocolMessage::addInt(client.out, static_cast<int32_t>(out.size()));
245 std::copy(out.begin(), out.end(), std::back_inserter(client.out));
246 FD_SET(client.socket, &_writeFDSet);
253 assert(client !=
nullptr);
254 if (client->socket == INVALID_SOCKET) {
261 IProtocolMessage::addInt(client->out, static_cast<int32_t>(out.size()));
262 std::copy(out.begin(), out.end(), std::back_inserter(client->out));
263 FD_SET(client->socket, &_writeFDSet);
267 #undef network_cleanup
268 #undef INVALID_SOCKET
A protocol message is used for the serialization of the ai states for remote debugging.
Definition: IProtocolMessage.h:60
bool broadcast(const IProtocolMessage &msg)
Definition: NetworkImpl.h:230