1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729 |
- /*
- EQ2Emulator: Everquest II Server Emulator
- Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net)
- This file is part of EQ2Emulator.
- EQ2Emulator is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
- EQ2Emulator is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
- */
- #include "../common/debug.h"
- #include <iostream>
- using namespace std;
- #include <string.h>
- #include <stdio.h>
- #include <iomanip>
- using namespace std;
- #include "TCPConnection.h"
- #include "../common/servertalk.h"
- #include "../common/timer.h"
- #include "../common/packet_dump.h"
- #include "Log.h"
- #ifdef FREEBSD //Timothy Whitman - January 7, 2003
- #define MSG_NOSIGNAL 0
- #endif
- #ifdef WIN32
- InitWinsock winsock;
- #endif
- #define LOOP_GRANULARITY 3 //# of ms between checking our socket/queues
- #define SERVER_LOOP_GRANULARITY 3 //# of ms between checking our socket/queues
- #define TCPN_DEBUG 0
- #define TCPN_DEBUG_Console 0
- #define TCPN_DEBUG_Memory 0
- #define TCPN_LOG_PACKETS 0
- #define TCPN_LOG_RAW_DATA_OUT 0
- #define TCPN_LOG_RAW_DATA_IN 0
- TCPConnection::TCPNetPacket_Struct* TCPConnection::MakePacket(ServerPacket* pack, int32 iDestination) {
- sint32 size = sizeof(TCPNetPacket_Struct) + pack->size;
- if (pack->compressed) {
- size += 4;
- }
- if (iDestination) {
- size += 4;
- }
- TCPNetPacket_Struct* tnps = (TCPNetPacket_Struct*) new uchar[size];
- tnps->size = size;
- tnps->opcode = pack->opcode;
- *((int8*) &tnps->flags) = 0;
- uchar* buffer = tnps->buffer;
- if (pack->compressed) {
- tnps->flags.compressed = 1;
- *((sint32*) buffer) = pack->InflatedSize;
- buffer += 4;
- }
- if (iDestination) {
- tnps->flags.destination = 1;
- *((sint32*) buffer) = iDestination;
- buffer += 4;
- }
- memcpy(buffer, pack->pBuffer, pack->size);
- return tnps;
- }
- TCPConnection::TCPConnection(bool iOldFormat, TCPServer* iRelayServer, eTCPMode iMode) {
- id = 0;
- Server = iRelayServer;
- if (Server)
- RelayServer = true;
- else
- RelayServer = false;
- RelayLink = 0;
- RelayCount = 0;
- RemoteID = 0;
- pOldFormat = iOldFormat;
- ConnectionType = Outgoing;
- TCPMode = iMode;
- pState = TCPS_Ready;
- pFree = false;
- pEcho = false;
- sock = 0;
- rIP = 0;
- rPort = 0;
- keepalive_timer = new Timer(SERVER_TIMEOUT);
- timeout_timer = new Timer(SERVER_TIMEOUT * 2);
- recvbuf = 0;
- sendbuf = 0;
- pRunLoop = false;
- charAsyncConnect = 0;
- pAsyncConnect = false;
- connection_socket = 0;
- recvbuf_size = 0;
- recvbuf_used = 0;
- recvbuf_echo = 0;
- sendbuf_size = 0;
- sendbuf_used = 0;
- #if TCPN_DEBUG_Memory >= 7
- cout << "Constructor #1 on outgoing TCP# " << GetID() << endl;
- #endif
- }
- TCPConnection::TCPConnection(TCPServer* iServer, SOCKET in_socket, int32 irIP, int16 irPort, bool iOldFormat) {
- Server = iServer;
- RelayLink = 0;
- RelayServer = false;
- RelayCount = 0;
- RemoteID = 0;
- id = Server->GetNextID();
- ConnectionType = Incomming;
- pOldFormat = iOldFormat;
- TCPMode = modePacket;
- pState = TCPS_Connected;
- pFree = false;
- pEcho = false;
- sock = 0;
- connection_socket = in_socket;
- rIP = irIP;
- rPort = irPort;
- keepalive_timer = new Timer(SERVER_TIMEOUT);
- timeout_timer = new Timer(SERVER_TIMEOUT * 2);
- recvbuf = 0;
- sendbuf = 0;
- pRunLoop = false;
- charAsyncConnect = 0;
- pAsyncConnect = false;
- recvbuf_size = 0;
- recvbuf_used = 0;
- recvbuf_echo = 0;
- sendbuf_size = 0;
- sendbuf_used = 0;
- #if TCPN_DEBUG_Memory >= 7
- cout << "Constructor #2 on outgoing TCP# " << GetID() << endl;
- #endif
- }
- TCPConnection::TCPConnection(TCPServer* iServer, TCPConnection* iRelayLink, int32 iRemoteID, int32 irIP, int16 irPort) {
- Server = iServer;
- RelayLink = iRelayLink;
- RelayServer = true;
- id = Server->GetNextID();
- RelayCount = 0;
- RemoteID = iRemoteID;
- if (!RemoteID)
- ThrowError("Error: TCPConnection: RemoteID == 0 on RelayLink constructor");
- pOldFormat = false;
- ConnectionType = Incomming;
- TCPMode = modePacket;
- pState = TCPS_Connected;
- pFree = false;
- pEcho = false;
- sock = 0;
- connection_socket = 0;
- rIP = irIP;
- rPort = irPort;
- keepalive_timer = 0;
- timeout_timer = 0;
- recvbuf = 0;
- sendbuf = 0;
- pRunLoop = false;
- charAsyncConnect = 0;
- pAsyncConnect = false;
- recvbuf_size = 0;
- recvbuf_used = 0;
- recvbuf_echo = 0;
- sendbuf_size = 0;
- sendbuf_used = 0;
- #if TCPN_DEBUG_Memory >= 7
- cout << "Constructor #3 on outgoing TCP# " << GetID() << endl;
- #endif
- }
- TCPConnection::~TCPConnection() {
- Disconnect();
- ClearBuffers();
- if (ConnectionType == Outgoing) {
- MRunLoop.lock();
- pRunLoop = false;
- MRunLoop.unlock();
- MLoopRunning.lock();
- MLoopRunning.unlock();
- #if TCPN_DEBUG_Memory >= 6
- cout << "Deconstructor on outgoing TCP# " << GetID() << endl;
- #endif
- }
- #if TCPN_DEBUG_Memory >= 5
- else {
- cout << "Deconstructor on incomming TCP# " << GetID() << endl;
- }
- #endif
- safe_delete(keepalive_timer);
- safe_delete(timeout_timer);
- safe_delete_array(recvbuf);
- safe_delete_array(sendbuf);
- safe_delete_array(charAsyncConnect);
- }
- void TCPConnection::SetState(int8 in_state) {
- MState.lock();
- pState = in_state;
- MState.unlock();
- }
- int8 TCPConnection::GetState() {
- int8 ret;
- MState.lock();
- ret = pState;
- MState.unlock();
- return ret;
- }
- void TCPConnection::Free() {
- if (ConnectionType == Outgoing) {
- ThrowError("TCPConnection::Free() called on an Outgoing connection");
- }
- #if TCPN_DEBUG_Memory >= 5
- cout << "Free on TCP# " << GetID() << endl;
- #endif
- Disconnect();
- pFree = true;
- }
- bool TCPConnection::SendPacket(ServerPacket* pack, int32 iDestination) {
- LockMutex lock(&MState);
- if (!Connected())
- return false;
- eTCPMode tmp = GetMode();
- if (tmp != modePacket && tmp != modeTransition)
- return false;
- if (RemoteID)
- return RelayLink->SendPacket(pack, RemoteID);
- else {
- TCPNetPacket_Struct* tnps = MakePacket(pack, iDestination);
- if (tmp == modeTransition) {
- InModeQueuePush(tnps);
- }
- else {
- #if TCPN_LOG_PACKETS >= 1
- if (pack && pack->opcode != 0) {
- struct in_addr in;
- in.s_addr = GetrIP();
- CoutTimestamp(true);
- cout << ": Logging outgoing TCP packet. OPCode: 0x" << hex << setw(4) << setfill('0') << pack->opcode << dec << ", size: " << setw(5) << setfill(' ') << pack->size << " " << inet_ntoa(in) << ":" << GetrPort() << endl;
- #if TCPN_LOG_PACKETS == 2
- if (pack->size >= 32)
- DumpPacket(pack->pBuffer, 32);
- else
- DumpPacket(pack);
- #endif
- #if TCPN_LOG_PACKETS >= 3
- DumpPacket(pack);
- #endif
- }
- #endif
- ServerSendQueuePushEnd((uchar**) &tnps, tnps->size);
- }
- }
- return true;
- }
- bool TCPConnection::SendPacket(TCPNetPacket_Struct* tnps) {
- LockMutex lock(&MState);
- if (RemoteID)
- return false;
- if (!Connected())
- return false;
- eTCPMode tmp = GetMode();
- if (tmp == modeTransition) {
- TCPNetPacket_Struct* tnps2 = (TCPNetPacket_Struct*) new uchar[tnps->size];
- memcpy(tnps2, tnps, tnps->size);
- InModeQueuePush(tnps2);
- return true;
- }
- if (GetMode() != modePacket)
- return false;
- #if TCPN_LOG_PACKETS >= 1
- if (tnps && tnps->opcode != 0) {
- struct in_addr in;
- in.s_addr = GetrIP();
- CoutTimestamp(true);
- cout << ": Logging outgoing TCP NetPacket. OPCode: 0x" << hex << setw(4) << setfill('0') << tnps->opcode << dec << ", size: " << setw(5) << setfill(' ') << tnps->size << " " << inet_ntoa(in) << ":" << GetrPort();
- if (pOldFormat)
- cout << " (OldFormat)";
- cout << endl;
- #if TCPN_LOG_PACKETS == 2
- if (tnps->size >= 32)
- DumpPacket((uchar*) tnps, 32);
- else
- DumpPacket((uchar*) tnps, tnps->size);
- #endif
- #if TCPN_LOG_PACKETS >= 3
- DumpPacket((uchar*) tnps, tnps->size);
- #endif
- }
- #endif
- ServerSendQueuePushEnd((const uchar*) tnps, tnps->size);
- return true;
- }
- bool TCPConnection::Send(const uchar* data, sint32 size) {
- if (!Connected())
- return false;
- if (GetMode() != modeConsole)
- return false;
- if (!size)
- return true;
- ServerSendQueuePushEnd(data, size);
- return true;
- }
- void TCPConnection::InModeQueuePush(TCPNetPacket_Struct* tnps) {
- MSendQueue.lock();
- InModeQueue.push(tnps);
- MSendQueue.unlock();
- }
- void TCPConnection::ServerSendQueuePushEnd(const uchar* data, sint32 size) {
- MSendQueue.lock();
- if (sendbuf == 0) {
- sendbuf = new uchar[size];
- sendbuf_size = size;
- sendbuf_used = 0;
- }
- else if (size > (sendbuf_size - sendbuf_used)) {
- sendbuf_size += size + 1024;
- uchar* tmp = new uchar[sendbuf_size];
- memcpy(tmp, sendbuf, sendbuf_used);
- safe_delete_array(sendbuf);
- sendbuf = tmp;
- }
- memcpy(&sendbuf[sendbuf_used], data, size);
- sendbuf_used += size;
- MSendQueue.unlock();
- }
- void TCPConnection::ServerSendQueuePushEnd(uchar** data, sint32 size) {
- MSendQueue.lock();
- if (sendbuf == 0) {
- sendbuf = *data;
- sendbuf_size = size;
- sendbuf_used = size;
- MSendQueue.unlock();
- *data = 0;
- return;
- }
- if (size > (sendbuf_size - sendbuf_used)) {
- sendbuf_size += size;
- uchar* tmp = new uchar[sendbuf_size];
- memcpy(tmp, sendbuf, sendbuf_used);
- safe_delete_array(sendbuf);
- sendbuf = tmp;
- }
- memcpy(&sendbuf[sendbuf_used], *data, size);
- sendbuf_used += size;
- MSendQueue.unlock();
- delete[] (TCPNetPacket_Struct*)*data;
- }
- void TCPConnection::ServerSendQueuePushFront(uchar* data, sint32 size) {
- MSendQueue.lock();
- if (sendbuf == 0) {
- sendbuf = new uchar[size];
- sendbuf_size = size;
- sendbuf_used = 0;
- }
- else if (size > (sendbuf_size - sendbuf_used)) {
- sendbuf_size += size;
- uchar* tmp = new uchar[sendbuf_size];
- memcpy(&tmp[size], sendbuf, sendbuf_used);
- safe_delete_array(sendbuf);
- sendbuf = tmp;
- }
- memcpy(sendbuf, data, size);
- sendbuf_used += size;
- MSendQueue.unlock();
- }
- bool TCPConnection::ServerSendQueuePop(uchar** data, sint32* size) {
- bool ret;
- if (!MSendQueue.trylock())
- return false;
- if (sendbuf) {
- *data = sendbuf;
- *size = sendbuf_used;
- sendbuf = 0;
- ret = true;
- }
- else {
- ret = false;
- }
- MSendQueue.unlock();
- return ret;
- }
- ServerPacket* TCPConnection::PopPacket() {
- ServerPacket* ret;
- if (!MOutQueueLock.trylock())
- return 0;
- ret = OutQueue.pop();
- MOutQueueLock.unlock();
- return ret;
- }
- char* TCPConnection::PopLine() {
- char* ret;
- if (!MOutQueueLock.trylock())
- return 0;
- ret = (char*) LineOutQueue.pop();
- MOutQueueLock.unlock();
- return ret;
- }
- void TCPConnection::OutQueuePush(ServerPacket* pack) {
- MOutQueueLock.lock();
- OutQueue.push(pack);
- MOutQueueLock.unlock();
- }
- void TCPConnection::LineOutQueuePush(char* line) {
- #if defined(GOTFRAGS) && 0
- if (strcmp(line, "**CRASHME**") == 0) {
- int i = 0;
- cout << (5 / i) << endl;
- }
- #endif
- if (strcmp(line, "**PACKETMODE**") == 0) {
- MSendQueue.lock();
- safe_delete_array(sendbuf);
- if (TCPMode == modeConsole)
- Send((const uchar*) "\0**PACKETMODE**\r", 16);
- TCPMode = modePacket;
- TCPNetPacket_Struct* tnps = 0;
- while ((tnps = InModeQueue.pop())) {
- SendPacket(tnps);
- safe_delete_array(tnps);
- }
- MSendQueue.unlock();
- safe_delete_array(line);
- return;
- }
- MOutQueueLock.lock();
- LineOutQueue.push(line);
- MOutQueueLock.unlock();
- }
- void TCPConnection::Disconnect(bool iSendRelayDisconnect) {
- if (connection_socket != INVALID_SOCKET && connection_socket != 0) {
- MState.lock();
- if (pState == TCPS_Connected || pState == TCPS_Disconnecting || pState == TCPS_Disconnected)
- SendData();
- pState = TCPS_Closing;
- MState.unlock();
- shutdown(connection_socket, 0x01);
- shutdown(connection_socket, 0x00);
- #ifdef WIN32
- closesocket(connection_socket);
- #else
- close(connection_socket);
- #endif
- connection_socket = 0;
- rIP = 0;
- rPort = 0;
- ClearBuffers();
- }
- SetState(TCPS_Ready);
- if (RelayLink) {
- RelayLink->RemoveRelay(this, iSendRelayDisconnect);
- RelayLink = 0;
- }
- }
- bool TCPConnection::GetAsyncConnect() {
- bool ret;
- MAsyncConnect.lock();
- ret = pAsyncConnect;
- MAsyncConnect.unlock();
- return ret;
- }
- bool TCPConnection::SetAsyncConnect(bool iValue) {
- bool ret;
- MAsyncConnect.lock();
- ret = pAsyncConnect;
- pAsyncConnect = iValue;
- MAsyncConnect.unlock();
- return ret;
- }
- void TCPConnection::AsyncConnect(char* irAddress, int16 irPort) {
- if (ConnectionType != Outgoing) {
- // If this code runs, we got serious problems
- // Crash and burn.
- ThrowError("TCPConnection::AsyncConnect() call on a Incomming connection object!");
- return;
- }
- if (GetState() != TCPS_Ready)
- return;
- MAsyncConnect.lock();
- if (pAsyncConnect) {
- MAsyncConnect.unlock();
- return;
- }
- pAsyncConnect = true;
- safe_delete_array(charAsyncConnect);
- charAsyncConnect = new char[strlen(irAddress) + 1];
- strcpy(charAsyncConnect, irAddress);
- rPort = irPort;
- MAsyncConnect.unlock();
- if (!pRunLoop) {
- pRunLoop = true;
- #ifdef WIN32
- _beginthread(TCPConnectionLoop, 0, this);
- #else
- pthread_t thread;
- pthread_create(&thread, NULL, TCPConnectionLoop, this);
- pthread_detach(thread);
- #endif
- }
- return;
- }
- void TCPConnection::AsyncConnect(int32 irIP, int16 irPort) {
- if (ConnectionType != Outgoing) {
- // If this code runs, we got serious problems
- // Crash and burn.
- ThrowError("TCPConnection::AsyncConnect() call on a Incomming connection object!");
- return;
- }
- if (GetState() != TCPS_Ready)
- return;
- MAsyncConnect.lock();
- if (pAsyncConnect) {
- MAsyncConnect.unlock();
- return;
- }
- pAsyncConnect = true;
- safe_delete(charAsyncConnect);
- rIP = irIP;
- rPort = irPort;
- MAsyncConnect.unlock();
- if (!pRunLoop) {
- pRunLoop = true;
- #ifdef WIN32
- _beginthread(TCPConnectionLoop, 0, this);
- #else
- pthread_t thread;
- pthread_create(&thread, NULL, TCPConnectionLoop, this);
- pthread_detach(thread);
- #endif
- }
- return;
- }
- bool TCPConnection::Connect(char* irAddress, int16 irPort, char* errbuf) {
- if (errbuf)
- errbuf[0] = 0;
- int32 tmpIP = ResolveIP(irAddress);
- if (!tmpIP) {
- if (errbuf) {
- #ifdef WIN32
- snprintf(errbuf, TCPConnection_ErrorBufferSize, "TCPConnection::Connect(): Couldnt resolve hostname. Error: %i", WSAGetLastError());
- #else
- snprintf(errbuf, TCPConnection_ErrorBufferSize, "TCPConnection::Connect(): Couldnt resolve hostname. Error #%i: %s", errno, strerror(errno));
- #endif
- }
- return false;
- }
- return Connect(tmpIP, irPort, errbuf);
- }
- bool TCPConnection::Connect(int32 in_ip, int16 in_port, char* errbuf) {
- if (errbuf)
- errbuf[0] = 0;
- if (ConnectionType != Outgoing) {
- // If this code runs, we got serious problems
- // Crash and burn.
- ThrowError("TCPConnection::Connect() call on a Incomming connection object!");
- return false;
- }
- MState.lock();
- if (pState == TCPS_Ready) {
- pState = TCPS_Connecting;
- }
- else {
- MState.unlock();
- SetAsyncConnect(false);
- return false;
- }
- MState.unlock();
- if (!pRunLoop) {
- pRunLoop = true;
- #ifdef WIN32
- _beginthread(TCPConnectionLoop, 0, this);
- #else
- pthread_t thread;
- pthread_create(&thread, NULL, TCPConnectionLoop, this);
- pthread_detach(thread);
- #endif
- }
- connection_socket = INVALID_SOCKET;
- struct sockaddr_in server_sin;
- // struct in_addr in;
- if ((connection_socket = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET || connection_socket == 0) {
- #ifdef WIN32
- if (errbuf)
- snprintf(errbuf, TCPConnection_ErrorBufferSize, "TCPConnection::Connect(): Allocating socket failed. Error: %i", WSAGetLastError());
- #else
- if (errbuf)
- snprintf(errbuf, TCPConnection_ErrorBufferSize, "TCPConnection::Connect(): Allocating socket failed. Error: %s", strerror(errno));
- #endif
- SetState(TCPS_Ready);
- SetAsyncConnect(false);
- return false;
- }
- server_sin.sin_family = AF_INET;
- server_sin.sin_addr.s_addr = in_ip;
- server_sin.sin_port = htons(in_port);
- // Establish a connection to the server socket.
- #ifdef WIN32
- if (connect(connection_socket, (PSOCKADDR) &server_sin, sizeof (server_sin)) == SOCKET_ERROR) {
- if (errbuf)
- snprintf(errbuf, TCPConnection_ErrorBufferSize, "TCPConnection::Connect(): connect() failed. Error: %i", WSAGetLastError());
- closesocket(connection_socket);
- connection_socket = 0;
- SetState(TCPS_Ready);
- SetAsyncConnect(false);
- return false;
- }
- #else
- if (connect(connection_socket, (struct sockaddr *) &server_sin, sizeof (server_sin)) == SOCKET_ERROR) {
- if (errbuf)
- snprintf(errbuf, TCPConnection_ErrorBufferSize, "TCPConnection::Connect(): connect() failed. Error: %s", strerror(errno));
- close(connection_socket);
- connection_socket = 0;
- SetState(TCPS_Ready);
- SetAsyncConnect(false);
- return false;
- }
- #endif
- int bufsize = 64 * 1024; // 64kbyte recieve buffer, up from default of 8k
- setsockopt(connection_socket, SOL_SOCKET, SO_RCVBUF, (char*) &bufsize, sizeof(bufsize));
- #ifdef WIN32
- unsigned long nonblocking = 1;
- ioctlsocket(connection_socket, FIONBIO, &nonblocking);
- #else
- fcntl(connection_socket, F_SETFL, O_NONBLOCK);
- #endif
- SetEcho(false);
- MSendQueue.lock();
- ClearBuffers();
- TCPMode = modePacket;
- MSendQueue.unlock();
- rIP = in_ip;
- rPort = in_port;
- SetState(TCPS_Connected);
- SetAsyncConnect(false);
- return true;
- }
- void TCPConnection::ClearBuffers() {
- LockMutex lock1(&MSendQueue);
- LockMutex lock2(&MOutQueueLock);
- LockMutex lock3(&MRunLoop);
- LockMutex lock4(&MState);
- safe_delete_array(recvbuf);
- safe_delete_array(sendbuf);
- ServerPacket* pack = 0;
- while ((pack = PopPacket()))
- safe_delete(pack);
- TCPNetPacket_Struct* tnps = 0;
- while ((tnps = InModeQueue.pop()))
- safe_delete(tnps);
- char* line = 0;
- while ((line = LineOutQueue.pop()))
- safe_delete_array(line);
- keepalive_timer->Start();
- timeout_timer->Start();
- }
- bool TCPConnection::CheckNetActive() {
- MState.lock();
- if (pState == TCPS_Connected || pState == TCPS_Disconnecting) {
- MState.unlock();
- return true;
- }
- MState.unlock();
- return false;
- }
- bool TCPConnection::Process() {
- char errbuf[TCPConnection_ErrorBufferSize];
- if (!CheckNetActive()) {
- if (ConnectionType == Outgoing) {
- if (GetAsyncConnect()) {
- if (charAsyncConnect)
- rIP = ResolveIP(charAsyncConnect);
- Connect(rIP, rPort);
- }
- }
- if (GetState() == TCPS_Disconnected) {
- Disconnect();
- return false;
- }
- else if (GetState() == TCPS_Connecting)
- return true;
- else
- return false;
- }
- if (!SendData(errbuf)) {
- struct in_addr in;
- in.s_addr = GetrIP();
- cout << inet_ntoa(in) << ":" << GetrPort() << ": " << errbuf << endl;
- return false;
- }
- if (!Connected())
- return false;
- if (!RecvData(errbuf)) {
- struct in_addr in;
- in.s_addr = GetrIP();
- cout << inet_ntoa(in) << ":" << GetrPort() << ": " << errbuf << endl;
- return false;
- }
- return true;
- }
- bool TCPConnection::RecvData(char* errbuf) {
- if (errbuf)
- errbuf[0] = 0;
- if (!Connected()) {
- return false;
- }
- int status = 0;
- if (recvbuf == 0) {
- recvbuf = new uchar[5120];
- recvbuf_size = 5120;
- recvbuf_used = 0;
- recvbuf_echo = 0;
- }
- else if ((recvbuf_size - recvbuf_used) < 2048) {
- uchar* tmpbuf = new uchar[recvbuf_size + 5120];
- memcpy(tmpbuf, recvbuf, recvbuf_used);
- recvbuf_size += 5120;
- safe_delete_array(recvbuf);
- recvbuf = tmpbuf;
- if (recvbuf_size >= MaxTCPReceiveBufferSize) {
- if (errbuf)
- snprintf(errbuf, TCPConnection_ErrorBufferSize, "TCPConnection::RecvData(): recvbuf_size >= MaxTCPReceiveBufferSize");
- return false;
- }
- }
- status = recv(connection_socket, (char *) &recvbuf[recvbuf_used], (recvbuf_size - recvbuf_used), 0);
- if (status >= 1) {
- #if TCPN_LOG_RAW_DATA_IN >= 1
- struct in_addr in;
- in.s_addr = GetrIP();
- CoutTimestamp(true);
- cout << ": Read " << status << " bytes from network. (recvbuf_used = " << recvbuf_used << ") " << inet_ntoa(in) << ":" << GetrPort();
- if (pOldFormat)
- cout << " (OldFormat)";
- cout << endl;
- #if TCPN_LOG_RAW_DATA_IN == 2
- sint32 tmp = status;
- if (tmp > 32)
- tmp = 32;
- DumpPacket(&recvbuf[recvbuf_used], status);
- #elif TCPN_LOG_RAW_DATA_IN >= 3
- DumpPacket(&recvbuf[recvbuf_used], status);
- #endif
- #endif
- recvbuf_used += status;
- timeout_timer->Start();
- if (!ProcessReceivedData(errbuf))
- return false;
- }
- else if (status == SOCKET_ERROR) {
- #ifdef WIN32
- if (!(WSAGetLastError() == WSAEWOULDBLOCK)) {
- if (errbuf)
- snprintf(errbuf, TCPConnection_ErrorBufferSize, "TCPConnection::RecvData(): Error: %i", WSAGetLastError());
- return false;
- }
- #else
- if (!(errno == EWOULDBLOCK)) {
- if (errbuf)
- snprintf(errbuf, TCPConnection_ErrorBufferSize, "TCPConnection::RecvData(): Error: %s", strerror(errno));
- return false;
- }
- #endif
- }
- if ((TCPMode == modePacket || TCPMode == modeTransition) && timeout_timer->Check()) {
- if (errbuf)
- snprintf(errbuf, TCPConnection_ErrorBufferSize, "TCPConnection::RecvData(): Connection timeout");
- return false;
- }
- return true;
- }
- bool TCPConnection::GetEcho() {
- bool ret;
- MEcho.lock();
- ret = pEcho;
- MEcho.unlock();
- return ret;
- }
- void TCPConnection::SetEcho(bool iValue) {
- MEcho.lock();
- pEcho = iValue;
- MEcho.unlock();
- }
- bool TCPConnection::ProcessReceivedData(char* errbuf) {
- if (errbuf)
- errbuf[0] = 0;
- if (!recvbuf)
- return true;
- if (TCPMode == modePacket) {
- //if (pOldFormat)
- // return ProcessReceivedDataAsOldPackets(errbuf);
- //else
- return ProcessReceivedDataAsPackets(errbuf);
- }
- else {
- #if TCPN_DEBUG_Console >= 4
- if (recvbuf_used) {
- cout << "Starting Processing: recvbuf=" << recvbuf_used << endl;
- DumpPacket(recvbuf, recvbuf_used);
- }
- #endif
- for (int i=0; i < recvbuf_used; i++) {
- if (GetEcho() && i >= recvbuf_echo) {
- Send(&recvbuf[i], 1);
- recvbuf_echo = i + 1;
- }
- switch(recvbuf[i]) {
- case 0: { // 0 is the code for clear buffer
- if (i==0) {
- recvbuf_used--;
- recvbuf_echo--;
- memcpy(recvbuf, &recvbuf[1], recvbuf_used);
- i = -1;
- } else {
- if (i == recvbuf_used) {
- safe_delete_array(recvbuf);
- i = -1;
- }
- else {
- uchar* tmpdel = recvbuf;
- recvbuf = new uchar[recvbuf_size];
- memcpy(recvbuf, &tmpdel[i+1], recvbuf_used-i);
- recvbuf_used -= i + 1;
- recvbuf_echo -= i + 1;
- safe_delete(tmpdel);
- i = -1;
- }
- }
- #if TCPN_DEBUG_Console >= 5
- cout << "Removed 0x00" << endl;
- if (recvbuf_used) {
- cout << "recvbuf left: " << recvbuf_used << endl;
- DumpPacket(recvbuf, recvbuf_used);
- }
- else
- cout << "recbuf left: None" << endl;
- #endif
- break;
- }
- case 10:
- case 13: // newline marker
- {
- if (i==0) { // empty line
- recvbuf_used--;
- recvbuf_echo--;
- memcpy(recvbuf, &recvbuf[1], recvbuf_used);
- i = -1;
- } else {
- char* line = new char[i+1];
- memset(line, 0, i+1);
- memcpy(line, recvbuf, i);
- #if TCPN_DEBUG_Console >= 3
- cout << "Line Out: " << endl;
- DumpPacket((uchar*) line, i);
- #endif
- //line[i] = 0;
- uchar* tmpdel = recvbuf;
- recvbuf = new uchar[recvbuf_size];
- recvbuf_used -= i+1;
- recvbuf_echo -= i+1;
- memcpy(recvbuf, &tmpdel[i+1], recvbuf_used);
- #if TCPN_DEBUG_Console >= 5
- cout << "i+1=" << i+1 << endl;
- if (recvbuf_used) {
- cout << "recvbuf left: " << recvbuf_used << endl;
- DumpPacket(recvbuf, recvbuf_used);
- }
- else
- cout << "recbuf left: None" << endl;
- #endif
- safe_delete(tmpdel);
- if (strlen(line) > 0)
- LineOutQueuePush(line);
- else
- safe_delete_array(line);
- if (TCPMode == modePacket) {
- return ProcessReceivedDataAsPackets(errbuf);
- }
- i = -1;
- }
- break;
- }
- case 8: // backspace
- {
- if (i==0) { // nothin to backspace
- recvbuf_used--;
- recvbuf_echo--;
- memcpy(recvbuf, &recvbuf[1], recvbuf_used);
- i = -1;
- } else {
- uchar* tmpdel = recvbuf;
- recvbuf = new uchar[recvbuf_size];
- memcpy(recvbuf, tmpdel, i-1);
- memcpy(&recvbuf[i-1], &tmpdel[i+1], recvbuf_used-i);
- recvbuf_used -= 2;
- recvbuf_echo -= 2;
- safe_delete(tmpdel);
- i -= 2;
- }
- break;
- }
- }
- }
- if (recvbuf_used < 0)
- safe_delete_array(recvbuf);
- }
- return true;
- }
- bool TCPConnection::ProcessReceivedDataAsPackets(char* errbuf) {
- if (errbuf)
- errbuf[0] = 0;
- sint32 base = 0;
- sint32 size = 0;
- uchar* buffer;
- sint32 sizeReq = sizeof(TCPNetPacket_Struct);
- ServerPacket* pack = 0;
- while ((recvbuf_used - base) >= size) {
- TCPNetPacket_Struct* tnps = (TCPNetPacket_Struct*) &recvbuf[base];
- buffer = tnps->buffer;
- size = tnps->size;
- if (size < sizeReq || recvbuf_used < sizeReq || size >= MaxTCPReceiveBufferSize) {
- #if TCPN_DEBUG_Memory >= 1
- cout << "TCPConnection[" << GetID() << "]::ProcessReceivedDataAsPackets(): size[" << size << "] >= MaxTCPReceiveBufferSize" << endl;
- #endif
- if (errbuf)
- snprintf(errbuf, TCPConnection_ErrorBufferSize, "TCPConnection::ProcessReceivedDataAsPackets(): size provided %i, recvbuf_used %i, checks failed: struct_size < %i || recvbuf_used < sizeReq || size >= MaxTCPReceiveBufferSize", size, recvbuf_used, sizeReq);
- return false;
- }
- if ((recvbuf_used - base) >= size) {
- // ok, we got enough data to make this packet!
- safe_delete(pack);
- pack = new ServerPacket;
- pack->size = size - sizeof(TCPNetPacket_Struct);
- // read headers
- pack->opcode = tnps->opcode;
- if (tnps->flags.compressed) {
- sizeReq += 4;
- if(size < sizeReq || recvbuf_used < sizeReq)
- {
- if (errbuf)
- snprintf(errbuf, TCPConnection_ErrorBufferSize, "TCPConnection::ProcessReceivedDataAsPackets(Flags.Compressed): size provided %i, recvbuf_used %i, checks failed: struct_size < %i || recvbuf_used < sizeReq", size, recvbuf_used, sizeReq);
- safe_delete(pack);
- return false;
- }
- pack->compressed = true;
- pack->InflatedSize = *((sint32*)buffer);
- pack->size -= 4;
- buffer += 4;
- }
- if (tnps->flags.destination) {
- sizeReq += 4;
- if(size < sizeReq || recvbuf_used < sizeReq)
- {
- if (errbuf)
- snprintf(errbuf, TCPConnection_ErrorBufferSize, "TCPConnection::ProcessReceivedDataAsPackets(Flags.Destination): size provided %i, recvbuf_used %i, checks failed: struct_size < %i || recvbuf_used < sizeReq", size, recvbuf_used, sizeReq);
- safe_delete(pack);
- return false;
- }
- pack->destination = *((sint32*)buffer);
- pack->size -= 4;
- buffer += 4;
- }
- // end read headers
- if (pack->size > 0) {
- if (tnps->flags.compressed) {
- // Lets decompress the packet here
- pack->compressed = false;
- if(pack->InflatedSize < MaxTCPReceiveBufferSize)
- {
- pack->pBuffer = new uchar[pack->InflatedSize];
- pack->size = InflatePacket(buffer, pack->size, pack->pBuffer, pack->InflatedSize);
- if(!pack->size)
- {
- if (errbuf)
- snprintf(errbuf, TCPConnection_ErrorBufferSize, "TCPConnection::ProcessReceivedDataAsPackets(InflatePacket): size provided %i, recvbuf_used: %i, sizeReq: %i, could not inflate packet", size, recvbuf_used, sizeReq);
- safe_delete(pack);
- return false;
- }
- }
- else
- {
- cout << "Invalid inflated packet." << endl;
- safe_delete(pack);
- return false;
- }
- }
- else {
- pack->pBuffer = new uchar[pack->size];
- memcpy(pack->pBuffer, buffer, pack->size);
- }
- }
- if (pack->opcode == 0) {
- if (pack->size) {
- #if TCPN_DEBUG >= 2
- cout << "Received TCP Network layer packet" << endl;
- #endif
- ProcessNetworkLayerPacket(pack);
- }
- #if TCPN_DEBUG >= 5
- else {
- cout << "Received TCP keepalive packet. (opcode=0)" << endl;
- }
- #endif
- }
- else {
- #if TCPN_LOG_PACKETS >= 1
- if (pack && pack->opcode != 0) {
- struct in_addr in;
- in.s_addr = GetrIP();
- CoutTimestamp(true);
- cout << ": Logging incoming TCP packet. OPCode: 0x" << hex << setw(4) << setfill('0') << pack->opcode << dec << ", size: " << setw(5) << setfill(' ') << pack->size << " " << inet_ntoa(in) << ":" << GetrPort() << endl;
- #if TCPN_LOG_PACKETS == 2
- if (pack->size >= 32)
- DumpPacket(pack->pBuffer, 32);
- else
- DumpPacket(pack);
- #endif
- #if TCPN_LOG_PACKETS >= 3
- DumpPacket(pack);
- #endif
- }
- #endif
- if (RelayServer && Server && pack->destination) {
- TCPConnection* con = Server->GetConnection(pack->destination);
- if (!con) {
- #if TCPN_DEBUG >= 1
- cout << "Error relaying packet: con = 0" << endl;
- #endif
- }
- else{
- con->OutQueuePush(pack);
- pack = 0;
- }
- }
- else{
- OutQueuePush(pack);
- pack = 0;
- }
- }
- base += size;
- size = 7;
- }
- }
- safe_delete(pack);
- if (base != 0) {
- if (base >= recvbuf_used) {
- safe_delete_array(recvbuf);
- }
- else {
- uchar* tmpbuf = new uchar[recvbuf_size - base];
- memcpy(tmpbuf, &recvbuf[base], recvbuf_used - base);
- safe_delete_array(recvbuf);
- recvbuf = tmpbuf;
- recvbuf_used -= base;
- recvbuf_size -= base;
- }
- }
- return true;
- }
- bool TCPConnection::ProcessReceivedDataAsOldPackets(char* errbuf) {
- sint32 base = 0;
- sint32 size = 4;
- uchar* buffer;
- ServerPacket* pack = 0;
- while ((recvbuf_used - base) >= size) {
- buffer = &recvbuf[base];
- memcpy(&size, &buffer[2], 2);
- if (size >= MaxTCPReceiveBufferSize) {
- #if TCPN_DEBUG_Memory >= 1
- cout << "TCPConnection[" << GetID() << "]::ProcessReceivedDataAsPackets(): size[" << size << "] >= MaxTCPReceiveBufferSize" << endl;
- #endif
- if (errbuf)
- snprintf(errbuf, TCPConnection_ErrorBufferSize, "TCPConnection::ProcessReceivedDataAsPackets(): size >= MaxTCPReceiveBufferSize");
- return false;
- }
- if ((recvbuf_used - base) >= size) {
- // ok, we got enough data to make this packet!
- pack = new ServerPacket;
- memcpy(&pack->opcode, &buffer[0], 2);
- pack->size = size - 4;
- LogWrite(MISC__TODO, 1, "TODO", "Checksum or size check or something similar\n\t(%s, function: %s, line #: %i)", __FILE__, __FUNCTION__, __LINE__);
- /*
- if () { // TODO: Checksum or size check or something similar
- // Datastream corruption, get the hell outta here!
- delete pack;
- return false;
- }
- */
- if (pack->size > 0) {
- pack->pBuffer = new uchar[pack->size];
- memcpy(pack->pBuffer, &buffer[4], pack->size);
- }
- if (pack->opcode == 0) {
- // keepalive, no need to process
- safe_delete(pack);
- }
- else {
- #if TCPN_LOG_PACKETS >= 1
- if (pack && pack->opcode != 0) {
- struct in_addr in;
- in.s_addr = GetrIP();
- CoutTimestamp(true);
- cout << ": Logging incoming TCP OldPacket. OPCode: 0x" << hex << setw(4) << setfill('0') << pack->opcode << dec << ", size: " << setw(5) << setfill(' ') << pack->size << " " << inet_ntoa(in) << ":" << GetrPort() << endl;
- #if TCPN_LOG_PACKETS == 2
- if (pack->size >= 32)
- DumpPacket(pack->pBuffer, 32);
- else
- DumpPacket(pack);
- #endif
- #if TCPN_LOG_PACKETS >= 3
- DumpPacket(pack);
- #endif
- }
- #endif
- OutQueuePush(pack);
- }
- base += size;
- size = 4;
- }
- }
- if (base != 0) {
- if (base >= recvbuf_used) {
- safe_delete_array(recvbuf);
- }
- else {
- uchar* tmpbuf = new uchar[recvbuf_size - base];
- memcpy(tmpbuf, &recvbuf[base], recvbuf_used - base);
- safe_delete_array(recvbuf);
- recvbuf = tmpbuf;
- recvbuf_used -= base;
- recvbuf_size -= base;
- }
- }
- return true;
- }
- void TCPConnection::ProcessNetworkLayerPacket(ServerPacket* pack) {
- int8 opcode = pack->pBuffer[0];
- /** disabling RELAY capabilities, this functionality is poorly implemented
- even if such a feature needs to be re-used need authentication BEFORE allowing relay to take place
- secondly we need to protect the LS accepting new connections as bogus data can be passed to open
- fake TCP connections
- opcode 0 is OK, that is Keep-Alive
- **/
- if (opcode > 0)
- {
- Disconnect();
- return;
- }
- int8* data = &pack->pBuffer[1];
- switch (opcode) {
- case 0: {
- break;
- }
- case 1: { // Switch to RelayServer mode
- if (pack->size != 1) {
- SendNetErrorPacket("New RelayClient: wrong size, expected 1");
- break;
- }
- if (RelayServer) {
- SendNetErrorPacket("Switch to RelayServer mode when already in RelayServer mode");
- break;
- }
- if (RemoteID) {
- SendNetErrorPacket("Switch to RelayServer mode by a Relay Client");
- break;
- }
- if (ConnectionType != Incomming) {
- SendNetErrorPacket("Switch to RelayServer mode on outgoing connection");
- break;
- }
- #if TCPC_DEBUG >= 3
- struct in_addr in;
- in.s_addr = GetrIP();
- cout << "Switching to RelayServer mode: " << inet_ntoa(in) << ":" << GetPort() << endl;
- #endif
- RelayServer = true;
- break;
- }
- case 2: { // New Relay Client
- if (!RelayServer) {
- SendNetErrorPacket("New RelayClient when not in RelayServer mode");
- break;
- }
- if (pack->size != 11) {
- SendNetErrorPacket("New RelayClient: wrong size, expected 11");
- break;
- }
- if (ConnectionType != Incomming) {
- SendNetErrorPacket("New RelayClient: illegal on outgoing connection");
- break;
- }
- TCPConnection* con = new TCPConnection(Server, this, *((int32*) data), *((int32*) &data[4]), *((int16*) &data[8]));
- Server->AddConnection(con);
- RelayCount++;
- break;
- }
- case 3: { // Delete Relay Client
- if (!RelayServer) {
- SendNetErrorPacket("Delete RelayClient when not in RelayServer mode");
- break;
- }
- if (pack->size != 5) {
- SendNetErrorPacket("Delete RelayClient: wrong size, expected 5");
- break;
- }
- TCPConnection* con = Server->GetConnection(*((int32*)data));
- if (con) {
- if (ConnectionType == Incomming) {
- if (con->GetRelayLink() != this) {
- SendNetErrorPacket("Delete RelayClient: RelayLink != this");
- break;
- }
- }
- con->Disconnect(false);
- }
- break;
- }
- case 255: {
- #if TCPC_DEBUG >= 1
- struct in_addr in;
- in.s_addr = GetrIP();
- cout "Received NetError: '";
- if (pack->size > 1)
- cout << (char*) data;
- cout << "': " << inet_ntoa(in) << ":" << GetPort() << endl;
- #endif
- break;
- }
- }
- }
- void TCPConnection::SendNetErrorPacket(const char* reason) {
- #if TCPC_DEBUG >= 1
- struct in_addr in;
- in.s_addr = GetrIP();
- cout "NetError: '";
- if (reason)
- cout << reason;
- cout << "': " << inet_ntoa(in) << ":" << GetPort() << endl;
- #endif
- ServerPacket* pack = new ServerPacket(0);
- pack->size = 1;
- if (reason)
- pack->size += strlen(reason) + 1;
- pack->pBuffer = new uchar[pack->size];
- memset(pack->pBuffer, 0, pack->size);
- pack->pBuffer[0] = 255;
- strcpy((char*) &pack->pBuffer[1], reason);
- SendPacket(pack);
- safe_delete(pack);
- }
- void TCPConnection::RemoveRelay(TCPConnection* relay, bool iSendRelayDisconnect) {
- if (iSendRelayDisconnect) {
- ServerPacket* pack = new ServerPacket(0, 5);
- pack->pBuffer[0] = 3;
- *((int32*) &pack->pBuffer[1]) = relay->GetRemoteID();
- SendPacket(pack);
- safe_delete(pack);
- }
- RelayCount--;
- }
- bool TCPConnection::SendData(char* errbuf) {
- if (errbuf)
- errbuf[0] = 0;
- /************ Get first send packet on queue and send it! ************/
- uchar* data = 0;
- sint32 size = 0;
- int status = 0;
- if (ServerSendQueuePop(&data, &size)) {
- #ifdef WIN32
- status = send(connection_socket, (const char *) data, size, 0);
- #else
- status = send(connection_socket, data, size, MSG_NOSIGNAL);
- if(errno==EPIPE) status = SOCKET_ERROR;
- #endif
- if (status >= 1) {
- #if TCPN_LOG_RAW_DATA_OUT >= 1
- struct in_addr in;
- in.s_addr = GetrIP();
- CoutTimestamp(true);
- cout << ": Wrote " << status << " bytes to network. " << inet_ntoa(in) << ":" << GetrPort();
- if (pOldFormat)
- cout << " (OldFormat)";
- cout << endl;
- #if TCPN_LOG_RAW_DATA_OUT == 2
- sint32 tmp = status;
- if (tmp > 32)
- tmp = 32;
- DumpPacket(data, status);
- #elif TCPN_LOG_RAW_DATA_OUT >= 3
- DumpPacket(data, status);
- #endif
- #endif
- keepalive_timer->Start();
- if (status < (signed)size) {
- #if TCPN_LOG_RAW_DATA_OUT >= 1
- struct in_addr in;
- in.s_addr = GetrIP();
- CoutTimestamp(true);
- cout << ": Pushed " << (size - status) << " bytes back onto the send queue. " << inet_ntoa(in) << ":" << GetrPort();
- if (pOldFormat)
- cout << " (OldFormat)";
- cout << endl;
- #endif
- // If there's network congestion, the number of bytes sent can be less than
- // what we tried to give it... Push the extra back on the queue for later
- ServerSendQueuePushFront(&data[status], size - status);
- }
- else if (status > (signed)size) {
- ThrowError("TCPConnection::SendData(): WTF! status > size");
- return false;
- }
- // else if (status == size) {}
- }
- else {
- ServerSendQueuePushFront(data, size);
- }
- safe_delete_array(data);
- if (status == SOCKET_ERROR) {
- #ifdef WIN32
- if (WSAGetLastError() != WSAEWOULDBLOCK)
- #else
- if (errno != EWOULDBLOCK)
- #endif
- {
- if (errbuf) {
- #ifdef WIN32
- snprintf(errbuf, TCPConnection_ErrorBufferSize, "TCPConnection::SendData(): send(): Errorcode: %i", WSAGetLastError());
- #else
- snprintf(errbuf, TCPConnection_ErrorBufferSize, "TCPConnection::SendData(): send(): Errorcode: %s", strerror(errno));
- #endif
- }
- return false;
- }
- }
- }
- if (TCPMode == modePacket && keepalive_timer->Check()) {
- ServerPacket* pack = new ServerPacket(0, 0);
- SendPacket(pack);
- safe_delete(pack);
- #if TCPN_DEBUG >= 5
- cout << "Sending TCP keepalive packet. (timeout=" << timeout_timer->GetRemainingTime() << " remaining)" << endl;
- #endif
- }
- return true;
- }
- ThreadReturnType TCPConnectionLoop(void* tmp) {
- #ifdef WIN32
- SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);
- #endif
- if (tmp == 0) {
- ThrowError("TCPConnectionLoop(): tmp = 0!");
- THREAD_RETURN(NULL);
- }
- TCPConnection* tcpc = (TCPConnection*) tmp;
- tcpc->MLoopRunning.lock();
- while (tcpc->RunLoop()) {
- Sleep(LOOP_GRANULARITY);
- if (tcpc->GetState() != TCPS_Ready) {
- if (!tcpc->Process()) {
- tcpc->Disconnect();
- }
- }
- else if (tcpc->GetAsyncConnect()) {
- if (tcpc->charAsyncConnect)
- tcpc->Connect(tcpc->charAsyncConnect, tcpc->GetrPort());
- else
- tcpc->Connect(tcpc->GetrIP(), tcpc->GetrPort());
- tcpc->SetAsyncConnect(false);
- }
- else
- Sleep(10);
- }
- tcpc->MLoopRunning.unlock();
- THREAD_RETURN(NULL);
- }
- bool TCPConnection::RunLoop() {
- bool ret;
- MRunLoop.lock();
- ret = pRunLoop;
- MRunLoop.unlock();
- return ret;
- }
- TCPServer::TCPServer(int16 in_port, bool iOldFormat) {
- NextID = 1;
- pPort = in_port;
- sock = 0;
- pOldFormat = iOldFormat;
- list = new LinkedList<TCPConnection*>;
- pRunLoop = true;
- #ifdef WIN32
- _beginthread(TCPServerLoop, 0, this);
- #else
- pthread_t thread;
- pthread_create(&thread, NULL, &TCPServerLoop, this);
- pthread_detach(thread);
- #endif
- }
- TCPServer::~TCPServer() {
- MRunLoop.lock();
- pRunLoop = false;
- MRunLoop.unlock();
- MLoopRunning.lock();
- MLoopRunning.unlock();
- while (NewQueue.pop()); // the objects are deleted with the list, clear this queue so it doesnt try to delete them again
- safe_delete(list);
- }
- bool TCPServer::RunLoop() {
- bool ret;
- MRunLoop.lock();
- ret = pRunLoop;
- MRunLoop.unlock();
- return ret;
- }
- ThreadReturnType TCPServerLoop(void* tmp) {
- #ifdef WIN32
- SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);
- #endif
- if (tmp == 0) {
- ThrowError("TCPServerLoop(): tmp = 0!");
- THREAD_RETURN(NULL);
- }
- TCPServer* tcps = (TCPServer*) tmp;
- tcps->MLoopRunning.lock();
- while (tcps->RunLoop()) {
- Sleep(SERVER_LOOP_GRANULARITY);
- tcps->Process();
- }
- tcps->MLoopRunning.unlock();
- THREAD_RETURN(NULL);
- }
- void TCPServer::Process() {
- CheckInQueue();
- ListenNewConnections();
- LinkedListIterator<TCPConnection*> iterator(*list);
- iterator.Reset();
- while(iterator.MoreElements()) {
- if (iterator.GetData()->IsFree() && (!iterator.GetData()->CheckNetActive())) {
- #if _DEBUG
- LogWrite(NET__DEBUG, 0, "Net", "EQStream Connection deleted.");
- #endif
- iterator.RemoveCurrent();
- }
- else {
- if (!iterator.GetData()->Process())
- iterator.GetData()->Disconnect();
- iterator.Advance();
- }
- }
- }
- void TCPServer::ListenNewConnections() {
- SOCKET tmpsock;
- struct sockaddr_in from;
- struct in_addr in;
- unsigned int fromlen;
- TCPConnection* con;
- from.sin_family = AF_INET;
- fromlen = sizeof(from);
- LockMutex lock(&MSock);
- if (!sock)
- return;
- // Check for pending connects
- #ifdef WIN32
- unsigned long nonblocking = 1;
- while ((tmpsock = accept(sock, (struct sockaddr*) &from, (int *) &fromlen)) != INVALID_SOCKET) {
- ioctlsocket (tmpsock, FIONBIO, &nonblocking);
- #else
- while ((tmpsock = accept(sock, (struct sockaddr*) &from, &fromlen)) != INVALID_SOCKET) {
- fcntl(tmpsock, F_SETFL, O_NONBLOCK);
- #endif
- int bufsize = 64 * 1024; // 64kbyte recieve buffer, up from default of 8k
- setsockopt(tmpsock, SOL_SOCKET, SO_RCVBUF, (char*) &bufsize, sizeof(bufsize));
- in.s_addr = from.sin_addr.s_addr;
- // New TCP connection
- con = new TCPConnection(this, tmpsock, in.s_addr, ntohs(from.sin_port), pOldFormat);
- #if TCPN_DEBUG >= 1
- cout << "New TCP connection: " << inet_ntoa(in) << ":" << con->GetrPort() << endl;
- #endif
- AddConnection(con);
- }
- }
- bool TCPServer::Open(int16 in_port, char* errbuf) {
- if (errbuf)
- errbuf[0] = 0;
- LockMutex lock(&MSock);
- if (sock != 0) {
- if (errbuf)
- snprintf(errbuf, TCPConnection_ErrorBufferSize, "Listening socket already open");
- return false;
- }
- if (in_port != 0) {
- pPort = in_port;
- }
- #ifdef WIN32
- SOCKADDR_IN address;
- unsigned long nonblocking = 1;
- #else
- struct sockaddr_in address;
- #endif
- int reuse_addr = 1;
- // Setup internet address information.
- // This is used with the bind() call
- memset((char *) &address, 0, sizeof(address));
- address.sin_family = AF_INET;
- address.sin_port = htons(pPort);
- address.sin_addr.s_addr = htonl(INADDR_ANY);
- // Setting up TCP port for new TCP connections
- sock = socket(AF_INET, SOCK_STREAM, 0);
- if (sock == INVALID_SOCKET) {
- if (errbuf)
- snprintf(errbuf, TCPConnection_ErrorBufferSize, "socket(): INVALID_SOCKET");
- return false;
- }
- // Quag: dont think following is good stuff for TCP, good for UDP
- // Mis: SO_REUSEADDR shouldn't be a problem for tcp--allows you to restart
- // without waiting for conns in TIME_WAIT to die
- setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &reuse_addr, sizeof(reuse_addr));
- if (::bind(sock, (struct sockaddr *) &address, sizeof(address)) < 0) {
- #ifdef WIN32
- closesocket(sock);
- #else
- close(sock);
- #endif
- sock = 0;
- if (errbuf)
- sprintf(errbuf, "bind(): <0");
- return false;
- }
- int bufsize = 64 * 1024; // 64kbyte recieve buffer, up from default of 8k
- setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char*) &bufsize, sizeof(bufsize));
- #ifdef WIN32
- ioctlsocket (sock, FIONBIO, &nonblocking);
- #else
- fcntl(sock, F_SETFL, O_NONBLOCK);
- #endif
- if (listen(sock, SOMAXCONN) == SOCKET_ERROR) {
- #ifdef WIN32
- closesocket(sock);
- if (errbuf)
- snprintf(errbuf, TCPConnection_ErrorBufferSize, "listen() failed, Error: %d", WSAGetLastError());
- #else
- close(sock);
- if (errbuf)
- snprintf(errbuf, TCPConnection_ErrorBufferSize, "listen() failed, Error: %s", strerror(errno));
- #endif
- sock = 0;
- return false;
- }
- return true;
- }
- void TCPServer::Close() {
- LockMutex lock(&MSock);
- if (sock) {
- #ifdef WIN32
- closesocket(sock);
- #else
- close(sock);
- #endif
- }
- sock = 0;
- }
- bool TCPServer::IsOpen() {
- MSock.lock();
- bool ret = (bool) (sock != 0);
- MSock.unlock();
- return ret;
- }
- TCPConnection* TCPServer::NewQueuePop() {
- TCPConnection* ret;
- MNewQueue.lock();
- ret = NewQueue.pop();
- MNewQueue.unlock();
- return ret;
- }
- void TCPServer::AddConnection(TCPConnection* con) {
- list->Append(con);
- MNewQueue.lock();
- NewQueue.push(con);
- MNewQueue.unlock();
- }
- TCPConnection* TCPServer::GetConnection(int32 iID) {
- LinkedListIterator<TCPConnection*> iterator(*list);
- iterator.Reset();
- while(iterator.MoreElements()) {
- if (iterator.GetData()->GetID() == iID)
- return iterator.GetData();
- iterator.Advance();
- }
- return 0;
- }
- void TCPServer::SendPacket(ServerPacket* pack) {
- TCPConnection::TCPNetPacket_Struct* tnps = TCPConnection::MakePacket(pack);
- SendPacket(&tnps);
- }
- void TCPServer::SendPacket(TCPConnection::TCPNetPacket_Struct** tnps) {
- MInQueue.lock();
- InQueue.push(*tnps);
- MInQueue.unlock();
- tnps = 0;
- }
- void TCPServer::CheckInQueue() {
- LinkedListIterator<TCPConnection*> iterator(*list);
- TCPConnection::TCPNetPacket_Struct* tnps = 0;
- while (( tnps = InQueuePop() )) {
- iterator.Reset();
- while(iterator.MoreElements()) {
- if (iterator.GetData()->GetMode() != modeConsole && iterator.GetData()->GetRemoteID() == 0)
- iterator.GetData()->SendPacket(tnps);
- iterator.Advance();
- }
- safe_delete(tnps);
- }
- }
- TCPConnection::TCPNetPacket_Struct* TCPServer::InQueuePop() {
- TCPConnection::TCPNetPacket_Struct* ret;
- MInQueue.lock();
- ret = InQueue.pop();
- MInQueue.unlock();
- return ret;
- }
|