Mercurial > pidgin
changeset 1432:4c510ca3563f
[gaim-migrate @ 1442]
icqlib 1.1.5
committer: Tailor Script <tailor@pidgin.im>
line wrap: on
line diff
--- a/plugins/icq/.cvsignore Sat Jan 27 11:18:17 2001 +0000 +++ b/plugins/icq/.cvsignore Sun Jan 28 01:52:27 2001 +0000 @@ -14,6 +14,7 @@ list.lo proxy.lo queue.lo +socketmanager.lo stdpackets.lo tcp.lo tcpchathandle.lo
--- a/plugins/icq/CHANGES_SINCE_1.0 Sat Jan 27 11:18:17 2001 +0000 +++ b/plugins/icq/CHANGES_SINCE_1.0 Sun Jan 28 01:52:27 2001 +0000 @@ -1,6 +1,6 @@ -This file is intendended to be a list of source incompatable changes have -been made since icqlib-1.0.0. +This file is intendended to be a list of source incompatable changes +that have been made since icqlib-1.0.0. 2000-12-19: ICQLINKs have been reworked. Members that provide no useful information to the library client have been moved to a private structure @@ -17,7 +17,60 @@ and icq_ICQLINKDelete instead. In addition, icq_ICQLINKNew has gained an additional parameter: a flag to turn TCP on or off. +2001-01-16: The chat and file request/session interface has been +significantly reworked. icq_RequestNotify now will return +ICQ_NOTIFY_SUCCESS as soon as the file or chat *request* is complete, but +not before returning a handle to an icq_ChatSession or icq_FileSession. +See ICQ_NOTIFY_CHATSESSION and ICQ_NOTIFY_FILESESSION. All future +operations on the chat or file session should be performed using this +handle and the appropriate icq_ChatSession* or icq_FileSession* functions. +Old function New function + +icq_TCPCloseChat icq_ChatSessionClose +icq_TCPSendChatData icq_ChatSessionSendData +icq_TCPSendChatData_n icq_ChatSessionSendData_n + +In addition, notification messages for chat and file sessions come back +through two new callbacks: icq_ChatNotify and icq_FileNotify. +icq_ChatSession has also been exposed in the public interface, as well as +a number of chat status constants. + +Old notification New notification + +icq_RequestNotify/ICQ_NOTIFY_CHAT icq_ChatNotify/CHAT_NOTIFY_STATUS +icq_RequestNotify/ICQ_NOTIFY_CHATDATA icq_ChatNotify/CHAT_NOTIFY_DATA +icq_RequestNotify/ICQ_NOTIFY_SUCCESS icq_ChatNotify/CHAT_NOTIFY_CLOSE + +icq_RequestNotify/ICQ_NOTIFY_FILE icq_FileNotify/FILE_NOTIFY_STATUS +icq_RequestNotify/ICQ_NOTIFY_FILEDATA icq_FileNotify/FILE_NOTIFY_DATAPACKET +icq_RequestNotify/ICQ_NOTIFY_SUCCESS icq_FileNotify/FILE_NOTIFY_CLOSE +Finally, some fake file status values now come through seperate +FILE_NOTIFY events, and one has been renamed: +Old status New Notification/Status +FILE_STATUS_NEW_SPEED icq_FileNotify/FILE_NOTIFY_NEW_SPEED +FILE_STATUS_STOP_FILE icq_FileNotify/FILE_NOTIFY_STOP_FILE +FILE_STATUS_INITIALIZED FILE_STATUS_INITIALIZING + +2001-01-16: icqlib now reports when it needs read and write ready +notifications for sockets through icq_SocketNotify. Install a callback +for the icq_SocketNotify function, which takes the following parameters: + + void (*icq_SocketNotify)(int socket, int type, int status); + +socket will be the socket number, type will be either ICQ_SOCKET_READ or +ICQ_SOCKET_WRITE, and status will be either true or false, true indicating +icqlib now needs notification, and false indicating icqlib no longer needs +notification. Your application should use this to install some sort of +socket notification object (e.g., in Kicq, we use a QSocketNotifier). +When the socket is ready, you should invoke the new +icq_HandleReadySocket(socket, type) function. + +This mechanism is completely optional - you can simply set up a timer to +call icq_Main every 1/10 of a second or so. This has the disadvantage of +wasting CPU cycles and poor TCP file transfer performance, though. + +
--- a/plugins/icq/ChangeLog Sat Jan 27 11:18:17 2001 +0000 +++ b/plugins/icq/ChangeLog Sun Jan 28 01:52:27 2001 +0000 @@ -1,3 +1,81 @@ +2001-01-27 Bill Soudan <soudan@kde.org> + + * icqlib/socketmanager.c, icqlib/socketmanager.h, + icqlib/tcplink.c: fix bugs related to TCP and new socket manager: + implemented accepting TCP sockets, fixed crashes when sending + TCP messages. + +2001-01-24 Bill Soudan <soudan@kde.org> + + * icqlib/stdpackets.c, icqlib/stdpackets.h, icqlib/tcphandle.c, + icqlib/icq.h.in: applied patch from Robin Ericsson + (lobbin@localhost.nu) which implements receiving contact lists. + See new icq_RecvContactList callback. + +2001-01-20 Bill Soudan <soudan@kde.org> + + * icqlib/chatsession.c, icqlib/icq.h.in: added documentation + + * icqlib/icqbyteorder.h: applied patch from Eric Warmenhoven + to fix byte order on HP/UX. + + * icqlib/tcplink.h: applied patch from Eric Warmenhoven to + fix compilation on FreeBSD. + +2001-01-16 Bill Soudan <soudan@kde.org> + + Phase 2 of my interface cleanups. See CHANGES_SINCE_1.0 for + more details. icqlib developers be sure to look at + socketmanager.c - all future socket create/delete/handling needs + to go through this code so the new icq_SocketNotify callback + works properly. + + * icqlib/socketmanager.c, icqlib/socketmanager.h, + icqlib/Makefile.am: added socketmanager.c & socketmanager.h + + * icqlib/contacts.h, icqlib/list.h, icqlib/proxy.c: cleanup + + * icqlib/chatsession.c, icqlib/chatsession.h, icqlib/filesession.c, + icqlib/icq.h.in, icqlib/icqevent.c, icqlib/icqevent.h, + icqlib/icqlib.c, icqlib/icqlib.h, icqlib/tcp.c, + icqlib/tcpchathandle.c, icqlib/tcpfilehandle.c, + icqlib/tcphandle.c, icqlib/tcplink.c, icqlib/tcplink.h: + Rework chat and file interfaces; implement socket notifications. + + * VERSION: bumped to 1.1.5 + +2001-01-16 Denis V. Dmitrienko <denis@null.net> + + * icqlib/contacts.c, icqlib/contacts.h, icqlib/icq.h.in, icqlib/udp.c: + Invisible list has been finished. + +2001-01-15 Denis V. Dmitrienko <denis@null.net> + + * icqlib/tcplink.c: + Applied patch from Ilya Melamed <ilya@ort.org.il> which fixes random + icq_TCPLinkAccept() fails. + + * icqlib/udphandle.c: + Applied patch from Andrey Chernomyrdin <andrey@excom.spb.su> to + handle icq2000 specific "You've been added" packet. + + * icqlib/icq.h.in: + Prototype for icq_SendInvisibleList() has been added. + + * .cvsignore, icqlib.spec.in: + Applied patch from Ryan Weaver <ryanw@infohwy.com> for .spec file + generation. + + * configure.in, Makefile.am, Makefile.cvs, admin/acinclude.m4.in, + admin/config.guess, admin/config.sub, admin/icqlib.m4.in, + admin/install-sh, admin/libtool.m4.in, admin/ltconfig, + admin/ltmain.sh, admin/missing, admin/mkinstalldirs, + acinclude.m4.in, am_edit, config.guess, config.sub, icqlib.m4.in, + install-sh, libtool.m4.in, ltconfig, ltmain.sh, missing, + mkinstalldirs: + autoconf/automake files have been moved to admin directory. + + * TODO, icqlib/icqlib.c: Cleanup. 2000-12-19 Bill Soudan <wes0472@rit.edu>
--- a/plugins/icq/Makefile.am Sat Jan 27 11:18:17 2001 +0000 +++ b/plugins/icq/Makefile.am Sun Jan 28 01:52:27 2001 +0000 @@ -1,4 +1,4 @@ -CFLAGS += -I\$(top_srcdir)/src +CFLAGS += -I\$(top_srcdir)/src $(DEBUG_CFLAGS) LIBS = $(GTK_LIBS) EXTRA_DIST = AUTHORS \ @@ -35,6 +35,8 @@ proxy.c \ queue.c \ queue.h \ + socketmanager.c \ + socketmanager.h \ stdpackets.c \ stdpackets.h \ tcp.c \
--- a/plugins/icq/VERSION Sat Jan 27 11:18:17 2001 +0000 +++ b/plugins/icq/VERSION Sun Jan 28 01:52:27 2001 +0000 @@ -1,1 +1,1 @@ -1.1.0 +1.1.5
--- a/plugins/icq/chatsession.c Sat Jan 27 11:18:17 2001 +0000 +++ b/plugins/icq/chatsession.c Sun Jan 28 01:52:27 2001 +0000 @@ -1,7 +1,9 @@ #include <stdlib.h> +#include "icq.h" #include "icqlib.h" +#include "tcplink.h" #include "chatsession.h" #include "list.h" @@ -11,10 +13,10 @@ if (p) { - p->remote_handle=0L; p->status=0; p->id=0L; p->icqlink=icqlink; + p->tcplink=NULL; list_insert(icqlink->d->icq_ChatSessions, 0, p); } @@ -23,15 +25,13 @@ void icq_ChatSessionDelete(void *p) { + icq_ChatSession *pchat = (icq_ChatSession *)p; + invoke_callback(pchat->icqlink, icq_ChatNotify)(pchat, CHAT_NOTIFY_CLOSE, + 0, NULL); + free(p); } -void icq_ChatSessionClose(icq_ChatSession *p) -{ - list_remove(p->icqlink->d->icq_ChatSessions, p); - icq_ChatSessionDelete(p); -} - int _icq_FindChatSession(void *p, va_list data) { DWORD uin=va_arg(data, DWORD); @@ -48,6 +48,77 @@ { p->status=status; if(p->id) - if(p->icqlink->icq_RequestNotify) - (*p->icqlink->icq_RequestNotify)(p->icqlink, p->id, ICQ_NOTIFY_CHAT, status, 0); + invoke_callback(p->icqlink, icq_ChatNotify)(p, CHAT_NOTIFY_STATUS, + status, NULL); +} + +/* public */ + +/** Closes a chat session. + * @param session desired icq_ChatSession + * @ingroup ChatSession + */ +void icq_ChatSessionClose(icq_ChatSession *session) +{ + icq_TCPLink *plink = session->tcplink; + + /* if we're attached to a tcplink, unattach so the link doesn't try + * to close us, and then close the tcplink */ + if (plink) + { + plink->session=NULL; + icq_TCPLinkClose(plink); + } + + icq_ChatSessionDelete(session); + + list_remove(session->icqlink->d->icq_ChatSessions, session); } + +/** Sends chat data to the remote uin. + * @param session desired icq_ChatSession + * @param data pointer to data buffer, null-terminated + * @ingroup ChatSession + */ +void icq_ChatSessionSendData(icq_ChatSession *session, const char *data) +{ + icq_TCPLink *plink = session->tcplink; + int data_length = strlen(data); + char *buffer; + + if(!plink) + return; + + buffer = (char *)malloc(data_length); + strcpy(buffer, data); + icq_ChatRusConv_n("kw", buffer, data_length); + + send(plink->socket, buffer, data_length, 0); + + free(buffer); +} + +/** Sends chat data to the remote uin. + * @param session desired icq_ChatSession + * @param data pointer to data buffer + * @param length length of data + * @ingroup ChatSession + */ +void icq_ChatSessionSendData_n(icq_ChatSession *session, const char *data, + int length) +{ + icq_TCPLink *plink = session->tcplink; + char *buffer; + + if(!plink) + return; + + buffer = (char *)malloc(length); + memcpy(buffer, data, length); + icq_ChatRusConv_n("kw", buffer, length); + + send(plink->socket, buffer, length, 0); + + free(buffer); +} +
--- a/plugins/icq/chatsession.h Sat Jan 27 11:18:17 2001 +0000 +++ b/plugins/icq/chatsession.h Sun Jan 28 01:52:27 2001 +0000 @@ -5,19 +5,6 @@ #include "icq.h" #include "icqtypes.h" -/* chat session statuses- request receiver */ -#define CHAT_STATUS_LISTENING 1 -#define CHAT_STATUS_CONNECTED 3 -#define CHAT_STATUS_WAIT_NAME 4 -#define CHAT_STATUS_WAIT_FONT 6 - -/* chat session statuses- request sender */ -#define CHAT_STATUS_CONNECTING 2 -#define CHAT_STATUS_WAIT_ALLINFO 5 - -/* once negotiation is complete, both sides enter ready state */ -#define CHAT_STATUS_READY 7 - /* chat session states: accepting chat request @@ -60,20 +47,8 @@ ICQ_NOTIFY_SUCCESS */ -typedef struct icq_ChatSession_s { - - DWORD id; - int status; - ICQLINK *icqlink; - - DWORD remote_uin; - char *remote_handle; - -} icq_ChatSession; - icq_ChatSession *icq_ChatSessionNew(ICQLINK *); void icq_ChatSessionDelete(void *); -void icq_ChatSessionClose(icq_ChatSession *); void icq_ChatSessionSetStatus(icq_ChatSession *, int); icq_ChatSession *icq_FindChatSession(ICQLINK *, DWORD);
--- a/plugins/icq/contacts.c Sat Jan 27 11:18:17 2001 +0000 +++ b/plugins/icq/contacts.c Sun Jan 28 01:52:27 2001 +0000 @@ -1,9 +1,12 @@ /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* -$Id: contacts.c 1319 2000-12-19 10:08:29Z warmenhoven $ +$Id: contacts.c 1442 2001-01-28 01:52:27Z warmenhoven $ $Log$ -Revision 1.2 2000/12/19 10:08:29 warmenhoven -Yay, new icqlib +Revision 1.3 2001/01/28 01:52:27 warmenhoven +icqlib 1.1.5 + +Revision 1.6 2001/01/16 00:10:13 denis +Invisible list has been finished. Revision 1.5 2000/12/19 06:00:07 bills moved members from ICQLINK to ICQLINK_private struct @@ -96,6 +99,13 @@ p->vis_list = vu; } +void icq_ContactSetInvis(ICQLINK *link, DWORD cuin, BYTE vu) +{ + icq_ContactItem *p = icq_ContactFind(link, cuin); + if(p) + p->invis_list = vu; +} + icq_ContactItem *icq_ContactGetFirst(ICQLINK *link) { return list_first(link->d->icq_ContactList); @@ -109,5 +119,4 @@ return p->next->item; else return 0L; - }
--- a/plugins/icq/contacts.h Sat Jan 27 11:18:17 2001 +0000 +++ b/plugins/icq/contacts.h Sun Jan 28 01:52:27 2001 +0000 @@ -5,11 +5,12 @@ #include "icq.h" #include "icqtypes.h" -typedef struct icq_ContItem +typedef struct icq_ContactItem_s { ICQLINK *icqlink; unsigned long uin; int vis_list; + int invis_list; unsigned long remote_ip; unsigned long remote_real_ip; unsigned long remote_port;
--- a/plugins/icq/cyrillic.c Sat Jan 27 11:18:17 2001 +0000 +++ b/plugins/icq/cyrillic.c Sun Jan 28 01:52:27 2001 +0000 @@ -1,9 +1,9 @@ /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* -$Id: cyrillic.c 1319 2000-12-19 10:08:29Z warmenhoven $ +$Id: cyrillic.c 1442 2001-01-28 01:52:27Z warmenhoven $ $Log$ -Revision 1.2 2000/12/19 10:08:29 warmenhoven -Yay, new icqlib +Revision 1.3 2001/01/28 01:52:27 warmenhoven +icqlib 1.1.5 Revision 1.7 2000/05/21 17:41:14 denis Applied patch for russian letters IO and io by
--- a/plugins/icq/eventhandle.c Sat Jan 27 11:18:17 2001 +0000 +++ b/plugins/icq/eventhandle.c Sun Jan 28 01:52:27 2001 +0000 @@ -1,11 +1,11 @@ /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* - * $Id: eventhandle.c 1319 2000-12-19 10:08:29Z warmenhoven $ + * $Id: eventhandle.c 1442 2001-01-28 01:52:27Z warmenhoven $ * * $Log$ - * Revision 1.1 2000/12/19 10:08:29 warmenhoven - * Yay, new icqlib + * Revision 1.2 2001/01/28 01:52:27 warmenhoven + * icqlib 1.1.5 * * Revision 1.3 2000/12/19 06:00:07 bills * moved members from ICQLINK to ICQLINK_private struct
--- a/plugins/icq/eventhandle.h Sat Jan 27 11:18:17 2001 +0000 +++ b/plugins/icq/eventhandle.h Sun Jan 28 01:52:27 2001 +0000 @@ -1,11 +1,11 @@ /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* - * $Id: eventhandle.h 1319 2000-12-19 10:08:29Z warmenhoven $ + * $Id: eventhandle.h 1442 2001-01-28 01:52:27Z warmenhoven $ * * $Log$ - * Revision 1.1 2000/12/19 10:08:29 warmenhoven - * Yay, new icqlib + * Revision 1.2 2001/01/28 01:52:27 warmenhoven + * icqlib 1.1.5 * * Revision 1.1 2000/06/15 18:50:03 bills * committed for safekeeping - this code will soon replace tcphandle.c
--- a/plugins/icq/filesession.c Sat Jan 27 11:18:17 2001 +0000 +++ b/plugins/icq/filesession.c Sun Jan 28 01:52:27 2001 +0000 @@ -47,6 +47,9 @@ { icq_FileSession *p=(icq_FileSession *)pv; + invoke_callback(p->icqlink, icq_FileNotify)(p, FILE_NOTIFY_CLOSE, 0, + NULL); + if(p->files) { char **p2=p->files; while(*p2) @@ -84,9 +87,14 @@ if(status!=p->status) { p->status=status; - if(p->id && p->icqlink->icq_RequestNotify) - (*p->icqlink->icq_RequestNotify)(p->icqlink, p->id, ICQ_NOTIFY_FILE, - status, 0); + if(p->id) + invoke_callback(p->icqlink, icq_FileNotify)(p, FILE_NOTIFY_STATUS, + status, NULL); + if (status == FILE_STATUS_SENDING) + icq_SocketSetHandler(p->tcplink->socket, ICQ_SOCKET_WRITE, + icq_FileSessionSendData, p); + else + icq_SocketSetHandler(p->tcplink->socket, ICQ_SOCKET_WRITE, NULL, NULL); } } @@ -181,10 +189,9 @@ p->total_transferred_bytes+=count; p->current_file_progress+=count; icq_FileSessionSetStatus(p, FILE_STATUS_SENDING); - - if (p->icqlink->icq_RequestNotify) - (*p->icqlink->icq_RequestNotify)(p->icqlink, p->id, - ICQ_NOTIFY_FILEDATA, count, NULL); + + invoke_callback(p->icqlink, icq_FileNotify)(p, FILE_NOTIFY_DATAPACKET, + count, buffer); } /* done transmitting if read returns less that 2048 bytes */
--- a/plugins/icq/gaim_icq.c Sat Jan 27 11:18:17 2001 +0000 +++ b/plugins/icq/gaim_icq.c Sun Jan 28 01:52:27 2001 +0000 @@ -1,5 +1,6 @@ #include <gtk/gtk.h> #include <string.h> +#include <stdlib.h> #include "icq.h" /* well, we're doing ICQ, right? */ #include "multi.h" /* needed for gaim_connection */ #include "prpl.h" /* needed for prpl */ @@ -17,7 +18,6 @@ struct icq_data { ICQLINK *link; int cur_status; - int tcp_timer; int ack_timer; }; @@ -48,17 +48,45 @@ debug_printf("ICQ debug %d: %s", level, log); } -static gint icq_tcp_timer(ICQLINK *link) { - icq_TCPMain(link); - return TRUE; +GList *sockets = NULL; +struct gaim_sock { + int socket; + gint inpa; +}; + +static void gaim_icq_handler(gpointer data, gint source, GdkInputCondition cond) { + if ((cond & GDK_INPUT_READ) || (cond & GDK_INPUT_EXCEPTION)) + icq_HandleReadySocket(source, ICQ_SOCKET_READ); + if (cond & GDK_INPUT_WRITE) + icq_HandleReadySocket(source, ICQ_SOCKET_WRITE); } -static void icq_callback(gpointer data, gint source, GdkInputCondition condition) { - struct gaim_connection *gc = (struct gaim_connection *)data; - struct icq_data *id = (struct icq_data *)gc->proto_data; - debug_printf("ICQ Callback handler\n"); - - icq_HandleServerResponse(id->link); +static void icq_sock_notify(int socket, int type, int status) { + struct gaim_sock *gs; + if (status) { + GdkInputCondition cond; + if (type == ICQ_SOCKET_READ) + cond = GDK_INPUT_READ | GDK_INPUT_EXCEPTION; + else + cond = GDK_INPUT_WRITE | GDK_INPUT_EXCEPTION; + gs = g_new0(struct gaim_sock, 1); + gs->socket = socket; + gs->inpa = gdk_input_add(socket, cond, gaim_icq_handler, NULL); + sockets = g_list_append(sockets, gs); + } else { + GList *m = sockets; + while (m) { + gs = m->data; + if (gs->socket == socket) + break; + m = g_list_next(m); + } + if (m) { + gdk_input_remove(gs->inpa); + sockets = g_list_remove(sockets, gs); + g_free(gs); + } + } } static void icq_online(ICQLINK *link) { @@ -78,10 +106,6 @@ static void icq_logged_off(ICQLINK *link) { struct gaim_connection *gc = find_gaim_conn_by_icq_link(link); struct icq_data *id = (struct icq_data *)gc->proto_data; - int icqSocket; - - gtk_timeout_remove(id->tcp_timer); - gdk_input_remove(gc->inpa); if (icq_Connect(link, "icq.mirabilis.com", 4000) < 1) { hide_login_progress(gc, "Unable to connect"); @@ -89,13 +113,8 @@ return; } - icqSocket = icq_GetSok(link); - gc->inpa = gdk_input_add(icqSocket, GDK_INPUT_READ | GDK_INPUT_EXCEPTION, icq_callback, gc); - icq_Login(link, STATUS_ONLINE); id->cur_status = STATUS_ONLINE; - - id->tcp_timer = gtk_timeout_add(100, (GtkFunction)icq_tcp_timer, link); } static void icq_msg_incoming(ICQLINK *link, unsigned long uin, unsigned char hour, unsigned char minute, @@ -196,10 +215,6 @@ g_show_info_text(buf); } -static void icq_req_notify(struct icq_link *link, unsigned long id, int result, - unsigned int length, void *data) { -} - static void icq_web_pager(struct icq_link *link, unsigned char hour, unsigned char minute, unsigned char day, unsigned char month, unsigned short year, const char *nick, const char *email, const char *msg) { @@ -225,13 +240,17 @@ static void icq_login(struct aim_user *user) { struct gaim_connection *gc = new_gaim_conn(user); struct icq_data *id = gc->proto_data = g_new0(struct icq_data, 1); - ICQLINK *link = id->link = icq_ICQLINKNew(atol(user->username), user->password, - user->proto_opt[USEROPT_NICK][0] ? user->proto_opt[USEROPT_NICK] : "gaim user", - TRUE); - int icqSocket; + ICQLINK *link; + + if (!icq_SocketNotify) + icq_SocketNotify = icq_sock_notify; icq_LogLevel = ICQ_LOG_MESSAGE; + link = id->link = icq_ICQLINKNew(atol(user->username), user->password, + user->proto_opt[USEROPT_NICK][0] ? user->proto_opt[USEROPT_NICK] : "gaim user", + TRUE); + link->icq_Logged = icq_online; link->icq_Disconnected = icq_logged_off; link->icq_RecvMessage = icq_msg_incoming; @@ -245,7 +264,6 @@ link->icq_WrongPassword = icq_wrong_passwd; link->icq_InvalidUIN = icq_invalid_uin; link->icq_Log = icq_do_log; - link->icq_RequestNotify = icq_req_notify; link->icq_SetTimeout = icq_set_timeout; icq_UnsetProxy(link); @@ -256,24 +274,15 @@ return; } - icqSocket = icq_GetSok(link); - gc->inpa = gdk_input_add(icqSocket, GDK_INPUT_READ | GDK_INPUT_EXCEPTION, icq_callback, gc); - icq_Login(link, STATUS_ONLINE); id->cur_status = STATUS_ONLINE; - id->tcp_timer = gtk_timeout_add(100, (GtkFunction)icq_tcp_timer, link); - set_login_progress(gc, 0, "Connecting..."); } static void icq_close(struct gaim_connection *gc) { struct icq_data *id = (struct icq_data *)gc->proto_data; - if (id->tcp_timer > 0) - gtk_timeout_remove(id->tcp_timer); - if (gc->inpa > 0) - gdk_input_remove(gc->inpa); icq_Logout(id->link); icq_Disconnect(id->link); icq_ICQLINKDelete(id->link); @@ -297,7 +306,6 @@ struct icq_data *id = (struct icq_data *)gc->proto_data; icq_ContactAdd(id->link, atol(who)); icq_ContactSetVis(id->link, atol(who), TRUE); - icq_SendNewUser(id->link, atol(who)); } static void icq_add_buddies(struct gaim_connection *gc, GList *whos) { @@ -448,6 +456,8 @@ m = g_list_append(m, "Occupied"); m = g_list_append(m, "Free For Chat"); m = g_list_append(m, "Invisible"); + + return m; } static void icq_init(struct prpl *ret) {
--- a/plugins/icq/icq.h Sat Jan 27 11:18:17 2001 +0000 +++ b/plugins/icq/icq.h Sun Jan 28 01:52:27 2001 +0000 @@ -6,22 +6,22 @@ #include <config.h> #endif -#define ICQLIBVER 0x010100 -#define ICQLIBMAJOR 1 -#define ICQLIBMINOR 1 -#define ICQLIBMICRO 0 - -#include <time.h> - #ifndef _WIN32 #include <sys/time.h> #include <sys/types.h> #include <unistd.h> -#endif +#else +#include <winsock.h> +#endif /* _WIN32 */ + +#include <time.h> -#ifdef _WIN32 -#include <winsock.h> -#endif +/* ICQLIB version defines */ +#define ICQLIBVER 0x010105 +#define ICQLIBMAJOR 1 +#define ICQLIBMINOR 1 +#define ICQLIBMICRO 5 + #define ICQ_LOG_OFF 0 #define ICQ_LOG_FATAL 1 @@ -49,12 +49,8 @@ #define ICQ_NOTIFY_SENT 4 #define ICQ_NOTIFY_ACK 5 -#define ICQ_NOTIFY_CHAT 6 -#define ICQ_NOTIFY_CHATDATA 7 - -#define ICQ_NOTIFY_FILE 10 -#define ICQ_NOTIFY_FILESESSION 11 -#define ICQ_NOTIFY_FILEDATA 12 +#define ICQ_NOTIFY_CHATSESSION 7 +#define ICQ_NOTIFY_FILESESSION 8 #ifdef __cplusplus extern "C" { @@ -66,7 +62,11 @@ unsigned short code; } icq_ArrayType; +/* dummy forward declarations */ struct icq_link_private; +typedef struct icq_TCPLink_s icq_TCPLink; +typedef struct icq_FileSession_s icq_FileSession; +typedef struct icq_ChatSession_s icq_ChatSession; /** * The ICQLINK structure represents a single connection to the ICQ servers. @@ -164,6 +164,8 @@ unsigned char hour, unsigned char minute, unsigned char day, unsigned char month, unsigned short year, const char *url, const char *descr); + void (*icq_RecvContactList)(struct icq_link *link, unsigned long uin, + int nr, const char **contact_uin, const char **contact_nick); void (*icq_RecvWebPager)(struct icq_link *link,unsigned char hour, unsigned char minute, unsigned char day, unsigned char month, unsigned short year, const char *nick, const char *email, @@ -211,8 +213,12 @@ void (*icq_Log)(struct icq_link *link, time_t time, unsigned char level, const char *str); void (*icq_SrvAck)(struct icq_link *link, unsigned short seq); - void (*icq_RequestNotify)(struct icq_link *link, unsigned long id, int result, - unsigned int length, void *data); + void (*icq_RequestNotify)(struct icq_link *link, unsigned long id, + int type, int arg, void *data); + void (*icq_FileNotify)(icq_FileSession *session, int type, int arg, + void *data); + void (*icq_ChatNotify)(icq_ChatSession *session, int type, int arg, + void *data); void (*icq_NewUIN)(struct icq_link *link, unsigned long uin); void (*icq_SetTimeout)(struct icq_link *link, long interval); void (*icq_MetaUserFound)(struct icq_link *link, unsigned short seq2, @@ -269,9 +275,6 @@ const char *nick, unsigned char useTCP); void icq_ICQLINKDelete(ICQLINK *link); -void icq_Init(ICQLINK *link, unsigned long uin, const char *password, - const char *nick, unsigned char useTCP); -void icq_Done(ICQLINK *link); int icq_Connect(ICQLINK *link, const char *hostname, int port); void icq_Disconnect(ICQLINK *link); int icq_GetSok(ICQLINK *link); @@ -285,6 +288,7 @@ void icq_Logout(ICQLINK *link); void icq_SendContactList(ICQLINK *link); void icq_SendVisibleList(ICQLINK *link); +void icq_SendInvisibleList(ICQLINK *link); void icq_SendNewUser(ICQLINK * link, unsigned long uin); unsigned long icq_SendMessage(ICQLINK *link, unsigned long uin, const char *text, unsigned char thruSrv); @@ -330,6 +334,7 @@ void icq_ContactRemove(ICQLINK *link, unsigned long cuin); void icq_ContactClear(ICQLINK *link ); void icq_ContactSetVis(ICQLINK *link, unsigned long cuin, unsigned char vu); +void icq_ContactSetInvis(ICQLINK *link, unsigned long cuin, unsigned char vu); /*** TCP ***/ void icq_TCPMain(ICQLINK *link); @@ -344,10 +349,6 @@ const char *message); void icq_AcceptChatRequest(ICQLINK *link, unsigned long uin, unsigned long seq); -void icq_TCPSendChatData(ICQLINK *link, unsigned long uin, const char *data); -void icq_TCPSendChatData_n(ICQLINK *link, unsigned long uin, const char *data, int len); -void icq_TCPCloseChat(ICQLINK *link, unsigned long uin); - void icq_CancelChatRequest(ICQLINK *link, unsigned long uin, unsigned long sequence); void icq_RefuseChatRequest(ICQLINK *link, unsigned long uin, @@ -355,6 +356,181 @@ /*** TCP ***/ +/** \defgroup ChatSession Chat Session Documentation + * icqlib's 'Chat Session' abstraction represents ICQ's 'chat' function + * between two participants. Multi-party chat is not yet supported. + * + * An icq_ChatSession is instantiated when a 'Chat Request' event is + * accepted. Upon receipt of a 'Chat Accept' event or a call to + * icq_AcceptChatRequest, icqlib will create a new chat session and pass the + * new chat session pointer back to the library client through the + * icq_RequestNotify / ICQ_NOTIFY_CHATSESSION callback. This pointer should + * be stored by the library client, as multiple chat sessions may be in + * progress at any given time. The icq_ChatSession pointer is used as a key + * for all future communication between the library and the library client to + * indicate which icq_ChatSession is currently being dealt with. + * + * icqlib communicates chat session events through use of the icq_ChatNotify + * callback, such as the CHAT_NOTIFY_DATA event. The library client + * can perform operations on a chat session by use of the icq_ChatSession* + * functions, such as sending data to the remote uin by using the + * icq_ChatSessionSendData function. + * + * A new chat session must first undergo an initialization sequence before is + * ready to transmit and receive data. As this initialization is in progress + * the chat session will transition through various statuses depending on + * whether icqlib sent the accept event or it received the accept event. + * Each change in chat session status will be reported to the library + * client through use of the icq_ChatNotify callback, with a @type parameter + * of CHAT_NOTIFY_STATUS and an @a arg parameter of the status value. + * + * Once the chat session initialization is complete, both sides will enter + * the CHAT_STATUS_READY state, indicating that the chat session is + * ready to send and receive data. Received data is reported through the + * icq_ChatNotify callback, with a @type of CHAT_NOTIFY_DATA. The library + * client can send data using icq_ChatSessionSendData or + * icq_ChatSessionSendData_n. + * + * Chat sessions may be terminated at any time, by either side. The library + * client may terminate a chat session by using icq_ChatSessionClose, or + * the remote uin may terminate a chat session. In either instance, a + * CHAT_STATUS_CLOSE event will be reported through the icq_ChatNotify + * callback. Once this callback is complete (e.g. your application's + * callback handler returns), the icq_ChatSession will be deleted by icqlib + * and the session pointer becomes invalid. + */ + +/** @name Type Constants + * @ingroup ChatSession + * These values are used as the @a type parameter in the icq_ChatNotify + * callback to indicate the type of chat session event that has occured. + * The remaining @a arg and @a data parameters passed by the callback + * are specific to each event; see the documentation for each type + * constant. + */ + +/*@{*/ + +/** Status has changed. + * @param arg new session status - one of the CHAT_STATUS_* defines + * @param data unused. + * @ingroup ChatSession + */ +#define CHAT_NOTIFY_STATUS 1 + +/** Data has been received from a chat participant. + * @param arg length of data received + * @param data pointer to buffer containing received data + * @ingroup ChatSession + */ +#define CHAT_NOTIFY_DATA 2 + +/** Session has been closed, either automatically by icqlib or + * explicitly by a call to icq_ChatSessionClose. + * @param arg unused + * @param data unused + * @ingroup ChatSession + */ +#define CHAT_NOTIFY_CLOSE 3 + +/*@}*/ + +/** @name Status Constants + * @ingroup ChatSession + * These constants are used as the @a arg parameter during in the + * icq_ChatNotify/CHAT_NOTIFY_STATUS callback to indicate the + * new status of the chat session. + */ + +/*@{*/ + +/** icqlib is listening for a chat connection from the remote uin. + * @ingroup ChatSession + */ +#define CHAT_STATUS_LISTENING 1 + +/** A connection has been established with the remote uin. + * @ingroup ChatSession + */ +#define CHAT_STATUS_CONNECTED 3 + +/** icqlib is currently waiting for the remote uin to send the chat + * initialization packet which contains the remote uin's chat handle. + * @ingroup ChatSession + */ +#define CHAT_STATUS_WAIT_NAME 4 + +/** icqlib is currently waiting for the remote uin to send the chat + * initialization packet which contains the remote uin's font information. + * @ingroup ChatSession + */ +#define CHAT_STATUS_WAIT_FONT 6 + +/** A connection to the chat session port of the remote uin is in + * progress. + * @ingroup ChatSession + */ +/* chat session statuses - request sender */ +#define CHAT_STATUS_CONNECTING 2 + +/** icqlib is currently waiting for the remote uin to send the chat + * initialization packet which contains the remote uin's chat handle + * and font information. + * @ingroup ChatSession + */ +#define CHAT_STATUS_WAIT_ALLINFO 5 + +/** Chat session initialization has completed successfully. The session + * is now fully established - both sides can begin to send data and + * should be prepared to accept data. + * @ingroup ChatSession + */ +#define CHAT_STATUS_READY 7 + +/*@}*/ + +/** Chat Session state structure. This structure is used internally by + * icqlib to maintain state information about each chat session. All + * members should be considered read-only! Use the appropriate + * icq_ChatSession* function to change the state of a chat session, + * results are undefined if your application attempts to manipulate this + * structure itself. + */ +struct icq_ChatSession_s { + + /** For internal icqlib use only. */ + unsigned long id; + + /** Current status of the chat session. See 'Status Constants' group. */ + int status; + + /** ICQLINK that spawned this chat session. */ + ICQLINK *icqlink; + + /** For internal icqlib use only. */ + icq_TCPLink *tcplink; + + /** Remote uin number. */ + unsigned long remote_uin; + + /** Remote uin's chat handle. */ + char remote_handle[64]; + +}; + +void icq_ChatSessionClose(icq_ChatSession *session); +void icq_ChatSessionSendData(icq_ChatSession *session, const char *data); +void icq_ChatSessionSendData_n(icq_ChatSession *session, const char *data, + int length); + + +/* FileNotify constants */ +#define FILE_NOTIFY_DATAPACKET 1 +#define FILE_NOTIFY_STATUS 2 +#define FILE_NOTIFY_CLOSE 3 +#define FILE_NOTIFY_NEW_SPEED 4 +#define FILE_NOTIFY_STOP_FILE 5 + /* file session statuses- request receiver */ #define FILE_STATUS_LISTENING 1 #define FILE_STATUS_CONNECTED 3 @@ -362,24 +538,20 @@ /* file session statuses- request sender */ #define FILE_STATUS_CONNECTING 2 -#define FILE_STATUS_INITIALIZED 4 +#define FILE_STATUS_INITIALIZING 4 + #define FILE_STATUS_NEXT_FILE 5 -#define FILE_STATUS_STOP_FILE 6 -#define FILE_STATUS_NEW_SPEED 7 /* once negotiation is complete, file session enters proper state */ -#define FILE_STATUS_READY 8 -#define FILE_STATUS_SENDING 8 -#define FILE_STATUS_RECEIVING 9 +#define FILE_STATUS_SENDING 6 +#define FILE_STATUS_RECEIVING 7 -struct icq_TCPLink_s; - -typedef struct icq_FileSession_s { +struct icq_FileSession_s { unsigned long id; int status; ICQLINK *icqlink; - struct icq_TCPLink_s *tcplink; + icq_TCPLink *tcplink; int direction; @@ -400,7 +572,7 @@ int current_speed; -} icq_FileSession; +}; icq_FileSession *icq_AcceptFileRequest(ICQLINK *link, unsigned long uin, unsigned long sequence); @@ -416,6 +588,16 @@ void icq_FileSessionSetWorkingDir(icq_FileSession *p, const char *dir); void icq_FileSessionSetFiles(icq_FileSession *p, char **files); +/* Socket Manager */ + +#define ICQ_SOCKET_READ 0 +#define ICQ_SOCKET_WRITE 1 +#define ICQ_SOCKET_MAX 2 + +extern void (*icq_SocketNotify)(int socket, int type, int status); + +void icq_HandleReadySocket(int socket, int type); + #ifdef __cplusplus } #endif /* __cplusplus */
--- a/plugins/icq/icqbyteorder.c Sat Jan 27 11:18:17 2001 +0000 +++ b/plugins/icq/icqbyteorder.c Sun Jan 28 01:52:27 2001 +0000 @@ -1,5 +1,5 @@ /* - * $Id: icqbyteorder.c 1319 2000-12-19 10:08:29Z warmenhoven $ + * $Id: icqbyteorder.c 1442 2001-01-28 01:52:27Z warmenhoven $ * * This header defines macros to handle ICQ protocol byte order conversion. *
--- a/plugins/icq/icqbyteorder.h Sat Jan 27 11:18:17 2001 +0000 +++ b/plugins/icq/icqbyteorder.h Sun Jan 28 01:52:27 2001 +0000 @@ -1,5 +1,5 @@ /* - * $Id: icqbyteorder.h 1385 2001-01-04 22:46:19Z warmenhoven $ + * $Id: icqbyteorder.h 1442 2001-01-28 01:52:27Z warmenhoven $ * * This header defines macros to handle ICQ protocol byte order conversion. * @@ -54,6 +54,11 @@ # include <machine/endian.h> #endif +/* hpux way */ +#ifdef hpux +#include <arpa/nameser.h> +#endif + /* * Kind of portable way. this common header, at least I found it on BSD and Solaris. * On Solaris this is only place where endiannes is defined. @@ -62,12 +67,6 @@ # include <arpa/nameser_compat.h> #endif -/* put in by EWarmenhoven; jlsantiago told me what to do. I should send this on to the - * icqlib guys. */ -#ifdef hpux -#include <arpa/nameser.h> -#endif - /* * I am really trying to use builtin optimized byte swap routines. * they are highly optimised on some platforms.
--- a/plugins/icq/icqevent.c Sat Jan 27 11:18:17 2001 +0000 +++ b/plugins/icq/icqevent.c Sun Jan 28 01:52:27 2001 +0000 @@ -1,11 +1,11 @@ /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* - * $Id: icqevent.c 1319 2000-12-19 10:08:29Z warmenhoven $ + * $Id: icqevent.c 1442 2001-01-28 01:52:27Z warmenhoven $ * * $Log$ - * Revision 1.1 2000/12/19 10:08:29 warmenhoven - * Yay, new icqlib + * Revision 1.2 2001/01/28 01:52:27 warmenhoven + * icqlib 1.1.5 * * Revision 1.2 2000/06/15 18:54:09 bills * added time attribute and handleEvent function pointer to icq_Event,
--- a/plugins/icq/icqevent.h Sat Jan 27 11:18:17 2001 +0000 +++ b/plugins/icq/icqevent.h Sun Jan 28 01:52:27 2001 +0000 @@ -1,11 +1,11 @@ /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* - * $Id: icqevent.h 1319 2000-12-19 10:08:29Z warmenhoven $ + * $Id: icqevent.h 1442 2001-01-28 01:52:27Z warmenhoven $ * * $Log$ - * Revision 1.1 2000/12/19 10:08:29 warmenhoven - * Yay, new icqlib + * Revision 1.2 2001/01/28 01:52:27 warmenhoven + * icqlib 1.1.5 * * Revision 1.2 2000/06/15 18:54:09 bills * added time attribute and handleEvent function pointer to icq_Event,
--- a/plugins/icq/icqlib.c Sat Jan 27 11:18:17 2001 +0000 +++ b/plugins/icq/icqlib.c Sun Jan 28 01:52:27 2001 +0000 @@ -1,9 +1,18 @@ /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* -$Id: icqlib.c 1319 2000-12-19 10:08:29Z warmenhoven $ +$Id: icqlib.c 1442 2001-01-28 01:52:27Z warmenhoven $ $Log$ -Revision 1.2 2000/12/19 10:08:29 warmenhoven -Yay, new icqlib +Revision 1.3 2001/01/28 01:52:27 warmenhoven +icqlib 1.1.5 + +Revision 1.49 2001/01/17 01:29:17 bills +Rework chat and file session interfaces; implement socket notifications. + +Revision 1.48 2001/01/15 06:20:24 denis +Cleanup. + +Revision 1.47 2000/12/19 21:29:51 bills +actually return the link in icq_ICQLINKNew Revision 1.46 2000/12/19 06:00:07 bills moved members from ICQLINK to ICQLINK_private struct @@ -17,121 +26,7 @@ Revision 1.43 2000/07/09 22:05:11 bills removed unnecessary functions - -Revision 1.42 2000/07/09 18:28:07 denis -Initial memset() in icq_Init() replaced by callback's clearance. - -Revision 1.41 2000/06/15 01:50:39 bills -removed *Seq functions - -Revision 1.40 2000/05/10 19:06:59 denis -UDP outgoing packet queue was implemented. - -Revision 1.39 2000/05/03 18:12:36 denis -Unfinished UDP queue was commented out. - -Revision 1.38 2000/04/10 16:36:04 denis -Some more Win32 compatibility from Guillaume Rosanis <grs@mail.com> - -Revision 1.37 2000/04/06 16:38:04 denis -icq_*Send*Seq() functions with specified sequence number were added. - -Revision 1.36 2000/04/05 14:37:02 denis -Applied patch from "Guillaume R." <grs@mail.com> for basic Win32 -compatibility. - -Revision 1.35 2000/01/16 03:59:10 bills -reworked list code so list_nodes don't need to be inside item structures, -removed strlist code and replaced with generic list calls - -Revision 1.34 1999/12/27 16:06:32 bills -cleanups - -Revision 1.33 1999/10/03 21:35:55 tim -Fixed "url" and "descr" parameters order when sending a URL via TCP. - -Revision 1.32 1999/09/29 16:49:43 denis -Host/network/icq byteorder systemized. -icq_Init() cleaned up. - -Revision 1.31 1999/07/18 20:15:55 bills -changed to use new byte-order functions & contact list functions - -Revision 1.30 1999/07/16 12:27:06 denis -Other global variables moved to ICQLINK structure. -Initialization of random number generator added in icq_Init() -Cleaned up. - -Revision 1.29 1999/07/12 15:13:31 cproch -- added definition of ICQLINK to hold session-specific global variabled - applications which have more than one connection are now possible -- changed nearly every function defintion to support ICQLINK parameter - -Revision 1.28 1999/07/03 02:26:02 bills -added new code to support thruSrv arg to SendMessage and SendURL - -Revision 1.27 1999/04/17 19:21:37 bills -modified Send* Functions to return DWORD instead of WORD - -Revision 1.26 1999/04/14 14:48:18 denis -Switched from icq_Log callback to icq_Fmt function. -Cleanups for "strict" compiling (-ansi -pedantic) - -Revision 1.25 1999/04/05 13:14:57 denis -Send messages and URLs to 'not in list' users fixed. - -Revision 1.24 1999/03/31 01:43:40 bills -added TCP support to SendURL - -Revision 1.23 1999/03/30 22:47:44 lord -list of countries now sorted. - -Revision 1.22 1999/03/28 03:18:22 bills -enable tcp messaging in icq_SendMessage, uncommented icq_OurPort and -icq_OurIp and fixed function names so icqlib compiles - -Revision 1.21 1999/03/25 22:16:43 bills -added #include "util.h" - -Revision 1.20 1999/03/24 11:37:36 denis -Underscored files with TCP stuff renamed. -TCP stuff cleaned up -Function names changed to corresponding names. -icqlib.c splitted to many small files by subject. -C++ comments changed to ANSI C comments. - -Revision 1.19 1999/03/22 20:51:28 bills -added code in icq_HandleUserOnline to set/clear new struct entries in -icq_ContactItem; added cleanup code in icq_HandleUserOffline for same - -Revision 1.18 1999/03/09 13:14:05 denis -Cyrillic recoding removed from URLs - -Revision 1.17 1999/03/05 13:57:54 denis -Some cosmetic changes... - -Revision 1.16 1998/12/08 16:00:59 denis -Cleaned up a little before releasing - -Revision 1.15 1998/11/25 19:18:16 denis -Added close icq_ProxySok in icq_Disconnect - -Revision 1.14 1998/11/25 09:48:49 denis -icq_GetProxySok and icq_HandleProxyResponse methods added -Connection terminated support added - -Revision 1.13 1998/11/19 12:22:48 denis -SOCKS support cleaned a little -icq_RecvUrl renamed to icq_RecvURL -icq_ProxyAuth added for Username/Password Authentication -URL/Description order inverted -icq_Quit splitted to icq_Logout and icq_Disconnect -icq_ProxyName and icq_ProxyPass range checking added - -Revision 1.12 1998/11/18 16:21:29 denis -Fixed SOCKS5 proxy support - - */ +*/ #include "icqlib.h" @@ -163,10 +58,13 @@ #include "udp.h" #include "tcp.h" #include "queue.h" +#include "socketmanager.h" int icq_Russian = FALSE; BYTE icq_LogLevel = 0; +void (*icq_SocketNotify)(int socket, int type, int status); + DWORD icq_SendMessage(ICQLINK *link, DWORD uin, const char *text, BYTE thruSrv) { if(thruSrv==ICQ_SEND_THRUSERVER) @@ -216,14 +114,15 @@ } ICQLINK *icq_ICQLINKNew(DWORD uin, const char *password, const char *nick, - unsigned char useTCP) + unsigned char useTCP) { - ICQLINK *link = (ICQLINK *)malloc(sizeof(ICQLINK)); - link->d = (ICQLINK_private *)malloc(sizeof(ICQLINK_private)); + ICQLINK *link = (ICQLINK*)malloc(sizeof(ICQLINK)); + link->d = (ICQLINK_private*)malloc(sizeof(ICQLINK_private)); srand(time(0L)); - -/* memset(link, 0, sizeof(ICQLINK)); */ + /* initialize icq_SocketList on first call */ + if (!icq_SocketList) + icq_SocketList = list_new(); /* Initialize all callbacks */ link->icq_Logged = 0L; @@ -276,6 +175,7 @@ link->d->icq_UDPSession = 0; icq_UDPQueueNew(link); + /* TCP stuff */ icq_TCPInit(link); link->icq_UseTCP = useTCP; @@ -316,17 +216,7 @@ *******************************/ void icq_Main(ICQLINK *link) { - struct timeval tv; - fd_set readfds; - - tv.tv_sec = 0; - tv.tv_usec = 0; - FD_ZERO(&readfds); - FD_SET(link->icq_UDPSok, &readfds); - select(link->icq_UDPSok+1, &readfds, 0L, 0L, &tv); - if(FD_ISSET(link->icq_UDPSok, &readfds)) - icq_HandleServerResponse(link); - icq_TCPMain(link); + icq_SocketPoll(); } /********************************** @@ -343,7 +233,9 @@ struct sockaddr_in sin, prsin; /* used to store inet addr stuff */ struct hostent *host_struct; /* used in DNS llokup */ - link->icq_UDPSok = socket(AF_INET, SOCK_DGRAM, 0);/* create the unconnected socket*/ + /* create the unconnected socket*/ + link->icq_UDPSok = icq_SocketNew(AF_INET, SOCK_DGRAM, 0); + if(link->icq_UDPSok == -1) { icq_FmtLog(link, ICQ_LOG_FATAL, "Socket creation failed\n"); @@ -356,6 +248,8 @@ if(bind(link->icq_UDPSok, (struct sockaddr*)&sin, sizeof(struct sockaddr))<0) { icq_FmtLog(link, ICQ_LOG_FATAL, "Can't bind socket to free port\n"); + icq_SocketDelete(link->icq_UDPSok); + link->icq_UDPSok = -1; return -1; } length = sizeof(sin); @@ -378,7 +272,10 @@ link->icq_ProxyIP = ntohl(prsin.sin_addr.s_addr); prsin.sin_family = AF_INET; /* we're using the inet not appletalk*/ prsin.sin_port = htons(link->icq_ProxyPort); /* port */ - link->icq_ProxySok = socket(AF_INET, SOCK_STREAM, 0);/* create the unconnected socket*/ + + /* create the unconnected socket*/ + link->icq_ProxySok = icq_SocketNew(AF_INET, SOCK_STREAM, 0); + if(link->icq_ProxySok == -1) { icq_FmtLog(link, ICQ_LOG_FATAL, "[SOCKS] Socket creation failed\n"); @@ -409,11 +306,7 @@ if(res != 2 || buf[0] != 5 || buf[1] != 2) /* username/password authentication*/ { icq_FmtLog(link, ICQ_LOG_FATAL, "[SOCKS] Authentication method incorrect\n"); -#ifdef _WIN32 - closesocket(link->icq_ProxySok); -#else - close(link->icq_ProxySok); -#endif + icq_SocketDelete(link->icq_ProxySok); return -1; } buf[0] = 1; /* version of subnegotiation */ @@ -431,11 +324,7 @@ if(res != 2 || buf[0] != 1 || buf[1] != 0) { icq_FmtLog(link, ICQ_LOG_FATAL, "[SOCKS] Authorization failure\n"); -#ifdef _WIN32 - closesocket(link->icq_ProxySok); -#else - close(link->icq_ProxySok); -#endif + icq_SocketDelete(link->icq_ProxySok); return -1; } } @@ -444,11 +333,7 @@ if(res != 2 || buf[0] != 5 || buf[1] != 0) /* no authentication required */ { icq_FmtLog(link, ICQ_LOG_FATAL, "[SOCKS] Authentication method incorrect\n"); -#ifdef _WIN32 - closesocket(link->icq_ProxySok); -#else - close(link->icq_ProxySok); -#endif + icq_SocketDelete(link->icq_ProxySok); return -1; } } @@ -501,11 +386,8 @@ icq_FmtLog(link, ICQ_LOG_FATAL, "[SOCKS] Unknown SOCKS server failure\n"); break; } -#ifdef _WIN32 - closesocket(link->icq_ProxySok); -#else - close(link->icq_ProxySok); -#endif + icq_SocketDelete(link->icq_ProxySok); + link->icq_ProxySok = -1; return -1; } } @@ -518,11 +400,7 @@ icq_FmtLog(link, ICQ_LOG_FATAL, "Can't find hostname: %s\n", hostname); if(link->icq_UseProxy) { -#ifdef _WIN32 - closesocket(link->icq_ProxySok); -#else - close(link->icq_ProxySok); -#endif + icq_SocketDelete(link->icq_ProxySok); } return -1; } @@ -546,11 +424,7 @@ icq_FmtLog(link, ICQ_LOG_FATAL, "Connection refused\n"); if(link->icq_UseProxy) { -#ifdef _WIN32 - closesocket(link->icq_ProxySok); -#else - close(link->icq_ProxySok); -#endif + icq_SocketDelete(link->icq_ProxySok); } return -1; } @@ -558,23 +432,22 @@ getsockname(link->icq_UDPSok, (struct sockaddr*)&sin, &length); link->icq_OurIP = ntohl(sin.sin_addr.s_addr); link->icq_OurPort = ntohs(sin.sin_port); + + /* sockets are ready to receive data - install handlers */ + icq_SocketSetHandler(link->icq_UDPSok, ICQ_SOCKET_READ, + icq_HandleServerResponse, link); + if (link->icq_UseProxy) + icq_SocketSetHandler(link->icq_ProxySok, ICQ_SOCKET_READ, + icq_HandleProxyResponse, link); return link->icq_UDPSok; } void icq_Disconnect(ICQLINK *link) { -#ifdef _WIN32 - closesocket(link->icq_UDPSok); -#else - close(link->icq_UDPSok); -#endif + icq_SocketDelete(link->icq_UDPSok); if(link->icq_UseProxy) { -#ifdef _WIN32 - closesocket(link->icq_ProxySok); -#else - close(link->icq_ProxySok); -#endif + icq_SocketDelete(link->icq_ProxySok); } icq_UDPQueueFree(link); }
--- a/plugins/icq/icqlib.h Sat Jan 27 11:18:17 2001 +0000 +++ b/plugins/icq/icqlib.h Sun Jan 28 01:52:27 2001 +0000 @@ -62,10 +62,10 @@ void *icq_TCPLinks; void *icq_ChatSessions; void *icq_FileSessions; - int TCP_maxfd; - fd_set TCP_readfds; - fd_set TCP_writefds; } ICQLINK_private; +#define invoke_callback(plink, callback) \ + if (plink->callback) (*(plink->callback)) + #endif /* _ICQLIB_H_ */
--- a/plugins/icq/icqpacket.c Sat Jan 27 11:18:17 2001 +0000 +++ b/plugins/icq/icqpacket.c Sun Jan 28 01:52:27 2001 +0000 @@ -1,9 +1,9 @@ /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* -$Id: icqpacket.c 1319 2000-12-19 10:08:29Z warmenhoven $ +$Id: icqpacket.c 1442 2001-01-28 01:52:27Z warmenhoven $ $Log$ -Revision 1.2 2000/12/19 10:08:29 warmenhoven -Yay, new icqlib +Revision 1.3 2001/01/28 01:52:27 warmenhoven +icqlib 1.1.5 Revision 1.10 2000/07/07 15:26:35 denis "icq_Packet data overflow" log message temporarily commented out.
--- a/plugins/icq/list.c Sat Jan 27 11:18:17 2001 +0000 +++ b/plugins/icq/list.c Sun Jan 28 01:52:27 2001 +0000 @@ -1,9 +1,9 @@ /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* -$Id: list.c 1319 2000-12-19 10:08:29Z warmenhoven $ +$Id: list.c 1442 2001-01-28 01:52:27Z warmenhoven $ $Log$ -Revision 1.2 2000/12/19 10:08:29 warmenhoven -Yay, new icqlib +Revision 1.3 2001/01/28 01:52:27 warmenhoven +icqlib 1.1.5 Revision 1.14 2000/07/10 01:44:20 bills i really don't learn - removed LIST_TRACE define
--- a/plugins/icq/list.h Sat Jan 27 11:18:17 2001 +0000 +++ b/plugins/icq/list.h Sun Jan 28 01:52:27 2001 +0000 @@ -14,19 +14,22 @@ #define list_dequeue(plist) \ list_remove_node(plist, plist->head) -typedef struct list_node_s +typedef struct list_node_s list_node; +typedef struct list_s list; + +struct list_node_s { - struct list_node_s *next; - struct list_node_s *previous; + list_node *next; + list_node *previous; void *item; -} list_node; +}; -typedef struct list_s +struct list_s { list_node *head; list_node *tail; int count; -} list; +}; list *list_new(void); void list_delete(list *plist, void (*item_free_f)(void *));
--- a/plugins/icq/proxy.c Sat Jan 27 11:18:17 2001 +0000 +++ b/plugins/icq/proxy.c Sun Jan 28 01:52:27 2001 +0000 @@ -1,9 +1,12 @@ /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* -$Id: proxy.c 1319 2000-12-19 10:08:29Z warmenhoven $ +$Id: proxy.c 1442 2001-01-28 01:52:27Z warmenhoven $ $Log$ -Revision 1.2 2000/12/19 10:08:29 warmenhoven -Yay, new icqlib +Revision 1.3 2001/01/28 01:52:27 warmenhoven +icqlib 1.1.5 + +Revision 1.9 2001/01/17 01:19:49 bills +cleanup Revision 1.8 2000/05/10 18:51:23 denis icq_Disconnect() now called before icq_Disconnected callback to @@ -42,9 +45,7 @@ #ifndef _WIN32 #include <unistd.h> -#endif - -#ifdef _WIN32 +#else #include <winsock.h> #endif
--- a/plugins/icq/queue.c Sat Jan 27 11:18:17 2001 +0000 +++ b/plugins/icq/queue.c Sun Jan 28 01:52:27 2001 +0000 @@ -1,9 +1,9 @@ /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* -$Id: queue.c 1319 2000-12-19 10:08:29Z warmenhoven $ +$Id: queue.c 1442 2001-01-28 01:52:27Z warmenhoven $ $Log$ -Revision 1.3 2000/12/19 10:08:29 warmenhoven -Yay, new icqlib +Revision 1.4 2001/01/28 01:52:27 warmenhoven +icqlib 1.1.5 Revision 1.12 2000/12/19 06:00:07 bills moved members from ICQLINK to ICQLINK_private struct
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/icq/socketmanager.c Sun Jan 28 01:52:27 2001 +0000 @@ -0,0 +1,234 @@ +/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ + +/* + $Id: socketmanager.c 1442 2001-01-28 01:52:27Z warmenhoven $ +*/ + +#include "socketmanager.h" + +/** + * The icqlib socket manager is a simple socket abstraction layer, which + * supports opening and closing sockets as well as installing handler + * functions for read ready and write ready events. Its purpose is to + * both unify socket handling in icqlib and expose icqlib's socket + * requirements so the library client can assist with socket housekeeping. + * + * Library clients have two options to support icqlib: + * + * 1. Periodically call icq_Main. This will handle all select logic + * internally. Advantage is implementation ease, disadvantage is wasted + * CPU cycles because of polling and poor TCP file transfer performance. + * + * 2. Install a icq_SocketNotify callback, perform your own socket + * management, and notify icqlib using the icq_SocketReady method when + * a socket is ready for reading or writing. Advantage is efficiency, + * disadvantage is extra code. + * + */ + +/* need to track: + * socket wants read notification + * socket no longer wants read notification + * socket wants write notification + * socket no longer wants write notification + */ + +#include <sys/types.h> + +#ifndef _WIN32 +#include <unistd.h> +#include <sys/time.h> +#include <sys/socket.h> +#else +#include <winsock.h> +#endif + +list *icq_SocketList = NULL; +fd_set icq_FdSets[ICQ_SOCKET_MAX]; +int icq_MaxSocket; + +/** + * Creates a new socket using the operating system's socket creation + * facitily. + */ +int icq_SocketNew(int domain, int type, int protocol) +{ + int s = socket(domain, type, protocol); + + icq_SocketAlloc(s); + + return s; +} + + +/** + * Creates a new socket by accepting a connection from a listening + * socket. + */ +int icq_SocketAccept(int listens, struct sockaddr *addr, socklen_t *addrlen) +{ + int s = accept(listens, addr, addrlen); + + icq_SocketAlloc(s); + + return s; +} + +/** + * Creates a new icq_Socket structure, and appends it to the + * socketmanager's global socket list. + */ +void icq_SocketAlloc(int s) +{ + if (s != -1) + { + icq_Socket *psocket = (icq_Socket *)malloc(sizeof(icq_Socket)); + int i; + psocket->socket = s; + + for (i=0; i<ICQ_SOCKET_MAX; i++) + psocket->handlers[i] = NULL; + + list_enqueue(icq_SocketList, psocket); + } +} + +/** + * Closes a socket. This function will notify the library client + * through the icq_SocketNotify callback if the socket had an installed + * read or write handler. + */ +int icq_SocketDelete(int socket) +{ +#ifdef _WIN32 + int result = closesocket(socket); +#else + int result = close(socket); +#endif + + if (result != -1) + { + icq_Socket *s = icq_FindSocket(socket); + int i; + + /* uninstall all handlers - this will take care of notifing library + * client */ + for (i=0; i<ICQ_SOCKET_MAX; i++) + { + if (s->handlers[i]) + icq_SocketSetHandler(s->socket, i, NULL, NULL); + } + + list_remove(icq_SocketList, s); + free(s); + } + + return result; +} + +/** + * Installs a socket event handler. The handler will be called when + * the socket is ready for reading or writing, depending on the type + * which should be either ICQ_SOCKET_READ or ICQ_SOCKET_WRITE. In + * addition, user data can be passed to the callback function through + * the data member. + */ +void icq_SocketSetHandler(int socket, int type, icq_SocketHandler handler, + void *data) +{ + icq_Socket *s = icq_FindSocket(socket); + if (s) + { + s->data[type] = data; + s->handlers[type] = handler; + if (icq_SocketNotify) + (*icq_SocketNotify)(socket, type, handler ? 1 : 0); + icq_SocketBuildFdSets(); + } +} + +/** + * Handles a socket ready event by calling the installed callback + * function, if any. + */ +void icq_SocketReady(icq_Socket *s, int type) +{ + if (s && s->handlers[type]) + { + (*s->handlers[type])(s->data[type]); + } +} + +void icq_HandleReadySocket(int socket, int type) +{ + icq_SocketReady(icq_FindSocket(socket), type); +} + +int _icq_SocketBuildFdSets(void *p, va_list data) +{ + icq_Socket *s = p; + int i; + + for (i=0; i<ICQ_SOCKET_MAX; i++) + if (s->handlers[i]) + FD_SET(s->socket, &icq_FdSets[i]); + + if (s->socket > icq_MaxSocket) + icq_MaxSocket = s->socket; + + return 0; /* traverse entire list */ +} + +void icq_SocketBuildFdSets() +{ + int i; + + /* clear fdsets */ + for (i=0; i<ICQ_SOCKET_MAX; i++) + FD_ZERO(&icq_FdSets[i]); + + icq_MaxSocket = 0; + + /* build fd lists for open sockets */ + (void)list_traverse(icq_SocketList, _icq_SocketBuildFdSets); +} + +int _icq_SocketHandleReady(void *p, va_list data) +{ + icq_Socket *s = p; + int i; + + for (i=0; i<ICQ_SOCKET_MAX; i++) + if (FD_ISSET(s->socket, &icq_FdSets[i])) + icq_SocketReady(s, i); + + return 0; /* traverse entire list */ +} + +void icq_SocketPoll() +{ + struct timeval tv; + int max_socket = 0; + int i; + + tv.tv_sec = 0; tv.tv_usec = 0; + + /* determine which sockets require maintenance */ + select(icq_MaxSocket+1, &icq_FdSets[0], &icq_FdSets[1], NULL, &tv); + + /* handle ready sockets */ + (void)list_traverse(icq_SocketList, _icq_SocketHandleReady); +} + +int _icq_FindSocket(void *p, va_list data) +{ + int socket = va_arg(data, int); + return (((icq_Socket *)p)->socket == socket); +} + +icq_Socket *icq_FindSocket(int socket) +{ + return list_traverse(icq_SocketList, _icq_FindSocket, socket); +} + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugins/icq/socketmanager.h Sun Jan 28 01:52:27 2001 +0000 @@ -0,0 +1,39 @@ +/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +#ifndef _SOCKETMANAGER_H +#define _SOCKETMANAGER_H + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <sys/types.h> +#include <sys/socket.h> + +#include "icq.h" +#include "list.h" + +typedef struct icq_Socket_s icq_Socket; +typedef void (*icq_SocketHandler)(void *data); + +struct icq_Socket_s +{ + int socket; + + icq_SocketHandler handlers[ICQ_SOCKET_MAX]; + void *data[ICQ_SOCKET_MAX]; +}; + +int icq_SocketNew(int domain, int type, int protocol); +int icq_SocketAccept(int listens, struct sockaddr *addr, socklen_t *addrlen); +void icq_SocketAlloc(int s); +int icq_SocketDelete(int socket); +void icq_SocketSetHandler(int socket, int type, icq_SocketHandler handler, + void *data); +void icq_SocketReady(icq_Socket *s, int type); +void icq_SocketBuildFdSets(void); +void icq_SocketPoll(); +icq_Socket *icq_FindSocket(int socket); + +extern list *icq_SocketList; + +#endif /* _SOCKETMANAGER_H */
--- a/plugins/icq/stdpackets.c Sat Jan 27 11:18:17 2001 +0000 +++ b/plugins/icq/stdpackets.c Sun Jan 28 01:52:27 2001 +0000 @@ -1,9 +1,13 @@ /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* -$Id: stdpackets.c 1319 2000-12-19 10:08:29Z warmenhoven $ +$Id: stdpackets.c 1442 2001-01-28 01:52:27Z warmenhoven $ $Log$ -Revision 1.2 2000/12/19 10:08:29 warmenhoven -Yay, new icqlib +Revision 1.3 2001/01/28 01:52:27 warmenhoven +icqlib 1.1.5 + +Revision 1.12 2001/01/24 05:11:14 bills +applied patch from Robin Ericsson <lobbin@localhost.nu> which implements +receiving contact lists. See new icq_RecvContactList callback. Revision 1.11 2000/12/19 06:00:07 bills moved members from ICQLINK to ICQLINK_private struct @@ -422,6 +426,18 @@ return p; } +icq_Packet *icq_TCPCreateContactListAck(icq_TCPLink *plink, const unsigned char *message) +{ + icq_Packet *p=icq_TCPCreateStdPacket( + plink, + ICQ_TCP_ACK, + ICQ_TCP_MSG_CONTACTLIST, + message, + 0, /* status */ + ICQ_TCP_MSG_ACK); + + return p; +} icq_Packet *icq_TCPCreateFile00Packet(DWORD num_files, DWORD total_bytes, DWORD speed, const char *name)
--- a/plugins/icq/stdpackets.h Sat Jan 27 11:18:17 2001 +0000 +++ b/plugins/icq/stdpackets.h Sun Jan 28 01:52:27 2001 +0000 @@ -20,6 +20,7 @@ #define ICQ_TCP_MSG_CHAT 0x0002 #define ICQ_TCP_MSG_FILE 0x0003 #define ICQ_TCP_MSG_URL 0x0004 +#define ICQ_TCP_MSG_CONTACTLIST 0x0013 #define ICQ_TCP_MSG_READAWAY 0x03E8 #define ICQ_TCP_MSG_READOCCUPIED 0x03E9 #define ICQ_TCP_MSG_READNA 0x03EA @@ -70,6 +71,7 @@ icq_Packet *icq_TCPCreateMessageAck(icq_TCPLink *plink, const unsigned char *message); icq_Packet *icq_TCPCreateURLAck(icq_TCPLink *plink, const unsigned char *message); +icq_Packet *icq_TCPCreateContactListAck(icq_TCPLink *plink, const unsigned char *message); icq_Packet *icq_TCPCreateWebPagerAck(icq_TCPLink *plink, const unsigned char *message); icq_Packet *icq_TCPCreateChatReqAck(icq_TCPLink *plink, WORD port); icq_Packet *icq_TCPCreateChatReqCancel(icq_TCPLink *plink, WORD port);
--- a/plugins/icq/tcp.c Sat Jan 27 11:18:17 2001 +0000 +++ b/plugins/icq/tcp.c Sun Jan 28 01:52:27 2001 +0000 @@ -1,9 +1,12 @@ /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* -$Id: tcp.c 1319 2000-12-19 10:08:29Z warmenhoven $ +$Id: tcp.c 1442 2001-01-28 01:52:27Z warmenhoven $ $Log$ -Revision 1.2 2000/12/19 10:08:29 warmenhoven -Yay, new icqlib +Revision 1.3 2001/01/28 01:52:27 warmenhoven +icqlib 1.1.5 + +Revision 1.38 2001/01/17 01:29:17 bills +Rework chat and file session interfaces; implement socket notifications. Revision 1.37 2000/12/19 06:00:07 bills moved members from ICQLINK to ICQLINK_private struct @@ -126,10 +129,6 @@ #include <stdlib.h> -#ifndef _WIN32 -#include <unistd.h> -#endif - #include <fcntl.h> #include <stdarg.h> #include <errno.h> @@ -140,14 +139,12 @@ #include <winsock.h> #else #include <sys/socket.h> +#include <sys/time.h> +#include <unistd.h> #endif #include <sys/stat.h> -#ifndef _WIN32 -#include <sys/time.h> -#endif - #include "icqtypes.h" #include "icqlib.h" @@ -195,53 +192,7 @@ list_delete(link->d->icq_FileSessions, icq_FileSessionDelete); } -/* helper function for icq_TCPMain */ -int _generate_fds(void *p, va_list data) -{ - icq_TCPLink *plink=(icq_TCPLink *)p; - ICQLINK *icqlink = plink->icqlink; - - (void)data; - - if(plink->socket>-1) - { - int socket=plink->socket; - - FD_SET(socket, &icqlink->d->TCP_readfds); - - /* we only care about writing if socket is trying to connect */ - if(plink->mode & TCP_LINK_MODE_CONNECTING) - { - if(plink->mode & (TCP_LINK_SOCKS_AUTHORIZATION | TCP_LINK_SOCKS_NOAUTHSTATUS | TCP_LINK_SOCKS_AUTHSTATUS | TCP_LINK_SOCKS_CONNSTATUS)) - FD_SET(socket, &icqlink->d->TCP_readfds); - else - FD_SET(socket, &icqlink->d->TCP_writefds); - } - - if(socket+1>icqlink->d->TCP_maxfd) - icqlink->d->TCP_maxfd=socket+1; - } - - return 0; /* traverse the entire list */ -} - -/* helper function for icq_TCPMain */ -int _handle_ready_sockets(void *p, va_list data) -{ - icq_TCPLink *plink=(icq_TCPLink *)p; - ICQLINK *icqlink = plink->icqlink; - int socket=plink->socket; - - (void)data; - - /* handle connecting sockets */ - if (plink->mode & TCP_LINK_MODE_CONNECTING) - { - if(socket>-1 && (FD_ISSET(socket, &icqlink->d->TCP_writefds) || FD_ISSET(socket, &icqlink->d->TCP_readfds))) - { - icq_TCPLinkOnConnect(plink); - return 0; - } +/* need to do this somehow... if((time(0L) - plink->connect_time) > TCP_LINK_CONNECT_TIMEOUT) { @@ -249,73 +200,7 @@ return 0; } } - - /* handle ready for read sockets- either a connection is waiting on * - * the listen sockets or data is ready to be read */ - if(socket>-1 && FD_ISSET(socket, &icqlink->d->TCP_readfds)) - { - if(plink->mode & TCP_LINK_MODE_LISTEN) - (void)icq_TCPLinkAccept(plink); - else { - - int result=icq_TCPLinkOnDataReceived(plink); - - /* close the link if there was a receive error or if * - * the remote end has closed the connection */ - if (result < 1) - icq_TCPLinkClose(plink); - - } - } - - return 0; /* traverse the entire list */ -} - -/* helper function for icq_TCPMain */ -int _process_links(void *p, va_list data) -{ - icq_TCPLink *plink=(icq_TCPLink *)p; - - (void)data; - - /* receive any packets watiting on the link */ - icq_TCPLinkProcessReceived(plink); - - /* if this a currently sending file link, send data! */ - if(plink->type==TCP_LINK_FILE) { - icq_FileSession *psession=plink->session; - if(psession && psession->status==FILE_STATUS_SENDING) - icq_FileSessionSendData(psession); - } - - return 0; /* traverse entire list */ -} - -void icq_TCPMain(ICQLINK *link) -{ - struct timeval tv; - - tv.tv_sec = 0; - tv.tv_usec = 0; - - link->d->TCP_maxfd = 0; - FD_ZERO(&link->d->TCP_readfds); - FD_ZERO(&link->d->TCP_writefds); - - /* generate the fd sets for all open tcp links */ - (void)list_traverse(link->d->icq_TCPLinks, _generate_fds); - - /* determine which sockets require maintenance */ - select(link->d->TCP_maxfd, &link->d->TCP_readfds, &link->d->TCP_writefds, 0, &tv); - - /* call icq_TCPLinkOnDataReceived for any sockets with ready data, - * send all packets on send queue if socket has connected, and - * accept() from any listening sockets with pending connections */ - (void)list_traverse(link->d->icq_TCPLinks, _handle_ready_sockets, 0, 0); - - /* process all packets waiting for each TCPLink */ - (void)list_traverse(link->d->icq_TCPLinks, _process_links, 0, 0); -} +*/ icq_TCPLink *icq_TCPCheckLink(ICQLINK *link, DWORD uin, int type) { @@ -519,15 +404,6 @@ } -void icq_TCPCloseChat(ICQLINK *link, unsigned long uin) -{ - icq_TCPLink *plink=icq_FindTCPLink(link, uin, TCP_LINK_CHAT); - - if(plink) - icq_TCPLinkClose(plink); - -} - icq_FileSession *icq_AcceptFileRequest(ICQLINK *link, DWORD uin, unsigned long sequence) {
--- a/plugins/icq/tcpchathandle.c Sat Jan 27 11:18:17 2001 +0000 +++ b/plugins/icq/tcpchathandle.c Sun Jan 28 01:52:27 2001 +0000 @@ -1,9 +1,12 @@ /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* -$Id: tcpchathandle.c 1319 2000-12-19 10:08:29Z warmenhoven $ +$Id: tcpchathandle.c 1442 2001-01-28 01:52:27Z warmenhoven $ $Log$ -Revision 1.2 2000/12/19 10:08:29 warmenhoven -Yay, new icqlib +Revision 1.3 2001/01/28 01:52:27 warmenhoven +icqlib 1.1.5 + +Revision 1.9 2001/01/17 01:29:17 bills +Rework chat and file session interfaces; implement socket notifications. Revision 1.8 2000/07/24 03:10:08 bills added support for real nickname during TCP transactions like file and @@ -57,15 +60,25 @@ icq_ChatSession *pchat; icq_Packet *p2; - if(plink->icqlink->icq_RequestNotify) - (*plink->icqlink->icq_RequestNotify)(plink->icqlink, p->id, ICQ_NOTIFY_ACK, 0, 0); + invoke_callback(plink->icqlink, icq_RequestNotify)(plink->icqlink, + p->id, ICQ_NOTIFY_ACK, 0, NULL); + pchatlink=icq_TCPLinkNew(plink->icqlink); pchatlink->type=TCP_LINK_CHAT; pchatlink->id=p->id; - + + /* once the ack packet has been processed, create a new chat session */ pchat=icq_ChatSessionNew(plink->icqlink); + pchat->id=p->id; pchat->remote_uin=plink->remote_uin; + pchat->tcplink=pchatlink; + + invoke_callback(plink->icqlink, icq_RequestNotify)(plink->icqlink, p->id, + ICQ_NOTIFY_CHATSESSION, sizeof(icq_ChatSession), pchat); + invoke_callback(plink->icqlink, icq_RequestNotify)(plink->icqlink, p->id, + ICQ_NOTIFY_SUCCESS, 0, NULL); + icq_ChatSessionSetStatus(pchat, CHAT_STATUS_CONNECTING); icq_TCPLinkConnect(pchatlink, plink->remote_uin, port); @@ -123,13 +136,15 @@ } } -void icq_TCPChatUpdateFont(icq_TCPLink *plink, const char *font, WORD encoding, DWORD style, DWORD size) +void icq_TCPChatUpdateFont(icq_ChatSession *psession, const char *font, + WORD encoding, DWORD style, DWORD size) { + ICQLINK *icqlink = psession->icqlink; int packet_len, fontlen; char *buffer; - if(!plink->icqlink->icq_RequestNotify) - return; - buffer = malloc(packet_len = (2 + (fontlen = strlen(font) + 1)) + 2 + 1 + (4+1)*2); + + buffer = malloc(packet_len = (2 + (fontlen = strlen(font) + 1)) + + 2 + 1 + (4+1)*2); buffer[0] = '\x11'; *((DWORD *)&buffer[1]) = style; buffer[5] = '\x12'; @@ -137,26 +152,30 @@ buffer[10] = '\x10'; *((WORD *)&buffer[11]) = fontlen; strcpy(&buffer[13], font); + icq_RusConv("wk", &buffer[13]); + *((WORD *)&buffer[13 + fontlen]) = encoding; - if(plink->icqlink->icq_RequestNotify) - (*plink->icqlink->icq_RequestNotify)(plink->icqlink, plink->id, ICQ_NOTIFY_CHATDATA, packet_len, buffer); + + invoke_callback(icqlink, icq_ChatNotify)(psession, CHAT_NOTIFY_DATA, + packet_len, buffer); + free(buffer); } -void icq_TCPChatUpdateColors(icq_TCPLink *plink, DWORD foreground, DWORD background) +void icq_TCPChatUpdateColors(icq_ChatSession *psession, DWORD foreground, + DWORD background) { + ICQLINK *icqlink = psession->icqlink; char buffer[10]; - if(!plink->icqlink->icq_RequestNotify) - return; buffer[0] = '\x00'; *((DWORD *)&buffer[1]) = foreground; buffer[5] = '\x01'; *((DWORD *)&buffer[6]) = background; - if(plink->icqlink->icq_RequestNotify) - (*plink->icqlink->icq_RequestNotify)(plink->icqlink, plink->id, ICQ_NOTIFY_CHATDATA, - sizeof(buffer), buffer); + + invoke_callback(icqlink, icq_ChatNotify)(psession, + CHAT_NOTIFY_DATA, sizeof(buffer), buffer); } void icq_TCPProcessChatPacket(icq_Packet *p, icq_TCPLink *plink) @@ -204,7 +223,7 @@ encoding = icq_PacketRead16(p); } if(font) - icq_TCPChatUpdateFont(plink, font, encoding, fontstyle, fontsize); + icq_TCPChatUpdateFont(pchat, font, encoding, fontstyle, fontsize); icq_ChatSessionSetStatus(pchat, CHAT_STATUS_READY); plink->mode|=TCP_LINK_MODE_RAW; } @@ -216,7 +235,7 @@ icq_PacketRead16(p); /* Unknown */; fg = icq_PacketRead32(p); bg = icq_PacketRead32(p); - icq_TCPChatUpdateColors(plink, fg, bg); + icq_TCPChatUpdateColors(pchat, fg, bg); presponse=icq_TCPCreateChatInfo2Packet(plink, plink->icqlink->icq_Nick, 0x00ffffff, 0x00000000); @@ -229,7 +248,7 @@ user = icq_PacketReadString(p); fg = icq_PacketRead32(p); bg = icq_PacketRead32(p); - icq_TCPChatUpdateColors(plink, fg, bg); + icq_TCPChatUpdateColors(pchat, fg, bg); font = (char *)NULL; encoding = 0; fontstyle = 0; @@ -259,7 +278,7 @@ encoding = icq_PacketRead16(p); } if(font) - icq_TCPChatUpdateFont(plink, font, encoding, fontstyle, fontsize); + icq_TCPChatUpdateFont(pchat, font, encoding, fontstyle, fontsize); presponse=icq_TCPCreateChatFontInfoPacket(plink); icq_PacketSend(presponse, plink->socket); icq_PacketDelete(presponse);
--- a/plugins/icq/tcpfilehandle.c Sat Jan 27 11:18:17 2001 +0000 +++ b/plugins/icq/tcpfilehandle.c Sun Jan 28 01:52:27 2001 +0000 @@ -1,9 +1,12 @@ /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* -$Id: tcpfilehandle.c 1319 2000-12-19 10:08:29Z warmenhoven $ +$Id: tcpfilehandle.c 1442 2001-01-28 01:52:27Z warmenhoven $ $Log$ -Revision 1.2 2000/12/19 10:08:29 warmenhoven -Yay, new icqlib +Revision 1.3 2001/01/28 01:52:27 warmenhoven +icqlib 1.1.5 + +Revision 1.16 2001/01/17 01:29:17 bills +Rework chat and file session interfaces; implement socket notifications. Revision 1.15 2000/07/24 03:10:08 bills added support for real nickname during TCP transactions like file and @@ -110,6 +113,7 @@ void icq_TCPProcessFilePacket(icq_Packet *p, icq_TCPLink *plink) { icq_FileSession *psession=(icq_FileSession *)plink->session; + ICQLINK *icqlink = plink->icqlink; BYTE type; DWORD num_files; DWORD total_bytes; @@ -136,10 +140,10 @@ psession->total_bytes=total_bytes; psession->current_speed=speed; icq_FileSessionSetHandle(psession, name); - icq_FileSessionSetStatus(psession, FILE_STATUS_INITIALIZED); + icq_FileSessionSetStatus(psession, FILE_STATUS_INITIALIZING); /* respond */ - presponse=icq_TCPCreateFile01Packet(speed, plink->icqlink->icq_Nick); + presponse=icq_TCPCreateFile01Packet(speed, icqlink->icq_Nick); icq_TCPLinkSend(plink, presponse); #ifdef TCP_PACKET_TRACE @@ -153,7 +157,7 @@ name=icq_PacketReadString(p); psession->current_speed=speed; icq_FileSessionSetHandle(psession, name); - icq_FileSessionSetStatus(psession, FILE_STATUS_INITIALIZED); + icq_FileSessionSetStatus(psession, FILE_STATUS_INITIALIZING); /* respond */ icq_FileSessionPrepareNextFile(psession); @@ -193,7 +197,7 @@ printf("file 03 packet sent to uin %lu\n", plink->remote_uin); #endif break; - + case 0x03: filesize=icq_PacketRead32(p); (void)icq_PacketRead32(p); @@ -208,29 +212,33 @@ case 0x04: (void)icq_PacketRead32(p); - icq_FileSessionSetStatus(psession, FILE_STATUS_STOP_FILE); + invoke_callback(icqlink, icq_FileNotify)(psession, + FILE_NOTIFY_STOP_FILE, 0, NULL); break; case 0x05: speed=icq_PacketRead32(p); psession->current_speed=speed; - if(plink->icqlink->icq_RequestNotify) - (*plink->icqlink->icq_RequestNotify)(plink->icqlink, plink->id, - ICQ_NOTIFY_FILE, FILE_STATUS_NEW_SPEED, 0); + invoke_callback(icqlink, icq_FileNotify)(psession, + FILE_NOTIFY_NEW_SPEED, speed, NULL); break; case 0x06: - if(plink->icqlink->icq_RequestNotify) - (*plink->icqlink->icq_RequestNotify)(plink->icqlink, plink->id, ICQ_NOTIFY_FILEDATA, - p->length-sizeof(BYTE), p->data+sizeof(BYTE)); + { + void *data = p->data+sizeof(BYTE); + int length = p->length-sizeof(BYTE); + + invoke_callback(icqlink, icq_FileNotify)(psession, + FILE_NOTIFY_DATAPACKET, length, data); icq_FileSessionSetStatus(psession, FILE_STATUS_RECEIVING); - result=write(psession->current_fd, p->data+sizeof(BYTE), p->length-sizeof(BYTE)); - psession->current_file_progress+=p->length-sizeof(BYTE); - psession->total_transferred_bytes+=p->length-sizeof(BYTE); + result=write(psession->current_fd, data, length); + psession->current_file_progress+=length; + psession->total_transferred_bytes+=length; break; + } default: - icq_FmtLog(plink->icqlink, ICQ_LOG_WARNING, "unknown file packet type %d!\n", type); + icq_FmtLog(icqlink, ICQ_LOG_WARNING, "unknown file packet type %d!\n", type); } } @@ -266,8 +274,9 @@ icq_FileSession *pfile; icq_Packet *p2; - if(plink->icqlink->icq_RequestNotify) - (*plink->icqlink->icq_RequestNotify)(plink->icqlink, p->id, ICQ_NOTIFY_ACK, 0, 0); + invoke_callback(plink->icqlink, icq_RequestNotify)(plink->icqlink, + p->id, ICQ_NOTIFY_ACK, 0, NULL); + pfilelink=icq_TCPLinkNew(plink->icqlink); pfilelink->type=TCP_LINK_FILE; pfilelink->id=p->id; @@ -278,9 +287,10 @@ pfile->tcplink=pfilelink; pfilelink->id=pfile->id; - if (plink->icqlink->icq_RequestNotify) - (*plink->icqlink->icq_RequestNotify)(plink->icqlink, pfile->id, - ICQ_NOTIFY_FILESESSION, sizeof(icq_FileSession), pfile); + invoke_callback(plink->icqlink, icq_RequestNotify)(plink->icqlink, + pfile->id, ICQ_NOTIFY_FILESESSION, sizeof(icq_FileSession), pfile); + invoke_callback(plink->icqlink, icq_RequestNotify)(plink->icqlink, + pfile->id, ICQ_NOTIFY_SUCCESS, 0, NULL); icq_FileSessionSetStatus(pfile, FILE_STATUS_CONNECTING); icq_TCPLinkConnect(pfilelink, plink->remote_uin, port);
--- a/plugins/icq/tcphandle.c Sat Jan 27 11:18:17 2001 +0000 +++ b/plugins/icq/tcphandle.c Sun Jan 28 01:52:27 2001 +0000 @@ -1,9 +1,16 @@ /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* -$Id: tcphandle.c 1319 2000-12-19 10:08:29Z warmenhoven $ +$Id: tcphandle.c 1442 2001-01-28 01:52:27Z warmenhoven $ $Log$ -Revision 1.2 2000/12/19 10:08:29 warmenhoven -Yay, new icqlib +Revision 1.3 2001/01/28 01:52:27 warmenhoven +icqlib 1.1.5 + +Revision 1.16 2001/01/24 05:11:14 bills +applied patch from Robin Ericsson <lobbin@localhost.nu> which implements +receiving contact lists. See new icq_RecvContactList callback. + +Revision 1.15 2001/01/17 01:31:47 bills +Rework chat and file interfaces; implement socket notifications. Revision 1.14 2000/12/06 05:15:45 denis Handling for mass TCP messages has been added based on patch by @@ -85,6 +92,7 @@ */ +#include <stdlib.h> #include <time.h> #ifndef _WIN32 @@ -101,6 +109,7 @@ void icq_TCPOnMessageReceived(ICQLINK *link, DWORD uin, const char *message, DWORD id, icq_TCPLink *plink); void icq_TCPOnURLReceived(ICQLINK *link, DWORD uin, const char *message, DWORD id); +void icq_TCPOnContactListReceived(ICQLINK *link, DWORD uin, const char *message, DWORD id); void icq_TCPOnChatReqReceived(ICQLINK *link, DWORD uin, const char *message, DWORD id); void icq_TCPOnFileReqReceived(ICQLINK *link, DWORD uin, const char *message, const char *filename, unsigned long filesize, DWORD id); @@ -144,6 +153,7 @@ { case ICQ_TCP_MSG_MSG: case ICQ_TCP_MSG_URL: + case ICQ_TCP_MSG_CONTACTLIST: p->id=icq_PacketRead32(p); break; @@ -197,6 +207,10 @@ icq_TCPOnFileReqReceived(plink->icqlink, uin, message, filename, filesize, p->id); break; + case ICQ_TCP_MSG_CONTACTLIST: + icq_TCPOnContactListReceived(plink->icqlink, uin, message, p->id); + break; + default: icq_FmtLog(plink->icqlink, ICQ_LOG_WARNING, "unknown message type %d!\n", type); break; @@ -219,9 +233,10 @@ if(plink->icqlink->icq_RequestNotify) { icq_FmtLog(plink->icqlink, ICQ_LOG_MESSAGE, "received ack %d\n", p->id); - (*plink->icqlink->icq_RequestNotify)(plink->icqlink, p->id, ICQ_NOTIFY_ACK, status, - (void *)message); - (*plink->icqlink->icq_RequestNotify)(plink->icqlink, p->id, ICQ_NOTIFY_SUCCESS, 0, 0); + invoke_callback(plink->icqlink, icq_RequestNotify) + (plink->icqlink, p->id, ICQ_NOTIFY_ACK, status, (void *)message); + invoke_callback(plink->icqlink, icq_RequestNotify) + (plink->icqlink, p->id, ICQ_NOTIFY_SUCCESS, 0, NULL); } break; } @@ -372,3 +387,42 @@ icq_PacketDelete(pack); } } + +void icq_TCPOnContactListReceived(ICQLINK *link, DWORD uin, const char *message, DWORD id) +{ +#ifdef TCP_PACKET_TRACE + printf("tcp contactlist packet received from %lu { sequence=%lx }\n", uin, id); +#endif /* TCP_PACKET_TRACE */ + + if (link->icq_RecvContactList) { + /* use the current system time for time received */ + time_t t=time(0); + struct tm *ptime=localtime(&t); + icq_Packet *pack; + list *strList = list_new(); + int i, k, nr = icq_SplitFields(strList, message); + char *contact_uin[(nr - 2) /2], *contact_nick[(nr - 2) /2]; + icq_TCPLink *plink=icq_FindTCPLink(link, uin, TCP_LINK_MESSAGE); + + /* split message */ + for (i = 1, k = 0; i < (nr - 1); k++) + { + contact_uin[k] = list_at(strList, i); + contact_nick[k] = list_at(strList, i + 1); + i += 2; + } + + (*link->icq_RecvContactList)(link, uin, k, (const char **) + contact_uin, (const char **) contact_nick); + /* send an acknowledement to the remote client */ + pack=icq_TCPCreateContactListAck(plink, 0); + icq_PacketAppend32(pack, id); + icq_PacketSend(pack, plink->socket); +#ifdef TCP_PACKET_TRACE + printf("tcp message ack sent to %lu { sequence=%lx }\n", uin, id); +#endif /* TCP_PACKE_TRACE */ + icq_PacketDelete(pack); + + list_delete(strList, free); + } +}
--- a/plugins/icq/tcplink.c Sat Jan 27 11:18:17 2001 +0000 +++ b/plugins/icq/tcplink.c Sun Jan 28 01:52:27 2001 +0000 @@ -1,9 +1,20 @@ /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* -$Id: tcplink.c 1319 2000-12-19 10:08:29Z warmenhoven $ +$Id: tcplink.c 1442 2001-01-28 01:52:27Z warmenhoven $ $Log$ -Revision 1.2 2000/12/19 10:08:29 warmenhoven -Yay, new icqlib +Revision 1.3 2001/01/28 01:52:27 warmenhoven +icqlib 1.1.5 + +Revision 1.43 2001/01/27 22:48:01 bills +fix bugs related to TCP and new socket manager: implemented accepting TCP +sockets, fixed crashes when sending TCP messages. + +Revision 1.42 2001/01/17 01:29:17 bills +Rework chat and file session interfaces; implement socket notifications. + +Revision 1.41 2001/01/15 06:19:12 denis +Applied patch from Ilya Melamed <ilya@ort.org.il> which fixes random +icq_TCPLinkAccept() fails. Revision 1.40 2000/12/19 06:00:07 bills moved members from ICQLINK to ICQLINK_private struct @@ -233,12 +244,6 @@ list_delete(p->send_queue, icq_PacketDelete); list_delete(p->received_queue, icq_PacketDelete); - /* notify app if this was a chat or file xfer session and there is an - * id assigned */ - if((p->type==TCP_LINK_CHAT || p->type==TCP_LINK_FILE) && p->id) - if(p->icqlink->icq_RequestNotify) - (*p->icqlink->icq_RequestNotify)(p->icqlink, p->id, ICQ_NOTIFY_SUCCESS, 0, 0); - /* if this is a chat or file link, delete the associated session as * well, but make sure we unassociate ourself first so the session * doesn't try to close us */ @@ -247,13 +252,13 @@ if(p->type==TCP_LINK_CHAT) { icq_ChatSession *psession=p->session; - /*psession->tcplink=0L;*/ + psession->tcplink=NULL; icq_ChatSessionClose(psession); } if(p->type==TCP_LINK_FILE) { icq_FileSession *psession=p->session; - psession->tcplink=0L; + psession->tcplink=NULL; icq_FileSessionClose(psession); } } @@ -261,11 +266,7 @@ /* close the socket after we notify app so app can read errno if necessary */ if (p->socket > -1) { -#ifdef _WIN32 - closesocket(p->socket); -#else - close(p->socket); -#endif + icq_SocketDelete(p->socket); } free(p); @@ -353,7 +354,9 @@ int res; char buf[1024]; - plink->mode = (plink->mode & (~TCP_LINK_SOCKS_AUTHORIZATION)) | TCP_LINK_SOCKS_AUTHSTATUS; + plink->mode &= ~TCP_LINK_SOCKS_AUTHORIZATION; + plink->mode |= TCP_LINK_SOCKS_AUTHSTATUS; + #ifdef _WIN32 res = recv(plink->socket, buf, 2, 0); #else @@ -362,11 +365,7 @@ if(res != 2 || buf[0] != 5 || buf[1] != 2) /* username/password authentication*/ { icq_FmtLog(plink->icqlink, ICQ_LOG_FATAL, "[SOCKS] Authentication method incorrect\n"); -#ifdef _WIN32 - closesocket(plink->socket); -#else - close(plink->socket); -#endif + icq_SocketDelete(plink->socket); return -1; } buf[0] = 1; /* version of subnegotiation */ @@ -398,11 +397,7 @@ if(res != 2 || buf[0] != 1 || buf[1] != 0) { icq_FmtLog(plink->icqlink, ICQ_LOG_FATAL, "[SOCKS] Authorization failure\n"); -#ifdef _WIN32 - closesocket(plink->socket); -#else - close(plink->socket); -#endif + icq_SocketDelete(plink->socket); return -1; } return 0; @@ -422,11 +417,7 @@ if(res != 2 || buf[0] != 5 || buf[1] != 0) /* no authentication required */ { icq_FmtLog(plink->icqlink, ICQ_LOG_FATAL, "[SOCKS] Authentication method incorrect\n"); -#ifdef _WIN32 - closesocket(plink->socket); -#else - close(plink->socket); -#endif + icq_SocketDelete(plink->socket); return -1; } return 0; @@ -505,11 +496,7 @@ res = EFAULT; break; } -#ifdef _WIN32 - closesocket(plink->socket); -#else - close(plink->socket); -#endif + icq_SocketDelete(plink->socket); return res; } return 0; @@ -532,7 +519,7 @@ if(!pcontact) return -2; - if((plink->socket=socket(AF_INET, SOCK_STREAM, 0)) < 0) + if((plink->socket=icq_SocketNew(AF_INET, SOCK_STREAM, 0)) < 0) return -3; /* bzero(&(plink->remote_address), sizeof(plink->remote_address)); Win32 incompatible... */ @@ -606,6 +593,9 @@ printf("hello packet queued for %lu\n", uin); #endif /* TCP_PACKET_TRACE */ + icq_SocketSetHandler(plink->socket, ICQ_SOCKET_WRITE, + icq_TCPLinkOnConnect, plink); + return 1; } @@ -622,21 +612,26 @@ if(pnewlink) { - socket=accept(plink->socket, (struct sockaddr *)&(plink->remote_address), - &remote_length); + remote_length = sizeof(struct sockaddr_in); + socket=icq_SocketAccept(plink->socket, + (struct sockaddr *)&(plink->remote_address), &remote_length); - icq_FmtLog(plink->icqlink, ICQ_LOG_MESSAGE, - "accepting tcp connection from %s:%d\n", - inet_ntoa(*((struct in_addr *)(&(plink->remote_address.sin_addr)))), - ntohs(plink->remote_address.sin_port)); + icq_FmtLog(plink->icqlink, ICQ_LOG_MESSAGE, + "accepting tcp connection from %s:%d\n", + inet_ntoa(*((struct in_addr *)(&(plink->remote_address.sin_addr)))), + ntohs(plink->remote_address.sin_port)); - /* FIXME: make sure accept succeeded */ + /* FIXME: make sure accept succeeded */ pnewlink->type=plink->type; pnewlink->socket=socket; /* first packet sent on an icq tcp link is always the hello packet */ pnewlink->mode|=TCP_LINK_MODE_HELLOWAIT; + + /* install socket handler for new socket */ + icq_SocketSetHandler(socket, ICQ_SOCKET_READ, icq_TCPLinkOnDataReceived, + pnewlink); } /* set the socket to non-blocking */ @@ -659,7 +654,7 @@ plink->remote_uin=0; /* create tcp listen socket */ - if((plink->socket=socket(AF_INET, SOCK_STREAM, 0)) < 0) + if((plink->socket=icq_SocketNew(AF_INET, SOCK_STREAM, 0)) < 0) return -1; /* must use memset, no bzero for Win32! */ @@ -685,7 +680,10 @@ ntohs(plink->socket_address.sin_port)); plink->mode|=TCP_LINK_MODE_LISTEN; - + + icq_SocketSetHandler(plink->socket, ICQ_SOCKET_READ, icq_TCPLinkAccept, + plink); + return 0; } @@ -729,7 +727,7 @@ icq_RusConv_n(to, &t_in[j], i - j); } -int icq_TCPLinkOnDataReceived(icq_TCPLink *plink) +void icq_TCPLinkOnDataReceived(icq_TCPLink *plink) { int process_count=0, recv_result=0; char *buffer=plink->buffer; @@ -763,9 +761,8 @@ /* notify the app with the new data */ if(plink->type == TCP_LINK_CHAT) icq_ChatRusConv_n("wk", plink->buffer, plink->buffer_count); - if(plink->icqlink->icq_RequestNotify) - (*plink->icqlink->icq_RequestNotify)(plink->icqlink, plink->id, ICQ_NOTIFY_CHATDATA, - plink->buffer_count, plink->buffer); + invoke_callback(plink->icqlink, icq_ChatNotify)(plink->session, + CHAT_NOTIFY_DATA, plink->buffer_count, plink->buffer); plink->buffer_count=0; continue; } @@ -782,7 +779,7 @@ icq_FmtLog(plink->icqlink, ICQ_LOG_WARNING, "tcplink buffer " "overflow, packet size = %d, buffer size = %d, closing link\n", packet_size, icq_TCPLinkBufferSize); - return 0; + return; } if(packet_size+sizeof(WORD) <= (unsigned)plink->buffer_count) @@ -815,9 +812,14 @@ icq_FmtLog(plink->icqlink, ICQ_LOG_WARNING, "recv failed from %d (%d-%s)," " closing link\n", plink->remote_uin, errno, strerror(errno)); + icq_TCPLinkClose(plink); + + } else { + + icq_TCPLinkProcessReceived(plink); + } - return process_count; } void icq_TCPLinkOnPacketReceived(icq_TCPLink *plink, icq_Packet *p) @@ -881,7 +883,12 @@ } if(plink->mode & (TCP_LINK_SOCKS_CONNECTING | TCP_LINK_SOCKS_AUTHORIZATION | TCP_LINK_SOCKS_AUTHSTATUS | TCP_LINK_SOCKS_NOAUTHSTATUS | TCP_LINK_SOCKS_CROSSCONNECT | TCP_LINK_SOCKS_CONNSTATUS)) + { + icq_SocketSetHandler(plink->socket, ICQ_SOCKET_WRITE, NULL, NULL); + icq_SocketSetHandler(plink->socket, ICQ_SOCKET_READ, + icq_TCPLinkOnConnect, plink); return; + } len=sizeof(plink->socket_address); getsockname(plink->socket, (struct sockaddr *)&plink->socket_address, &len); @@ -896,6 +903,10 @@ plink->mode&= ~TCP_LINK_MODE_CONNECTING; + icq_SocketSetHandler(plink->socket, ICQ_SOCKET_READ, + icq_TCPLinkOnDataReceived, plink); + icq_SocketSetHandler(plink->socket, ICQ_SOCKET_WRITE, NULL, NULL); + /* socket is now connected, notify each request that connection * has been established and send pending data */ while(plink->send_queue->count>0)
--- a/plugins/icq/tcplink.h Sat Jan 27 11:18:17 2001 +0000 +++ b/plugins/icq/tcplink.h Sun Jan 28 01:52:27 2001 +0000 @@ -40,8 +40,8 @@ #define icq_TCPLinkBufferSize 4096 #define TCP_LINK_CONNECT_TIMEOUT 30 -typedef struct icq_TCPLink_s -{ +struct icq_TCPLink_s { + /* icq_TCPLink ICQLINK, type, mode, and session */ ICQLINK *icqlink; int type; @@ -71,7 +71,7 @@ /* connect timer */ time_t connect_time; -} icq_TCPLink; +}; icq_TCPLink *icq_TCPLinkNew(ICQLINK *link); void icq_TCPLinkDelete(void *p); @@ -82,7 +82,7 @@ icq_TCPLink *icq_TCPLinkAccept(icq_TCPLink *plink); int icq_TCPLinkListen(icq_TCPLink *plink); -int icq_TCPLinkOnDataReceived(icq_TCPLink *plink); +void icq_TCPLinkOnDataReceived(icq_TCPLink *plink); void icq_TCPLinkOnPacketReceived(icq_TCPLink *plink, icq_Packet *p); void icq_TCPLinkOnConnect(icq_TCPLink *plink);
--- a/plugins/icq/udp.c Sat Jan 27 11:18:17 2001 +0000 +++ b/plugins/icq/udp.c Sun Jan 28 01:52:27 2001 +0000 @@ -1,9 +1,12 @@ /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* -$Id: udp.c 1319 2000-12-19 10:08:29Z warmenhoven $ +$Id: udp.c 1442 2001-01-28 01:52:27Z warmenhoven $ $Log$ -Revision 1.2 2000/12/19 10:08:29 warmenhoven -Yay, new icqlib +Revision 1.3 2001/01/28 01:52:27 warmenhoven +icqlib 1.1.5 + +Revision 1.27 2001/01/16 00:10:13 denis +Invisible list has been finished. Revision 1.26 2000/12/19 06:00:07 bills moved members from ICQLINK to ICQLINK_private struct @@ -439,7 +442,7 @@ icq_PacketAdvance(p,1); while(ptr) { - if(ptr->vis_list) + if(ptr->invis_list) { icq_PacketAppend32(p, ptr->uin); num_used++;
--- a/plugins/icq/udphandle.c Sat Jan 27 11:18:17 2001 +0000 +++ b/plugins/icq/udphandle.c Sun Jan 28 01:52:27 2001 +0000 @@ -1,9 +1,13 @@ /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* -$Id: udphandle.c 1319 2000-12-19 10:08:29Z warmenhoven $ +$Id: udphandle.c 1442 2001-01-28 01:52:27Z warmenhoven $ $Log$ -Revision 1.2 2000/12/19 10:08:29 warmenhoven -Yay, new icqlib +Revision 1.3 2001/01/28 01:52:27 warmenhoven +icqlib 1.1.5 + +Revision 1.30 2001/01/15 06:17:35 denis +Applied patch from Andrey Chernomyrdin <andrey@excom.spb.su> to +handle icq2000 specific "You've been added" packet. Revision 1.29 2000/11/02 07:28:30 denis Do not ack unhandled protocol version. @@ -155,15 +159,18 @@ BYTE minute, BYTE day, BYTE month, WORD year) { list *strList; + int fieldCount; strList = list_new(); switch(type) { case TYPE_ADDED: /* Format: Nick, 0xFE, FName, 0xFE, LName, 0xFE, EMail */ - if(icq_SplitFields(strList, data)!=4) + fieldCount = icq_SplitFields(strList, data); + if(fieldCount != 4 && fieldCount != 5) { - icq_FmtLog(link, ICQ_LOG_ERROR, "Bad packet!\n"); + icq_FmtLog(link, ICQ_LOG_ERROR, "Bad TYPE_ADDED packet (expected 4/5 args, received %i)!\n", + fieldCount); return; } icq_RusConv("wk", list_at(strList, 0)); /* Nick */ @@ -181,9 +188,11 @@ break; case TYPE_AUTH_REQ: /* Format: Nick, 0xFE, FName, 0xFE, LName, 0xFE, EMail, 0xFE, 0, 0xFE, Reason */ - if(icq_SplitFields(strList, data)!=6) + fieldCount = icq_SplitFields(strList, data); + if(fieldCount != 6) { - icq_FmtLog(link, ICQ_LOG_ERROR, "Bad packet!\n"); + icq_FmtLog(link, ICQ_LOG_ERROR, "Bad TYPE_AUTH_REQ packet (expected 6 args, received %i)!\n", + fieldCount); return; } icq_RusConv("wk", list_at(strList, 0)); /* Nick */ @@ -202,9 +211,10 @@ break; case TYPE_URL: /* Format: Description, 0xFE, URL */ - if(icq_SplitFields(strList, data)!=2) + fieldCount = icq_SplitFields(strList, data); + if(fieldCount != 2) { - icq_FmtLog(link, ICQ_LOG_ERROR, "Bad packet!\n"); + icq_FmtLog(link, ICQ_LOG_ERROR, "Bad TYPE_URL packet (expected 2 args, recived %i)!\n", fieldCount); return; } icq_RusConv("wk", list_at(strList, 0)); /* Description */ @@ -217,9 +227,11 @@ case TYPE_WEBPAGER: /* Format: Nick, 0xFE, Empty-FName, 0xFE, Empty-LName, 0xFE, EMail, 0xFE, * Reason(3), 0xFE, Message with IP & Subject */ - if(icq_SplitFields(strList, data)!=6) + fieldCount = icq_SplitFields(strList, data); + if(fieldCount != 6) { - icq_FmtLog(link, ICQ_LOG_ERROR, "Bad packet!\n"); + icq_FmtLog(link, ICQ_LOG_ERROR, "Bad TYPE_WEBPAGER packet (expected 6 args, received %i)!\n", + fieldCount); return; } icq_RusConv("wk", list_at(strList, 0)); /* Nick */ @@ -234,9 +246,11 @@ case TYPE_EXPRESS: /* Format: Nick, 0xFE, Empty-FName, 0xFE, Empty-LName, 0xFE, EMail, 0xFE, * Reason(3), 0xFE, Message Subject */ - if(icq_SplitFields(strList, data)!=6) + fieldCount = icq_SplitFields(strList, data); + if(fieldCount != 6) { - icq_FmtLog(link, ICQ_LOG_ERROR, "Bad packet!\n"); + icq_FmtLog(link, ICQ_LOG_ERROR, "Bad TYPE_EXPRESS packet (expected 6 args, received %i)!\n", + fieldCount); return; } icq_RusConv("wk", list_at(strList, 0)); /* Nick */
--- a/plugins/icq/util.c Sat Jan 27 11:18:17 2001 +0000 +++ b/plugins/icq/util.c Sun Jan 28 01:52:27 2001 +0000 @@ -1,9 +1,9 @@ /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* -$Id: util.c 1319 2000-12-19 10:08:29Z warmenhoven $ +$Id: util.c 1442 2001-01-28 01:52:27Z warmenhoven $ $Log$ -Revision 1.2 2000/12/19 10:08:29 warmenhoven -Yay, new icqlib +Revision 1.3 2001/01/28 01:52:27 warmenhoven +icqlib 1.1.5 Revision 1.33 2000/08/13 19:26:50 denis icq_Genders[] array have been added.