// Functions really sending Xtraz stuff DWORD CIcqProto::SendXtrazNotifyRequest(MCONTACT hContact, char* szQuery, char* szNotify, int bForced) { char *szQueryBody; char *szNotifyBody; DWORD dwUin; int nBodyLen; char *szBody; DWORD dwCookie; if (getContactUid(hContact, &dwUin, NULL)) return 0; // Invalid contact if (!CheckContactCapabilities(hContact, CAPF_XTRAZ) && !bForced) return 0; // Contact does not support xtraz, do not send anything szQueryBody = MangleXml(szQuery, strlennull(szQuery)); szNotifyBody = MangleXml(szNotify, strlennull(szNotify)); nBodyLen = strlennull(szQueryBody) + strlennull(szNotifyBody) + 41; szBody = (char*)_alloca(nBodyLen); nBodyLen = mir_snprintf(szBody, nBodyLen, "<N><QUERY>%s</QUERY><NOTIFY>%s</NOTIFY></N>", szQueryBody, szNotifyBody); SAFE_FREE((void**)&szQueryBody); SAFE_FREE((void**)&szNotifyBody); // Set up the ack type cookie_message_data *pCookieData = CreateMessageCookie(MTYPE_SCRIPT_NOTIFY, ACKTYPE_CLIENT); dwCookie = AllocateCookie(CKT_MESSAGE, 0, hContact, (void*)pCookieData); // have we a open DC, send through that if (m_bDCMsgEnabled && IsDirectConnectionOpen(hContact, DIRECTCONN_STANDARD, 0)) icq_sendXtrazRequestDirect(hContact, dwCookie, szBody, nBodyLen, MTYPE_SCRIPT_NOTIFY); else icq_sendXtrazRequestServ(dwUin, dwCookie, szBody, nBodyLen, pCookieData); return dwCookie; }
void CIcqProto::makeContactTemporaryVisible(MCONTACT hContact) { if (getByte(hContact, "TemporaryVisible", 0)) return; // already there DWORD dwUin; uid_str szUid; if (getContactUid(hContact, &dwUin, &szUid)) return; // Invalid contact icq_sendGenericContact(dwUin, szUid, ICQ_BOS_FAMILY, ICQ_CLI_ADDTEMPVISIBLE); setByte(hContact, "TemporaryVisible", 1); debugLogA("Added contact %s to temporary visible list", strUID(dwUin, szUid)); }
void CIcqProto::makeContactTemporaryVisible(HANDLE hContact) { DWORD dwUin; uid_str szUid; if (getSettingByte(hContact, "TemporaryVisible", 0)) return; // already there if (getContactUid(hContact, &dwUin, &szUid)) return; // Invalid contact icq_sendGenericContact(dwUin, szUid, ICQ_BOS_FAMILY, ICQ_CLI_ADDTEMPVISIBLE); setSettingByte(hContact, "TemporaryVisible", 1); #ifdef _DEBUG NetLog_Server("Added contact %s to temporary visible list", strUID(dwUin, szUid)); #endif }
char* CIcqProto::buildUinList(int subtype, size_t wMaxLen, MCONTACT *hContactResume) { MCONTACT hContact; WORD wCurrentLen = 0; int add; char *szList = (char*)SAFE_MALLOC(CallService(MS_DB_CONTACT_GETCOUNT, 0, 0) * UINMAXLEN); char szLen[2]; szLen[1] = '\0'; if (*hContactResume) hContact = *hContactResume; else hContact = db_find_first(m_szModuleName); while (hContact != NULL) { DWORD dwUIN; uid_str szUID; if (!getContactUid(hContact, &dwUIN, &szUID)) { szLen[0] = (char)mir_strlen(strUID(dwUIN, szUID)); switch (subtype) { case BUL_VISIBLE: add = ID_STATUS_ONLINE == getWord(hContact, "ApparentMode", 0); break; case BUL_INVISIBLE: add = ID_STATUS_OFFLINE == getWord(hContact, "ApparentMode", 0); break; case BUL_TEMPVISIBLE: add = getByte(hContact, "TemporaryVisible", 0); // clear temporary flag // Here we assume that all temporary contacts will be in one packet setByte(hContact, "TemporaryVisible", 0); break; default: add = 1; // If we are in SS mode, we only add those contacts that are // not in our SS list, or are awaiting authorization, to our // client side list if (m_bSsiEnabled && getWord(hContact, DBSETTING_SERVLIST_ID, 0) && !getByte(hContact, "Auth", 0)) add = 0; // Never add hidden contacts to CS list if (db_get_b(hContact, "CList", "Hidden", 0)) add = 0; break; } if (add) { wCurrentLen += szLen[0] + 1; if (wCurrentLen > wMaxLen) { *hContactResume = hContact; return szList; } mir_strcat(szList, szLen); mir_strcat(szList, szUID); } } hContact = db_find_next(hContact, m_szModuleName); } *hContactResume = NULL; return szList; }
void __cdecl CIcqProto::ServerThread(serverthread_start_info *infoParam) { serverthread_info info = {0}; info.isLoginServer = 1; info.wAuthKeyLen = infoParam->wPassLen; null_strcpy((char*)info.szAuthKey, infoParam->szPass, info.wAuthKeyLen); // store server port info.wServerPort = infoParam->nloc.wPort; srand(time(NULL)); ResetSettingsOnConnect(); // Connect to the login server NetLog_Server("Authenticating to server"); { NETLIBOPENCONNECTION nloc = infoParam->nloc; nloc.timeout = 6; if (m_bGatewayMode) nloc.flags |= NLOCF_HTTPGATEWAY; hServerConn = NetLib_OpenConnection(m_hServerNetlibUser, NULL, &nloc); SAFE_FREE((void**)&nloc.szHost); SAFE_FREE((void**)&infoParam); if (hServerConn && m_bSecureConnection) { if (!CallService(MS_NETLIB_STARTSSL, (WPARAM)hServerConn, 0)) { icq_LogMessage(LOG_ERROR, LPGEN("Unable to connect to ICQ login server, SSL could not be negotiated")); SetCurrentStatus(ID_STATUS_OFFLINE); NetLib_CloseConnection(&hServerConn, TRUE); return; } } } // Login error if (hServerConn == NULL) { DWORD dwError = GetLastError(); SetCurrentStatus(ID_STATUS_OFFLINE); icq_LogUsingErrorCode(LOG_ERROR, dwError, LPGEN("Unable to connect to ICQ login server")); return; } // Initialize direct connection ports { DWORD dwInternalIP; BYTE bConstInternalIP = getSettingByte(NULL, "ConstRealIP", 0); info.hDirectBoundPort = NetLib_BindPort(icq_newConnectionReceived, this, &wListenPort, &dwInternalIP); if (!info.hDirectBoundPort) { icq_LogUsingErrorCode(LOG_WARNING, GetLastError(), LPGEN("Miranda was unable to allocate a port to listen for direct peer-to-peer connections between clients. You will be able to use most of the ICQ network without problems but you may be unable to send or receive files.\n\nIf you have a firewall this may be blocking Miranda, in which case you should configure your firewall to leave some ports open and tell Miranda which ports to use in M->Options->ICQ->Network.")); wListenPort = 0; if (!bConstInternalIP) deleteSetting(NULL, "RealIP"); } else if (!bConstInternalIP) setSettingDword(NULL, "RealIP", dwInternalIP); } // Initialize rate limiting queues { icq_lock l(m_ratesMutex); m_ratesQueue_Request = new rates_queue(this, "request", RML_IDLE_30, RML_IDLE_50, 1); m_ratesQueue_Response = new rates_queue(this, "response", RML_IDLE_10, RML_IDLE_30, -1); } // This is the "infinite" loop that receives the packets from the ICQ server { int recvResult; NETLIBPACKETRECVER packetRecv = {0}; info.hPacketRecver = (HANDLE)CallService(MS_NETLIB_CREATEPACKETRECVER, (WPARAM)hServerConn, 0x2400); packetRecv.cbSize = sizeof(packetRecv); packetRecv.dwTimeout = INFINITE; while (serverThreadHandle) { if (info.bReinitRecver) { // we reconnected, reinit struct info.bReinitRecver = 0; ZeroMemory(&packetRecv, sizeof(packetRecv)); packetRecv.cbSize = sizeof(packetRecv); packetRecv.dwTimeout = INFINITE; } recvResult = CallService(MS_NETLIB_GETMOREPACKETS, (WPARAM)info.hPacketRecver, (LPARAM)&packetRecv); if (recvResult == 0) { NetLog_Server("Clean closure of server socket"); break; } if (recvResult == SOCKET_ERROR) { NetLog_Server("Abortive closure of server socket, error: %d", GetLastError()); break; } if (m_iDesiredStatus == ID_STATUS_OFFLINE) { // Disconnect requested, send disconnect packet icq_sendCloseConnection(); // disconnected upon request m_bConnectionLost = FALSE; SetCurrentStatus(ID_STATUS_OFFLINE); NetLog_Server("Logged off."); break; } // Deal with the packet packetRecv.bytesUsed = handleServerPackets(packetRecv.buffer, packetRecv.bytesAvailable, &info); } serverThreadHandle = NULL; // Time to shutdown NetLib_CloseConnection(&hServerConn, TRUE); // Close the packet receiver (connection may still be open) NetLib_SafeCloseHandle(&info.hPacketRecver); // Close DC port NetLib_SafeCloseHandle(&info.hDirectBoundPort); } // disable auto info-update thread icq_EnableUserLookup(FALSE); if (m_iStatus != ID_STATUS_OFFLINE && m_iDesiredStatus != ID_STATUS_OFFLINE) { if (!info.bLoggedIn) icq_LogMessage(LOG_FATAL, LPGEN("Connection failed.\nLogin sequence failed for unknown reason.\nTry again later.")); // set flag indicating we were kicked out m_bConnectionLost = TRUE; SetCurrentStatus(ID_STATUS_OFFLINE); } // signal keep-alive thread to stop StopKeepAlive(&info); // Close all open DC connections CloseContactDirectConns(NULL); // Close avatar connection if any StopAvatarThread(); // Offline all contacts HANDLE hContact = FindFirstContact(); while (hContact) { DWORD dwUIN; uid_str szUID; if (!getContactUid(hContact, &dwUIN, &szUID)) { if (getContactStatus(hContact) != ID_STATUS_OFFLINE) { char tmp = 0; setSettingWord(hContact, "Status", ID_STATUS_OFFLINE); handleXStatusCaps(dwUIN, szUID, hContact, (BYTE*)&tmp, 0, &tmp, 0); } } hContact = FindNextContact(hContact); } setSettingDword(NULL, "LogonTS", 0); // clear logon time servlistPendingFlushOperations(); // clear pending operations list { // release rates queues icq_lock l(m_ratesMutex); SAFE_DELETE((void_struct**)&m_ratesQueue_Request); SAFE_DELETE((void_struct**)&m_ratesQueue_Response); SAFE_DELETE((void_struct**)&m_rates); } FlushServerIDs(); // clear server IDs list NetLog_Server("%s thread ended.", "Server"); }