+ if ( (hdrlen = aim_recv(conn->fd, hdrbuf1, 6)) < 6) {
+ faimdprintf(2, "faim: rend: read error (fd: %i) %02x%02x%02x%02x%02x%02x (%i)\n",
+ conn->fd, hdrbuf1[0],hdrbuf1[1],hdrbuf1[2],hdrbuf1[3],hdrbuf1[4],hdrbuf1[5],hdrlen);
+ faim_mutex_unlock(&conn->active);
+ if(hdrlen < 0)
+ perror("read");
+ else { /* disconnected */
+ switch(conn->subtype) {
+ case AIM_CONN_SUBTYPE_OFT_DIRECTIM: {
+ /* XXX: clean up cookies here ? */
+ struct aim_directim_priv *priv = NULL;
+ if(!(priv = (struct aim_directim_priv *)conn->priv) )
+ return -1;
+
+ aim_uncachecookie(sess, priv->cookie, AIM_COOKIETYPE_OFTIM);
+ if ( (userfunc = aim_callhandler(conn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMDISCONNECT)) ) {
+ aim_conn_close(conn);
+ return userfunc(sess, NULL, conn, priv->sn);
+ }
+ break;
+ }
+ case AIM_CONN_SUBTYPE_OFT_GETFILE: {
+ struct aim_filetransfer_priv *priv;
+ if(!(priv = (struct aim_filetransfer_priv *)conn->priv))
+ return -1;
+ aim_uncachecookie(sess, priv->cookie, AIM_COOKIETYPE_OFTGET);
+ if ( (userfunc = aim_callhandler(conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILEDISCONNECT)) ) {
+ aim_conn_close(conn);
+ return userfunc(sess, NULL, conn, priv->sn);
+ }
+ break;
+ }
+ case AIM_CONN_SUBTYPE_OFT_SENDFILE: {
+ struct aim_filetransfer_priv *priv;
+ if(!(priv = (struct aim_filetransfer_priv *)conn->priv))
+ return -1;
+ aim_uncachecookie(sess, priv->cookie, AIM_COOKIETYPE_OFTSEND);
+ if ( (userfunc = aim_callhandler(conn, AIM_CB_FAM_OFT, AIM_CB_OFT_SENDFILEDISCONNECT)) ) {
+ aim_conn_close(conn);
+ return userfunc(sess, NULL, conn, priv->sn);
+ }
+ break;
+ }
+ }
+
+ aim_conn_close(conn);
+ return -1;
+ }
+ }
+
+ hdrlen = aimutil_get16(hdrbuf1+4);
+ hdrlen -= 6;
+
+ if (!(hdr = malloc(hdrlen))) {
+ faim_mutex_unlock(&conn->active);
+ return -1;
+ }
+
+ if (aim_recv(conn->fd, hdr, hdrlen) < hdrlen) {
+ perror("read");
+ faimdprintf(2,"faim: rend: read2 error on %d (%d)\n", conn->fd, hdrlen);
+ free(hdr);
+ faim_mutex_unlock(&conn->active);
+ aim_conn_close(conn);
+ return -1;
+ }
+ hdrtype = aimutil_get16(hdr);
+ printf("\tgot 0x%04x", hdrtype);
+ switch (hdrtype) {
+ case 0x0001: { /* directim */
+ int payloadlength = 0;
+ char *snptr = NULL;
+ struct aim_directim_priv *priv;
+ int i;
+
+ if(!(priv = (struct aim_directim_priv *)calloc(1, sizeof(struct aim_directim_priv)))) {
+ faim_mutex_unlock(&conn->active);
+ return -1;
+ }
+
+ payloadlength = aimutil_get32(hdr+22);
+ flags = aimutil_get16(hdr+32);
+ snptr = (char *)hdr+38;
+ strncpy(priv->sn, snptr, MAXSNLEN);
+
+ faimdprintf(2, "faim: OFT frame: %04x / %04x / %04x / %s\n", hdrtype, payloadlength, flags, snptr);
+
+ if (flags == 0x000e) {
+ faim_mutex_unlock(&conn->active);
+ if ( (userfunc = aim_callhandler(conn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMTYPING)) )
+ return userfunc(sess, NULL, snptr);
+ } else
+ if ((flags == 0x0000) && payloadlength) {
+ unsigned char *msg;
+ if(! (msg = calloc(1, payloadlength+1)) ) {
+ faim_mutex_unlock(&conn->active);
+ return -1;
+ }
+ if (aim_recv(conn->fd, msg, payloadlength) < payloadlength) {
+ perror("read");
+ printf("faim: rend: read3 error\n");
+ free(msg);
+ faim_mutex_unlock(&conn->active);
+ aim_conn_close(conn);
+ return -1;
+ }
+ faim_mutex_unlock(&conn->active);
+ msg[payloadlength] = 0x00;
+ faimdprintf(2, "faim: directim: %s/%04x/%04x/%s\n", snptr, payloadlength, flags, msg);
+ if ( (userfunc = aim_callhandler(conn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMINCOMING)) )
+ i = userfunc(sess, NULL, conn, snptr, msg);
+ free(msg);
+ return i;
+ }
+ break;
+ }
+ case 0x1108: { /* getfile listing.txt incoming tx->rx */
+ struct aim_filetransfer_priv *ft;
+ struct aim_fileheader_t *fh;
+ struct aim_msgcookie_t *cook;
+ struct command_tx_struct *newoft;
+ faimdprintf(2,"faim: rend: fileget 0x1108\n");
+ fh = aim_oft_getfh(hdr);
+ faim_mutex_unlock(&conn->active);
+ if(!(cook = aim_checkcookie(sess, fh->bcookie, AIM_COOKIETYPE_OFTGET))) {
+ faim_mutex_unlock(&conn->active);
+ free(fh);
+ return -1;
+ }
+ ft = cook->data;
+ ft->state = 2;
+
+ /* we're waaaaiiiting.. for listing.txt */
+
+ memcpy(&(ft->fh), fh, sizeof(struct aim_fileheader_t));
+ aim_cachecookie(sess, cook);
+ free(fh);
+
+ if(!(newoft = aim_tx_new(AIM_FRAMETYPE_OFT, 0x1209, conn, 0))) {
+ aim_conn_close(conn);
+ return -1;
+ }
+
+ memcpy(newoft->hdr.oft.magic, "OFT2", 4);
+ newoft->hdr.oft.hdr2len = 0x100 - 8;
+
+ if (!(newoft->hdr.oft.hdr2 = (char *)calloc(1,newoft->hdr.oft.hdr2len))) {
+ newoft->lock = 0;
+ aim_tx_destroy(newoft);
+ return -1;
+ }
+
+ if(!(aim_oft_buildheader((unsigned char *)newoft->hdr.oft.hdr2, &(ft->fh)))) {
+ newoft->lock = 0;
+ aim_tx_destroy(newoft);
+ return -1;
+ }
+
+ newoft->lock = 0;
+ aim_tx_enqueue(sess, newoft);
+ break;
+
+ }
+ case 0x1209: { /* get file listing ack rx->tx */
+ struct aim_filetransfer_priv *ft;
+ struct aim_fileheader_t *fh;
+ struct aim_msgcookie_t *cook;
+ int ret;
+
+ fh = aim_oft_getfh(hdr);
+ faim_mutex_unlock(&conn->active);
+
+ if(!(cook = aim_checkcookie(sess, fh->bcookie, AIM_COOKIETYPE_OFTGET)))
+ faimdprintf(2, "shit, no cookie in 0x1209. (%i/%s)going to crash..\n",
+ AIM_COOKIETYPE_OFTGET, fh->bcookie);
+
+ ft = cook->data;
+
+ if(ft->fh.size != fh->size)
+ faimdprintf(2, "hrm. ft->fh.size (%ld) != fh->size (%ld). um. using ft->fh.size\n",
+ ft->fh.size, fh->size);
+
+
+ if ( (userfunc = aim_callhandler(conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILELISTINGREQ)))
+ ret = userfunc(sess, NULL, conn, fh);
+
+ faimdprintf(2, "faim: get_command_rendezvous: hit end of 1209\n");
+
+ free(fh);
+
+ return ret;
+
+ break;
+ }
+ case 0x120b: { /* getfile listing.txt rx confirm */
+ struct aim_filetransfer_priv *ft;
+ struct aim_msgcookie_t *cook;
+ struct aim_fileheader_t *fh;
+
+ fh = aim_oft_getfh(hdr);
+ faim_mutex_unlock(&conn->active);
+
+ if(!(cook = aim_checkcookie(sess, fh->bcookie, AIM_COOKIETYPE_OFTGET))) {
+ free(fh);
+ return -1;
+ }
+
+ ft = cook->data;
+ aim_cachecookie(sess, cook);
+ free(fh);
+
+ /* XXX: call listing.txt rx confirm */
+ break;
+ }
+ case 0x120c: { /* getfile file request */
+ struct aim_filetransfer_priv *ft;
+ struct aim_msgcookie_t *cook;
+ struct aim_fileheader_t *fh;
+ struct command_tx_struct *newoft;
+ int i;
+
+ fh = aim_oft_getfh(hdr);
+ faim_mutex_unlock(&conn->active);