Files
m2dev-client-src/src/EterLib/NetStream.cpp

986 lines
24 KiB
C++

#include "StdAfx.h"
#include "NetStream.h"
//#include "eterCrypt.h"
#include <iomanip>
#include <sstream>
#ifndef _IMPROVED_PACKET_ENCRYPTION_
#include "EterBase/tea.h"
#endif
#ifdef _DEBUG
#define _PACKETDUMP
#endif
#ifndef _IMPROVED_PACKET_ENCRYPTION_
void CNetworkStream::SetSecurityMode(bool isSecurityMode, const char* c_szTeaKey)
{
m_isSecurityMode = isSecurityMode;
memcpy(m_szEncryptKey, c_szTeaKey, TEA_KEY_LENGTH);
memcpy(m_szDecryptKey, c_szTeaKey, TEA_KEY_LENGTH);
}
void CNetworkStream::SetSecurityMode(bool isSecurityMode, const char* c_szTeaEncryptKey, const char* c_szTeaDecryptKey)
{
m_isSecurityMode = isSecurityMode;
memcpy(m_szEncryptKey, c_szTeaEncryptKey, TEA_KEY_LENGTH);
memcpy(m_szDecryptKey, c_szTeaDecryptKey, TEA_KEY_LENGTH);
}
#endif // _IMPROVED_PACKET_ENCRYPTION_
bool CNetworkStream::IsSecurityMode()
{
#ifdef _IMPROVED_PACKET_ENCRYPTION_
return m_cipher.activated();
#else
return m_isSecurityMode;
#endif
}
void CNetworkStream::SetRecvBufferSize(int recvBufSize)
{
if (m_recvBuf)
{
if (m_recvBufSize>recvBufSize)
return;
delete [] m_recvBuf;
if (m_recvTEABuf)
delete [] m_recvTEABuf;
}
m_recvBufSize = recvBufSize;
m_recvBuf = new char[m_recvBufSize];
m_recvTEABufSize = ((m_recvBufSize>>3)+1)<<3;
m_recvTEABuf = new char[m_recvTEABufSize];
}
void CNetworkStream::SetSendBufferSize(int sendBufSize)
{
if (m_sendBuf)
{
if (m_sendBufSize > sendBufSize)
return;
delete [] m_sendBuf;
if (m_sendTEABuf)
delete [] m_sendTEABuf;
}
m_sendBufSize = sendBufSize;
m_sendBuf = new char[m_sendBufSize];
m_sendTEABufSize = ((m_sendBufSize>>3)+1)<<3;
m_sendTEABuf = new char[m_sendTEABufSize];
}
bool CNetworkStream::__RecvInternalBuffer()
{
if (m_recvBufOutputPos>0)
{
int recvBufDataSize = m_recvBufInputPos - m_recvBufOutputPos;
if (recvBufDataSize>0)
{
memmove(m_recvBuf, m_recvBuf + m_recvBufOutputPos, recvBufDataSize);
}
m_recvBufInputPos -= m_recvBufOutputPos;
m_recvBufOutputPos = 0;
}
#ifdef _IMPROVED_PACKET_ENCRYPTION_
int restSize = m_recvBufSize - m_recvBufInputPos;
if (restSize>0)
{
int recvSize = recv(m_sock, m_recvBuf + m_recvBufInputPos, m_recvBufSize - m_recvBufInputPos, 0);
//Tracenf("RECV %d %d(%d, %d)", recvSize, restSize, m_recvTEABufSize - m_recvTEABufInputPos, m_recvBufSize - m_recvBufInputPos);
if (recvSize < 0)
{
int error = WSAGetLastError();
if (error != WSAEWOULDBLOCK)
{
return false;
}
}
else if (recvSize == 0)
{
return false;
}
if (IsSecurityMode()) {
m_cipher.Decrypt(m_recvBuf + m_recvBufInputPos, recvSize);
}
m_recvBufInputPos += recvSize;
}
#else
if (IsSecurityMode())
{
int restSize = std::min(m_recvTEABufSize - m_recvTEABufInputPos, m_recvBufSize - m_recvBufInputPos);
if (restSize > 0)
{
int recvSize = recv(m_sock, m_recvTEABuf + m_recvTEABufInputPos, restSize, 0);
//Tracenf("RECV %d %d(%d, %d)", recvSize, restSize, m_recvTEABufSize - m_recvTEABufInputPos, m_recvBufSize - m_recvBufInputPos);
if (recvSize < 0)
{
int error = WSAGetLastError();
if (error != WSAEWOULDBLOCK)
{
return false;
}
}
else if (recvSize == 0)
{
return false;
}
m_recvTEABufInputPos += recvSize;
int decodeSize = m_recvTEABufInputPos;
if (decodeSize >= 8)
{
decodeSize >>= 3;
decodeSize <<= 3;
/*int decodeDstSize = tea_decrypt((DWORD *) (m_recvBuf + m_recvBufInputPos),
(DWORD *) m_recvTEABuf,
(const DWORD *) m_szDecryptKey,
decodeSize);
*/
int decodeDstSize = tea_decrypt((DWORD *) (m_recvBuf + m_recvBufInputPos),
(DWORD *) m_recvTEABuf,
(const DWORD *) m_szDecryptKey,
decodeSize);
m_recvBufInputPos += decodeDstSize;
if (m_recvTEABufInputPos>decodeSize)
memmove(m_recvTEABuf, m_recvTEABuf+decodeSize, m_recvTEABufInputPos-decodeSize);
m_recvTEABufInputPos -= decodeSize;
//Tracenf("!!!!!! decrypt decodeSrcSize %d -> decodeDstSize %d (recvOutputPos %d, recvInputPos %d, teaInputPos %d)",
// decodeSize, decodeDstSize, m_recvBufOutputPos, m_recvBufInputPos, m_recvTEABufInputPos);
}
}
}
else
{
int restSize = m_recvBufSize - m_recvBufInputPos;
if (restSize>0)
{
int recvSize = recv(m_sock, m_recvBuf + m_recvBufInputPos, m_recvBufSize - m_recvBufInputPos, 0);
//Tracenf("RECV %d %d(%d, %d)", recvSize, restSize, m_recvTEABufSize - m_recvTEABufInputPos, m_recvBufSize - m_recvBufInputPos);
if (recvSize < 0)
{
int error = WSAGetLastError();
if (error != WSAEWOULDBLOCK)
{
return false;
}
}
else if (recvSize == 0)
{
return false;
}
m_recvBufInputPos += recvSize;
}
}
#endif // _IMPROVED_PACKET_ENCRYPTION_
//Tracef("recvSize: %d input pos %d output pos %d\n", recvSize, m_recvBufInputPos, m_recvBufOutputPos);
return true;
}
bool CNetworkStream::__SendInternalBuffer()
{
#ifdef _IMPROVED_PACKET_ENCRYPTION_
int dataSize=__GetSendBufferSize();
if (dataSize<=0)
return true;
if (IsSecurityMode()) {
m_cipher.Encrypt(m_sendBuf + m_sendBufOutputPos, dataSize);
}
int sendSize = send(m_sock, m_sendBuf+m_sendBufOutputPos, dataSize, 0);
if (sendSize < 0)
return false;
m_sendBufOutputPos+=sendSize;
__PopSendBuffer();
#else
if (IsSecurityMode())
{
int encodeSize=__GetSendBufferSize();
if (encodeSize<=0)
return true;
m_sendTEABufInputPos += tea_encrypt((DWORD *) (m_sendTEABuf + m_sendTEABufInputPos),
(DWORD *) (m_sendBuf + m_sendBufOutputPos),
(const DWORD *) m_szEncryptKey,
encodeSize);
m_sendBufOutputPos += encodeSize;
if (m_sendTEABufInputPos>0)
{
int sendSize = send(m_sock, m_sendTEABuf, m_sendTEABufInputPos, 0);
if (sendSize < 0)
return false;
if (m_sendTEABufInputPos>sendSize)
memmove(m_sendTEABuf, m_sendTEABuf+sendSize, m_sendTEABufInputPos-sendSize);
m_sendTEABufInputPos-=sendSize;
}
__PopSendBuffer();
}
else
{
int dataSize=__GetSendBufferSize();
if (dataSize<=0)
return true;
int sendSize = send(m_sock, m_sendBuf+m_sendBufOutputPos, dataSize, 0);
if (sendSize < 0)
return false;
m_sendBufOutputPos+=sendSize;
__PopSendBuffer();
}
#endif // _IMPROVED_PACKET_ENCRYPTION_
return true;
}
void CNetworkStream::__PopSendBuffer()
{
if (m_sendBufOutputPos<=0)
return;
int sendBufDataSize = m_sendBufInputPos - m_sendBufOutputPos;
if (sendBufDataSize>0)
{
memmove(m_sendBuf, m_sendBuf+m_sendBufOutputPos, sendBufDataSize);
}
m_sendBufInputPos = sendBufDataSize;
m_sendBufOutputPos = 0;
}
#pragma warning(push)
#pragma warning(disable:4127)
void CNetworkStream::Process()
{
if (m_sock == INVALID_SOCKET)
return;
fd_set fdsRecv;
fd_set fdsSend;
FD_ZERO(&fdsRecv);
FD_ZERO(&fdsSend);
FD_SET(m_sock, &fdsRecv);
FD_SET(m_sock, &fdsSend);
TIMEVAL delay;
delay.tv_sec = 0;
delay.tv_usec = 0;
if (select(0, &fdsRecv, &fdsSend, NULL, &delay) == SOCKET_ERROR)
return;
if (!m_isOnline)
{
if (FD_ISSET(m_sock, &fdsSend))
{
m_isOnline = true;
OnConnectSuccess();
}
else if (time(NULL) > m_connectLimitTime)
{
Clear();
OnConnectFailure();
}
return;
}
if (FD_ISSET(m_sock, &fdsSend) && (m_sendBufInputPos > m_sendBufOutputPos))
{
if (!__SendInternalBuffer())
{
int error = WSAGetLastError();
if (error != WSAEWOULDBLOCK)
{
OnRemoteDisconnect();
Clear();
return;
}
}
}
if (FD_ISSET(m_sock, &fdsRecv))
{
if (!__RecvInternalBuffer())
{
OnRemoteDisconnect();
Clear();
return;
}
}
if (!OnProcess())
{
OnRemoteDisconnect();
Clear();
}
}
#pragma warning(pop)
void CNetworkStream::Disconnect()
{
if (m_sock == INVALID_SOCKET)
return;
//OnDisconnect();
Clear();
}
void CNetworkStream::Clear()
{
if (m_sock == INVALID_SOCKET)
return;
#ifdef _IMPROVED_PACKET_ENCRYPTION_
m_cipher.CleanUp();
#endif
closesocket(m_sock);
m_sock = INVALID_SOCKET;
#ifndef _IMPROVED_PACKET_ENCRYPTION_
memset(m_szEncryptKey, 0, sizeof(m_szEncryptKey));
memset(m_szDecryptKey, 0, sizeof(m_szDecryptKey));
m_isSecurityMode = false;
#endif
m_isOnline = false;
m_connectLimitTime = 0;
m_recvTEABufInputPos = 0;
m_sendTEABufInputPos = 0;
m_recvBufInputPos = 0;
m_recvBufOutputPos = 0;
m_sendBufInputPos = 0;
m_sendBufOutputPos = 0;
m_SequenceGenerator.seed(SEQUENCE_SEED);
}
bool CNetworkStream::Connect(const CNetworkAddress& c_rkNetAddr, int limitSec)
{
Clear();
m_addr = c_rkNetAddr;
m_sock = socket(AF_INET, SOCK_STREAM, 0);
if (m_sock == INVALID_SOCKET)
{
Clear();
OnConnectFailure();
return false;
}
DWORD arg = 1;
ioctlsocket(m_sock, FIONBIO, &arg); // Non-blocking mode
// Enable TCP_NODELAY to disable Nagle's algorithm for lower latency
int opt = 1;
if (setsockopt(m_sock, IPPROTO_TCP, TCP_NODELAY, (const char*)&opt, sizeof(opt)) != 0)
{
TraceError("setsockopt TCP_NODELAY failed: %d", WSAGetLastError());
}
if (connect(m_sock, (PSOCKADDR)&m_addr, m_addr.GetSize()) == SOCKET_ERROR)
{
int error = WSAGetLastError();
if (error != WSAEWOULDBLOCK)
{
Tracen("error != WSAEWOULDBLOCK");
Clear();
OnConnectFailure();
return false;
}
}
m_connectLimitTime = time(NULL) + limitSec;
return true;
}
bool CNetworkStream::Connect(DWORD dwAddr, int port, int limitSec)
{
char szAddr[256];
{
BYTE ip[4];
ip[0]=dwAddr&0xff;dwAddr>>=8;
ip[1]=dwAddr&0xff;dwAddr>>=8;
ip[2]=dwAddr&0xff;dwAddr>>=8;
ip[3]=dwAddr&0xff;dwAddr>>=8;
sprintf(szAddr, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
}
return Connect(szAddr, port, limitSec);
}
bool CNetworkStream::Connect(const char* c_szAddr, int port, int /*limitSec*/)
{
CNetworkAddress kNetAddr;
kNetAddr.Set(c_szAddr, port);
return Connect(kNetAddr);
}
void CNetworkStream::ClearRecvBuffer()
{
m_recvBufOutputPos = m_recvBufInputPos = 0;
}
int CNetworkStream::GetRecvBufferSize()
{
return m_recvBufInputPos - m_recvBufOutputPos;
}
bool CNetworkStream::Peek(int size)
{
if (GetRecvBufferSize() < size)
return false;
return true;
}
bool CNetworkStream::Peek(int size, char * pDestBuf)
{
if (GetRecvBufferSize() < size)
return false;
memcpy(pDestBuf, m_recvBuf + m_recvBufOutputPos, size);
return true;
}
#ifdef _PACKETDUMP
const char * GetSendHeaderName(BYTE header)
{
static bool b = false;
static std::string stringList[UCHAR_MAX+1];
if (b==false)
{
for (DWORD i = 0; i < UCHAR_MAX+1; i++)
{
char buf[10];
sprintf(buf,"%d",i);
stringList[i] = buf;
}
stringList[1] = "HEADER_CG_LOGIN";
stringList[2] = "HEADER_CG_ATTACK";
stringList[3] = "HEADER_CG_CHAT";
stringList[4] = "HEADER_CG_PLAYER_CREATE";
stringList[5] = "HEADER_CG_PLAYER_DESTROY";
stringList[6] = "HEADER_CG_PLAYER_SELECT";
stringList[7] = "HEADER_CG_CHARACTER_MOVE";
stringList[8] = "HEADER_CG_SYNC_POSITION";
stringList[9] = "HEADER_CG_DIRECT_ENTER";
stringList[10] = "HEADER_CG_ENTERGAME";
stringList[11] = "HEADER_CG_ITEM_USE";
stringList[12] = "HEADER_CG_ITEM_DROP";
stringList[13] = "HEADER_CG_ITEM_MOVE";
stringList[15] = "HEADER_CG_ITEM_PICKUP";
stringList[16] = "HEADER_CG_QUICKSLOT_ADD";
stringList[17] = "HEADER_CG_QUICKSLOT_DEL";
stringList[18] = "HEADER_CG_QUICKSLOT_SWAP";
stringList[19] = "HEADER_CG_WHISPER";
stringList[20] = "HEADER_CG_ITEM_DROP2";
stringList[26] = "HEADER_CG_ON_CLICK";
stringList[27] = "HEADER_CG_EXCHANGE";
stringList[28] = "HEADER_CG_CHARACTER_POSITION";
stringList[29] = "HEADER_CG_SCRIPT_ANSWER";
stringList[30] = "HEADER_CG_QUEST_INPUT_STRING";
stringList[31] = "HEADER_CG_QUEST_CONFIRM";
stringList[41] = "HEADER_CG_PVP";
stringList[50] = "HEADER_CG_SHOP";
stringList[51] = "HEADER_CG_FLY_TARGETING";
stringList[52] = "HEADER_CG_USE_SKILL";
stringList[53] = "HEADER_CG_ADD_FLY_TARGETING";
stringList[54] = "HEADER_CG_SHOOT";
stringList[55] = "HEADER_CG_MYSHOP";
stringList[60] = "HEADER_CG_ITEM_USE_TO_ITEM";
stringList[61] = "HEADER_CG_TARGET";
stringList[65] = "HEADER_CG_WARP";
stringList[66] = "HEADER_CG_SCRIPT_BUTTON";
stringList[67] = "HEADER_CG_MESSENGER";
stringList[69] = "HEADER_CG_MALL_CHECKOUT";
stringList[70] = "HEADER_CG_SAFEBOX_CHECKIN";
stringList[71] = "HEADER_CG_SAFEBOX_CHECKOUT";
stringList[72] = "HEADER_CG_PARTY_INVITE";
stringList[73] = "HEADER_CG_PARTY_INVITE_ANSWER";
stringList[74] = "HEADER_CG_PARTY_REMOVE";
stringList[75] = "HEADER_CG_PARTY_SET_STATE";
stringList[76] = "HEADER_CG_PARTY_USE_SKILL";
stringList[77] = "HEADER_CG_SAFEBOX_ITEM_MOVE";
stringList[78] = "HEADER_CG_PARTY_PARAMETER";
stringList[80] = "HEADER_CG_GUILD";
stringList[81] = "HEADER_CG_ANSWER_MAKE_GUILD";
stringList[82] = "HEADER_CG_FISHING";
stringList[83] = "HEADER_CG_GIVE_ITEM";
stringList[90] = "HEADER_CG_EMPIRE";
stringList[96] = "HEADER_CG_REFINE";
stringList[100] = "HEADER_CG_MARK_LOGIN";
stringList[101] = "HEADER_CG_MARK_CRCLIST";
stringList[102] = "HEADER_CG_MARK_UPLOAD";
stringList[103] = "HEADER_CG_CRC_REPORT";
stringList[105] = "HEADER_CG_HACK";
stringList[106] = "HEADER_CG_CHANGE_NAME";
stringList[107] = "HEADER_CG_SMS";
stringList[108] = "HEADER_CG_MATRIX_CARD";
stringList[109] = "HEADER_CG_LOGIN2";
stringList[110] = "HEADER_CG_DUNGEON";
stringList[111] = "HEADER_CG_LOGIN3";
stringList[112] = "HEADER_CG_GUILD_SYMBOL_UPLOAD";
stringList[113] = "HEADER_CG_GUILD_SYMBOL_CRC";
stringList[114] = "HEADER_CG_SCRIPT_SELECT_ITEM";
#ifdef _IMPROVED_PACKET_ENCRYPTION_
stringList[0xfb] = "HEADER_CG_KEY_AGREEMENT";
#endif
stringList[0xfc] = "HEADER_CG_TIME_SYNC";
stringList[0xfd] = "HEADER_CG_CLIENT_VERSION";
stringList[0xfe] = "HEADER_CG_PONG";
stringList[0xff] = "HEADER_CG_HANDSHAKE";
}
return stringList[header].c_str();
}
const char * GetRecvHeaderName(BYTE header)
{
static bool b = false;
static std::string stringList[UCHAR_MAX+1];
if (b==false)
{
for (DWORD i = 0; i < UCHAR_MAX+1; i++)
{
char buf[10];
sprintf(buf,"%d",i);
stringList[i] = buf;
}
stringList[1] = "HEADER_GC_CHARACTER_ADD";
stringList[2] = "HEADER_GC_CHARACTER_DEL";
stringList[3] = "HEADER_GC_CHARACTER_MOVE";
stringList[4] = "HEADER_GC_CHAT";
stringList[5] = "HEADER_GC_SYNC_POSITION";
stringList[6] = "HEADER_GC_LOGIN_SUCCESS";
stringList[7] = "HEADER_GC_LOGIN_FAILURE";
stringList[8] = "HEADER_GC_PLAYER_CREATE_SUCCESS";
stringList[9] = "HEADER_GC_PLAYER_CREATE_FAILURE";
stringList[10] = "HEADER_GC_PLAYER_DELETE_SUCCESS";
stringList[11] = "HEADER_GC_PLAYER_DELETE_WRONG_SOCIAL_ID";
stringList[13] = "HEADER_GC_STUN";
stringList[14] = "HEADER_GC_DEAD";
stringList[15] = "HEADER_GC_MAIN_CHARACTER";
stringList[16] = "HEADER_GC_PLAYER_POINTS";
stringList[17] = "HEADER_GC_PLAYER_POINT_CHANGE";
stringList[18] = "HEADER_GC_CHANGE_SPEED";
stringList[19] = "HEADER_GC_CHARACTER_UPDATE";
stringList[20] = "HEADER_GC_ITEM_DEL";
stringList[21] = "HEADER_GC_ITEM_SET";
stringList[22] = "HEADER_GC_ITEM_USE";
stringList[23] = "HEADER_GC_ITEM_DROP";
stringList[25] = "HEADER_GC_ITEM_UPDATE";
stringList[26] = "HEADER_GC_ITEM_GROUND_ADD";
stringList[27] = "HEADER_GC_ITEM_GROUND_DEL";
stringList[28] = "HEADER_GC_QUICKSLOT_ADD";
stringList[29] = "HEADER_GC_QUICKSLOT_DEL";
stringList[30] = "HEADER_GC_QUICKSLOT_SWAP";
stringList[31] = "HEADER_GC_ITEM_OWNERSHIP";
stringList[33] = "HEADER_GC_ITEM_UNBIND_TIME";
stringList[34] = "HEADER_GC_WHISPER ";
stringList[35] = "HEADER_GC_ALERT";
stringList[36] = "HEADER_GC_MOTION";
stringList[38] = "HEADER_GC_SHOP";
stringList[39] = "HEADER_GC_SHOP_SIGN";
stringList[41] = "HEADER_GC_PVP";
stringList[42] = "HEADER_GC_EXCHANGE";
stringList[43] = "HEADER_GC_CHARACTER_POSITION";
stringList[44] = "HEADER_GC_PING";
stringList[45] = "HEADER_GC_SCRIPT";
stringList[46] = "HEADER_GC_QUEST_CONFIRM";
stringList[61] = "HEADER_GC_MOUNT";
stringList[62] = "HEADER_GC_OWNERSHIP";
stringList[63] = "HEADER_GC_TARGET";
stringList[65] = "HEADER_GC_WARP";
stringList[69] = "HEADER_GC_ADD_FLY_TARGETING";
stringList[70] = "HEADER_GC_CREATE_FLY";
stringList[71] = "HEADER_GC_FLY_TARGETING";
stringList[72] = "HEADER_GC_SKILL_LEVEL";
stringList[73] = "HEADER_GC_SKILL_COOLTIME_END";
stringList[74] = "HEADER_GC_MESSENGER";
stringList[75] = "HEADER_GC_GUILD";
stringList[76] = "HEADER_GC_SKILL_LEVEL_NEW";
stringList[77] = "HEADER_GC_PARTY_INVITE";
stringList[78] = "HEADER_GC_PARTY_ADD";
stringList[79] = "HEADER_GC_PARTY_UPDATE";
stringList[80] = "HEADER_GC_PARTY_REMOVE";
stringList[81] = "HEADER_GC_QUEST_INFO";
stringList[82] = "HEADER_GC_REQUEST_MAKE_GUILD";
stringList[83] = "HEADER_GC_PARTY_PARAMETER";
stringList[84] = "HEADER_GC_SAFEBOX_MONEY_CHANGE";
stringList[85] = "HEADER_GC_SAFEBOX_SET";
stringList[86] = "HEADER_GC_SAFEBOX_DEL";
stringList[87] = "HEADER_GC_SAFEBOX_WRONG_PASSWORD";
stringList[88] = "HEADER_GC_SAFEBOX_SIZE";
stringList[89] = "HEADER_GC_FISHING";
stringList[90] = "HEADER_GC_EMPIRE";
stringList[91] = "HEADER_GC_PARTY_LINK";
stringList[92] = "HEADER_GC_PARTY_UNLINK";
stringList[95] = "HEADER_GC_REFINE_INFORMATION";
stringList[96] = "HEADER_GC_OBSERVER_ADD";
stringList[97] = "HEADER_GC_OBSERVER_REMOVE";
stringList[98] = "HEADER_GC_OBSERVER_MOVE";
stringList[99] = "HEADER_GC_VIEW_EQUIP";
stringList[100] = "HEADER_GC_MARK_BLOCK";
stringList[101] = "HEADER_GC_MARK_DIFF_DATA";
stringList[106] = "HEADER_GC_TIME";
stringList[107] = "HEADER_GC_CHANGE_NAME";
stringList[110] = "HEADER_GC_DUNGEON";
stringList[111] = "HEADER_GC_WALK_MODE";
stringList[112] = "HEADER_GC_CHANGE_SKILL_GROUP";
stringList[113] = "HEADER_GC_MAIN_CHARACTER_NEW";
stringList[114] = "HEADER_GC_USE_POTION";
stringList[115] = "HEADER_GC_NPC_POSITION";
stringList[116] = "HEADER_GC_MATRIX_CARD";
stringList[117] = "HEADER_GC_CHARACTER_UPDATE2";
stringList[118] = "HEADER_GC_LOGIN_KEY";
stringList[119] = "HEADER_GC_REFINE_INFORMATION_NEW";
stringList[120] = "HEADER_GC_CHARACTER_ADD2";
stringList[121] = "HEADER_GC_CHANNEL";
stringList[122] = "HEADER_GC_MALL_OPEN";
stringList[123] = "HEADER_GC_TARGET_UPDATE";
stringList[124] = "HEADER_GC_TARGET_DELETE";
stringList[125] = "HEADER_GC_TARGET_CREATE_NEW";
stringList[126] = "HEADER_GC_AFFECT_ADD";
stringList[127] = "HEADER_GC_AFFECT_REMOVE";
stringList[128] = "HEADER_GC_MALL_SET";
stringList[129] = "HEADER_GC_MALL_DEL";
stringList[130] = "HEADER_GC_LAND_LIST";
stringList[131] = "HEADER_GC_LOVER_INFO";
stringList[132] = "HEADER_GC_LOVE_POINT_UPDATE";
stringList[133] = "HEADER_GC_GUILD_SYMBOL_DATA";
stringList[134] = "HEADER_GC_DIG_MOTION";
stringList[135] = "HEADER_GC_DAMAGE_INFO";
stringList[136] = "HEADER_GC_CHAR_ADDITIONAL_INFO";
stringList[150] = "HEADER_GC_AUTH_SUCCESS";
#ifdef _IMPROVED_PACKET_ENCRYPTION_
stringList[0xfa] = "HEADER_GC_KEY_AGREEMENT_COMPLETED";
stringList[0xfb] = "HEADER_GC_KEY_AGREEMENT";
#endif
stringList[0xfc] = "HEADER_GC_HANDSHAKE_OK";
stringList[0xfd] = "HEADER_GC_PHASE";
stringList[0xfe] = "HEADER_GC_BINDUDP";
stringList[0xff] = "HEADER_GC_HANDSHAKE";
}
return stringList[header].c_str();
}
#endif
bool CNetworkStream::Recv(int size)
{
if (!Peek(size))
return false;
m_recvBufOutputPos += size;
return true;
}
static std::string dump_hex(const uint8_t* ptr, const std::size_t length)
{
if (!ptr || !length)
return {};
std::stringstream ss;
std::vector <uint8_t> buffer(length);
memcpy(&buffer[0], ptr, length);
for (size_t i = 0; i < length; ++i)
ss << std::hex << std::setfill('0') << std::setw(2) << (int)buffer.at(i) << ", ";
const auto str = ss.str();
return str.substr(0, str.size() - 2);
}
bool CNetworkStream::Recv(int size, char * pDestBuf)
{
if (!Peek(size, pDestBuf))
return false;
#ifdef _PACKETDUMP
if (*pDestBuf != 0)
{
const auto kHeader = *pDestBuf;
TraceError("RECV< %s %u(0x%X) (%d)", GetRecvHeaderName(kHeader), kHeader, kHeader, size);
const auto contents = dump_hex(reinterpret_cast<const uint8_t*>(pDestBuf), size);
TraceError("%s", contents.c_str());
}
#endif
m_recvBufOutputPos += size;
return true;
}
int CNetworkStream::__GetSendBufferSize()
{
return m_sendBufInputPos-m_sendBufOutputPos;
}
bool CNetworkStream::Send(int size, const char * pSrcBuf)
{
int sendBufRestSize = m_sendBufSize - m_sendBufInputPos;
if ((size + 1) > sendBufRestSize)
return false;
memcpy(m_sendBuf + m_sendBufInputPos, pSrcBuf, size);
m_sendBufInputPos += size;
#ifdef _PACKETDUMP
if (*pSrcBuf != 0)
{
const auto kHeader = *pSrcBuf;
TraceError("SEND> %s %u(0x%X) (%d)", GetSendHeaderName(kHeader), kHeader, kHeader, size);
const auto contents = dump_hex(reinterpret_cast<const uint8_t*>(pSrcBuf), size);
TraceError("%s", contents.c_str());
}
#endif
return true;
/*
if (size > 0)
{
if (IsSecurityMode())
{
m_sendBufInputPos += TEA_Encrypt((DWORD *) (m_sendBuf + m_sendBufInputPos),
(DWORD *) (m_sendBuf + m_sendBufInputPos),
(const DWORD *) gs_szTeaKey,
size);
}
else
{
}
}
return __SendInternalBuffer();
*/
}
bool CNetworkStream::Peek(int len, void* pDestBuf)
{
return Peek(len, (char*)pDestBuf);
}
bool CNetworkStream::Recv(int len, void* pDestBuf)
{
return Recv(len, (char*)pDestBuf);
}
bool CNetworkStream::SendFlush(int len, const void* pSrcBuf)
{
if (!Send(len, pSrcBuf))
return false;
return __SendInternalBuffer();
}
bool CNetworkStream::Send(int len, const void* pSrcBuf)
{
return Send(len, (const char*)pSrcBuf);
}
bool CNetworkStream::IsOnline()
{
return m_isOnline;
}
void CNetworkStream::SetPacketSequenceMode(bool isOn)
{
m_bUseSequence = isOn;
}
bool CNetworkStream::SendSequence()
{
if (!m_bUseSequence)
return true;
BYTE bSeq = m_SequenceGenerator(UINT8_MAX + 1);
return Send(sizeof(BYTE), &bSeq);
}
uint8_t CNetworkStream::GetNextSequence()
{
return m_SequenceGenerator(UINT8_MAX + 1);
}
bool CNetworkStream::OnProcess()
{
return true;
}
void CNetworkStream::OnRemoteDisconnect()
{
}
void CNetworkStream::OnDisconnect()
{
}
void CNetworkStream::OnConnectSuccess()
{
Tracen("Succeed connecting.");
}
void CNetworkStream::OnConnectFailure()
{
Tracen("Failed to connect.");
}
//void CNetworkStream::OnCheckinSuccess()
//{
//}
//void CNetworkStream::OnCheckinFailure()
//{
//}
CNetworkStream::CNetworkStream()
{
m_sock = INVALID_SOCKET;
#ifndef _IMPROVED_PACKET_ENCRYPTION_
m_isSecurityMode = false;
#endif
m_isOnline = false;
m_connectLimitTime = 0;
m_recvTEABuf = NULL;
m_recvTEABufSize = 0;
m_recvTEABufInputPos = 0;
m_recvBuf = NULL;
m_recvBufSize = 0;
m_recvBufOutputPos = 0;
m_recvBufInputPos = 0;
m_sendTEABuf = NULL;
m_sendTEABuf = 0;
m_sendTEABufInputPos = 0;
m_sendBuf = NULL;
m_sendBufSize = 0;
m_sendBufOutputPos = 0;
m_sendBufInputPos = 0;
m_SequenceGenerator.seed(SEQUENCE_SEED);
m_bUseSequence = false;
}
CNetworkStream::~CNetworkStream()
{
Clear();
if (m_sendTEABuf)
{
delete [] m_sendTEABuf;
m_sendTEABuf=NULL;
}
if (m_recvTEABuf)
{
delete [] m_recvTEABuf;
m_recvTEABuf=NULL;
}
if (m_recvBuf)
{
delete [] m_recvBuf;
m_recvBuf=NULL;
}
if (m_sendBuf)
{
delete [] m_sendBuf;
m_sendBuf=NULL;
}
}
#ifdef _IMPROVED_PACKET_ENCRYPTION_
size_t CNetworkStream::Prepare(void* buffer, size_t* length)
{
return m_cipher.Prepare(buffer, length);
}
bool CNetworkStream::Activate(size_t agreed_length, const void* buffer, size_t length)
{
return m_cipher.Activate(true, agreed_length, buffer, length);
}
void CNetworkStream::ActivateCipher()
{
return m_cipher.set_activated(true);
}
// If cipher is active and there's unread data in buffer, decrypt it in-place
void CNetworkStream::DecryptAlreadyReceivedData()
{
if (!IsSecurityMode())
return;
const int unreadSize = m_recvBufInputPos - m_recvBufOutputPos;
if (unreadSize <= 0)
return;
m_cipher.Decrypt(m_recvBuf + m_recvBufOutputPos, unreadSize);
}
#endif // _IMPROVED_PACKET_ENCRYPTION_