+ faimdprintf(sess, 0, "rend: badly damaged file get request from %s...\n", userinfo->sn);
+ aim_cookie_free(sess, cachedcook);
+
+ return 0;
+ }
+
+ snprintf(ip, 30, "%d.%d.%d.%d:%d",
+ aimutil_get8(iptlv->value+0),
+ aimutil_get8(iptlv->value+1),
+ aimutil_get8(iptlv->value+2),
+ aimutil_get8(iptlv->value+3),
+ aimutil_get16(porttlv->value));
+
+ if (aim_gettlv(list2, 0x000c, 1))
+ desc = aim_gettlv_str(list2, 0x000c, 1);
+
+ faimdprintf(sess, 0, "rend: file transfer request from %s: %s (%s)\n",
+ userinfo->sn, desc, ip);
+
+ memcpy(cachedcook->cookie, args->cookie, 8);
+
+ ft = malloc(sizeof(struct aim_filetransfer_priv)); /* XXX */
+ strncpy(ft->sn, userinfo.sn, sizeof(ft->sn));
+ strncpy(ft->ip, ip, sizeof(ft->ip));
+ strncpy(ft->fh.name, miscinfo->value+8, sizeof(ft->fh.name));
+ cachedcook->type = AIM_COOKIETYPE_OFTSEND;
+ cachedcook->data = ft;
+
+ if (aim_cachecookie(sess, cachedcook) == -1)
+ faimdprintf(sess, 0, "ERROR caching message cookie\n");
+
+ aim_accepttransfer(sess, rx->conn, ft->sn, cookie, AIM_CAPS_SENDFILE);
+
+ if (desc)
+ free(desc);
+
+ if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
+ ret = userfunc(sess, rx, 0x0002, userinfo, &args);
+#endif
+ return 0;
+}
+
+static int incomingim_ch2_imimage(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, aim_userinfo_t *userinfo, struct aim_incomingim_ch2_args *args, aim_tlvlist_t *list2)
+{
+ aim_rxcallback_t userfunc;
+ int ret = 0;
+
+ /* Primary IP address */
+ if (aim_gettlv(list2, 0x0003, 1)) {
+ aim_tlv_t *tlv;
+
+ tlv = aim_gettlv(list2, 0x0003, 1);
+
+ snprintf(args->info.imimage.ip, sizeof(args->info.imimage.ip),
+ "%d.%d.%d.%d:4443",
+ tlv->value[0],
+ tlv->value[1],
+ tlv->value[2],
+ tlv->value[3]);
+ }
+
+ /*
+ * Alternate IP address
+ *
+ * Sort of. The peer doesn't send this -- the OSCAR
+ * server does. So it will be the IP address that the
+ * peer is directly connected to the internet with, which
+ * may not be the same as the IP above. If these two
+ * values differ, it's rather unlikely that this
+ * rendezvous is going to happen...
+ *
+ */
+ if (aim_gettlv(list2, 0x0004, 1))
+ ;
+
+ /* Port number (not correct -- ignore) */
+ if (aim_gettlv(list2, 0x0005, 1))
+ ;
+
+ /* Unknown -- two bytes = 0x0001 */
+ if (aim_gettlv(list2, 0x000a, 1))
+ ;
+
+ /* Unknown -- no value */
+ if (aim_gettlv(list2, 0x000f, 1))
+ ;
+
+ faimdprintf(sess, 1, "rend: directIM request from %s (%s)\n", userinfo->sn, args->info.imimage.ip);
+
+ /*
+ * XXX: there are a couple of different request packets for
+ * different things
+ */
+
+ if ((userfunc = aim_callhandler(sess, rx->conn, snac->family, snac->subtype)))
+ ret = userfunc(sess, rx, 0x0002, userinfo, args);
+
+ return ret;
+}
+
+/* XXX Ugh. I think its obvious. */
+static int incomingim_ch2(aim_session_t *sess, aim_module_t *mod, aim_frame_t *rx, aim_modsnac_t *snac, fu16_t channel, aim_userinfo_t *userinfo, aim_tlvlist_t *tlvlist, fu8_t *cookie)
+{
+ aim_tlv_t *block1;
+ aim_tlvlist_t *list2;
+ int ret = 0;
+ struct aim_incomingim_ch2_args args;
+ aim_bstream_t bbs;
+ fu8_t *cookie2;
+
+ memset(&args, 0, sizeof(args));
+
+ /*
+ * There's another block of TLVs embedded in the type 5 here.
+ */
+ if (!(block1 = aim_gettlv(tlvlist, 0x0005, 1)) || !block1->value) {
+ faimdprintf(sess, 0, "no tlv 0x0005 in rendezvous transaction!\n");
+ return 0;
+ }
+
+ aim_bstream_init(&bbs, block1->value, block1->length);
+
+ /*
+ * First two bytes represent the status of the connection.
+ *
+ * 0 is a request, 2 is an accept
+ */
+ args.status = aimbs_get16(&bbs);