/*
Plugin of Miranda IM for communicating with users of the AIM protocol.
Copyright (c) 2008-2009 Boris Krasnovskiy
Copyright (C) 2005-2006 Aaron Myles Landwehr
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, see .
*/
#include "aim.h"
int CAimProto::LOG(const char *fmt, ...)
{
va_list va;
char szText[1024];
if (!hNetlib)
return 0;
va_start(va, fmt);
mir_vsnprintf(szText, sizeof(szText), fmt, va);
va_end(va);
return CallService(MS_NETLIB_LOG, (WPARAM) hNetlib, (LPARAM) szText);
}
HANDLE CAimProto::aim_connect(const char* server, unsigned short port, bool use_ssl, const char* host)
{
NETLIBOPENCONNECTION ncon = { 0 };
ncon.cbSize = sizeof(ncon);
ncon.szHost = server;
ncon.wPort = port;
ncon.timeout = 6;
ncon.flags = NLOCF_V2;
LOG("%s:%u", server, port);
HANDLE con = (HANDLE) CallService(MS_NETLIB_OPENCONNECTION, (WPARAM)hNetlib, (LPARAM)&ncon);
if (con && use_ssl)
{
NETLIBSSL ssl = {0};
ssl.cbSize = sizeof(ssl);
ssl.host = host;
if (!CallService(MS_NETLIB_STARTSSL, (WPARAM)con, (LPARAM)&ssl))
{
Netlib_CloseHandle(con);
con = NULL;
}
}
return con;
}
HANDLE CAimProto::aim_peer_connect(const char* ip, unsigned short port)
{
NETLIBOPENCONNECTION ncon = { 0 };
ncon.cbSize = sizeof(ncon);
ncon.flags = NLOCF_V2;
ncon.szHost = ip;
ncon.wPort = port;
ncon.timeout = 3;
HANDLE con = (HANDLE) CallService(MS_NETLIB_OPENCONNECTION, (WPARAM) hNetlibPeer, (LPARAM) & ncon);
return con;
}
HANDLE CAimProto::aim_peer_connect(unsigned long ip, unsigned short port)
{
char ips[20];
long_ip_to_char_ip(ip, ips);
return aim_peer_connect(ips, port);
}
void CAimProto::aim_connection_authorization(void)
{
DBVARIANT dbv;
char *password = NULL;
NETLIBPACKETRECVER packetRecv = {0};
HANDLE hServerPacketRecver = NULL;
if (m_iDesiredStatus == ID_STATUS_OFFLINE)
goto exit;
if (!getString(AIM_KEY_PW, &dbv))
{
CallService(MS_DB_CRYPT_DECODESTRING, strlen(dbv.pszVal) + 1, (LPARAM) dbv.pszVal);
password = mir_strdup(dbv.pszVal);
DBFreeVariant(&dbv);
}
else
goto exit;
mir_free(username);
username = getSetting(AIM_KEY_SN);
if (username == NULL)
goto exit;
hServerPacketRecver = (HANDLE)CallService(MS_NETLIB_CREATEPACKETRECVER, (WPARAM)hServerConn, 2048 * 4);
packetRecv.cbSize = sizeof(packetRecv);
packetRecv.dwTimeout = 5000;
for(;;)
{
int recvResult = CallService(MS_NETLIB_GETMOREPACKETS, (WPARAM) hServerPacketRecver, (LPARAM) & packetRecv);
if (recvResult == 0)
{
LOG("Connection Closed: No Error? during Connection Authorization");
break;
}
else if (recvResult < 0)
{
LOG("Connection Closed: Socket Error during Connection Authorization %d", WSAGetLastError());
break;
}
else
{
unsigned short flap_length=0;
for(;packetRecv.bytesUsed0)
{
unsigned short flap_length=0;
for(;packetRecv.bytesUsed0)
{
unsigned short flap_length=0;
for(;packetRecv.bytesUsed 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(hAvatarConn, avatar_seqno, AVATAR_COOKIE_LENGTH, AVATAR_COOKIE);//cookie challenge
mir_free(AVATAR_COOKIE);
AVATAR_COOKIE = NULL;
AVATAR_COOKIE_LENGTH = 0;
}
else if(flap.cmp(0x02))
{
SNAC snac(flap.val(), flap.snaclen());
if (snac.cmp(0x0001))
{
snac_supported_families(snac, hAvatarConn, avatar_seqno);
snac_supported_family_versions(snac, hAvatarConn, avatar_seqno);
snac_avatar_rate_limitations(snac, hAvatarConn, avatar_seqno);
snac_error(snac);
}
if (snac.cmp(0x0010))
{
snac_retrieve_avatar(snac);
snac_upload_reply_avatar(snac);
}
}
else if (flap.cmp(0x04))
goto exit;
}
}
}
exit:
Netlib_CloseHandle(hServerPacketRecver);
Netlib_CloseHandle(hAvatarConn);
hAvatarConn=NULL;
ResetEvent(hAvatarEvent);
LOG("Avatar Server Connection has ended");
}
void __cdecl CAimProto::aim_chatnav_negotiation( void* )
{
unsigned idle_chat = 0;
HANDLE hServerPacketRecver = (HANDLE) CallService(MS_NETLIB_CREATEPACKETRECVER, (WPARAM)hChatNavConn, 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)
break;
if (recvResult == SOCKET_ERROR)
{
if (WSAGetLastError() == ERROR_TIMEOUT)
{
if (chat_rooms.getCount())
idle_chat = 0;
else if (++idle_chat >= 6)
break;
if (aim_keepalive(hChatNavConn, chatnav_seqno) < 0)
break;
}
else
break;
}
if(recvResult>0)
{
unsigned short flap_length=0;
for(;packetRecv.bytesUsedhconn, 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)
break;
if (recvResult == SOCKET_ERROR)
{
if (WSAGetLastError() == ERROR_TIMEOUT)
{
if (aim_keepalive(item->hconn, item->seqno) < 0)
break;
}
else
break;
}
if(recvResult>0)
{
unsigned short flap_length=0;
for(;packetRecv.bytesUsedhconn,item->seqno,item->CHAT_COOKIE_LENGTH,item->CHAT_COOKIE);//cookie challenge
mir_free(item->CHAT_COOKIE);
item->CHAT_COOKIE=NULL;
item->CHAT_COOKIE_LENGTH=0;
}
else if(flap.cmp(0x02))
{
SNAC snac(flap.val(),flap.snaclen());
if(snac.cmp(0x0001))
{
snac_supported_families(snac,item->hconn,item->seqno);
snac_supported_family_versions(snac,item->hconn,item->seqno);
snac_chat_rate_limitations(snac,item->hconn,item->seqno);
snac_error(snac);
}
if(snac.cmp(0x000E))
{
snac_chat_received_message(snac, item);
snac_chat_joined_left_users(snac, item);
snac_error(snac);
}
}
else if(flap.cmp(0x04))
goto exit;
}
}
}
exit:
Netlib_CloseHandle(hServerPacketRecver);
Netlib_CloseHandle(item->hconn);
chat_leave(item->id);
remove_chat_by_ptr(item);
LOG("Chat Server Connection has ended");
}
void __cdecl CAimProto::aim_admin_negotiation( void* )
{
HANDLE hServerPacketRecver = (HANDLE)CallService(MS_NETLIB_CREATEPACKETRECVER, (WPARAM)hAdminConn, 2048 * 8);
NETLIBPACKETRECVER packetRecv = {0};
packetRecv.cbSize = sizeof(packetRecv);
packetRecv.dwTimeout = 300000;//5 minutes connected
for(;;)
{
int recvResult = CallService(MS_NETLIB_GETMOREPACKETS, (WPARAM) hServerPacketRecver, (LPARAM) & packetRecv);
if (recvResult == 0)
break;
if (recvResult == SOCKET_ERROR)
break;
if(recvResult>0)
{
unsigned short flap_length=0;
for(;packetRecv.bytesUsed