--- 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)