void __cdecl CIcqProto::KeepAliveThread(void *arg) { serverthread_info *info = (serverthread_info*)arg; icq_packet packet; DWORD dwInterval = getDword("KeepAliveInterval", KEEPALIVE_INTERVAL); debugLogA("Keep alive thread starting."); info->hKeepAliveEvent = CreateEvent(NULL, FALSE, FALSE, NULL); for (;;) { DWORD dwWait = ICQWaitForSingleObject(info->hKeepAliveEvent, dwInterval); if (serverThreadHandle == NULL) // connection lost, end break; if (dwWait == WAIT_TIMEOUT) { // Send a keep alive packet to server packet.wLen = 0; write_flap(&packet, ICQ_PING_CHAN); sendServPacket(&packet); } else if (dwWait == WAIT_IO_COMPLETION) // Possible shutdown in progress if (Miranda_Terminated()) break; else break; } debugLogA("Keep alive thread ended."); CloseHandle(info->hKeepAliveEvent); info->hKeepAliveEvent = NULL; }
void CIcqProto::sendClientAuth(const char *szKey, size_t wKeyLen, BOOL bSecure) { char szUin[UINMAXLEN]; icq_packet packet; size_t wUinLen = mir_strlen(strUID(m_dwLocalUIN, szUin)); packet.wLen = WORD((m_bLegacyFix ? 65 : 70) + sizeof(CLIENT_ID_STRING) + wUinLen + wKeyLen + (m_bSecureConnection ? 4 : 0)); if (bSecure) { serverPacketInit(&packet, packet.wLen + 10); packFNACHeader(&packet, ICQ_AUTHORIZATION_FAMILY, ICQ_SIGNON_LOGIN_REQUEST, 0, 0); } else { write_flap(&packet, ICQ_LOGIN_CHAN); packDWord(&packet, 0x00000001); } packTLV(&packet, 0x0001, wUinLen, (LPBYTE)szUin); if (bSecure) { // Pack MD5 auth digest packTLV(&packet, 0x0025, wKeyLen, (BYTE*)szKey); packDWord(&packet, 0x004C0000); // empty TLV(0x4C): unknown } else { // Pack old style password hash BYTE hash[20]; icq_encryptPassword(szKey, hash); packTLV(&packet, 0x0002, wKeyLen, hash); } // Pack client identification details. packTLV(&packet, 0x0003, (WORD)sizeof(CLIENT_ID_STRING)-1, (LPBYTE)CLIENT_ID_STRING); packTLVWord(&packet, 0x0017, CLIENT_VERSION_MAJOR); packTLVWord(&packet, 0x0018, CLIENT_VERSION_MINOR); packTLVWord(&packet, 0x0019, CLIENT_VERSION_LESSER); packTLVWord(&packet, 0x001a, CLIENT_VERSION_BUILD); packTLVWord(&packet, 0x0016, CLIENT_ID_CODE); packTLVDWord(&packet, 0x0014, CLIENT_DISTRIBUTION); packTLV(&packet, 0x000f, 0x0002, (LPBYTE)CLIENT_LANGUAGE); packTLV(&packet, 0x000e, 0x0002, (LPBYTE)CLIENT_COUNTRY); if (!m_bLegacyFix) packTLV(&packet, 0x0094, 0x0001, &m_bConnectionLost); // CLIENT_RECONNECT flag if (m_bSecureConnection) packDWord(&packet, 0x008C0000); // empty TLV(0x8C): use SSL sendServPacket(&packet); }
void __fastcall serverCookieInit(icq_packet *pPacket, BYTE *pCookie, WORD wCookieSize) { pPacket->wLen = (WORD)(wCookieSize + 8 + sizeof(CLIENT_ID_STRING) + 66); write_flap(pPacket, ICQ_LOGIN_CHAN); packDWord(pPacket, 0x00000001); packTLV(pPacket, 0x06, wCookieSize, pCookie); // Pack client identification details. packTLV(pPacket, 0x0003, (WORD)sizeof(CLIENT_ID_STRING)-1, (LPBYTE)CLIENT_ID_STRING); packTLVWord(pPacket, 0x0017, CLIENT_VERSION_MAJOR); packTLVWord(pPacket, 0x0018, CLIENT_VERSION_MINOR); packTLVWord(pPacket, 0x0019, CLIENT_VERSION_LESSER); packTLVWord(pPacket, 0x001a, CLIENT_VERSION_BUILD); packTLVWord(pPacket, 0x0016, CLIENT_ID_CODE); packTLVDWord(pPacket, 0x0014, CLIENT_DISTRIBUTION); packTLV(pPacket, 0x000f, 0x0002, (LPBYTE)CLIENT_LANGUAGE); packTLV(pPacket, 0x000e, 0x0002, (LPBYTE)CLIENT_COUNTRY); packDWord(pPacket, 0x00940001); // reconnect flag packByte(pPacket, 0); packTLVDWord(pPacket, 0x8003, 0x00100000); // Unknown }
void avatars_server_connection::connectionThread() { // This is the "infinite" loop that receives the packets from the ICQ avatar server NETLIBPACKETRECVER packetRecv = { 0 }; DWORD dwLastKeepAlive = time(0) + KEEPALIVE_INTERVAL; hPacketRecver = (HANDLE)CallService(MS_NETLIB_CREATEPACKETRECVER, (WPARAM)hConnection, 65536); packetRecv.cbSize = sizeof(packetRecv); packetRecv.dwTimeout = 1000; // timeout - for stopThread to work while (!stopThread) { int recvResult = CallService(MS_NETLIB_GETMOREPACKETS, (WPARAM)hPacketRecver, (LPARAM)&packetRecv); if (recvResult == 0) { ppro->debugLogA("Clean closure of avatar socket"); break; } if (recvResult == SOCKET_ERROR) { if (GetLastError() == ERROR_TIMEOUT) { // timeout, check if we should be still running if (Miranda_Terminated()) break; if (time(0) >= dwLastKeepAlive) { // limit frequency (HACK: on some systems select() does not work well) if (!ppro->m_bGatewayMode && ppro->getByte("KeepAlive", DEFAULT_KEEPALIVE_ENABLED)) { // send keep-alive packet icq_packet packet; packet.wLen = 0; write_flap(&packet, ICQ_PING_CHAN); sendServerPacket(&packet); } dwLastKeepAlive = time(0) + KEEPALIVE_INTERVAL; } // check if we got something to request checkRequestQueue(); continue; } if (!stopThread) ppro->debugLogA("Avatar socket closed abortively, error: %d", GetLastError()); else ppro->debugLogA("Avatar socket gracefully closed."); break; } // Deal with the packet packetRecv.bytesUsed = handleServerPackets(packetRecv.buffer, packetRecv.bytesAvailable); if (isActive && (packetRecv.bytesAvailable == packetRecv.bytesUsed)) // no packets pending checkRequestQueue(); // process request queue } { // release connection mir_cslock l(localSeqMutex); NetLib_SafeCloseHandle(&hPacketRecver); // Close the packet receiver NetLib_CloseConnection(&hConnection, FALSE); // Close the connection } { // release rates mir_cslock l(m_ratesMutex); delete m_rates; m_rates = NULL; } SAFE_FREE((void**)&pCookie); }
void __fastcall serverPacketInit(icq_packet *pPacket, WORD wSize) { pPacket->wLen = wSize; write_flap(pPacket, ICQ_DATA_CHAN); }
void avatars_server_connection::connectionThread() { // This is the "infinite" loop that receives the packets from the ICQ avatar server NETLIBPACKETRECVER packetRecv = {0}; DWORD wLastKeepAlive = 0; // we send keep-alive at most one per 30secs DWORD dwKeepAliveInterval = ppro->getDword("KeepAliveInterval", KEEPALIVE_INTERVAL); hPacketRecver = (HANDLE)CallService(MS_NETLIB_CREATEPACKETRECVER, (WPARAM)hConnection, 65536); packetRecv.cbSize = sizeof(packetRecv); packetRecv.dwTimeout = dwKeepAliveInterval < KEEPALIVE_INTERVAL ? dwKeepAliveInterval: KEEPALIVE_INTERVAL; // timeout - for stopThread to work while (!stopThread) { int recvResult = CallService(MS_NETLIB_GETMOREPACKETS, (WPARAM)hPacketRecver, (LPARAM)&packetRecv); if (recvResult == 0) { ppro->debugLogA("Clean closure of server socket"); break; } if (recvResult == SOCKET_ERROR) { if (GetLastError() == ERROR_TIMEOUT) { // timeout, check if we should be still running if (Miranda_Terminated()) { // we must stop here, cause due to a hack in netlib, we always get timeout, even if the connection is already dead stopThread = 1; continue; } #ifdef _DEBUG else ppro->debugLogA("Thread is Idle."); #endif if (GetTickCount() > wLastKeepAlive) { // limit frequency (HACK: on some systems select() does not work well) if (!ppro->m_bGatewayMode && ppro->getByte("KeepAlive", DEFAULT_KEEPALIVE_ENABLED)) { // send keep-alive packet icq_packet packet; packet.wLen = 0; write_flap(&packet, ICQ_PING_CHAN); sendServerPacket(&packet); } wLastKeepAlive = GetTickCount() + dwKeepAliveInterval; } else { // this is bad, the system does not handle select() properly #ifdef _DEBUG ppro->debugLogA("Thread is Forcing Idle."); #endif SleepEx(500, TRUE); // wait some time, can we do anything else ?? if (Miranda_Terminated()) { stopThread = 1; continue; } } // check if we got something to request checkRequestQueue(); continue; } if (!stopThread) ppro->debugLogA("Abortive closure of server socket, error: %d", GetLastError()); else ppro->debugLogA("Connection closed."); break; } // Deal with the packet packetRecv.bytesUsed = handleServerPackets(packetRecv.buffer, packetRecv.bytesAvailable); if (isActive && (packetRecv.bytesAvailable == packetRecv.bytesUsed)) // no packets pending { // process request queue checkRequestQueue(); } } { // release connection icq_lock l(localSeqMutex); NetLib_SafeCloseHandle(&hPacketRecver); // Close the packet receiver NetLib_CloseConnection(&hConnection, FALSE); // Close the connection } { // release rates icq_lock l(m_ratesMutex); SAFE_DELETE((MZeroedObject**)&m_rates); } SAFE_FREE((void**)&pCookie); }
void CIcqProto::handleLoginChannel(BYTE *buf, WORD datalen, serverthread_info *info) { icq_packet packet; #ifdef _DEBUG NetLog_Server("Received SRV_HELLO from %s", info->isLoginServer ? "login server" : "communication server"); #endif // isLoginServer is "1" if we just received SRV_HELLO if (info->isLoginServer) { if (m_bSecureLogin) { char szUin[UINMAXLEN]; WORD wUinLen; #ifdef _DEBUG NetLog_Server("Sending %s to %s", "CLI_HELLO", "login server"); #endif packet.wLen = 12; write_flap(&packet, ICQ_LOGIN_CHAN); packDWord(&packet, 0x00000001); packTLVDWord(&packet, 0x8003, 0x00100000); // unknown sendServPacket(&packet); // greet login server wUinLen = strlennull(strUID(m_dwLocalUIN, szUin)); #ifdef _DEBUG NetLog_Server("Sending %s to %s", "ICQ_SIGNON_AUTH_REQUEST", "login server"); #endif serverPacketInit(&packet, (WORD)(14 + wUinLen)); packFNACHeader(&packet, ICQ_AUTHORIZATION_FAMILY, ICQ_SIGNON_AUTH_REQUEST, 0, 0); packTLV(&packet, 0x0001, wUinLen, (LPBYTE)szUin); sendServPacket(&packet); // request login digest } else { sendClientAuth((char*)info->szAuthKey, info->wAuthKeyLen, FALSE); #ifdef _DEBUG NetLog_Server("Sent CLI_IDENT to %s", "login server"); #endif } info->isLoginServer = 0; if (info->cookieDataLen) { SAFE_FREE((void**)&info->cookieData); info->cookieDataLen = 0; } } else { if (info->cookieDataLen) { wLocalSequence = generate_flap_sequence(); serverCookieInit(&packet, info->cookieData, (WORD)info->cookieDataLen); sendServPacket(&packet); #ifdef _DEBUG NetLog_Server("Sent CLI_IDENT to %s", "communication server"); #endif SAFE_FREE((void**)&info->cookieData); info->cookieDataLen = 0; } else { // We need a cookie to identify us to the communication server NetLog_Server("Error: Connected to %s without a cookie!", "communication server"); } } }