12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688 |
- /*
- 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 = 7;
- uchar* buffer;
- ServerPacket* pack = 0;
- while ((recvbuf_used - base) >= size) {
- TCPNetPacket_Struct* tnps = (TCPNetPacket_Struct*) &recvbuf[base];
- buffer = tnps->buffer;
- size = tnps->size;
- 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!
- safe_delete(pack);
- pack = new ServerPacket;
- pack->size = size - sizeof(TCPNetPacket_Struct);
- // read headers
- pack->opcode = tnps->opcode;
- if (tnps->flags.compressed) {
- pack->compressed = true;
- pack->InflatedSize = *((sint32*)buffer);
- pack->size -= 4;
- buffer += 4;
- }
- if (tnps->flags.destination) {
- 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);
- }
- 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];
- 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;
- }
|