# HG changeset patch # User Mark Doliner # Date 1050550101 0 # Node ID ac9ca88d4b2572fc95aa190fd23cf1623d355c7b # Parent fc09679bffbe4a0c9c75c62d49318f1fc5077ae5 [gaim-migrate @ 5510] I guess I'm gonna go ahead and commit this... I don't think there's any real functionality change. AIM file transfer might work a little better, I guess. I probably fixed a bug or two. Like, filenames>64 characters won't cause infinite loopage. Changed AIM file transfer a bit with the following two goals: -Move some code from oscar.c to libfaim. Should make it easier for 3rd parties to use libfaim for file transfer. -Allow for easier code reuse with "get file" (in the works) committer: Tailor Script diff -r fc09679bffbe -r ac9ca88d4b25 src/ft.c --- a/src/ft.c Thu Apr 17 01:20:22 2003 +0000 +++ b/src/ft.c Thu Apr 17 03:28:21 2003 +0000 @@ -63,10 +63,8 @@ if (xfer == NULL) return; - if (!xfer->completed) { + if (!xfer->completed) gaim_xfer_cancel_local(xfer); - return; - } ui_ops = gaim_xfer_get_ui_ops(xfer); diff -r fc09679bffbe -r ac9ca88d4b25 src/protocols/oscar/aim.h --- a/src/protocols/oscar/aim.h Thu Apr 17 01:20:22 2003 +0000 +++ b/src/protocols/oscar/aim.h Thu Apr 17 03:28:21 2003 +0000 @@ -836,9 +836,9 @@ /* 0x0006 */ faim_export int aim_im_sendch2_icon(aim_session_t *sess, const char *sn, const fu8_t *icon, int iconlen, time_t stamp, fu16_t iconsum); /* 0x0006 */ faim_export int aim_im_sendch2_rtfmsg(aim_session_t *sess, struct aim_sendrtfmsg_args *args); /* 0x0006 */ faim_export int aim_im_sendch2_odcrequest(aim_session_t *sess, fu8_t *cookie, const char *sn, const fu8_t *ip, fu16_t port); -/* 0x0006 */ faim_export int aim_im_sendch2_sendfile_ask(aim_session_t *sess, fu8_t *cookie, const char *sn, const fu8_t *ip, fu16_t port, const char *filename, fu16_t numfiles, fu32_t totsize); -/* 0x0006 */ faim_export int aim_im_sendch2_sendfile_accept(aim_session_t *sess, const fu8_t *cookie, const char *sn, fu16_t rendid); -/* 0x0006 */ faim_export int aim_im_sendch2_sendfile_cancel(aim_session_t *sess, const fu8_t *cookie, const char *sn, fu16_t rendid); +/* 0x0006 */ faim_export int aim_im_sendch2_sendfile_ask(aim_session_t *sess, struct aim_oft_info *oft_info); +/* 0x0006 */ faim_export int aim_im_sendch2_sendfile_accept(aim_session_t *sess, struct aim_oft_info *info); +/* 0x0006 */ faim_export int aim_im_sendch2_sendfile_cancel(aim_session_t *sess, struct aim_oft_info *oft_info); /* 0x0006 */ faim_export int aim_im_sendch2_geticqaway(aim_session_t *sess, const char *sn, int type); /* 0x0006 */ faim_export int aim_im_sendch4(aim_session_t *sess, char *sn, fu16_t type, fu8_t *message); /* 0x0008 */ faim_export int aim_im_warn(aim_session_t *sess, aim_conn_t *conn, const char *destsn, fu32_t flags); @@ -885,7 +885,13 @@ struct aim_oft_info { char cookie[8]; - char ip[30]; + char *sn; + char *proxyip; + char *clientip; + char *verifiedip; + fu16_t port; + aim_conn_t *conn; + aim_session_t *sess; struct aim_fileheader_t fh; struct aim_oft_info *next; }; @@ -899,14 +905,15 @@ faim_export aim_conn_t *aim_odc_getconn(aim_session_t *sess, const char *sn); faim_export aim_conn_t *aim_odc_initiate(aim_session_t *sess, const char *sn); faim_export aim_conn_t *aim_odc_connect(aim_session_t *sess, const char *sn, const char *addr, const fu8_t *cookie); -faim_export struct aim_oft_info *aim_oft_createnewheader(fu8_t *cookie, char *ip, fu32_t size, fu32_t modtime, char *filename); -faim_export aim_conn_t *aim_sendfile_listen(aim_session_t *sess, const fu8_t *cookie, const fu8_t *ip, fu16_t port); -faim_export int aim_oft_sendheader(aim_session_t *sess, aim_conn_t *conn, fu16_t type, const fu8_t *cookie, const char *filename, fu16_t filesdone, fu16_t numfiles, fu32_t size, fu32_t totsize, fu32_t modtime, fu32_t checksum, fu8_t flags, fu32_t bytesreceived, fu32_t recvcsum); + +faim_export struct aim_oft_info *aim_oft_createinfo(aim_session_t *sess, const fu8_t *cookie, const char *sn, const char *ip, fu16_t port, fu32_t size, fu32_t modtime, char *filename); +faim_export int aim_oft_destroyinfo(struct aim_oft_info *oft_info); +faim_export int aim_sendfile_listen(aim_session_t *sess, struct aim_oft_info *oft_info); +faim_export int aim_oft_sendheader(aim_session_t *sess, fu16_t type, struct aim_oft_info *oft_info); /* info.c */ -/* info.c */ /* * AIM User Info, Standard Form. */ diff -r fc09679bffbe -r ac9ca88d4b25 src/protocols/oscar/ft.c --- a/src/protocols/oscar/ft.c Thu Apr 17 01:20:22 2003 +0000 +++ b/src/protocols/oscar/ft.c Thu Apr 17 03:28:21 2003 +0000 @@ -23,7 +23,7 @@ * number that we're listening on. * 2) The receiver connects to the sender on the given IP address * and port. After the connection is established, the receiver - * sends another ICBM signifying that we are ready and waiting. + * sends an ICBM signifying that we are ready and waiting. * 3) The sender sends an OFT PROMPT message over the OFT * connection. * 4) The receiver of the file sends back an exact copy of this @@ -35,7 +35,8 @@ * until the entire file has been sent. * 6) The receiver knows the file is finished because the sender * sent the file size in an earlier OFT packet. So then the - * receiver sends the DONE thingy and closes the connection. + * receiver sends the DONE thingy (after filling in the + * "received" checksum and size) and closes the connection. */ #define FAIM_INTERNAL @@ -521,9 +522,6 @@ * will accept the pending connection and stop listening. * * @param sess The session - * @param conn The BOS conn. - * @param priv A dummy priv value (we'll let it get filled in later) - * (if you pass a %NULL, we alloc one). * @param sn The screen name to connect to. * @return The new connection. */ @@ -598,9 +596,8 @@ if (!sess || !sn) return NULL; - if (!(intdata = malloc(sizeof(struct aim_odc_intdata)))) + if (!(intdata = calloc(1, sizeof(struct aim_odc_intdata)))) return NULL; - memset(intdata, 0, sizeof(struct aim_odc_intdata)); memcpy(intdata->cookie, cookie, 8); strncpy(intdata->sn, sn, sizeof(intdata->sn)); if (addr) @@ -703,6 +700,78 @@ return ret; } +faim_export struct aim_oft_info *aim_oft_createinfo(aim_session_t *sess, const fu8_t *cookie, const char *sn, const char *ip, fu16_t port, fu32_t size, fu32_t modtime, char *filename) +{ + struct aim_oft_info *new; + + if (!sess) + return NULL; + + if (!(new = (struct aim_oft_info *)calloc(1, sizeof(struct aim_oft_info)))) + return NULL; + + new->sess = sess; + if (cookie) + memcpy(new->cookie, cookie, 8); + if (ip) + new->clientip = strdup(ip); + if (sn) + new->sn = strdup(sn); + new->port = port; + new->fh.totfiles = 1; + new->fh.filesleft = 1; + new->fh.totparts = 1; + new->fh.partsleft = 1; + new->fh.totsize = size; + new->fh.size = size; + new->fh.modtime = modtime; + new->fh.checksum = 0xffff0000; + new->fh.rfrcsum = 0xffff0000; + new->fh.rfcsum = 0xffff0000; + new->fh.recvcsum = 0xffff0000; + strncpy(new->fh.idstring, "OFT_Windows ICBMFT V1.1 32", 31); + if (filename) + strncpy(new->fh.name, filename, 63); + + new->next = sess->oft_info; + sess->oft_info = new; + + return new; +} + +/** + * Remove the given oft_info struct from the oft_info linked list, and + * then free its memory. + * + * @param sess The session. + * @param oft_info The aim_oft_info struct that we're destroying. + * @return Return 0 if no errors, otherwise return the error number. + */ +faim_export int aim_oft_destroyinfo(struct aim_oft_info *oft_info) +{ + aim_session_t *sess; + + if (!oft_info || !(sess = oft_info->sess)) + return -EINVAL; + + if (sess->oft_info && (sess->oft_info == oft_info)) { + sess->oft_info = sess->oft_info->next; + } else { + struct aim_oft_info *cur; + for (cur=sess->oft_info; (cur->next && (cur->next!=oft_info)); cur=cur->next); + if (cur->next) + cur->next = cur->next->next; + } + + free(oft_info->sn); + free(oft_info->proxyip); + free(oft_info->clientip); + free(oft_info->verifiedip); + free(oft_info); + + return 0; +} + /** * Creates a listener socket so the other dude can connect to us. * @@ -712,30 +781,30 @@ * will accept the pending connection and stop listening. * * @param sess The session. - * @param cookie This better be Mrs. Fields or I'm going to be pissed. - * @param ip Should be 4 bytes, each byte is 1 quartet of the IP address. - * @param port Ye olde port number to listen on. - * @return Return the new conn if everything went as planned. Otherwise, - * return NULL. + * @param oft_info File transfer information associated with this + * connection. + * @return Return 0 if no errors, otherwise return the error number. */ -faim_export aim_conn_t *aim_sendfile_listen(aim_session_t *sess, const fu8_t *cookie, const fu8_t *ip, fu16_t port) +faim_export int aim_sendfile_listen(aim_session_t *sess, struct aim_oft_info *oft_info) { - aim_conn_t *newconn; int listenfd; - if ((listenfd = listenestablish(port)) == -1) - return NULL; + if (!oft_info) + return -EINVAL; - if (!(newconn = aim_newconn(sess, AIM_CONN_TYPE_LISTENER, NULL))) { + if ((listenfd = listenestablish(oft_info->port)) == -1) + return 1; + + if (!(oft_info->conn = aim_newconn(sess, AIM_CONN_TYPE_LISTENER, NULL))) { close(listenfd); - return NULL; + return -ENOMEM; } - newconn->fd = listenfd; - newconn->subtype = AIM_CONN_SUBTYPE_OFT_SENDFILE; - newconn->lastactivity = time(NULL); + oft_info->conn->fd = listenfd; + oft_info->conn->subtype = AIM_CONN_SUBTYPE_OFT_SENDFILE; + oft_info->conn->lastactivity = time(NULL); - return newconn; + return 0; } /** @@ -830,110 +899,52 @@ return 0; } -faim_export struct aim_oft_info *aim_oft_createnewheader(fu8_t *cookie, char *ip, fu32_t size, fu32_t modtime, char *filename) -{ - struct aim_oft_info *new; - - if (!(new = (struct aim_oft_info *)calloc(1, sizeof(struct aim_oft_info)))) - return NULL; - - if (cookie && (sizeof(cookie) == 8)) { - memcpy(new->cookie, cookie, 8); - memcpy(new->fh.bcookie, cookie, 8); - } - if (ip) - strncpy(new->ip, ip, 30); - new->fh.filesleft = 0; - new->fh.totparts = 1; - new->fh.partsleft = 1; - new->fh.totsize = size; - new->fh.size = size; - new->fh.modtime = modtime; - strcpy(new->fh.idstring, "OFT_Windows ICBMFT V1.1 32"); - if (filename) - strncpy(new->fh.name, filename, 64); - - return new; -} - /** * Create an OFT packet based on the given information, and send it on its merry way. * * @param sess The session. - * @param conn The already-connected OFT connection. - * @param cookie The cookie associated with this file transfer. - * @param filename The filename. - * @param filesdone Number of files already transferred. - * @param numfiles Total number of files. - * @param size Size in bytes of this file. - * @param totsize Size in bytes of all files combined. - * @param checksum Funky checksum of this file. - * @param flags Any flags you want, baby. Send 0x21 when sending the - * "AIM_CB_OFT_DONE" message, and "0x02" for everything else. + * @param type The subtype of the OFT packet we're sending. + * @param oft_info The aim_oft_info struct with the connection and OFT + * info we're sending. * @return Return 0 if no errors, otherwise return the error number. */ -faim_export int aim_oft_sendheader(aim_session_t *sess, aim_conn_t *conn, fu16_t type, const fu8_t *cookie, const char *filename, fu16_t filesdone, fu16_t numfiles, fu32_t size, fu32_t totsize, fu32_t modtime, fu32_t checksum, fu8_t flags, fu32_t bytesreceived, fu32_t recvcsum) +faim_export int aim_oft_sendheader(aim_session_t *sess, fu16_t type, struct aim_oft_info *oft_info) { - aim_frame_t *newoft; - struct aim_fileheader_t *fh; + aim_frame_t *fr; - if (!sess || !conn || (conn->type != AIM_CONN_TYPE_RENDEZVOUS) || !filename) + if (!sess || !oft_info || !oft_info->conn || (oft_info->conn->type != AIM_CONN_TYPE_RENDEZVOUS)) return -EINVAL; - if (!(fh = (struct aim_fileheader_t *)calloc(1, sizeof(struct aim_fileheader_t)))) - return -ENOMEM; - +#if 0 /* * If you are receiving a file, the cookie should be null, if you are sending a * file, the cookie should be the same as the one used in the ICBM negotiation * SNACs. */ - if (cookie) - memcpy(fh->bcookie, cookie, 8); - fh->totfiles = numfiles; - fh->filesleft = numfiles - filesdone; - fh->totparts = 0x0001; /* set to 0x0002 sending Mac resource forks */ - fh->partsleft = 0x0001; - fh->totsize = totsize; - fh->size = size; - fh->modtime = modtime; - fh->checksum = checksum; - fh->nrecvd = bytesreceived; - fh->recvcsum = recvcsum; - - strncpy(fh->idstring, "OFT_Windows ICBMFT V1.1 32", sizeof(fh->idstring)); - fh->flags = flags; fh->lnameoffset = 0x1a; fh->lsizeoffset = 0x10; - memset(fh->dummy, 0, sizeof(fh->dummy)); - memset(fh->macfileinfo, 0, sizeof(fh->macfileinfo)); /* apparently 0 is ASCII, 2 is UCS-2 */ /* it is likely that 3 is ISO 8859-1 */ /* I think "nlanguage" might be the same thing as "subenc" in im.c */ fh->nencode = 0x0000; fh->nlanguage = 0x0000; +#endif - strncpy(fh->name, filename, sizeof(fh->name)); - aim_oft_dirconvert_tostupid(fh->name); + aim_oft_dirconvert_tostupid(oft_info->fh.name); - if (!(newoft = aim_tx_new(sess, conn, AIM_FRAMETYPE_OFT, type, 0))) { - free(fh); + if (!(fr = aim_tx_new(sess, oft_info->conn, AIM_FRAMETYPE_OFT, type, 0))) + return -ENOMEM; + + if (aim_oft_buildheader(&fr->data, &oft_info->fh) == -1) { + aim_frame_destroy(fr); return -ENOMEM; } - if (aim_oft_buildheader(&newoft->data, fh) == -1) { - aim_frame_destroy(newoft); - free(fh); - return -ENOMEM; - } + memcpy(fr->hdr.rend.magic, "OFT2", 4); + fr->hdr.rend.hdrlen = aim_bstream_curpos(&fr->data); - memcpy(newoft->hdr.rend.magic, "OFT2", 4); - newoft->hdr.rend.hdrlen = aim_bstream_curpos(&newoft->data); - - aim_tx_enqueue(sess, newoft); - - free(fh); + aim_tx_enqueue(sess, fr); return 0; } diff -r fc09679bffbe -r ac9ca88d4b25 src/protocols/oscar/im.c --- a/src/protocols/oscar/im.c Thu Apr 17 01:20:22 2003 +0000 +++ b/src/protocols/oscar/im.c Thu Apr 17 03:28:21 2003 +0000 @@ -667,28 +667,21 @@ * Subtype 0x0006 - Send an "I want to send you this file" message * */ -faim_export int aim_im_sendch2_sendfile_ask(aim_session_t *sess, fu8_t *cookie, const char *sn, const fu8_t *ip, fu16_t port, const char *filename, fu16_t numfiles, fu32_t totsize) +faim_export int aim_im_sendch2_sendfile_ask(aim_session_t *sess, struct aim_oft_info *oft_info) { aim_conn_t *conn; aim_frame_t *fr; aim_snacid_t snacid; aim_tlvlist_t *tl=NULL, *subtl=NULL; - fu8_t *ck; int i; - if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004))) - return -EINVAL; - - if (!sn || !filename) + if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004)) || !oft_info) return -EINVAL; /* XXX - Should be like "21CBF95" and null terminated */ - ck = (fu8_t *)malloc(8*sizeof(fu8_t)); for (i = 0; i < 7; i++) - ck[i] = 0x30 + ((fu8_t)rand() % 10); - ck[7] = '\0'; - if (cookie) - memcpy(cookie, ck, 8); + oft_info->cookie[i] = 0x30 + ((fu8_t)rand() % 10); + oft_info->cookie[7] = '\0'; { /* Create the subTLV chain */ fu8_t *buf; @@ -700,22 +693,31 @@ /* aim_addtlvtochain_raw(&subtl, 0x000e, 2, "en"); aim_addtlvtochain_raw(&subtl, 0x000d, 8, "us-ascii"); aim_addtlvtochain_raw(&subtl, 0x000c, 24, "Please accept this file."); */ - if (ip[0]) + if (oft_info->clientip) { + fu8_t ip[4]; + char *nexttoken; + int i = 0; + nexttoken = strtok(oft_info->clientip, "."); + while (nexttoken && i<4) { + ip[i] = atoi(nexttoken); + nexttoken = strtok(NULL, "."); + i++; + } aim_addtlvtochain_raw(&subtl, 0x0003, 4, ip); - aim_addtlvtochain16(&subtl, 0x0005, port); + } + aim_addtlvtochain16(&subtl, 0x0005, oft_info->port); /* TLV t(2711) */ - buflen = 2+2+4+63; + buflen = 2+2+4+strlen(oft_info->fh.name)+1; buf = malloc(buflen); aim_bstream_init(&bs, buf, buflen); - aimbs_put16(&bs, (numfiles > 1) ? 0x0002 : 0x0001); - aimbs_put16(&bs, numfiles); - aimbs_put32(&bs, totsize); + aimbs_put16(&bs, (oft_info->fh.totfiles > 1) ? 0x0002 : 0x0001); + aimbs_put16(&bs, oft_info->fh.totfiles); + aimbs_put32(&bs, oft_info->fh.totsize); - /* Filename is a fixed size of 63 bytes, so pad with 0's */ - aimbs_putraw(&bs, filename, strlen(filename)); - for (i=0; i<(63-strlen(filename)); i++) - aimbs_put8(&bs, 0x00); + /* Filename - NULL terminated, for some odd reason */ + aimbs_putraw(&bs, oft_info->fh.name, strlen(oft_info->fh.name)); + aimbs_put8(&bs, 0x00); aim_addtlvtochain_raw(&subtl, 0x2711, bs.len, bs.data); free(buf); @@ -731,7 +733,7 @@ buf = malloc(buflen); aim_bstream_init(&bs, buf, buflen); aimbs_put16(&bs, AIM_RENDEZVOUS_PROPOSE); - aimbs_putraw(&bs, ck, 8); + aimbs_putraw(&bs, oft_info->cookie, 8); aim_putcap(&bs, AIM_CAPS_SENDFILE); aim_writetlvchain(&bs, &subtl); aim_freetlvchain(&subtl); @@ -742,14 +744,14 @@ aim_addtlvtochain_noval(&tl, 0x0003); } - if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 11+strlen(sn) + aim_sizetlvchain(&tl)))) + if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 11+strlen(oft_info->sn) + aim_sizetlvchain(&tl)))) return -ENOMEM; - snacid = aim_cachesnac(sess, 0x0004, 0x0006, AIM_SNACFLAGS_DESTRUCTOR, ck, sizeof(ck)); + snacid = aim_cachesnac(sess, 0x0004, 0x0006, AIM_SNACFLAGS_DESTRUCTOR, oft_info->cookie, sizeof(oft_info->cookie)); aim_putsnac(&fr->data, 0x0004, 0x0006, 0x0000, snacid); /* ICBM header */ - aim_im_puticbm(&fr->data, ck, 0x0002, sn); + aim_im_puticbm(&fr->data, oft_info->cookie, 0x0002, oft_info->sn); /* All that crap from above (the 0x0005 TLV and the 0x0003 TLV) */ aim_writetlvchain(&fr->data, &tl); @@ -765,29 +767,29 @@ * * @param rendid Capability type (AIM_CAPS_GETFILE or AIM_CAPS_SENDFILE) */ -faim_export int aim_im_sendch2_sendfile_accept(aim_session_t *sess, const fu8_t *cookie, const char *sn, fu16_t rendid) +faim_export int aim_im_sendch2_sendfile_accept(aim_session_t *sess, struct aim_oft_info *oft_info) { aim_conn_t *conn; aim_frame_t *fr; aim_snacid_t snacid; - if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004)) || !cookie || !sn) + if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004)) || !oft_info) return -EINVAL; - if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 11+strlen(sn) + 4+2+8+16))) + if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 11+strlen(oft_info->sn) + 4+2+8+16))) return -ENOMEM; snacid = aim_cachesnac(sess, 0x0004, 0x0006, 0x0000, NULL, 0); aim_putsnac(&fr->data, 0x0004, 0x0006, 0x0000, snacid); /* ICBM header */ - aim_im_puticbm(&fr->data, cookie, 0x0002, sn); + aim_im_puticbm(&fr->data, oft_info->cookie, 0x0002, oft_info->sn); aimbs_put16(&fr->data, 0x0005); aimbs_put16(&fr->data, 0x001a); aimbs_put16(&fr->data, AIM_RENDEZVOUS_ACCEPT); - aimbs_putraw(&fr->data, cookie, 8); - aim_putcap(&fr->data, rendid); + aimbs_putraw(&fr->data, oft_info->cookie, 8); + aim_putcap(&fr->data, AIM_CAPS_SENDFILE); aim_tx_enqueue(sess, fr); @@ -798,29 +800,29 @@ * Subtype 0x0006 - Send a "cancel this file transfer" message? * */ -faim_export int aim_im_sendch2_sendfile_cancel(aim_session_t *sess, const fu8_t *cookie, const char *sn, fu16_t rendid) +faim_export int aim_im_sendch2_sendfile_cancel(aim_session_t *sess, struct aim_oft_info *oft_info) { aim_conn_t *conn; aim_frame_t *fr; aim_snacid_t snacid; - if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004)) || !cookie || !sn) + if (!sess || !(conn = aim_conn_findbygroup(sess, 0x0004)) || !oft_info) return -EINVAL; - if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 11+strlen(sn) + 4+2+8+16))) + if (!(fr = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x02, 10 + 11+strlen(oft_info->sn) + 4+2+8+16))) return -ENOMEM; snacid = aim_cachesnac(sess, 0x0004, 0x0006, 0x0000, NULL, 0); aim_putsnac(&fr->data, 0x0004, 0x0006, 0x0000, snacid); /* ICBM header */ - aim_im_puticbm(&fr->data, cookie, 0x0002, sn); + aim_im_puticbm(&fr->data, oft_info->cookie, 0x0002, oft_info->sn); aimbs_put16(&fr->data, 0x0005); aimbs_put16(&fr->data, 0x001a); aimbs_put16(&fr->data, AIM_RENDEZVOUS_CANCEL); - aimbs_putraw(&fr->data, cookie, 8); - aim_putcap(&fr->data, rendid); + aimbs_putraw(&fr->data, oft_info->cookie, 8); + aim_putcap(&fr->data, AIM_CAPS_SENDFILE); aim_tx_enqueue(sess, fr); @@ -1769,6 +1771,8 @@ /* * Unknown -- no value + * + * Maybe means we should connect directly to transfer the file? */ if (aim_gettlv(list2, 0x000f, 1)) ; diff -r fc09679bffbe -r ac9ca88d4b25 src/protocols/oscar/oscar.c --- a/src/protocols/oscar/oscar.c Thu Apr 17 01:20:22 2003 +0000 +++ b/src/protocols/oscar/oscar.c Thu Apr 17 03:28:21 2003 +0000 @@ -160,19 +160,6 @@ fu8_t cookie[8]; }; -/* BBB */ -struct oscar_xfer_data { - fu8_t cookie[8]; - gchar *proxyip; - gchar *clientip; - gchar *verifiedip; - fu32_t modtime; - fu32_t checksum; - aim_conn_t *conn; - struct gaim_xfer *xfer; - struct gaim_connection *gc; -}; - /* Various PRPL-specific buddy info that we want to keep track of */ struct buddyinfo { time_t signon; @@ -820,64 +807,46 @@ static void oscar_sendfile_connected(gpointer data, gint source, GaimInputCondition condition); /* XXX - This function is pretty ugly */ -static void -oscar_xfer_init(struct gaim_xfer *xfer) +static void oscar_xfer_init(struct gaim_xfer *xfer) { - struct gaim_connection *gc; - struct oscar_data *od; - struct oscar_xfer_data *xfer_data; - - debug_printf("in oscar_xfer_init\n"); - if (!(xfer_data = xfer->data)) - return; - if (!(gc = xfer_data->gc)) - return; - if (!(od = gc->proto_data)) - return; + struct aim_oft_info *oft_info = xfer->data; + struct gaim_connection *gc = oft_info->sess->aux_data; + struct oscar_data *od = gc->proto_data; if (gaim_xfer_get_type(xfer) == GAIM_XFER_SEND) { int i; - char ip[4]; - gchar **ipsplit; - - if (xfer->local_ip) { - ipsplit = g_strsplit(xfer->local_ip, ".", 4); - for (i=0; ipsplit[i]; i++) - ip[i] = atoi(ipsplit[i]); - g_strfreev(ipsplit); - } else { - memset(ip, 0x00, 4); - } xfer->filename = g_path_get_basename(xfer->local_filename); - xfer_data->checksum = aim_oft_checksum_file(xfer->local_filename); + strncpy(oft_info->fh.name, xfer->filename, 64); + oft_info->fh.totsize = gaim_xfer_get_size(xfer); + oft_info->fh.size = gaim_xfer_get_size(xfer); + oft_info->fh.checksum = aim_oft_checksum_file(xfer->local_filename); /* - * First try the port specified earlier (5190). If that fails, try a - * few random ports. Maybe we need a way to tell libfaim to listen - * for multiple connections on one listener socket. + * First try the port specified earlier (5190). If that fails, + * increment by 1 and try again. */ - xfer_data->conn = aim_sendfile_listen(od->sess, xfer_data->cookie, ip, xfer->local_port); - for (i=0; (i<5 && !xfer_data->conn); i++) { - xfer->local_port = (rand() % (65535-1024)) + 1024; - xfer_data->conn = aim_sendfile_listen(od->sess, xfer_data->cookie, ip, xfer->local_port); + aim_sendfile_listen(od->sess, oft_info); + for (i=0; (i<5 && !oft_info->conn); i++) { + xfer->local_port = oft_info->port = oft_info->port + 1; + aim_sendfile_listen(od->sess, oft_info); } - debug_printf("port is %d, ip is %hhd.%hhd.%hhd.%hhd\n", xfer->local_port, ip[0], ip[1], ip[2], ip[3]); - if (xfer_data->conn) { - xfer->watcher = gaim_input_add(xfer_data->conn->fd, GAIM_INPUT_READ, oscar_callback, xfer_data->conn); - aim_im_sendch2_sendfile_ask(od->sess, xfer_data->cookie, xfer->who, ip, xfer->local_port, xfer->filename, 1, xfer->size); - aim_conn_addhandler(od->sess, xfer_data->conn, AIM_CB_FAM_OFT, AIM_CB_OFT_ESTABLISHED, oscar_sendfile_estblsh, 0); + debug_printf("port is %d, ip is %s\n", xfer->local_port, oft_info->clientip); + if (oft_info->conn) { + xfer->watcher = gaim_input_add(oft_info->conn->fd, GAIM_INPUT_READ, oscar_callback, oft_info->conn); + aim_im_sendch2_sendfile_ask(od->sess, oft_info); + aim_conn_addhandler(od->sess, oft_info->conn, AIM_CB_FAM_OFT, AIM_CB_OFT_ESTABLISHED, oscar_sendfile_estblsh, 0); } else { do_error_dialog(_("File Transfer Aborted"), _("Unable to establish listener socket."), GAIM_ERROR); /* XXX - The below line causes a crash because the transfer is canceled before the "Ok" callback on the file selection thing exists, I think */ /* gaim_xfer_cancel_remote(xfer); */ } } else if (gaim_xfer_get_type(xfer) == GAIM_XFER_RECEIVE) { - xfer_data->conn = aim_newconn(od->sess, AIM_CONN_TYPE_RENDEZVOUS, NULL); - if (xfer_data->conn) { - xfer_data->conn->subtype = AIM_CONN_SUBTYPE_OFT_SENDFILE; - aim_conn_addhandler(od->sess, xfer_data->conn, AIM_CB_FAM_OFT, AIM_CB_OFT_PROMPT, oscar_sendfile_prompt, 0); - xfer_data->conn->fd = xfer->fd = proxy_connect(gc->account, xfer->remote_ip, xfer->remote_port, oscar_sendfile_connected, xfer); + oft_info->conn = aim_newconn(od->sess, AIM_CONN_TYPE_RENDEZVOUS, NULL); + if (oft_info->conn) { + oft_info->conn->subtype = AIM_CONN_SUBTYPE_OFT_SENDFILE; + aim_conn_addhandler(od->sess, oft_info->conn, AIM_CB_FAM_OFT, AIM_CB_OFT_PROMPT, oscar_sendfile_prompt, 0); + oft_info->conn->fd = xfer->fd = proxy_connect(gc->account, xfer->remote_ip, xfer->remote_port, oscar_sendfile_connected, xfer); if (xfer->fd == -1) { do_error_dialog(_("File Transfer Aborted"), _("Unable to establish file descriptor."), GAIM_ERROR); /* gaim_xfer_cancel_remote(xfer); */ @@ -891,123 +860,67 @@ } } -static void -oscar_xfer_start(struct gaim_xfer *xfer) +static void oscar_xfer_start(struct gaim_xfer *xfer) { -/* struct gaim_connection *gc; - struct oscar_data *od; - struct oscar_xfer_data *xfer_data; - - if (!(xfer_data = xfer->data)) - return; - if (!(gc = xfer_data->gc)) - return; - if (!(od = gc->proto_data)) - return; - - od = xfer_data->od; -*/ + debug_printf("AAA - in oscar_xfer_start\n"); - /* I'm pretty sure we don't need to do jack here. Nor Jill. */ } -static void -oscar_xfer_end(struct gaim_xfer *xfer) +static void oscar_xfer_end(struct gaim_xfer *xfer) { - struct gaim_connection *gc; - struct oscar_data *od; - struct oscar_xfer_data *xfer_data; + struct aim_oft_info *oft_info = xfer->data; + struct gaim_connection *gc = oft_info->sess->aux_data; + struct oscar_data *od = gc->proto_data; debug_printf("AAA - in oscar_xfer_end\n"); - if (!(xfer_data = xfer->data)) - return; - - if (gaim_xfer_get_type(xfer) == GAIM_XFER_RECEIVE) - aim_oft_sendheader(xfer_data->conn->sessv, xfer_data->conn, AIM_CB_OFT_DONE, xfer_data->cookie, xfer->filename, 1, 1, xfer->size, xfer->size, xfer_data->modtime, xfer_data->checksum, 0x02, xfer->size, xfer_data->checksum); - - g_free(xfer_data->proxyip); - g_free(xfer_data->clientip); - g_free(xfer_data->verifiedip); - - if ((gc = xfer_data->gc)) { - if ((od = gc->proto_data)) - od->file_transfers = g_slist_remove(od->file_transfers, xfer); - } - - g_free(xfer_data); + + if (gaim_xfer_get_type(xfer) == GAIM_XFER_RECEIVE) { + oft_info->fh.nrecvd = gaim_xfer_get_bytes_sent(xfer); + aim_oft_sendheader(oft_info->sess, AIM_CB_OFT_DONE, oft_info); + } + + aim_conn_kill(oft_info->sess, &oft_info->conn); + aim_oft_destroyinfo(oft_info); xfer->data = NULL; + od->file_transfers = g_slist_remove(od->file_transfers, xfer); } -static void -oscar_xfer_cancel_send(struct gaim_xfer *xfer) +static void oscar_xfer_cancel_send(struct gaim_xfer *xfer) { - struct gaim_connection *gc; - struct oscar_data *od; - struct oscar_xfer_data *xfer_data; - aim_conn_t *conn; + struct aim_oft_info *oft_info = xfer->data; + struct gaim_connection *gc = oft_info->sess->aux_data; + struct oscar_data *od = gc->proto_data; debug_printf("AAA - in oscar_xfer_cancel_send\n"); - if (!(xfer_data = xfer->data)) - return; - - if ((conn = xfer_data->conn)) { - aim_session_t *sess; - if ((sess = conn->sessv)) - if (xfer_data->cookie && xfer->who) - aim_im_sendch2_sendfile_cancel(sess, xfer_data->cookie, xfer->who, AIM_CAPS_SENDFILE); - } - - g_free(xfer_data->proxyip); - g_free(xfer_data->clientip); - g_free(xfer_data->verifiedip); - - if ((gc = xfer_data->gc)) - if ((od = gc->proto_data)) - od->file_transfers = g_slist_remove(od->file_transfers, xfer); - - g_free(xfer_data); + + aim_im_sendch2_sendfile_cancel(oft_info->sess, oft_info); + + aim_conn_kill(oft_info->sess, &oft_info->conn); + aim_oft_destroyinfo(oft_info); xfer->data = NULL; + od->file_transfers = g_slist_remove(od->file_transfers, xfer); } -static void -oscar_xfer_cancel_recv(struct gaim_xfer *xfer) +static void oscar_xfer_cancel_recv(struct gaim_xfer *xfer) { - struct gaim_connection *gc; - struct oscar_data *od; - struct oscar_xfer_data *xfer_data; - aim_conn_t *conn; + struct aim_oft_info *oft_info = xfer->data; + struct gaim_connection *gc = oft_info->sess->aux_data; + struct oscar_data *od = gc->proto_data; debug_printf("AAA - in oscar_xfer_cancel_recv\n"); - if (!(xfer_data = xfer->data)) - return; - - if ((conn = xfer_data->conn)) { - aim_session_t *sess; - if ((sess = conn->sessv)) - if (xfer_data->cookie && xfer->who) - aim_im_sendch2_sendfile_cancel(sess, xfer_data->cookie, xfer->who, AIM_CAPS_SENDFILE); - } - - g_free(xfer_data->proxyip); - g_free(xfer_data->clientip); - g_free(xfer_data->verifiedip); - - if ((gc = xfer_data->gc)) - if ((od = gc->proto_data)) - od->file_transfers = g_slist_remove(od->file_transfers, xfer); - - g_free(xfer_data); + + aim_im_sendch2_sendfile_cancel(oft_info->sess, oft_info); + + aim_conn_kill(oft_info->sess, &oft_info->conn); + aim_oft_destroyinfo(oft_info); xfer->data = NULL; + od->file_transfers = g_slist_remove(od->file_transfers, xfer); } -static void -oscar_xfer_ack(struct gaim_xfer *xfer, const char *buffer, size_t size) +static void oscar_xfer_ack(struct gaim_xfer *xfer, const char *buffer, size_t size) { - struct oscar_xfer_data *xfer_data; - - if (!(xfer_data = xfer->data)) - return; + struct aim_oft_info *oft_info = xfer->data; if (gaim_xfer_get_type(xfer) == GAIM_XFER_SEND) { /* @@ -1016,27 +929,26 @@ */ if (gaim_xfer_get_bytes_remaining(xfer) <= 0) { gaim_input_remove(xfer->watcher); - xfer->watcher = gaim_input_add(xfer->fd, GAIM_INPUT_READ, oscar_callback, xfer_data->conn); + xfer->watcher = gaim_input_add(xfer->fd, GAIM_INPUT_READ, oscar_callback, oft_info->conn); xfer->fd = 0; gaim_xfer_set_completed(xfer, TRUE); } } else if (gaim_xfer_get_type(xfer) == GAIM_XFER_RECEIVE) { - /* Update our rolling checksum */ - /* xfer_data->checksum = aim_oft_checksum_chunk(buffer, size, xfer_data->checksum); */ + /* Update our rolling checksum. Like Walmart, yo. */ + oft_info->fh.recvcsum = aim_oft_checksum_chunk(buffer, size, oft_info->fh.recvcsum); } } -static struct gaim_xfer * -oscar_find_xfer_by_cookie(GSList *fts, const char *ck) +static struct gaim_xfer *oscar_find_xfer_by_cookie(GSList *fts, const char *ck) { struct gaim_xfer *xfer; - struct oscar_xfer_data *data; + struct aim_oft_info *oft_info; while (fts) { xfer = fts->data; - data = xfer->data; - - if (data && !strcmp(data->cookie, ck)) + oft_info = xfer->data; + + if (oft_info && !strcmp(ck, oft_info->cookie)) return xfer; fts = g_slist_next(fts); @@ -1045,17 +957,16 @@ return NULL; } -static struct gaim_xfer * -oscar_find_xfer_by_conn(GSList *fts, aim_conn_t *conn) +static struct gaim_xfer *oscar_find_xfer_by_conn(GSList *fts, aim_conn_t *conn) { struct gaim_xfer *xfer; - struct oscar_xfer_data *data; + struct aim_oft_info *oft_info; while (fts) { xfer = fts->data; - data = xfer->data; - - if (data && (conn == data->conn)) + oft_info = xfer->data; + + if (oft_info && (conn == oft_info->conn)) return xfer; fts = g_slist_next(fts); @@ -1066,28 +977,22 @@ static void oscar_ask_sendfile(struct gaim_connection *gc, const char *destsn) { struct oscar_data *od = (struct oscar_data *)gc->proto_data; + struct gaim_xfer *xfer; + struct aim_oft_info *oft_info; + aim_conn_t *conn; /* You want to send a file to someone else, you're so generous */ - struct gaim_xfer *xfer; - struct oscar_xfer_data *xfer_data; - - /* Create the oscar-specific data */ - xfer_data = g_malloc0(sizeof(struct oscar_xfer_data)); - xfer_data->gc = gc; /* Build the file transfer handle */ xfer = gaim_xfer_new(gc->account, GAIM_XFER_SEND, destsn); - xfer_data->xfer = xfer; - xfer->data = xfer_data; - - /* Set the info about the incoming file */ - if (od && od->sess) { - aim_conn_t *conn; - if ((conn = aim_conn_findbygroup(od->sess, 0x0004))) - xfer->local_ip = gaim_getip_from_fd(conn->fd); - } + if ((conn = aim_conn_findbygroup(od->sess, 0x0004))) + xfer->local_ip = gaim_getip_from_fd(conn->fd); xfer->local_port = 5190; + /* Create the oscar-specific data */ + oft_info = aim_oft_createinfo(od->sess, NULL, destsn, xfer->local_ip, xfer->local_port, 0, 0, NULL); + xfer->data = oft_info; + /* Setup our I/O op functions */ gaim_xfer_set_init_fnc(xfer, oscar_xfer_init); gaim_xfer_set_start_fnc(xfer, oscar_xfer_start); @@ -1937,7 +1842,7 @@ struct gaim_connection *gc = sess->aux_data; struct oscar_data *od = (struct oscar_data *)gc->proto_data; struct gaim_xfer *xfer; - struct oscar_xfer_data *xfer_data; + struct aim_oft_info *oft_info; va_list ap; aim_conn_t *conn, *listenerconn; @@ -1950,22 +1855,22 @@ if (!(xfer = oscar_find_xfer_by_conn(od->file_transfers, listenerconn))) return 1; - if (!(xfer_data = xfer->data)) + if (!(oft_info = xfer->data)) return 1; /* Stop watching listener conn; watch transfer conn instead */ gaim_input_remove(xfer->watcher); aim_conn_kill(sess, &listenerconn); - xfer_data->conn = conn; - xfer->fd = xfer_data->conn->fd; - - aim_conn_addhandler(sess, xfer_data->conn, AIM_CB_FAM_OFT, AIM_CB_OFT_ACK, oscar_sendfile_ack, 0); - aim_conn_addhandler(sess, xfer_data->conn, AIM_CB_FAM_OFT, AIM_CB_OFT_DONE, oscar_sendfile_done, 0); - xfer->watcher = gaim_input_add(xfer_data->conn->fd, GAIM_INPUT_READ, oscar_callback, xfer_data->conn); + oft_info->conn = conn; + xfer->fd = oft_info->conn->fd; + + aim_conn_addhandler(sess, oft_info->conn, AIM_CB_FAM_OFT, AIM_CB_OFT_ACK, oscar_sendfile_ack, 0); + aim_conn_addhandler(sess, oft_info->conn, AIM_CB_FAM_OFT, AIM_CB_OFT_DONE, oscar_sendfile_done, 0); + xfer->watcher = gaim_input_add(oft_info->conn->fd, GAIM_INPUT_READ, oscar_callback, oft_info->conn); /* Inform the other user that we are connected and ready to transfer */ - aim_oft_sendheader(sess, xfer_data->conn, AIM_CB_OFT_PROMPT, NULL, xfer->filename, 0, 1, xfer->size, xfer->size, time(NULL), xfer_data->checksum, 0x02, 0, 0); + aim_oft_sendheader(sess, AIM_CB_OFT_PROMPT, oft_info); return 0; } @@ -1975,28 +1880,25 @@ * user in order to transfer a file. */ static void oscar_sendfile_connected(gpointer data, gint source, GaimInputCondition condition) { - struct gaim_connection *gc; struct gaim_xfer *xfer; - struct oscar_xfer_data *xfer_data; + struct aim_oft_info *oft_info; debug_printf("AAA - in oscar_sendfile_connected\n"); if (!(xfer = data)) return; - if (!(xfer_data = xfer->data)) - return; - if (!(gc = xfer_data->gc)) + if (!(oft_info = xfer->data)) return; if (source < 0) return; xfer->fd = source; - xfer_data->conn->fd = source; - - aim_conn_completeconnect(xfer_data->conn->sessv, xfer_data->conn); - xfer->watcher = gaim_input_add(xfer->fd, GAIM_INPUT_READ, oscar_callback, xfer_data->conn); + oft_info->conn->fd = source; + + aim_conn_completeconnect(oft_info->sess, oft_info->conn); + xfer->watcher = gaim_input_add(xfer->fd, GAIM_INPUT_READ, oscar_callback, oft_info->conn); /* Inform the other user that we are connected and ready to transfer */ - aim_im_sendch2_sendfile_accept(xfer_data->conn->sessv, xfer_data->cookie, xfer->who, AIM_CAPS_SENDFILE); + aim_im_sendch2_sendfile_accept(oft_info->sess, oft_info); return; } @@ -2011,7 +1913,7 @@ struct gaim_connection *gc = sess->aux_data; struct oscar_data *od = gc->proto_data; struct gaim_xfer *xfer; - struct oscar_xfer_data *xfer_data; + struct aim_oft_info *oft_info; va_list ap; aim_conn_t *conn; fu8_t *cookie; @@ -2027,19 +1929,21 @@ if (!(xfer = oscar_find_xfer_by_conn(od->file_transfers, conn))) return 1; - if (!(xfer_data = xfer->data)) + if (!(oft_info = xfer->data)) return 1; - /* Jot down some data we'll need later */ - xfer_data->modtime = fh->modtime; - xfer_data->checksum = fh->checksum; - /* We want to stop listening with a normal thingy */ gaim_input_remove(xfer->watcher); xfer->watcher = 0; + /* They sent us some information about the file they're sending */ + memcpy(&oft_info->fh, fh, sizeof(*fh)); + + /* Fill in the cookie */ + memcpy(&oft_info->fh.bcookie, oft_info->cookie, 8); + /* XXX - convert the name from UTF-8 to UCS-2 if necessary, and pass the encoding to the call below */ - aim_oft_sendheader(xfer_data->conn->sessv, xfer_data->conn, AIM_CB_OFT_ACK, xfer_data->cookie, xfer->filename, 0, 1, xfer->size, xfer->size, fh->modtime, fh->checksum, 0x02, 0, 0); + aim_oft_sendheader(oft_info->sess, AIM_CB_OFT_ACK, oft_info); gaim_xfer_start(xfer, xfer->fd, NULL, 0); return 0; @@ -2301,12 +2205,14 @@ if (args->status == AIM_RENDEZVOUS_PROPOSE) { /* Someone wants to send a file (or files) to us */ struct gaim_xfer *xfer; - struct oscar_xfer_data *xfer_data; - - if (!args->cookie || !args->verifiedip || !args->port || - !args->info.sendfile.filename || !args->info.sendfile.totsize || + struct aim_oft_info *oft_info; + + if (!args->cookie || !args->port || !args->verifiedip || + !args->info.sendfile.filename || !args->info.sendfile.totsize || !args->info.sendfile.totfiles || !args->reqclass) { debug_printf("%s tried to send you a file with incomplete information.\n", userinfo->sn); + if (args->proxyip) + debug_printf("IP for a proxy server was given. Gaim does not support this yet.\n"); return 1; } @@ -2320,27 +2226,20 @@ } } - /* Setup the oscar-specific transfer xfer_data */ - xfer_data = g_malloc0(sizeof(struct oscar_xfer_data)); - xfer_data->gc = gc; - memcpy(xfer_data->cookie, args->cookie, 8); - /* Build the file transfer handle */ xfer = gaim_xfer_new(gc->account, GAIM_XFER_RECEIVE, userinfo->sn); - xfer_data->xfer = xfer; - xfer->data = xfer_data; - - /* Set the info about the incoming file */ + xfer->remote_ip = g_strdup(args->clientip); + xfer->remote_port = args->port; gaim_xfer_set_filename(xfer, args->info.sendfile.filename); gaim_xfer_set_size(xfer, args->info.sendfile.totsize); - xfer->remote_port = args->port; - xfer->remote_ip = g_strdup(args->verifiedip); + + /* Create the oscar-specific data */ + oft_info = aim_oft_createinfo(od->sess, args->cookie, userinfo->sn, xfer->remote_ip, xfer->remote_port, 0, 0, NULL); if (args->proxyip) - xfer_data->proxyip = g_strdup(args->proxyip); - if (args->clientip) - xfer_data->clientip = g_strdup(args->clientip); + oft_info->proxyip = g_strdup(args->proxyip); if (args->verifiedip) - xfer_data->verifiedip = g_strdup(args->verifiedip); + oft_info->verifiedip = g_strdup(args->verifiedip); + xfer->data = oft_info; /* Setup our I/O op functions */ gaim_xfer_set_init_fnc(xfer, oscar_xfer_init); @@ -4703,12 +4602,12 @@ } else { struct group *g; buddy = gaim_buddy_new(gc->account, curitem->name, alias_utf8); - + if (!(g = gaim_find_group(gname_utf8 ? gname_utf8 : _("Orphans")))) { g = gaim_group_new(gname_utf8 ? gname_utf8 : _("Orphans")); gaim_blist_add_group(g, NULL); } - + debug_printf("ssi: adding buddy %s to group %s to local list\n", curitem->name, gname_utf8 ? gname_utf8 : _("Orphans")); gaim_blist_add_buddy(buddy, g, NULL); export = TRUE;