2020-08-18 20:42:30 +00:00
|
|
|
#include "CNProtocol.hpp"
|
2020-08-19 01:34:39 +00:00
|
|
|
#include "CNStructs.hpp"
|
2020-08-18 20:42:30 +00:00
|
|
|
|
2020-12-04 19:09:39 +00:00
|
|
|
#include <assert.h>
|
|
|
|
|
2020-08-18 20:42:30 +00:00
|
|
|
// ========================================================[[ CNSocketEncryption ]]========================================================
|
|
|
|
|
|
|
|
// literally C/P from the client and converted to C++ (does some byte swapping /shrug)
|
|
|
|
int CNSocketEncryption::Encrypt_byte_change_A(int ERSize, uint8_t* data, int size) {
|
|
|
|
int num = 0;
|
|
|
|
int num2 = 0;
|
|
|
|
int num3 = 0;
|
|
|
|
|
2020-10-19 17:26:14 +00:00
|
|
|
while (num + ERSize <= size) {
|
2020-08-18 20:42:30 +00:00
|
|
|
int num4 = num + num3;
|
|
|
|
int num5 = num + (ERSize - 1 - num3);
|
|
|
|
|
|
|
|
uint8_t b = data[num4];
|
|
|
|
data[num4] = data[num5];
|
|
|
|
data[num5] = b;
|
|
|
|
num += ERSize;
|
|
|
|
num3++;
|
2020-10-19 17:26:14 +00:00
|
|
|
if (num3 > ERSize / 2) {
|
2020-08-18 20:42:30 +00:00
|
|
|
num3 = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
num2 = ERSize - (num + ERSize - size);
|
|
|
|
return num + num2;
|
|
|
|
}
|
|
|
|
|
|
|
|
int CNSocketEncryption::xorData(uint8_t* buffer, uint8_t* key, int size) {
|
|
|
|
// xor every 8 bytes with 8 byte key
|
|
|
|
for (int i = 0; i < size; i++) {
|
|
|
|
buffer[i] ^= key[i % keyLength];
|
|
|
|
}
|
|
|
|
|
|
|
|
return size;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t CNSocketEncryption::createNewKey(uint64_t uTime, int32_t iv1, int32_t iv2) {
|
|
|
|
uint64_t num = (uint64_t)(iv1 + 1);
|
|
|
|
uint64_t num2 = (uint64_t)(iv2 + 1);
|
|
|
|
uint64_t dEKey = (uint64_t)(*(uint64_t*)&defaultKey[0]);
|
|
|
|
return dEKey * (uTime * num * num2);
|
|
|
|
}
|
|
|
|
|
|
|
|
int CNSocketEncryption::encryptData(uint8_t* buffer, uint8_t* key, int size) {
|
|
|
|
int eRSize = size % (keyLength / 2 + 1) * 2 + keyLength; // C/P from client
|
|
|
|
int size2 = xorData(buffer, key, size);
|
|
|
|
return Encrypt_byte_change_A(eRSize, buffer, size2);
|
|
|
|
}
|
|
|
|
|
|
|
|
int CNSocketEncryption::decryptData(uint8_t* buffer, uint8_t* key, int size) {
|
|
|
|
int eRSize = size % (keyLength / 2 + 1) * 2 + keyLength; // size % of 18????
|
|
|
|
int size2 = Encrypt_byte_change_A(eRSize, buffer, size);
|
|
|
|
return xorData(buffer, key, size2);
|
|
|
|
}
|
|
|
|
|
|
|
|
// ========================================================[[ CNPacketData ]]========================================================
|
|
|
|
|
2020-08-23 17:19:12 +00:00
|
|
|
CNPacketData::CNPacketData(void* b, uint32_t t, int l): buf(b), size(l), type(t) {}
|
2020-08-18 20:42:30 +00:00
|
|
|
|
|
|
|
// ========================================================[[ CNSocket ]]========================================================
|
|
|
|
|
|
|
|
CNSocket::CNSocket(SOCKET s, PacketHandler ph): sock(s), pHandler(ph) {
|
|
|
|
EKey = (uint64_t)(*(uint64_t*)&CNSocketEncryption::defaultKey[0]);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CNSocket::sendData(uint8_t* data, int size) {
|
|
|
|
int sentBytes = 0;
|
2020-08-22 02:32:22 +00:00
|
|
|
int maxTries = 10;
|
2020-08-18 20:42:30 +00:00
|
|
|
|
|
|
|
while (sentBytes < size) {
|
2020-12-04 23:37:04 +00:00
|
|
|
int sent = send(sock, (buffer_t*)(data + sentBytes), size - sentBytes, 0);
|
2020-08-22 00:33:42 +00:00
|
|
|
if (SOCKETERROR(sent)) {
|
2020-08-24 18:23:28 +00:00
|
|
|
if (OF_ERRNO == OF_EWOULD && maxTries > 0) {
|
2020-08-22 02:32:22 +00:00
|
|
|
maxTries--;
|
2020-08-22 00:33:42 +00:00
|
|
|
continue; // try again
|
2020-08-22 02:32:22 +00:00
|
|
|
}
|
2020-12-08 20:02:37 +00:00
|
|
|
printSocketError("send");
|
2020-08-18 20:42:30 +00:00
|
|
|
return false; // error occured while sending bytes
|
2020-08-22 00:33:42 +00:00
|
|
|
}
|
2020-08-18 20:42:30 +00:00
|
|
|
sentBytes += sent;
|
|
|
|
}
|
2020-09-14 13:53:48 +00:00
|
|
|
|
2020-08-18 20:42:30 +00:00
|
|
|
return true; // it worked!
|
|
|
|
}
|
|
|
|
|
|
|
|
void CNSocket::setEKey(uint64_t k) {
|
|
|
|
EKey = k;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CNSocket::setFEKey(uint64_t k) {
|
|
|
|
FEKey = k;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t CNSocket::getEKey() {
|
|
|
|
return EKey;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t CNSocket::getFEKey() {
|
|
|
|
return FEKey;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CNSocket::isAlive() {
|
|
|
|
return alive;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CNSocket::kill() {
|
|
|
|
alive = false;
|
|
|
|
#ifdef _WIN32
|
|
|
|
shutdown(sock, SD_BOTH);
|
|
|
|
closesocket(sock);
|
|
|
|
#else
|
|
|
|
shutdown(sock, SHUT_RDWR);
|
|
|
|
close(sock);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2020-08-24 18:23:28 +00:00
|
|
|
// we don't own buf, TODO: queue packets up to send in step()
|
2020-08-22 23:31:09 +00:00
|
|
|
void CNSocket::sendPacket(void* buf, uint32_t type, size_t size) {
|
|
|
|
if (!alive)
|
2020-08-22 00:33:42 +00:00
|
|
|
return;
|
2020-09-14 13:53:48 +00:00
|
|
|
|
2020-08-27 19:39:04 +00:00
|
|
|
size_t bodysize = size + sizeof(uint32_t);
|
|
|
|
uint8_t* fullpkt = (uint8_t*)xmalloc(bodysize+4);
|
|
|
|
uint8_t* body = fullpkt+4;
|
|
|
|
memcpy(fullpkt, (void*)&bodysize, 4);
|
2020-08-18 20:42:30 +00:00
|
|
|
|
|
|
|
// copy packet type to the front of the buffer & then the actual buffer
|
2020-08-27 19:39:04 +00:00
|
|
|
memcpy(body, (void*)&type, sizeof(uint32_t));
|
|
|
|
memcpy(body+sizeof(uint32_t), buf, size);
|
2020-08-18 20:42:30 +00:00
|
|
|
|
|
|
|
// encrypt the packet
|
2020-08-22 23:31:09 +00:00
|
|
|
switch (activeKey) {
|
|
|
|
case SOCKETKEY_E:
|
2020-08-27 19:39:04 +00:00
|
|
|
CNSocketEncryption::encryptData((uint8_t*)body, (uint8_t*)(&EKey), bodysize);
|
2020-08-22 23:31:09 +00:00
|
|
|
break;
|
|
|
|
case SOCKETKEY_FE:
|
2020-08-27 19:39:04 +00:00
|
|
|
CNSocketEncryption::encryptData((uint8_t*)body, (uint8_t*)(&FEKey), bodysize);
|
2020-08-22 23:31:09 +00:00
|
|
|
break;
|
|
|
|
default: {
|
2020-08-27 19:39:04 +00:00
|
|
|
free(fullpkt);
|
2020-08-22 23:31:09 +00:00
|
|
|
DEBUGLOG(
|
|
|
|
std::cout << "[WARN]: UNSET KEYTYPE FOR SOCKET!! ABORTING SEND" << std::endl;
|
|
|
|
)
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2020-08-18 20:42:30 +00:00
|
|
|
|
|
|
|
// send packet data!
|
2020-09-14 13:53:48 +00:00
|
|
|
if (alive && !sendData(fullpkt, bodysize+4))
|
2020-08-22 00:33:42 +00:00
|
|
|
kill();
|
2020-08-18 20:42:30 +00:00
|
|
|
|
2020-08-27 19:39:04 +00:00
|
|
|
free(fullpkt);
|
2020-08-18 20:42:30 +00:00
|
|
|
}
|
|
|
|
|
2020-08-22 23:31:09 +00:00
|
|
|
void CNSocket::setActiveKey(ACTIVEKEY key) {
|
|
|
|
activeKey = key;
|
|
|
|
}
|
|
|
|
|
2020-08-18 20:42:30 +00:00
|
|
|
void CNSocket::step() {
|
2020-08-24 18:23:28 +00:00
|
|
|
// read step
|
|
|
|
|
2020-12-04 22:02:15 +00:00
|
|
|
// XXX NOTE: we must not recv() twice without a poll() inbetween
|
2020-08-18 20:42:30 +00:00
|
|
|
if (readSize <= 0) {
|
|
|
|
// we aren't reading a packet yet, try to start looking for one
|
|
|
|
int recved = recv(sock, (buffer_t*)readBuffer, sizeof(int32_t), 0);
|
2020-12-11 21:41:51 +00:00
|
|
|
if (recved == 0) {
|
|
|
|
// the socket was closed normally
|
|
|
|
kill();
|
|
|
|
} else if (!SOCKETERROR(recved)) {
|
2020-09-16 19:46:15 +00:00
|
|
|
// we got our packet size!!!!
|
2020-08-18 20:42:30 +00:00
|
|
|
readSize = *((int32_t*)readBuffer);
|
|
|
|
// sanity check
|
2020-08-28 14:09:26 +00:00
|
|
|
if (readSize > CN_PACKET_BUFFER_SIZE) {
|
2020-08-18 20:42:30 +00:00
|
|
|
kill();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// we'll just leave bufferIndex at 0 since we already have the packet size, it's safe to overwrite those bytes
|
|
|
|
activelyReading = true;
|
2020-08-24 18:23:28 +00:00
|
|
|
} else if (OF_ERRNO != OF_EWOULD) {
|
2020-08-23 20:09:51 +00:00
|
|
|
// serious socket issue, disconnect connection
|
2020-12-08 20:02:37 +00:00
|
|
|
printSocketError("recv");
|
2020-08-23 20:09:51 +00:00
|
|
|
kill();
|
|
|
|
return;
|
2020-08-18 20:42:30 +00:00
|
|
|
}
|
|
|
|
}
|
2020-12-04 23:37:04 +00:00
|
|
|
|
|
|
|
if (readSize > 0 && readBufferIndex < readSize) {
|
2020-08-18 20:42:30 +00:00
|
|
|
// read until the end of the packet! (or at least try too)
|
|
|
|
int recved = recv(sock, (buffer_t*)(readBuffer + readBufferIndex), readSize - readBufferIndex, 0);
|
2020-12-11 21:41:51 +00:00
|
|
|
if (recved == 0) {
|
|
|
|
// the socket was closed normally
|
|
|
|
kill();
|
|
|
|
} else if (!SOCKETERROR(recved))
|
2020-08-18 20:42:30 +00:00
|
|
|
readBufferIndex += recved;
|
2020-08-24 18:23:28 +00:00
|
|
|
else if (OF_ERRNO != OF_EWOULD) {
|
2020-08-23 20:09:51 +00:00
|
|
|
// serious socket issue, disconnect connection
|
2020-12-08 20:02:37 +00:00
|
|
|
printSocketError("recv");
|
2020-08-23 20:09:51 +00:00
|
|
|
kill();
|
|
|
|
return;
|
|
|
|
}
|
2020-08-18 20:42:30 +00:00
|
|
|
}
|
|
|
|
|
2020-12-04 22:02:15 +00:00
|
|
|
if (activelyReading && readBufferIndex >= readSize) {
|
2020-08-18 20:42:30 +00:00
|
|
|
// decrypt readBuffer and copy to CNPacketData
|
2020-08-25 22:09:31 +00:00
|
|
|
CNSocketEncryption::decryptData((uint8_t*)&readBuffer, (uint8_t*)(&EKey), readSize);
|
2020-08-18 20:42:30 +00:00
|
|
|
|
2020-08-26 19:23:40 +00:00
|
|
|
void* tmpBuf = readBuffer+sizeof(uint32_t);
|
2020-08-22 23:31:09 +00:00
|
|
|
CNPacketData tmp(tmpBuf, *((uint32_t*)readBuffer), readSize-sizeof(int32_t));
|
|
|
|
|
|
|
|
// call packet handler!!
|
|
|
|
pHandler(this, &tmp);
|
2020-08-18 20:42:30 +00:00
|
|
|
|
|
|
|
// reset vars :)
|
|
|
|
readSize = 0;
|
|
|
|
readBufferIndex = 0;
|
|
|
|
activelyReading = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-08 20:02:37 +00:00
|
|
|
void printSocketError(const char *call) {
|
|
|
|
#ifdef _WIN32
|
2020-12-08 21:22:06 +00:00
|
|
|
std::cerr << call << ": ";
|
|
|
|
|
|
|
|
LPSTR lpMsgBuf = nullptr; // string buffer
|
|
|
|
DWORD errCode = WSAGetLastError(); // error code
|
|
|
|
|
|
|
|
if (errCode == 0) {
|
|
|
|
std::cerr << "no error code" << std::endl;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t bufSize = FormatMessageA( // actually get the error message
|
|
|
|
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
|
|
|
FORMAT_MESSAGE_FROM_SYSTEM |
|
|
|
|
FORMAT_MESSAGE_IGNORE_INSERTS,
|
|
|
|
NULL,
|
|
|
|
errCode, // in
|
|
|
|
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
|
|
|
(LPTSTR)&lpMsgBuf, // out
|
|
|
|
0, NULL);
|
|
|
|
|
|
|
|
// convert buffer to string and output message to terminal
|
|
|
|
std::string msg(lpMsgBuf, bufSize);
|
|
|
|
std::cerr << msg; // newline included
|
|
|
|
|
|
|
|
LocalFree(lpMsgBuf); // free the buffer
|
2020-12-08 20:02:37 +00:00
|
|
|
#else
|
|
|
|
perror(call);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2020-12-05 22:16:09 +00:00
|
|
|
bool setSockNonblocking(SOCKET listener, SOCKET newSock) {
|
2020-12-05 03:58:49 +00:00
|
|
|
#ifdef _WIN32
|
|
|
|
unsigned long mode = 1;
|
|
|
|
if (ioctlsocket(newSock, FIONBIO, &mode) != 0) {
|
|
|
|
#else
|
2020-12-06 00:44:37 +00:00
|
|
|
if (fcntl(newSock, F_SETFL, (fcntl(newSock, F_GETFL, 0) | O_NONBLOCK)) != 0) {
|
2020-12-05 03:58:49 +00:00
|
|
|
#endif
|
2020-12-08 20:02:37 +00:00
|
|
|
printSocketError("fcntl");
|
2020-12-05 03:58:49 +00:00
|
|
|
std::cerr << "[WARN] OpenFusion: fcntl failed on new connection" << std::endl;
|
|
|
|
#ifdef _WIN32
|
|
|
|
shutdown(newSock, SD_BOTH);
|
|
|
|
closesocket(newSock);
|
|
|
|
#else
|
|
|
|
shutdown(newSock, SHUT_RDWR);
|
|
|
|
close(newSock);
|
|
|
|
#endif
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2020-08-18 20:42:30 +00:00
|
|
|
// ========================================================[[ CNServer ]]========================================================
|
|
|
|
|
|
|
|
void CNServer::init() {
|
2020-09-14 13:53:48 +00:00
|
|
|
// create socket file descriptor
|
2020-08-18 20:42:30 +00:00
|
|
|
sock = socket(AF_INET, SOCK_STREAM, 0);
|
2020-09-14 13:53:48 +00:00
|
|
|
if (SOCKETINVALID(sock)) {
|
2020-12-08 20:02:37 +00:00
|
|
|
printSocketError("socket");
|
2020-09-14 13:53:48 +00:00
|
|
|
std::cerr << "[FATAL] OpenFusion: socket failed" << std::endl;
|
|
|
|
exit(EXIT_FAILURE);
|
2020-08-18 20:42:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// attach socket to the port
|
|
|
|
int opt = 1;
|
|
|
|
#ifdef _WIN32
|
2020-09-14 13:53:48 +00:00
|
|
|
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char*)&opt, sizeof(opt)) != 0) {
|
2020-08-18 20:42:30 +00:00
|
|
|
#else
|
2020-09-14 13:53:48 +00:00
|
|
|
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) != 0) {
|
2020-08-18 20:42:30 +00:00
|
|
|
#endif
|
2020-09-14 13:53:48 +00:00
|
|
|
std::cerr << "[FATAL] OpenFusion: setsockopt failed" << std::endl;
|
2020-12-08 20:02:37 +00:00
|
|
|
printSocketError("setsockopt");
|
2020-09-14 13:53:48 +00:00
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
address.sin_family = AF_INET;
|
|
|
|
address.sin_addr.s_addr = INADDR_ANY;
|
|
|
|
address.sin_port = htons(port);
|
2020-08-18 20:42:30 +00:00
|
|
|
|
|
|
|
addressSize = sizeof(address);
|
|
|
|
|
|
|
|
// Bind to the port
|
2020-09-14 13:53:48 +00:00
|
|
|
if (SOCKETERROR(bind(sock, (struct sockaddr *)&address, addressSize))) {
|
|
|
|
std::cerr << "[FATAL] OpenFusion: bind failed" << std::endl;
|
2020-12-08 20:02:37 +00:00
|
|
|
printSocketError("bind");
|
2020-09-14 13:53:48 +00:00
|
|
|
exit(EXIT_FAILURE);
|
2020-08-18 20:42:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (SOCKETERROR(listen(sock, SOMAXCONN))) {
|
2020-09-14 13:53:48 +00:00
|
|
|
std::cerr << "[FATAL] OpenFusion: listen failed" << std::endl;
|
2020-12-08 20:02:37 +00:00
|
|
|
printSocketError("listen");
|
2020-09-14 13:53:48 +00:00
|
|
|
exit(EXIT_FAILURE);
|
2020-08-18 20:42:30 +00:00
|
|
|
}
|
2020-12-04 23:37:04 +00:00
|
|
|
|
|
|
|
// set server listener to non-blocking
|
|
|
|
#ifdef _WIN32
|
|
|
|
unsigned long mode = 1;
|
|
|
|
if (ioctlsocket(sock, FIONBIO, &mode) != 0) {
|
|
|
|
#else
|
|
|
|
if (fcntl(sock, F_SETFL, (fcntl(sock, F_GETFL, 0) | O_NONBLOCK)) != 0) {
|
|
|
|
#endif
|
2020-12-08 20:02:37 +00:00
|
|
|
printSocketError("fcntl");
|
2020-12-04 23:37:04 +00:00
|
|
|
std::cerr << "[FATAL] OpenFusion: fcntl failed" << std::endl;
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
2020-12-05 03:58:49 +00:00
|
|
|
|
|
|
|
// poll() configuration
|
2020-12-05 20:59:37 +00:00
|
|
|
fds.reserve(STARTFDSCOUNT);
|
|
|
|
fds.push_back({sock, POLLIN});
|
2020-08-18 20:42:30 +00:00
|
|
|
}
|
|
|
|
|
2020-08-24 21:11:40 +00:00
|
|
|
CNServer::CNServer() {};
|
|
|
|
CNServer::CNServer(uint16_t p): port(p) {}
|
2020-08-18 20:42:30 +00:00
|
|
|
|
2020-12-05 03:58:49 +00:00
|
|
|
void CNServer::addPollFD(SOCKET s) {
|
2020-12-05 20:59:37 +00:00
|
|
|
fds.push_back({s, POLLIN});
|
2020-12-05 03:58:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CNServer::removePollFD(int i) {
|
2020-12-05 20:59:37 +00:00
|
|
|
auto it = fds.begin();
|
|
|
|
while (it != fds.end() && it->fd != fds[i].fd)
|
|
|
|
it++;
|
|
|
|
assert(it != fds.end());
|
2020-12-05 03:58:49 +00:00
|
|
|
|
2020-12-05 20:59:37 +00:00
|
|
|
fds.erase(it);
|
2020-12-05 03:58:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CNServer::start() {
|
|
|
|
int oldnfds;
|
2020-12-04 19:09:39 +00:00
|
|
|
|
2020-08-18 20:42:30 +00:00
|
|
|
std::cout << "Starting server at *:" << port << std::endl;
|
2020-08-19 00:52:02 +00:00
|
|
|
while (active) {
|
2020-12-04 19:09:39 +00:00
|
|
|
// the timeout is to ensure shard timers are ticking
|
2020-12-05 20:59:37 +00:00
|
|
|
int n = poll(fds.data(), fds.size(), 50);
|
2020-12-04 23:52:36 +00:00
|
|
|
if (SOCKETERROR(n)) {
|
2020-12-08 19:10:02 +00:00
|
|
|
#ifndef _WIN32
|
|
|
|
if (errno == EINTR)
|
|
|
|
continue;
|
|
|
|
#endif
|
2020-12-04 23:52:36 +00:00
|
|
|
std::cout << "[FATAL] poll() returned error" << std::endl;
|
2020-12-08 20:02:37 +00:00
|
|
|
printSocketError("poll");
|
2020-12-06 04:25:23 +00:00
|
|
|
terminate(0);
|
2020-12-04 19:09:39 +00:00
|
|
|
}
|
2020-08-19 00:52:02 +00:00
|
|
|
|
2020-12-05 20:59:37 +00:00
|
|
|
oldnfds = fds.size();
|
2020-12-04 22:02:15 +00:00
|
|
|
|
|
|
|
for (int i = 0; i < oldnfds && n > 0; i++) {
|
2020-12-04 19:09:39 +00:00
|
|
|
if (fds[i].revents == 0)
|
|
|
|
continue; // nothing in this one; don't decrement n
|
|
|
|
|
2020-12-05 03:58:49 +00:00
|
|
|
n--;
|
|
|
|
|
2020-12-04 19:09:39 +00:00
|
|
|
// is it the listener?
|
|
|
|
if (fds[i].fd == sock) {
|
|
|
|
// any sort of error on the listener
|
|
|
|
if (fds[i].revents & ~POLLIN) {
|
|
|
|
std::cout << "[FATAL] Error on listener socket" << std::endl;
|
2020-12-06 04:25:23 +00:00
|
|
|
terminate(0);
|
2020-12-04 19:09:39 +00:00
|
|
|
}
|
|
|
|
|
2020-12-04 22:02:15 +00:00
|
|
|
SOCKET newConnectionSocket = accept(sock, (struct sockaddr *)&address, (socklen_t*)&addressSize);
|
2020-12-08 20:02:37 +00:00
|
|
|
if (SOCKETINVALID(newConnectionSocket)) {
|
|
|
|
printSocketError("accept");
|
2020-12-04 19:09:39 +00:00
|
|
|
continue;
|
2020-12-08 20:02:37 +00:00
|
|
|
}
|
2020-12-04 19:09:39 +00:00
|
|
|
|
2020-12-05 03:58:49 +00:00
|
|
|
if (!setSockNonblocking(sock, newConnectionSocket))
|
2020-12-04 23:37:04 +00:00
|
|
|
continue;
|
|
|
|
|
2020-12-04 19:09:39 +00:00
|
|
|
std::cout << "New connection! " << inet_ntoa(address.sin_addr) << std::endl;
|
|
|
|
|
2020-12-05 03:58:49 +00:00
|
|
|
addPollFD(newConnectionSocket);
|
2020-12-04 19:09:39 +00:00
|
|
|
|
|
|
|
// add connection to list!
|
|
|
|
CNSocket* tmp = new CNSocket(newConnectionSocket, pHandler);
|
2020-12-05 03:58:49 +00:00
|
|
|
connections[newConnectionSocket] = tmp;
|
2020-12-04 19:09:39 +00:00
|
|
|
newConnection(tmp);
|
|
|
|
|
2020-12-06 00:44:37 +00:00
|
|
|
} else if (checkExtraSockets(i)) {
|
|
|
|
// no-op. handled in checkExtraSockets().
|
|
|
|
|
2020-12-04 19:09:39 +00:00
|
|
|
} else {
|
2020-12-06 01:20:46 +00:00
|
|
|
std::lock_guard<std::mutex> lock(activeCrit); // protect operations on connections
|
|
|
|
|
2020-12-04 19:09:39 +00:00
|
|
|
// player sockets
|
2020-12-05 03:58:49 +00:00
|
|
|
if (connections.find(fds[i].fd) == connections.end()) {
|
|
|
|
std::cout << "[WARN] Event on non-existant socket?" << std::endl;
|
|
|
|
continue; // just to be safe
|
2020-12-04 19:09:39 +00:00
|
|
|
}
|
|
|
|
|
2020-12-05 03:58:49 +00:00
|
|
|
CNSocket* cSock = connections[fds[i].fd];
|
|
|
|
|
|
|
|
// kill the socket on hangup/error
|
|
|
|
if (fds[i].revents & ~POLLIN)
|
|
|
|
cSock->kill();
|
|
|
|
|
|
|
|
if (cSock->isAlive()) {
|
|
|
|
cSock->step();
|
|
|
|
} else {
|
|
|
|
killConnection(cSock);
|
|
|
|
connections.erase(fds[i].fd);
|
|
|
|
delete cSock;
|
|
|
|
|
|
|
|
removePollFD(i);
|
|
|
|
}
|
|
|
|
}
|
2020-12-04 19:09:39 +00:00
|
|
|
}
|
2020-08-18 20:42:30 +00:00
|
|
|
|
2020-08-24 21:11:40 +00:00
|
|
|
onStep();
|
2020-08-18 20:42:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-19 00:52:02 +00:00
|
|
|
void CNServer::kill() {
|
|
|
|
std::lock_guard<std::mutex> lock(activeCrit); // the lock will be removed when the function ends
|
|
|
|
active = false;
|
|
|
|
|
|
|
|
// kill all connections
|
2020-12-05 03:58:49 +00:00
|
|
|
for (auto& pair : connections) {
|
|
|
|
CNSocket *cSock = pair.second;
|
|
|
|
if (cSock->isAlive())
|
2020-08-19 00:52:02 +00:00
|
|
|
cSock->kill();
|
|
|
|
|
|
|
|
delete cSock;
|
|
|
|
}
|
|
|
|
|
|
|
|
connections.clear();
|
|
|
|
}
|
|
|
|
|
2020-08-23 21:09:31 +00:00
|
|
|
void CNServer::printPacket(CNPacketData *data, int type) {
|
|
|
|
if (settings::VERBOSITY < 2)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (settings::VERBOSITY < 3) switch (data->type) {
|
|
|
|
case P_CL2LS_REP_LIVE_CHECK:
|
|
|
|
case P_CL2FE_REP_LIVE_CHECK:
|
|
|
|
case P_CL2FE_REQ_PC_MOVE:
|
|
|
|
case P_CL2FE_REQ_PC_JUMP:
|
|
|
|
case P_CL2FE_REQ_PC_SLOPE:
|
|
|
|
case P_CL2FE_REQ_PC_MOVEPLATFORM:
|
|
|
|
case P_CL2FE_REQ_PC_MOVETRANSPORTATION:
|
|
|
|
case P_CL2FE_REQ_PC_ZIPLINE:
|
|
|
|
case P_CL2FE_REQ_PC_JUMPPAD:
|
|
|
|
case P_CL2FE_REQ_PC_LAUNCHER:
|
|
|
|
case P_CL2FE_REQ_PC_STOP:
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::cout << "OpenFusion: received " << Defines::p2str(type, data->type) << " (" << data->type << ")" << std::endl;
|
|
|
|
}
|
|
|
|
|
2020-12-06 00:44:37 +00:00
|
|
|
bool CNServer::checkExtraSockets(int i) { return false; } // stubbed
|
2020-08-22 23:31:09 +00:00
|
|
|
void CNServer::newConnection(CNSocket* cns) {} // stubbed
|
|
|
|
void CNServer::killConnection(CNSocket* cns) {} // stubbed
|
2020-08-24 21:11:40 +00:00
|
|
|
void CNServer::onStep() {} // stubbed
|