summaryrefslogtreecommitdiff
path: root/protocols/IcqOscarJ/icq_server.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'protocols/IcqOscarJ/icq_server.cpp')
-rw-r--r--protocols/IcqOscarJ/icq_server.cpp444
1 files changed, 0 insertions, 444 deletions
diff --git a/protocols/IcqOscarJ/icq_server.cpp b/protocols/IcqOscarJ/icq_server.cpp
deleted file mode 100644
index 63a5d63d84..0000000000
--- a/protocols/IcqOscarJ/icq_server.cpp
+++ /dev/null
@@ -1,444 +0,0 @@
-// ---------------------------------------------------------------------------80
-// ICQ plugin for Miranda Instant Messenger
-// ________________________________________
-//
-// Copyright © 2000-2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede
-// Copyright © 2001-2002 Jon Keating, Richard Hughes
-// Copyright © 2002-2004 Martin Öberg, Sam Kothari, Robert Rainwater
-// Copyright © 2004-2010 Joe Kucera
-//
-// 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 2
-// of the License, or (at your option) 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, write to the Free Software
-// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-//
-// -----------------------------------------------------------------------------
-// DESCRIPTION:
-//
-// Manages main server connection, low-level communication
-//
-// -----------------------------------------------------------------------------
-#include "icqoscar.h"
-
-
-void icq_newConnectionReceived(HANDLE hNewConnection, DWORD dwRemoteIP, void *pExtra);
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// ICQ Server thread
-
-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((MZeroedObject**)&m_ratesQueue_Request);
- SAFE_DELETE((MZeroedObject**)&m_ratesQueue_Response);
- SAFE_DELETE((MZeroedObject**)&m_rates);
- }
-
- FlushServerIDs(); // clear server IDs list
-
- NetLog_Server("%s thread ended.", "Server");
-}
-
-
-void CIcqProto::icq_serverDisconnect(BOOL bBlock)
-{
- if ( !hServerConn)
- return;
-
- NetLog_Server("Server shutdown requested");
- Netlib_Shutdown(hServerConn);
-
- if (serverThreadHandle) {
- // Not called from network thread?
- if (bBlock && GetCurrentThreadId() != serverThreadId)
- while (ICQWaitForSingleObject(serverThreadHandle, INFINITE) != WAIT_OBJECT_0);
-
- CloseHandle(serverThreadHandle);
- serverThreadHandle = NULL;
- }
-}
-
-
-int CIcqProto::handleServerPackets(BYTE *buf, int len, serverthread_info *info)
-{
- BYTE channel;
- WORD sequence;
- WORD datalen;
- int bytesUsed = 0;
-
- while (len > 0)
- {
- if (info->bReinitRecver)
- break;
-
- // All FLAPS begin with 0x2a
- if (*buf++ != FLAP_MARKER)
- break;
-
- if (len < 6)
- break;
-
- unpackByte(&buf, &channel);
- unpackWord(&buf, &sequence);
- unpackWord(&buf, &datalen);
-
- if (len < 6 + datalen)
- break;
-
-
-#ifdef _DEBUG
- NetLog_Server("Server FLAP: Channel %u, Seq %u, Length %u bytes", channel, sequence, datalen);
-#endif
-
- switch (channel) {
- case ICQ_LOGIN_CHAN:
- handleLoginChannel(buf, datalen, info);
- break;
-
- case ICQ_DATA_CHAN:
- handleDataChannel(buf, datalen, info);
- break;
-
- case ICQ_ERROR_CHAN:
- handleErrorChannel(buf, datalen);
- break;
-
- case ICQ_CLOSE_CHAN:
- handleCloseChannel(buf, datalen, info);
- break; // we need this for walking thru proxy
-
- case ICQ_PING_CHAN:
- handlePingChannel(buf, datalen);
- break;
-
- default:
- NetLog_Server("Warning: Unhandled Server FLAP Channel: Channel %u, Seq %u, Length %u bytes", channel, sequence, datalen);
- break;
- }
-
- /* Increase pointers so we can check for more FLAPs */
- buf += datalen;
- len -= (datalen + 6);
- bytesUsed += (datalen + 6);
- }
-
- return bytesUsed;
-}
-
-
-void CIcqProto::sendServPacket(icq_packet *pPacket)
-{
- // make sure to have the connection handle
- connectionHandleMutex->Enter();
-
- if (hServerConn)
- {
- int nSendResult;
-
- // This critsec makes sure that the sequence order doesn't get screwed up
- localSeqMutex->Enter();
-
- // :IMPORTANT:
- // The FLAP sequence must be a WORD. When it reaches 0xFFFF it should wrap to
- // 0x0000, otherwise we'll get kicked by server.
- wLocalSequence++;
-
- // Pack sequence number
- pPacket->pData[2] = ((wLocalSequence & 0xff00) >> 8);
- pPacket->pData[3] = (wLocalSequence & 0x00ff);
-
- nSendResult = Netlib_Send(hServerConn, (const char *)pPacket->pData, pPacket->wLen, 0);
-
- localSeqMutex->Leave();
- connectionHandleMutex->Leave();
-
- // Send error
- if (nSendResult == SOCKET_ERROR)
- {
- icq_LogUsingErrorCode(LOG_ERROR, GetLastError(), LPGEN("Your connection with the ICQ server was abortively closed"));
- icq_serverDisconnect(FALSE);
-
- if (m_iStatus != ID_STATUS_OFFLINE)
- {
- SetCurrentStatus(ID_STATUS_OFFLINE);
- }
- }
- else
- { // Rates management
- icq_lock l(m_ratesMutex);
- m_rates->packetSent(pPacket);
- }
-
- }
- else
- {
- connectionHandleMutex->Leave();
- NetLog_Server("Error: Failed to send packet (no connection)");
- }
-
- SAFE_FREE((void**)&pPacket->pData);
-}
-
-
-void __cdecl CIcqProto::SendPacketAsyncThread(icq_packet* pkt)
-{
- sendServPacket( pkt );
- SAFE_FREE((void**)&pkt);
-}
-
-
-void CIcqProto::sendServPacketAsync(icq_packet *packet)
-{
- icq_packet *pPacket;
-
- pPacket = (icq_packet*)SAFE_MALLOC(sizeof(icq_packet)); // This will be freed in the new thread
- memcpy(pPacket, packet, sizeof(icq_packet));
-
- ForkThread(( IcqThreadFunc )&CIcqProto::SendPacketAsyncThread, pPacket);
-}
-
-
-int CIcqProto::IsServerOverRate(WORD wFamily, WORD wCommand, int nLevel)
-{
- icq_lock l(m_ratesMutex);
-
- if (m_rates)
- {
- WORD wGroup = m_rates->getGroupFromSNAC(wFamily, wCommand);
-
- // check if the rate is not over specified level
- if (m_rates->getNextRateLevel(wGroup) < m_rates->getLimitLevel(wGroup, nLevel))
- return TRUE;
- }
-
- return FALSE;
-}
-
-
-/////////////////////////////////////////////////////////////////////////////////////////
-// ICQ Server thread
-
-void CIcqProto::icq_login(const char* szPassword)
-{
- DWORD dwUin = getContactUin(NULL);
- serverthread_start_info* stsi = (serverthread_start_info*)SAFE_MALLOC(sizeof(serverthread_start_info));
-
- // Server host name
- char szServer[MAX_PATH];
- if (getSettingStringStatic(NULL, "OscarServer", szServer, MAX_PATH))
- stsi->nloc.szHost = null_strdup(m_bSecureConnection ? DEFAULT_SERVER_HOST_SSL : DEFAULT_SERVER_HOST);
- else
- stsi->nloc.szHost = null_strdup(szServer);
-
- // Server port
- stsi->nloc.wPort = getSettingWord(NULL, "OscarPort", m_bSecureConnection ? DEFAULT_SERVER_PORT_SSL : DEFAULT_SERVER_PORT);
- if (stsi->nloc.wPort == 0)
- stsi->nloc.wPort = RandRange(1024, 65535);
-
- // User password
- stsi->wPassLen = strlennull(szPassword);
- if (stsi->wPassLen > 8) stsi->wPassLen = 8;
- null_strcpy(stsi->szPass, szPassword, stsi->wPassLen);
-
- // Randomize sequence
- wLocalSequence = generate_flap_sequence();
-
- m_dwLocalUIN = dwUin;
-
- // Initialize members
- m_avatarsConnectionPending = TRUE;
-
- serverThreadHandle = ForkThreadEx(( IcqThreadFunc )&CIcqProto::ServerThread, stsi, &serverThreadId);
-}