CAimProto::CAimProto(const char* aProtoName, const TCHAR* aUserName) : PROTO<CAimProto>(aProtoName, aUserName), chat_rooms(5) { debugLogA("Setting protocol/module name to '%s'", m_szModuleName); //create some events hAvatarEvent = CreateEvent(NULL, TRUE, FALSE, NULL); hChatNavEvent = CreateEvent(NULL, TRUE, FALSE, NULL); hAdminEvent = CreateEvent(NULL, TRUE, FALSE, NULL); CreateProtoService(PS_CREATEACCMGRUI, &CAimProto::SvcCreateAccMgrUI); CreateProtoService(PS_GETMYAWAYMSG, &CAimProto::GetMyAwayMsg); CreateProtoService(PS_GETAVATARINFOT, &CAimProto::GetAvatarInfo); CreateProtoService(PS_GETMYAVATART, &CAimProto::GetAvatar); CreateProtoService(PS_SETMYAVATART, &CAimProto::SetAvatar); CreateProtoService(PS_GETAVATARCAPS, &CAimProto::GetAvatarCaps); CreateProtoService(PS_JOINCHAT, &CAimProto::OnJoinChat); CreateProtoService(PS_LEAVECHAT, &CAimProto::OnLeaveChat); HookProtoEvent(ME_CLIST_PREBUILDCONTACTMENU, &CAimProto::OnPreBuildContactMenu); HookProtoEvent(ME_CLIST_GROUPCHANGE, &CAimProto::OnGroupChange); HookProtoEvent(ME_OPT_INITIALISE, &CAimProto::OnOptionsInit); offline_contacts(); TCHAR descr[MAX_PATH]; NETLIBUSER nlu = {0}; nlu.cbSize = sizeof(nlu); nlu.flags = NUF_OUTGOING | NUF_HTTPCONNS | NUF_TCHAR; nlu.szSettingsModule = m_szModuleName; mir_sntprintf(descr, SIZEOF(descr), TranslateT("%s server connection"), m_tszUserName); nlu.ptszDescriptiveName = descr; m_hNetlibUser = (HANDLE) CallService(MS_NETLIB_REGISTERUSER, 0, (LPARAM)&nlu); char szP2P[128]; mir_snprintf(szP2P, SIZEOF(szP2P), "%sP2P", m_szModuleName); nlu.flags = NUF_OUTGOING | NUF_INCOMING | NUF_TCHAR; mir_sntprintf(descr, SIZEOF(descr), TranslateT("%s Client-to-client connection"), m_tszUserName); nlu.szSettingsModule = szP2P; nlu.minIncomingPorts = 1; hNetlibPeer = (HANDLE) CallService(MS_NETLIB_REGISTERUSER, 0, (LPARAM)&nlu); }
void __cdecl CAimProto::aim_protocol_negotiation(void*) { HANDLE hServerPacketRecver = (HANDLE)CallService(MS_NETLIB_CREATEPACKETRECVER, (WPARAM)m_hServerConn, 2048 * 8); NETLIBPACKETRECVER packetRecv = { 0 }; packetRecv.cbSize = sizeof(packetRecv); packetRecv.dwTimeout = DEFAULT_KEEPALIVE_TIMER * 1000; for (;;) { int recvResult = CallService(MS_NETLIB_GETMOREPACKETS, (WPARAM)hServerPacketRecver, (LPARAM)&packetRecv); if (recvResult == 0) { debugLogA("Connection Closed: No Error during Connection Negotiation?"); break; } else if (recvResult == SOCKET_ERROR) { if (WSAGetLastError() == ERROR_TIMEOUT) { if (aim_keepalive(m_hServerConn, m_seqno) < 0) break; } else { debugLogA("Connection Closed: Socket Error during Connection Negotiation %d", WSAGetLastError()); break; } } else if (recvResult > 0) { unsigned short flap_length = 0; for (; packetRecv.bytesUsed < packetRecv.bytesAvailable; packetRecv.bytesUsed = flap_length) { if (!packetRecv.buffer) break; FLAP flap((char*)&packetRecv.buffer[packetRecv.bytesUsed], packetRecv.bytesAvailable - packetRecv.bytesUsed); if (!flap.len()) break; flap_length += FLAP_SIZE + flap.len(); if (flap.cmp(0x01)) { aim_send_cookie(m_hServerConn, m_seqno, COOKIE_LENGTH, COOKIE);//cookie challenge mir_free(COOKIE); COOKIE = NULL; COOKIE_LENGTH = 0; } else if (flap.cmp(0x02)) { SNAC snac(flap.val(), flap.snaclen()); if (snac.cmp(0x0001)) { snac_supported_families(snac, m_hServerConn, m_seqno); snac_supported_family_versions(snac, m_hServerConn, m_seqno); snac_rate_limitations(snac, m_hServerConn, m_seqno); snac_service_redirect(snac); snac_self_info(snac); snac_error(snac); } else if (snac.cmp(0x0002)) { snac_received_info(snac); snac_error(snac); } else if (snac.cmp(0x0003)) { snac_user_online(snac); snac_user_offline(snac); snac_error(snac); } else if (snac.cmp(0x0004)) { snac_icbm_limitations(snac, m_hServerConn, m_seqno); snac_message_accepted(snac); snac_received_message(snac, m_hServerConn, m_seqno); snac_typing_notification(snac); snac_error(snac); snac_file_decline(snac); } else if (snac.cmp(0x000A)) { snac_email_search_results(snac); /* If there's no match (error 0x14), AIM will pop up a message. Since it's annoying and there's no other errors that'll get generated, I just assume leave this commented out. It's here for consistency. */ //snac_error(snac); } else if (snac.cmp(0x0013)) { snac_contact_list(snac, m_hServerConn, m_seqno); snac_list_modification_ack(snac); snac_error(snac); } } else if (flap.cmp(0x04)) { ProtoBroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, NULL, LOGINERR_OTHERLOCATION); debugLogA("Connection Negotiation Thread Ending: Flap 0x04"); goto exit; } } } } exit: if (m_iStatus != ID_STATUS_OFFLINE) broadcast_status(ID_STATUS_OFFLINE); Netlib_CloseHandle(hServerPacketRecver); hServerPacketRecver = NULL; Netlib_CloseHandle(m_hServerConn); m_hServerConn = NULL; debugLogA("Connection Negotiation Thread Ending: End of Thread"); offline_contacts(); }