/* * Ascent MMORPG Server * Copyright (C) 2005-2007 Ascent Team * * This program 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 * any later version. * * This program 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 this program. If not, see . * */ // Class WorldSocket - Main network code functions, handles // reading/writing of all packets. #ifndef __WORLDSOCKET_H #define __WORLDSOCKET_H /* Normal WorldSocket when not using clustering */ #ifndef CLUSTERING #define WORLDSOCKET_SENDBUF_SIZE 131078 #define WORLDSOCKET_RECVBUF_SIZE 16384 class WorldPacket; class SocketHandler; class WorldSession; enum OUTPACKET_RESULT { OUTPACKET_RESULT_SUCCESS = 1, OUTPACKET_RESULT_NO_ROOM_IN_BUFFER = 2, OUTPACKET_RESULT_NOT_CONNECTED = 3, OUTPACKET_RESULT_SOCKET_ERROR = 4, }; class WorldSocket : public Socket { public: WorldSocket(SOCKET fd); ~WorldSocket(); // vs8 fix - send null on empty buffer inline void SendPacket(WorldPacket* packet) { if(!packet) return; OutPacket(packet->GetOpcode(), packet->size(), (packet->size() ? (const void*)packet->contents() : NULL)); } inline void SendPacket(StackBufferBase * packet) { if(!packet) return; OutPacket(packet->GetOpcode(), packet->GetSize(), (packet->GetSize() ? (const void*)packet->GetBufferPointer() : NULL)); } void __fastcall OutPacket(uint16 opcode, uint16 len, const void* data); OUTPACKET_RESULT __fastcall _OutPacket(uint16 opcode, uint16 len, const void* data); inline uint32 GetLatency() { return _latency; } void Authenticate(); void InformationRetreiveCallback(WorldPacket & recvData, uint32 requestid); void __fastcall UpdateQueuePosition(uint32 Position); void OnRead(); void OnConnect(); void OnDisconnect(); inline void SetSession(WorldSession * session) { mSession = session; } inline WorldSession * GetSession() { return mSession; } bool Authed; void UpdateQueuedPackets(); protected: void _HandleAuthSession(WorldPacket* recvPacket); void _HandlePing(WorldPacket* recvPacket); private: uint32 mOpcode; uint32 mRemaining; uint32 mSize; uint32 mSeed; uint32 mClientSeed; uint32 mClientBuild; uint32 mRequestID; WorldSession *mSession; WorldPacket * pAuthenticationPacket; FastQueue _queue; Mutex queueLock; WowCrypt _crypt; uint32 _latency; bool mQueued; bool m_nagleEanbled; }; #endif inline void FastGUIDPack(ByteBuffer & buf, const uint64 & oldguid) { // hehe speed freaks uint8 guidmask = 0; uint8 guidfields[9] = {0,0,0,0,0,0,0,0}; int j = 1; uint8 * test = (uint8*)&oldguid; if (*test) //7*8 { guidfields[j] = *test; guidmask |= 1; j++; } if (*(test+1)) //6*8 { guidfields[j] = *(test+1); guidmask |= 2; j++; } if (*(test+2)) //5*8 { guidfields[j] = *(test+2); guidmask |= 4; j++; } if (*(test+3)) //4*8 { guidfields[j] = *(test+3); guidmask |= 8; j++; } if (*(test+4)) //3*8 { guidfields[j] = *(test+4); guidmask |= 16; j++; } if (*(test+5))//2*8 { guidfields[j] = *(test+5); guidmask |= 32; j++; } if (*(test+6))//1*8 { guidfields[j] = *(test+6); guidmask |= 64; j++; } if (*(test+7)) //0*8 { guidfields[j] = *(test+7); guidmask |= 128; j++; } guidfields[0] = guidmask; buf.append(guidfields,j); } //!!! warning. This presumes that all guids can be compressed at least 1 byte //make sure you choose highguids acordingly inline unsigned int FastGUIDPack(const uint64 & oldguid, unsigned char * buffer, uint32 pos) { // hehe speed freaks uint8 guidmask = 0; int j = 1 + pos; #ifdef USING_BIG_ENDIAN uint64 t = swap64(oldguid); uint8 * test = (uint8*)&t; #else uint8 * test = (uint8*)&oldguid; #endif if (*test) //7*8 { buffer[j] = *test; guidmask |= 1; j++; } if (*(test+1)) //6*8 { buffer[j] = *(test+1); guidmask |= 2; j++; } if (*(test+2)) //5*8 { buffer[j] = *(test+2); guidmask |= 4; j++; } if (*(test+3)) //4*8 { buffer[j] = *(test+3); guidmask |= 8; j++; } if (*(test+4)) //3*8 { buffer[j] = *(test+4); guidmask |= 16; j++; } if (*(test+5))//2*8 { buffer[j] = *(test+5); guidmask |= 32; j++; } if (*(test+6))//1*8 { buffer[j] = *(test+6); guidmask |= 64; j++; } if (*(test+7)) //0*8 { buffer[j] = *(test+7); guidmask |= 128; j++; } buffer[pos] = guidmask; return (j - pos); } /* Modified/Simplified WorldSocket for use with clustering */ #ifdef CLUSTERING class WorldSocket { public: WorldSocket(uint32 sessionid); ~WorldSocket(); void Disconnect(); bool IsConnected(); inline string GetRemoteIP() { return string(inet_ntoa(m_address.sin_addr)); } inline uint32 GetRemotePort() { return ntohs(m_address.sin_port); } inline void SendPacket(WorldPacket* packet) { if(!packet) return; OutPacket(packet->GetOpcode(), packet->size(), (packet->size() ? (const void*)packet->contents() : NULL)); } inline void SendPacket(StackBufferBase * packet) { if(!packet) return; OutPacket(packet->GetOpcode(), packet->GetSize(), (packet->GetSize() ? (const void*)packet->GetBufferPointer() : NULL)); } void __fastcall OutPacket(uint16 opcode, uint16 len, const void* data); protected: uint32 m_sessionId; sockaddr_in m_address; }; #endif #endif