]> andersk Git - libfaim.git/blame - aim_ft.c
- Thu Dec 14 03:39:34 UTC 2000
[libfaim.git] / aim_ft.c
CommitLineData
7392c79f 1#include <faim/aim.h>
2
5ac21963 3#ifndef _WIN32
78b3fb13 4#include <netdb.h>
5#include <sys/socket.h>
6#include <netinet/in.h>
7392c79f 7#include <sys/utsname.h> /* for aim_directim_initiate */
8#include <arpa/inet.h> /* for inet_ntoa */
5ac21963 9#endif
7392c79f 10
11/* aim_msgcookies.c is mostly new. just look at the diff and replace yours, easiest. */
12
13/*
14 function name where i had it
15 aim_send_im_direct aim_im.c
16 aim_directim_initiate aim_im.c
17 aim_filetransfer_accept aim_im.c
18 aim_getlisting aim_misc.c (?!) -- prototype function. can be ignored.
19 establish aim_misc.c
78b3fb13 20 aim_get_command_rendezvous aim_r
7392c79f 21 oft_getfh aim_rxqueue.c
22*/
23
78b3fb13 24faim_export int aim_handlerendconnect(struct aim_session_t *sess, struct aim_conn_t *cur)
7392c79f 25{
26 int acceptfd = 0;
27 rxcallback_t userfunc;
28 struct sockaddr cliaddr;
29 socklen_t clilen = sizeof(cliaddr);
30 int ret = 0;
31
32 /*
33 * Listener sockets only have incoming connections. No data.
34 */
35 if( (acceptfd = accept(cur->fd, &cliaddr, &clilen)) == -1)
36 return -1;
37
38 if (cliaddr.sa_family != AF_INET) /* just in case IPv6 really is happening */
39 return -1;
40
41 switch(cur->subtype) {
42 case AIM_CONN_SUBTYPE_OFT_DIRECTIM: {
43 struct aim_directim_priv *priv;
44
45 priv = (struct aim_directim_priv *)calloc(1, sizeof(struct aim_directim_priv));
46
47 snprintf(priv->ip, sizeof(priv->ip), "%s:%u", inet_ntoa(((struct sockaddr_in *)&cliaddr)->sin_addr), ntohs(((struct sockaddr_in *)&cliaddr)->sin_port));
48
49 if(!cur->priv)
50 cur->priv = priv; /* what happens if there is one?! -- mid */
51
52 cur->type = AIM_CONN_TYPE_RENDEZVOUS;
53 close(cur->fd); /* should we really do this? seems like the client should decide. maybe clone the connection and keep the listener open. -- mid */
54 cur->fd = acceptfd;
55
56 if ( (userfunc = aim_callhandler(cur, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMINITIATE)))
57 ret = userfunc(sess, NULL, cur);
58
59 break;
60 }
61 case AIM_CONN_SUBTYPE_OFT_GETFILE: {
62 struct aim_filetransfer_priv *priv;
63
7392c79f 64 priv = (struct aim_filetransfer_priv *)calloc(1, sizeof(struct aim_filetransfer_priv));
65
66 snprintf(priv->ip, sizeof(priv->ip), "%s:%u", inet_ntoa(((struct sockaddr_in *)&cliaddr)->sin_addr), ntohs(((struct sockaddr_in *)&cliaddr)->sin_port));
67
68 if(!cur->priv)
69 cur->priv = priv;
70
71 if ( (userfunc = aim_callhandler(cur, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILEINITIATE)))
72 ret = userfunc(sess, NULL, cur);
73 break;
74 }
75 default: {
76 /* XXX */
77 }
78 }
79 return ret;
80}
81
82
83/*
84 * aim_send_im_direct:
85 * sess - session
86 * conn - directim connection
87 * msg - null-terminated string to send
88 */
89
78b3fb13 90faim_export int aim_send_im_direct(struct aim_session_t *sess,
91 struct aim_conn_t *conn,
92 char *msg)
7392c79f 93{
94 struct command_tx_struct *newpacket , *newpacket2;
95
96 /* newpacket contains a real header with data, newpacket2 is just a
97 null packet, with a cookie and a lot of 0x00s. newpacket is the
98 "i'm sending", newpacket2 is the "i'm typing".*/
99
100 /* uhm. the client should send those as two seperate things -- mid */
101
102 struct aim_directim_priv *priv = NULL;
103 int i;
104
871e2fd0 105 if (!sess || !conn || !(conn->type) || (conn->type != AIM_CONN_TYPE_RENDEZVOUS) || !conn->priv || !msg) {
7392c79f 106 printf("faim: directim: invalid arguments\n");
107 return -1;
108 };
109
871e2fd0 110 if (strlen(msg) >= MAXMSGLEN)
111 return -1;
112
7392c79f 113 priv = (struct aim_directim_priv *)conn->priv;
114
115 /* NULLish Header */
116
117 if (!(newpacket2 = aim_tx_new(AIM_FRAMETYPE_OFT, 0x0001, conn, 0))) {
118 printf("faim: directim: tx_new2 failed\n");
119 return -1;
120 }
121
122 newpacket2->lock = 1; /* lock struct */
123
124 memcpy(newpacket2->hdr.oft.magic, "ODC2", 4);
125 newpacket2->hdr.oft.hdr2len = 0x44;
126
127 if (!(newpacket2->hdr.oft.hdr2 = calloc(1,newpacket2->hdr.oft.hdr2len))) {
128 free(newpacket2);
129 return -1;
130 }
131
132 i = 0;
133 i += aimutil_put16(newpacket2->hdr.oft.hdr2+i, 0x0006);
134 i += aimutil_put16(newpacket2->hdr.oft.hdr2+i, 0x0000);
135
78b3fb13 136 i += aimutil_putstr(newpacket2->hdr.oft.hdr2+i, (char *)priv->cookie, 8);
7392c79f 137
138 i += aimutil_put16(newpacket2->hdr.oft.hdr2+i, 0x0000);
139 i += aimutil_put16(newpacket2->hdr.oft.hdr2+i, 0x0000);
140 i += aimutil_put16(newpacket2->hdr.oft.hdr2+i, 0x0000);
141 i += aimutil_put16(newpacket2->hdr.oft.hdr2+i, 0x0000);
142
143 i += aimutil_put32(newpacket2->hdr.oft.hdr2+i, 0x00000000);
144
145 i += aimutil_put16(newpacket2->hdr.oft.hdr2+i, 0x0000);
146 i += aimutil_put16(newpacket2->hdr.oft.hdr2+i, 0x0000);
147 i += aimutil_put16(newpacket2->hdr.oft.hdr2+i, 0x0000);
148
149 i += aimutil_put16(newpacket2->hdr.oft.hdr2+i, 0x000e);
150
151 i += aimutil_put16(newpacket2->hdr.oft.hdr2+i, 0x0000);
152 i += aimutil_put16(newpacket2->hdr.oft.hdr2+i, 0x0000);
153
68c5deb9 154 i += aimutil_putstr(newpacket2->hdr.oft.hdr2+i, sess->sn, strlen(sess->sn));
7392c79f 155
156 i = 52; /* 0x34 */
157 i += aimutil_put8(newpacket2->hdr.oft.hdr2+i, 0x00); /* 53 */
158 i += aimutil_put16(newpacket2->hdr.oft.hdr2+i, 0x0000); /* 55 */
159 i += aimutil_put16(newpacket2->hdr.oft.hdr2+i, 0x0000);
160 i += aimutil_put16(newpacket2->hdr.oft.hdr2+i, 0x0000);
161 i += aimutil_put16(newpacket2->hdr.oft.hdr2+i, 0x0000);/* 61 */
162 i += aimutil_put16(newpacket2->hdr.oft.hdr2+i, 0x0000);
163 i += aimutil_put16(newpacket2->hdr.oft.hdr2+i, 0x0000);/* 65 */
164 i += aimutil_put16(newpacket2->hdr.oft.hdr2+i, 0x0000);/* end of hdr2 */
165
166 newpacket2->lock = 0;
167 newpacket2->data = NULL;
168
169 aim_tx_enqueue(sess, newpacket2);
170
171 /* Header packet */
172
173 if (!(newpacket = aim_tx_new(AIM_FRAMETYPE_OFT, 0x0001, conn, strlen(msg)))) {
174 printf("faim: directim: tx_new failed\n");
175 return -1;
176 }
177
178 newpacket->lock = 1; /* lock struct */
179
180 memcpy(newpacket->hdr.oft.magic, "ODC2", 4);
181 newpacket->hdr.oft.hdr2len = 0x54;
182
183 if (!(newpacket->hdr.oft.hdr2 = calloc(1,newpacket->hdr.oft.hdr2len))) {
184 free(newpacket);
185 return -1;
186 }
187
188 i = 0;
189 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0006);
190 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0000);
191
78b3fb13 192 i += aimutil_putstr(newpacket->hdr.oft.hdr2+i, (char *)priv->cookie, 8);
7392c79f 193
194 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0000);
195 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0000);
196 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0000);
197 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0000);
198
199 i += aimutil_put32(newpacket->hdr.oft.hdr2+i, strlen(msg));
200
201 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0000);
202 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0000);
203 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0000);
204 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0000);
205 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0000);
206 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0000);
207
68c5deb9 208 i += aimutil_putstr(newpacket->hdr.oft.hdr2+i, sess->sn, strlen(sess->sn));
7392c79f 209
210 i = 52; /* 0x34 */
211 i += aimutil_put8(newpacket->hdr.oft.hdr2+i, 0x00); /* 53 */
212 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0000); /* 55 */
213 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0000);
214 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0000);
215 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0000);/* 61 */
216 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0000);
217 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0000);/* 65 */
218 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0000);/* end of hdr2 */
219
220 /* values grabbed from a dump */
221 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0008); /* 69 */
222 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x000c);
223 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0000);/* 71 */
224 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x1466);/* 73 */
225 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0001);/* 73 */
226 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x2e0f);
227 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x393e);
228 i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0xcac8);
229
230 memcpy(newpacket->data, msg, strlen(msg));
231
232 newpacket->lock = 0;
233
234 aim_tx_enqueue(sess, newpacket);
235
236 return 0;
237}
238
239/*
240 * aim_directim_intitiate:
241 * For those times when we want to open up the directim channel ourselves.
242 * sess is your session,
243 * conn is the BOS conn,
244 * priv is a dummy priv value (we'll let it get filled in later) (if
245 * you pass a NULL, we alloc one)
246 * destsn is the SN to connect to.
247 */
248
249
78b3fb13 250faim_export struct aim_conn_t *aim_directim_initiate(struct aim_session_t *sess,
251 struct aim_conn_t *conn,
252 struct aim_directim_priv *priv,
253 char *destsn)
7392c79f 254{
255 struct command_tx_struct *newpacket;
256 struct aim_conn_t *newconn;
257
258 struct aim_msgcookie_t *cookie;
259
260 int curbyte, i, listenfd;
261 short port = 4443;
262
263 struct hostent *hptr;
5ac21963 264 char localhost[129];
7392c79f 265
78b3fb13 266 unsigned char cap[16];
7392c79f 267 char d[4]; /* XXX: IPv6. *cough* */
268
269 /*
270 * Open our socket
271 */
272
273 if( (listenfd = aim_listenestablish(port)) == -1)
274 return NULL;
275
276 /*
277 * get our local IP
278 */
279
5ac21963 280 if(gethostname(localhost, 128) < 0)
7392c79f 281 return NULL;
282
5ac21963 283 if( (hptr = gethostbyname(localhost)) == NULL)
7392c79f 284 return NULL;
285
286 memcpy(&d, hptr->h_addr_list[0], 4); /* XXX: this probably isn't quite kosher, but it works */
287
288 aim_putcap(cap, 16, AIM_CAPS_IMIMAGE);
289
290 /*
291 * create the OSCAR packet
292 */
293
294 if (!(newpacket = aim_tx_new(AIM_FRAMETYPE_OSCAR, 0x0002, conn, 10+8+2+1+strlen(destsn)+4+4+0x32)))
295 return NULL;
296
297 newpacket->lock = 1; /* lock struct */
298
299 curbyte = 0;
300 curbyte += aim_putsnac(newpacket->data+curbyte,
301 0x0004, 0x0006, 0x0000, sess->snac_nextid);
302
303 /*
304 * Generate a random message cookie
305 * This cookie needs to be alphanumeric and NULL-terminated to be TOC-compatible.
306 */
307 for (i=0;i<7;i++)
5ac21963 308 curbyte += aimutil_put8(newpacket->data+curbyte, 0x30 + ((u_char) rand() % 20));
7392c79f 309 curbyte += aimutil_put8(newpacket->data+curbyte, 0x00);
310
311 /*
312 * grab all the data for cookie caching.
313 */
314 cookie = (struct aim_msgcookie_t *)calloc(1, sizeof(struct aim_msgcookie_t));
315
316 memcpy(cookie->cookie, newpacket->data+curbyte-8, 8);
317 cookie->type = AIM_COOKIETYPE_OFTIM;
318
319 if(!priv)
320 priv = (struct aim_directim_priv *)calloc(1, sizeof(struct aim_directim_priv));
321
322 memcpy(priv->cookie, cookie, 8);
323 memcpy(priv->sn, destsn, sizeof(priv->sn));
324
325 cookie->data = priv;
326
327 aim_cachecookie(sess, cookie); /* cache da cookie */
328
329 /*
330 * Channel ID
331 */
332 curbyte += aimutil_put16(newpacket->data+curbyte,0x0002);
333
334 /*
335 * Destination SN (prepended with byte length)
336 */
337 curbyte += aimutil_put8(newpacket->data+curbyte,strlen(destsn));
338 curbyte += aimutil_putstr(newpacket->data+curbyte, destsn, strlen(destsn));
339
340 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0003);
341 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0000);
342
343 /*
344 * enTLV start
345 */
346 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0005);
347 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0032);
348
349 /*
350 * Flag data / ICBM Parameters?
351 */
352 curbyte += aimutil_put8(newpacket->data+curbyte, 0x00);
353 curbyte += aimutil_put8(newpacket->data+curbyte, 0x00);
354
355 /*
356 * Cookie
357 */
358 curbyte += aimutil_putstr(newpacket->data+curbyte, (char *)cookie, 8);
359
360 /*
361 * Capability String
362 */
363 curbyte += aimutil_putstr(newpacket->data+curbyte, (char *)cap, 0x10);
364
365 /*
366 * 000a/0002 : 0001
367 */
368 curbyte += aimutil_put16(newpacket->data+curbyte, 0x000a);
369 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0002);
370 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0001);
371
372 /*
373 * 0003/0004: IP address
374 */
375
376 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0003);
377 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0004);
378
379 for(i = 0; i < 4; i++)
380 curbyte += aimutil_put8(newpacket->data+curbyte, d[i]); /* already in network byte order */
381
382 /*
383 * 0005/0002: Port
384 */
385
386 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0005);
387 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0002);
388 curbyte += aimutil_put16(newpacket->data+curbyte, port);
389
390 /*
391 * 000f/0000: umm.. dunno. Zigamorph[1]?
392 * [1]: see esr's TNHD.
393 */
394
395 curbyte += aimutil_put16(newpacket->data+curbyte, 0x000f);
396 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0000);
397
398 printf("curbyte: 0x%x\n",curbyte);
399
400 newpacket->commandlen = curbyte;
401 newpacket->lock = 0;
402
403 aim_tx_enqueue(sess, newpacket);
404
405 /*
406 * allocate and set up our connection
407 */
408
7392c79f 409 newconn = aim_newconn(sess, AIM_CONN_TYPE_RENDEZVOUS_OUT, NULL);
410 if (!newconn) {
411 perror("aim_newconn");
412 aim_conn_kill(sess, &newconn);
413 return NULL;
414 }
415
416 newconn->fd = listenfd;
417 newconn->subtype = AIM_CONN_SUBTYPE_OFT_DIRECTIM;
418 newconn->priv = priv;
419 printf("faim: listening (fd = %d, unconnected)\n", newconn->fd);
420
421 /*
422 * XXX We need some way of closing the listener socket after
423 * n seconds of no connection. -- mid
424 */
425
7392c79f 426 return (newconn);
427}
428
871e2fd0 429/*
430 * struct aim_conn_t *aim_directim_connect(struct aim_session_t *sess, struct aim_conn_t *conn, struct aim_directim_priv *priv)
431 * sess is the session to append the conn to,
432 * conn is the BOS connection,
433 * priv is the filled-in priv data structure for the connection
434 * returns conn if connected, NULL on error
435 */
436
7392c79f 437
78b3fb13 438faim_export struct aim_conn_t *aim_directim_connect(struct aim_session_t *sess,
439 struct aim_conn_t *conn,
440 struct aim_directim_priv *priv )
7392c79f 441{
442 struct aim_conn_t *newconn = NULL;;
443
444 newconn = aim_newconn(sess, AIM_CONN_TYPE_RENDEZVOUS, priv->ip);
445 if (!newconn || (newconn->fd == -1)) {
446 printf("could not connect to %s\n", priv->ip);
447 perror("aim_newconn");
448 aim_conn_kill(sess, &newconn);
449 return NULL;
450 } else {
451 newconn->subtype = AIM_CONN_SUBTYPE_OFT_DIRECTIM;
452 newconn->priv = priv;
453 printf("faim: connected to peer (fd = %d)\n", newconn->fd);
454 return newconn;
455 }
456 return newconn;
457}
458
871e2fd0 459/*
460 * struct aim_conn_t *aim_directim_getconn(struct aim_session_t *sess, const char *name)
461 * sess is your session,
462 * name is the name to get,
463 * returns conn for directim with name, NULL if none found.
464 */
465
466faim_export struct aim_conn_t *aim_directim_getconn(struct aim_session_t *sess, const char *name)
467{
468 struct aim_conn_t *cur;
469 struct aim_directim_priv *priv;
470
471 faim_mutex_lock(&sess->connlistlock);
472 for (cur = sess->connlist; cur; cur = cur->next) {
473 if (cur->type != AIM_CONN_TYPE_RENDEZVOUS || cur->subtype != AIM_CONN_SUBTYPE_OFT_DIRECTIM)
474 continue;
475
476 priv = cur->priv;
477 if (aim_sncmp(priv->sn, name) == 0)
478 break;
479 }
480 faim_mutex_unlock(&sess->connlistlock);
481
482 return cur;
483}
484
485/*
486 * aim_accepttransfer:
487 * accept a file transfer request.
488 * sess is the session,
489 * conn is the BOS conn for the CAP reply
490 * sn is the screenname to send it to,
491 * cookie is the cookie used
492 * ip is the ip to connect to
493 * file is the listing file to use
494 * rendid is CAP type
495 *
496 * returns connection
497 */
498
499faim_export struct aim_conn_t *aim_accepttransfer(struct aim_session_t *sess,
500 struct aim_conn_t *conn,
501 char *sn,
502 char *cookie,
503 char *ip,
504 FILE *file,
505 unsigned short rendid)
7392c79f 506{
507 struct command_tx_struct *newpacket, *newoft;
871e2fd0 508
509 struct aim_conn_t *newconn;
7392c79f 510 struct aim_fileheader_t *listingfh;
871e2fd0 511 struct aim_filetransfer_priv *priv;
512 struct aim_msgcookie_t *cachedcook;
513
7392c79f 514 int curbyte, i;
7392c79f 515
516 if(rendid == AIM_CAPS_GETFILE) {
871e2fd0 517
518 newconn = aim_newconn(sess, AIM_CONN_TYPE_RENDEZVOUS, ip);
7392c79f 519
871e2fd0 520 newconn->subtype = AIM_CONN_SUBTYPE_OFT_GETFILE;
7392c79f 521
871e2fd0 522 if (!newconn || (newconn->fd == -1)) {
523 perror("aim_newconn");
524 faimdprintf(2, "could not connect to %s (fd: %i)\n", ip, newconn?newconn->fd:0);
525 aim_conn_kill(sess, &newconn);
526 return NULL;
527 } else {
528 priv = (struct aim_filetransfer_priv *)calloc(1, sizeof(struct aim_filetransfer_priv));
529 memcpy(priv->cookie, cookie, 8);
530 strncpy(priv->sn, sn, MAXSNLEN);
531 strncpy(priv->ip, ip, sizeof(priv->ip));
532 newconn->priv = (void *)priv;
533 faimdprintf(2, "faim: connected to peer (fd = %d)\n", newconn->fd);
534 }
535
536 /* cache da cookie. COOOOOKIES! */
7392c79f 537
871e2fd0 538 if(!(cachedcook = (struct aim_msgcookie_t *)calloc(1, sizeof(struct aim_msgcookie_t)))) {
539 faimdprintf(1, "faim: accepttransfer: couldn't calloc cachedcook. yeep!\n");
540 /* XXX die here, or go on? search for cachedcook for future references */
541 }
7392c79f 542
871e2fd0 543 if(cachedcook)
544 memcpy(cachedcook->cookie, cookie, 8);
545
546 /* strncpy(ft->fh.name, miscinfo->value+8, sizeof(ft->fh.name)); */
7392c79f 547
871e2fd0 548 if(cachedcook) { /* see above calloc of cachedcook */
549 cachedcook->type = AIM_COOKIETYPE_OFTGET;
550 cachedcook->data = (void *)priv;
551
552 if (aim_cachecookie(sess, cachedcook) != 0)
553 faimdprintf(1, "faim: ERROR caching message cookie\n");
554 }
555
556 if(rendid == AIM_CAPS_GETFILE) {
557 faimdprintf(2, "faim: getfile request accept\n");
558 if(!(newoft = aim_tx_new(AIM_FRAMETYPE_OFT, 0x1108, newconn, 0))) {
559 faimdprintf(2, "faim: aim_accepttransfer: tx_new OFT failed\n");
560 /* XXX: what else do we need to clean up here? */
561 return NULL;
562 }
563
564 newoft->lock = 1;
7392c79f 565
871e2fd0 566 memcpy(newoft->hdr.oft.magic, "OFT2", 4);
567 newoft->hdr.oft.hdr2len = 0xf8; /* 0x100 - 8 */
7392c79f 568
871e2fd0 569 if(!(listingfh = aim_getlisting(file))) {
570 return NULL;
571 }
7392c79f 572
871e2fd0 573 if (!(newoft->hdr.oft.hdr2 = (char *)calloc(1,newoft->hdr.oft.hdr2len))) {
574 free(newoft);
575 return NULL;
576 }
7392c79f 577
871e2fd0 578 memcpy(listingfh->bcookie, cookie, 8);
7392c79f 579
871e2fd0 580 aim_oft_buildheader((void *)newoft->hdr.oft.hdr2, listingfh);
7392c79f 581
871e2fd0 582 free(listingfh);
583
584 newoft->lock = 0;
585 aim_tx_enqueue(sess, newoft);
586 printf("faim: getfile: OFT listing enqueued.\n");
7392c79f 587
871e2fd0 588 }
7392c79f 589
871e2fd0 590 /* OSCAR CAP accept packet */
7392c79f 591
871e2fd0 592 if(!(newpacket = aim_tx_new(AIM_FRAMETYPE_OSCAR, 0x0002, conn, 10+8+2+1+strlen(sn)+4+2+8+16)))
593 return NULL;
7392c79f 594
871e2fd0 595 newpacket->lock = 1;
7392c79f 596
871e2fd0 597 curbyte = aim_putsnac(newpacket->data, 0x0004, 0x0006, 0x0000, sess->snac_nextid);
598 for (i = 0; i < 8; i++)
599 curbyte += aimutil_put8(newpacket->data+curbyte, cookie[i]);
600 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0002);
601 curbyte += aimutil_put8(newpacket->data+curbyte, strlen(sn));
602 curbyte += aimutil_putstr(newpacket->data+curbyte, sn, strlen(sn));
603 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0005);
604 curbyte += aimutil_put16(newpacket->data+curbyte, 0x001a);
605 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0002 /* accept */);
606 for (i = 0; i < 8; i++)
607 curbyte += aimutil_put8(newpacket->data+curbyte, cookie[i]);
608 curbyte += aim_putcap(newpacket->data+curbyte, 0x10, rendid);
609
610 newpacket->lock = 0;
611 aim_tx_enqueue(sess, newpacket);
7392c79f 612
871e2fd0 613 return newconn;
614 }
615 return NULL;
7392c79f 616}
617
618/*
871e2fd0 619 * aim_getlisting(FILE *file)
7392c79f 620 *
871e2fd0 621 * file is an opened listing file
622 * returns a pointer to the filled-in fileheader_t
623 *
624 * currently omits checksum. we'll fix this when AOL breaks us, i
625 * guess.
626 *
7392c79f 627 */
628
871e2fd0 629faim_internal struct aim_fileheader_t *aim_getlisting(FILE *file)
7392c79f 630{
631 struct aim_fileheader_t *fh;
871e2fd0 632 u_long totsize = 0, size = 0, checksum = 0xffff0000;
633 short totfiles = 0;
634 char *linebuf, sizebuf[9];
635
636 int linelength = 1024;
637
638 /* XXX: if we have a line longer than 1024chars, God help us. */
639 if( (linebuf = (char *)calloc(1, linelength)) == NULL ) {
640 faimdprintf(2, "linebuf calloc failed\n");
641 return NULL;
642 }
643
644 if(fseek(file, 0, SEEK_END) == -1) { /* use this for sanity check */
645 perror("getlisting END1 fseek:");
646 faimdprintf(2, "getlising fseek END1 error\n");
647 }
648
649 if(fgetpos(file, &size) == -1) {
650 perror("getlisting END1 getpos:");
651 faimdprintf(2, "getlising getpos END1 error\n");
652 }
653
654 if(fseek(file, 0, SEEK_SET) != 0) {
655 perror("getlesting fseek(SET):");
656 faimdprintf(2, "faim: getlisting: couldn't seek to beginning of listing file\n");
657 }
658
659 bzero(linebuf, linelength);
660
661 size = 0;
662
663 while(fgets(linebuf, linelength, file)) {
664 totfiles++;
665 bzero(sizebuf, 9);
666
667 size += strlen(linebuf);
668
669 if(strlen(linebuf) < 23) {
670 faimdprintf(2, "line \"%s\" too short. skipping\n", linebuf);
671 continue;
672 }
673 if(linebuf[strlen(linebuf)-1] != '\n') {
674 faimdprintf(2, "faim: OFT: getlisting -- hit EOF or line too long!\n");
675 }
676
677 memcpy(sizebuf, linebuf+17, 8);
678
679 totsize += strtol(sizebuf, NULL, 10);
680 bzero(linebuf, linelength);
681 }
682
683 /* if(size != 0) {
684 faimdprintf(2, "faim: getlisting: size != 0 after while.. %i\n", size);
685 }*/
686
687 if(fseek(file, 0, SEEK_SET) == -1) {
688 perror("getlisting END2 fseek:");
689 faimdprintf(2, "getlising fseek END2 error\n");
690 }
691
692 free(linebuf);
693
694 /* we're going to ignore checksumming the data for now -- that
695 * requires walking the whole listing.txt. it should probably be
696 * done at register time and cached, but, eh. */
7392c79f 697
698 if(!(fh = (struct aim_fileheader_t*)calloc(1, sizeof(struct aim_fileheader_t))))
699 return NULL;
700
871e2fd0 701 printf( "faim: OFT: getlisting: totfiles: %u, totsize: %lu, size: %lu\n", totfiles, totsize, size);
702
7392c79f 703 fh->encrypt = 0x0000;
871e2fd0 704 fh->compress = 0x0000;
705 fh->totfiles = totfiles;
706 fh->filesleft = totfiles; /* is this right ?*/
7392c79f 707 fh->totparts = 0x0001;
708 fh->partsleft = 0x0001;
871e2fd0 709 fh->totsize = totsize;
710 fh->size = size; /* ls -l listing.txt */
711 fh->modtime = (int)time(NULL); /* we'll go with current time for now */
712 fh->checksum = checksum; /* XXX: checksum ! */
7392c79f 713 fh->rfcsum = 0x00000000;
714 fh->rfsize = 0x00000000;
715 fh->cretime = 0x00000000;
716 fh->rfcsum = 0x00000000;
717 fh->nrecvd = 0x00000000;
718 fh->recvcsum = 0x00000000;
719
871e2fd0 720 /* memset(fh->idstring, 0, sizeof(fh->idstring)); */
721 memcpy(fh->idstring, "OFT_Windows ICBMFT V1.1 32", sizeof(fh->idstring));
722 memset(fh->idstring+strlen(fh->idstring), 0, sizeof(fh->idstring)-strlen(fh->idstring));
7392c79f 723
724 fh->flags = 0x02;
725 fh->lnameoffset = 0x1a;
726 fh->lsizeoffset = 0x10;
727
871e2fd0 728 /* memset(fh->dummy, 0, sizeof(fh->dummy)); */
729 memset(fh->macfileinfo, 0, sizeof(fh->macfileinfo));
7392c79f 730
871e2fd0 731 fh->nencode = 0x0000; /* we need to figure out these encodings for filenames */
7392c79f 732 fh->nlanguage = 0x0000;
733
871e2fd0 734 /* memset(fh->name, 0, sizeof(fh->name)); */
735 memcpy(fh->name, "listing.txt", sizeof(fh->name));
736 memset(fh->name+strlen(fh->name), 0, 64-strlen(fh->name));
7392c79f 737
871e2fd0 738 faimdprintf(2, "faim: OFT: listing fh name %s / %s\n", fh->name, (fh->name+(strlen(fh->name))));
7392c79f 739 return fh;
740}
741
742/*
743 * establish: create a listening socket on a port. you need to call
744 * accept() when it's connected.
745 * portnum is the port number to bind to.
746 * returns your fd
747 */
748
78b3fb13 749faim_internal int aim_listenestablish(u_short portnum)
7392c79f 750{
5ac21963 751#if defined(__linux__) /* XXX what other OS's support getaddrinfo? */
7392c79f 752 int listenfd;
753 const int on = 1;
754 struct addrinfo hints, *res, *ressave;
755 char serv[5];
756 sprintf(serv, "%d", portnum);
757 memset(&hints, 0, sizeof(struct addrinfo));
758 hints.ai_flags = AI_PASSIVE;
759 hints.ai_family = AF_UNSPEC;
760 hints.ai_socktype = SOCK_STREAM;
761 if (getaddrinfo(NULL/*any IP*/, serv, &hints, &res) != 0) {
762 perror("getaddrinfo");
763 return -1;
764 }
765 ressave = res;
766 do {
767 listenfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
768 if (listenfd < 0)
769 continue;
770 setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
771 if (bind(listenfd, res->ai_addr, res->ai_addrlen) == 0)
772 break; /* success */
773 close(listenfd);
774 } while ( (res = res->ai_next) );
775 if (!res)
776 return -1;
777 if (listen(listenfd, 1024)!=0) {
778 perror("listen");
779 return -1;
780 }
781 freeaddrinfo(ressave);
782 return listenfd;
5ac21963 783#else
784 int listenfd;
785 const int on = 1;
786 struct sockaddr_in sockin;
787
5aab5195 788 if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
5ac21963 789 perror("socket(listenfd)");
790 return -1;
791 }
792 if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on) != 0)) {
793 perror("setsockopt(listenfd)");
794 close(listenfd);
795 return -1;
796 }
797 memset(&sockin, 0, sizeof(struct sockaddr_in));
798 sockin.sin_family = AF_INET;
799 sockin.sin_port = htons(portnum);
800 if (bind(listenfd, (struct sockaddr *)&sockin, sizeof(struct sockaddr_in)) != 0) {
801 perror("bind(listenfd)");
802 close(listenfd);
803 return -1;
804 }
805 if (listen(listenfd, 4) != 0) {
806 perror("listen(listenfd)");
807 close(listenfd);
808 return -1;
809 }
810
811 return listenfd;
5ac21963 812#endif
7392c79f 813}
814
78b3fb13 815faim_internal int aim_get_command_rendezvous(struct aim_session_t *sess, struct aim_conn_t *conn)
7392c79f 816{
7392c79f 817 unsigned char hdrbuf1[6];
818 unsigned char *hdr = NULL;
819 int hdrlen, hdrtype;
820 int flags = 0;
821 rxcallback_t userfunc = NULL;
822
823
824 memset(hdrbuf1, 0, sizeof(hdrbuf1));
825
4dd56961 826 faim_mutex_lock(&conn->active); /* gets locked down for the entirety */
827
5ac21963 828 if ( (hdrlen = aim_recv(conn->fd, hdrbuf1, 6)) < 6) {
871e2fd0 829
830 faimdprintf(2, "faim: rend: read error (fd: %i) %02x%02x%02x%02x%02x%02x (%i)\n", conn->fd, hdrbuf1[0],hdrbuf1[1],hdrbuf1[0],hdrbuf1[0],hdrbuf1[0],hdrbuf1[0],hdrlen);
4dd56961 831 faim_mutex_unlock(&conn->active);
871e2fd0 832
833 if(hdrlen < 0)
834 perror("read");
835 else { /* disconnected */
871e2fd0 836 switch(conn->subtype) {
837 case AIM_CONN_SUBTYPE_OFT_DIRECTIM: { /* XXX: clean up cookies here ? */
3b101546 838 struct aim_directim_priv *priv = NULL;
839 if(!(priv = (struct aim_directim_priv *)conn->priv) )
871e2fd0 840 return -1; /* not much we can do */
3b101546 841 aim_uncachecookie(sess, priv->cookie, AIM_COOKIETYPE_OFTIM);
871e2fd0 842
3b101546 843
844 if ( (userfunc = aim_callhandler(conn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMDISCONNECT)) ) {
845 aim_conn_close(conn);
846 return userfunc(sess, NULL, conn, priv->sn);
847 }
871e2fd0 848
3b101546 849 break;
871e2fd0 850 }
3b101546 851
871e2fd0 852 case AIM_CONN_SUBTYPE_OFT_GETFILE: {
853 struct aim_filetransfer_priv *priv;
854 if(!(priv = (struct aim_filetransfer_priv *)conn->priv))
855 return -1;
856
871e2fd0 857 aim_uncachecookie(sess, priv->cookie, AIM_COOKIETYPE_OFTGET);
3b101546 858
859 if ( (userfunc = aim_callhandler(conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILEDISCONNECT)) ) {
860 aim_conn_close(conn);
861 return userfunc(sess, NULL, conn, priv->sn);
862 }
863
864 break;
871e2fd0 865 }
3b101546 866
871e2fd0 867 case AIM_CONN_SUBTYPE_OFT_SENDFILE: {
868 struct aim_filetransfer_priv *priv;
869 if(!(priv = (struct aim_filetransfer_priv *)conn->priv))
870 return -1;
871
3b101546 872 aim_uncachecookie(sess, priv->cookie, AIM_COOKIETYPE_OFTSEND);
871e2fd0 873
3b101546 874 if ( (userfunc = aim_callhandler(conn, AIM_CB_FAM_OFT, AIM_CB_OFT_SENDFILEDISCONNECT)) ) {
875 aim_conn_close(conn);
876 return userfunc(sess, NULL, conn, priv->sn);
877 }
871e2fd0 878
3b101546 879 break;
871e2fd0 880 }
881 }
882
3b101546 883 aim_conn_close(conn);
884 aim_conn_kill(sess, &conn);
885
886 return -1;
871e2fd0 887 }
7392c79f 888 }
889
890 hdrlen = aimutil_get16(hdrbuf1+4);
891
892 hdrlen -= 6;
871e2fd0 893 if (!(hdr = malloc(hdrlen))) {
894 faim_mutex_unlock(&conn->active);
7392c79f 895 return -1;
871e2fd0 896 }
7392c79f 897
5ac21963 898 if (aim_recv(conn->fd, hdr, hdrlen) < hdrlen) {
7392c79f 899 perror("read");
871e2fd0 900 faimdprintf(2,"faim: rend: read2 error\n");
7392c79f 901 free(hdr);
4dd56961 902 faim_mutex_unlock(&conn->active);
1a8c261b 903 aim_conn_close(conn);
871e2fd0 904 return -1;
7392c79f 905 }
906
7392c79f 907 hdrtype = aimutil_get16(hdr);
908
909 switch (hdrtype) {
910 case 0x0001: { /* directim */
911 int payloadlength = 0;
912 char *snptr = NULL;
913 struct aim_directim_priv *priv;
914 int i;
915
916 priv = (struct aim_directim_priv *)calloc(1, sizeof(struct aim_directim_priv));
917
918 payloadlength = aimutil_get32(hdr+22);
919 flags = aimutil_get16(hdr+32);
78b3fb13 920 snptr = (char *)hdr+38;
7392c79f 921
922 strncpy(priv->sn, snptr, MAXSNLEN);
923
871e2fd0 924 faimdprintf(2, "faim: OFT frame: %04x / %04x / %04x / %s\n", hdrtype, payloadlength, flags, snptr);
7392c79f 925
926 if (flags == 0x000e) {
4dd56961 927 faim_mutex_unlock(&conn->active);
7392c79f 928 if ( (userfunc = aim_callhandler(conn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMTYPING)) )
929 return userfunc(sess, NULL, snptr);
930 } else if ((flags == 0x0000) && payloadlength) {
931 unsigned char *msg;
4dd56961 932
933 if(! (msg = calloc(1, payloadlength+1)) ) {
934 faim_mutex_unlock(&conn->active);
871e2fd0 935 return -1;
4dd56961 936 }
7392c79f 937
5ac21963 938 if (aim_recv(conn->fd, msg, payloadlength) < payloadlength) {
7392c79f 939 perror("read");
940 printf("faim: rend: read3 error\n");
941 free(msg);
4dd56961 942 faim_mutex_unlock(&conn->active);
1a8c261b 943 aim_conn_close(conn);
944 return -1;
7392c79f 945 }
4dd56961 946 faim_mutex_unlock(&conn->active);
7392c79f 947 msg[payloadlength] = '\0';
871e2fd0 948 faimdprintf(2, "faim: directim: %s/%04x/%04x/%s\n", snptr, payloadlength, flags, msg);
949
7392c79f 950
951 if ( (userfunc = aim_callhandler(conn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMINCOMING)) )
952 i = userfunc(sess, NULL, conn, snptr, msg);
953
954 free(msg);
955 return i;
956 }
957 break;
871e2fd0 958 }
959#if 0
960 /* currently experimental to a non-compiling degree */
961 case 0x1108: { /* getfile listing.txt incoming tx->rx */
7392c79f 962 struct aim_filetransfer_priv *ft;
963 struct aim_fileheader_t *fh;
964 struct aim_msgcookie_t *cook;
871e2fd0 965 struct aim_conn_type *newoft;
7392c79f 966
7392c79f 967 int commandlen;
968 char *data;
969
871e2fd0 970 faimdprintf(2,"faim: rend: fileget 0x1108\n");
971
972 if(!(ft = (struct aim_filetransfer_priv *)calloc(1, sizeof(struct aim_filetransfer_priv)))) {
973 faimdprintf(2, "faim: couldn't malloc ft. um. bad. bad bad. file transfer will likely fail, sorry.\n");
974 faim_mutex_unlock(&conn->active);
975 return -1;
976 }
7392c79f 977
871e2fd0 978 ft->state = 1; /* we're waaaaiiiting.. */
979
980 fh = aim_oft_getfh(hdr);
981
982 memcpy(&(ft->fh), fh, sizeof(struct aim_fileheader_t));
7392c79f 983
871e2fd0 984 if(!(cook = aim_checkcookie(sess, ft->fh.bcookie, AIM_COOKIETYPE_OFTGET))) {
985 faim_mutex_unlock(&conn->active);
986 return -1;
987 }
988
989 if(cook->data)
990 free(cook->data);
991
992 cook->data = ft;
993
994 aim_cachecookie(sess, cook);
995
996 if(!(newoft = aim_tx_new(AIM_FRAMETYPE_OFT, 0x1209, conn, 0))) {
997 /* XXX: what else do we need to clean up here? */
998 faim_mutex_unlock(&conn->active);
999 return -1;
1000 }
1001
1002
1003 aim_oft_buildheader((void *)newoft->hdr.oft.hdr2, ft->fh); /* no change */
1004 newoft->lock = 0;
1005 aim_tx_enqueue(sess, newoft);
1006 break;
1007 }
1008#endif
1009 case 0x1209: { /* get file listing ack rx->tx */
1010 struct aim_filetransfer_priv *ft;
1011 struct aim_fileheader_t *fh;
1012 struct aim_msgcookie_t *cook;
1013
1014 int commandlen;
1015 char *data;
1016
1017 faimdprintf(2,"faim: rend: fileget 0x1209\n");
1018
7392c79f 1019 if(!(ft = (struct aim_filetransfer_priv *)calloc(1, sizeof(struct aim_filetransfer_priv)))) {
871e2fd0 1020 faimdprintf(2, "faim: couldn't malloc ft. um. bad. bad bad. file transfer will likely fail, sorry.\n");
4dd56961 1021 faim_mutex_unlock(&conn->active);
871e2fd0 1022 return -1;
7392c79f 1023 }
1024
1025 fh = aim_oft_getfh(hdr);
1026
1027 memcpy(&(ft->fh), fh, sizeof(struct aim_fileheader_t));
1028
871e2fd0 1029 cook = aim_checkcookie(sess, ft->fh.bcookie, AIM_COOKIETYPE_OFTGET);
1030
1031 /* we currently trust the other client to be giving us Valid
1032 * Enough input, else this gets to be a messy function (and we
1033 * won't break like winaim does when it gets bad input =) */
7392c79f 1034
1035 if(cook->data)
1036 free(cook->data); /* XXX */
1037
1038 cook->data = ft;
1039
1040 aim_cachecookie(sess, cook);
1041
871e2fd0 1042 /* XXX: have this send chunks of the file instead of the whole
1043 * file. requires rethinking some code. */
1044
1045 if(fseek(sess->oft.listing, 0, SEEK_SET) != 0) {
1046 perror("get_command_rendezvous 1209 fseek(SET):");
1047 faimdprintf(2, "faim: getlisting: couldn't seek to beginning of listing file\n");
1048 }
1049 commandlen = ft->fh.size;
1050
1051 if((data = (char *)calloc(1, commandlen)) == NULL) {
1052 faimdprintf(2, "faim: get_command_rendezvous 1209: couldn't malloc data.\n");
1053 faim_mutex_unlock(&conn->active);
1054 return -1;
1055
1056 }
1057
1058 for(commandlen = 0; commandlen < ft->fh.size; commandlen++)
1059 if( (data[commandlen] = (unsigned char)fgetc(sess->oft.listing)) == EOF)
1060 faimdprintf(2, "faim: get_command_rendezvous 1209: got early EOF (error?)\n");
7392c79f 1061
871e2fd0 1062 commandlen = ft->fh.size;
7392c79f 1063
871e2fd0 1064 if (write(conn->fd, data, commandlen) != commandlen) {
7392c79f 1065 perror("listing write error");
1066 }
4dd56961 1067 faim_mutex_unlock(&conn->active);
7392c79f 1068
871e2fd0 1069 faimdprintf(2, "faim: get_command_rendezvous: hit end of 1209\n");
1070
1071 free(data);
7392c79f 1072
1073 break;
1074 }
1075 case 0x120b: { /* get file second */
1076 struct aim_filetransfer_priv *ft;
1077 struct aim_msgcookie_t *cook;
1078
1079 struct aim_fileheader_t *fh;
1080
871e2fd0 1081 faimdprintf(2, "faim: rend: fileget 120b\n");
7392c79f 1082
1083 if(!(ft = (struct aim_filetransfer_priv *)calloc(1, sizeof(struct aim_filetransfer_priv)))) {
871e2fd0 1084 faimdprintf(2, "faim: couldn't malloc ft. um. bad. bad bad. file transfer will likely fail, sorry.\n");
4dd56961 1085 faim_mutex_unlock(&conn->active);
871e2fd0 1086 return -1;
7392c79f 1087 }
1088
7392c79f 1089 fh = aim_oft_getfh(hdr);
1090
1091 memcpy(&(ft->fh), fh, sizeof(struct aim_fileheader_t));
871e2fd0 1092
1093 if(!(cook = aim_checkcookie(sess, ft->fh.bcookie, AIM_COOKIETYPE_OFTGET))) {
1094 faim_mutex_unlock(&conn->active);
1095 return -1;
1096 }
7392c79f 1097
1098 if(cook->data)
1099 free(cook->data); /* XXX: integrate cookie caching */
1100
1101 cook->data = ft;
1102
1103 aim_cachecookie(sess, cook);
4dd56961 1104
1105 faim_mutex_unlock(&conn->active);
871e2fd0 1106
1107 /* call listing.txt rx confirm */
1108
7392c79f 1109 break;
1110 }
1111 case 0x120c: { /* yet more get file */
1112 struct aim_filetransfer_priv *ft;
1113 struct aim_msgcookie_t *cook;
1114 struct aim_fileheader_t *listingfh;
1115 struct command_tx_struct *newoft;
871e2fd0 1116
1117 int i;
1118
1119 rxcallback_t userfunc;
7392c79f 1120
1121 printf("faim: rend: fileget 120c\n");
1122
1123 if(!(ft = (struct aim_filetransfer_priv *)calloc(1, sizeof(struct aim_filetransfer_priv)))) {
1124 printf("faim: couldn't malloc ft. um. bad. bad bad. file transfer will likely fail, sorry.\n");
4dd56961 1125 faim_mutex_unlock(&conn->active);
871e2fd0 1126 return -1;
7392c79f 1127 }
1128
1129 if(hdrlen != 0x100)
1130 printf("faim: fileget_command(120c): um. hdrlen != 0x100..\n");
1131
871e2fd0 1132 listingfh = aim_oft_getfh((char *)hdr);
7392c79f 1133
1134 memcpy(&(ft->fh), listingfh, sizeof(struct aim_fileheader_t));
1135
871e2fd0 1136 if(!(cook = aim_checkcookie(sess, ft->fh.bcookie, AIM_COOKIETYPE_OFTGET))) {
1137 faim_mutex_unlock(&conn->active);
1138 return -1;
1139 }
7392c79f 1140
1141 if(cook->data)
1142 free(cook->data); /* XXX */
1143
1144 cook->data = ft;
1145
1146 aim_cachecookie(sess, cook);
1147
4dd56961 1148 faim_mutex_unlock(&conn->active);
1149
871e2fd0 1150 faimdprintf(2, "faim: fileget: %s seems to want %s\n", ft->sn, ft->fh.name);
1151
1152 if( (userfunc = aim_callhandler(conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILEFILEREQ)) )
1153 i = userfunc(sess, NULL, conn, &ft->fh, cook->cookie);
1154
1155 if(i < 0)
1156 return -1;
1157
1158 if(!(newoft = aim_tx_new(AIM_FRAMETYPE_OFT, 0x0101, conn, 0))) {
1159 faimdprintf(2, "faim: send_final_transfer: tx_new OFT failed\n");
1160 return -1;
7392c79f 1161 }
1162
7392c79f 1163 newoft->lock = 1;
871e2fd0 1164
7392c79f 1165 memcpy(newoft->hdr.oft.magic, "OFT2", 4);
1166 newoft->hdr.oft.hdr2len = 0xf8; /* 0x100 - 8 */
1167
1168 if (!(newoft->hdr.oft.hdr2 = calloc(1,newoft->hdr.oft.hdr2len))) {
871e2fd0 1169 newoft->lock = 0;
1170 aim_tx_destroy(newoft);
1171 return -1;
7392c79f 1172 }
7392c79f 1173
871e2fd0 1174 /* memcpy(listingfh->bcookie, ft->fh.bcookie, 8); */
7392c79f 1175
871e2fd0 1176 listingfh->nrecvd = 0; /* these need reset for protocol-correctness */
1177 listingfh->recvcsum = 0;
7392c79f 1178
871e2fd0 1179 aim_oft_buildheader((void *)newoft->hdr.oft.hdr2, listingfh);
1180
1181 newoft->lock = 0;
1182 aim_tx_enqueue(sess, newoft);
1183 faimdprintf(2, "faim: OFT: OFT file enqueued.\n");
1184
1185 if( (userfunc = aim_callhandler(conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILEFILEREQ)) == NULL)
1186 return 1;
1187
1188 i = userfunc(sess, NULL, conn, listingfh, listingfh->bcookie);
7392c79f 1189
1190 free(listingfh);
1191
871e2fd0 1192 return i;
7392c79f 1193
1194 break;
1195 }
1196 case 0x0202: { /* get file: ready to recieve data */
7392c79f 1197 struct aim_fileheader_t *fh;
871e2fd0 1198 fh = aim_oft_getfh((char *)hdr);
7392c79f 1199
871e2fd0 1200 faimdprintf(2, "faim: get_rend: looks like we're ready to send data.(oft 0x0202)\n");
7392c79f 1201
871e2fd0 1202 faim_mutex_unlock(&conn->active);
7392c79f 1203
871e2fd0 1204 if ( (userfunc = aim_callhandler(conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILEFILESEND)) == NULL)
1205 return 1;
7392c79f 1206
871e2fd0 1207 return userfunc(sess, NULL, conn, fh);
7392c79f 1208
871e2fd0 1209 free(fh);
4dd56961 1210
7392c79f 1211 break;
1212 }
1213 case 0x0204: { /* get file: finished. close it up */
871e2fd0 1214 int i;
1215
1216 struct aim_fileheader_t *fh;
1217 fh = aim_oft_getfh((char *)hdr);
1218
1219 faimdprintf(2, "faim: get_rend: looks like we're done with a transfer (oft 0x0204)\n");
1220
4dd56961 1221 faim_mutex_unlock(&conn->active);
871e2fd0 1222
1223 if ( (userfunc = aim_callhandler(conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILECOMPLETE)) )
1224 i = userfunc(sess, NULL, conn, fh);
1225 else
1226 i = 1;
1227
1228 /*
1229 free(fh); */
1230 /* not sure where to do this yet, as we need to keep it to allow multiple file sends... bleh */
1231
1232 return i;
7392c79f 1233 break;
1234 }
1235 default: {
1236 printf("OFT frame: type %04x\n", hdrtype);
1237 /* data connection may be unreliable here */
4dd56961 1238 faim_mutex_unlock(&conn->active);
7392c79f 1239 break;
1240 }
1241 } /* switch */
1242
1243 free(hdr);
1244
1245 return 0;
1246}
1247
1248/*
871e2fd0 1249 * aim_oft_registerlisting()
1250 * sess: aim session
1251 * file: opened FILE *
1252 * listingdir: the path to listing.txt
1253 * returns -1 on error, 0 on success.
1254 *
1255 * it's not my problem if the listing fd is already set.
7392c79f 1256 */
1257
871e2fd0 1258faim_export int aim_oft_registerlisting(struct aim_session_t *sess, FILE *file, char* listingdir)
1259{
1260 if(!sess)
1261 return -1;
1262
1263 /* XXX: checksum each file in the listing */
1264
1265#if 0
1266 if(sess->oft.listing) {
1267 faimdprintf(1, "We already have a file pointer. Closing and overwriting.\n");
1268 fclose(sess->oft.listing);
1269 }
1270#endif
1271 sess->oft.listing = file;
1272#if 0
1273 if(sess->oft.listingdir) {
1274 faimdprintf(1, "We already have a directory string. Freeing and overwriting\n");
1275 free(sess->oft.listingdir);
1276 }
1277#endif
1278
1279 if( (sess->oft.listingdir = (char *)calloc(1, strlen(listingdir)+1)) )
1280 memcpy(sess->oft.listingdir, listingdir, strlen(listingdir));
1281 else
1282 return -1;
1283 return 0;
1284}
1285
78b3fb13 1286faim_internal struct aim_fileheader_t *aim_oft_getfh(unsigned char *hdr)
7392c79f 1287{
1288 struct aim_fileheader_t *fh;
1289 int i, j;
1290
1291 if(!(fh = calloc(1, sizeof(struct aim_fileheader_t))))
1292 return NULL;
1293
1294 /* [0] and [1] are the type. we can ignore those here. */
1295
1296 i = 2;
1297
1298 for(j = 0; j < 8; j++, i++)
1299 fh->bcookie[j] = hdr[i];
1300 fh->encrypt = aimutil_get16(hdr+i);
1301 i += 2;
1302 fh->compress = aimutil_get16(hdr+i);
1303 i += 2;
1304 fh->totfiles = aimutil_get16(hdr+i);
1305 i += 2;
1306 fh->filesleft = aimutil_get16(hdr+i);
1307 i += 2;
1308 fh->totparts = aimutil_get16(hdr+i);
1309 i += 2;
1310 fh->partsleft = aimutil_get16(hdr+i);
1311 i += 2;
1312 fh->totsize = aimutil_get32(hdr+i);
1313 i += 4;
1314 fh->size = aimutil_get32(hdr+i);
1315 i += 4;
1316 fh->modtime = aimutil_get32(hdr+i);
1317 i += 4;
1318 fh->checksum = aimutil_get32(hdr+i);
1319 i += 4;
1320 fh->rfrcsum = aimutil_get32(hdr+i);
1321 i += 4;
1322 fh->rfsize = aimutil_get32(hdr+i);
1323 i += 4;
1324 fh->cretime = aimutil_get32(hdr+i);
1325 i += 4;
1326 fh->rfcsum = aimutil_get32(hdr+i);
1327 i += 4;
1328 fh->nrecvd = aimutil_get32(hdr+i);
1329 i += 4;
1330 fh->recvcsum = aimutil_get32(hdr+i);
1331 i += 4;
1332
1333 memcpy(fh->idstring, hdr+i, 32);
1334 i += 32;
1335
1336 fh->flags = aimutil_get8(hdr+i);
1337 i += 1;
1338 fh->lnameoffset = aimutil_get8(hdr+i);
1339 i += 1;
1340 fh->lsizeoffset = aimutil_get8(hdr+i);
1341 i += 1;
1342
1343 memcpy(fh->dummy, hdr+i, 69);
1344 i += 69;
1345
1346 memcpy(fh->macfileinfo, hdr+i, 16);
1347 i += 16;
1348
1349 fh->nencode = aimutil_get16(hdr+i);
1350 i += 2;
1351 fh->nlanguage = aimutil_get16(hdr+i);
1352 i += 2;
1353
1354 memcpy(fh->name, hdr+i, 64);
1355 i += 64;
1356
1357 return fh;
1358}
871e2fd0 1359
1360faim_export int aim_oft_checksum(char *buffer, int bufsize, int *checksum)
1361{
1362 short check0, check1;
1363 int i;
1364
1365 check0 = ((*checksum & 0xFF000000) >> 16);
1366 check1 = ((*checksum & 0x00ff0000) >> 16);
1367
1368 for(i = 0; i < bufsize; i++) {
1369
1370 if(i % 2) { /* use check1 -- second byte */
1371 if ( (short)buffer[i] > check1 ) { /* wrapping */
1372
1373 check1 += 0x100; /* this is a cheap way to wrap */
1374
1375 /* if we're wrapping, decrement the other one */
1376 if(check0 == 0) /* XXX: check this corner case */
1377 check0 = 0x00ff;
1378 else
1379 check0--;
1380 }
1381
1382 check1 -= buffer[i];
1383 } else { /* use check0 -- first byte */
1384 if ( (short)buffer[i] > check0 ) { /* wrapping */
1385
1386 check0 += 0x100; /* this is a cheap way to wrap */
1387
1388 /* if we're wrapping, decrement the other one */
1389 if(check1 == 0) /* XXX: check this corner case */
1390 check1 = 0x00ff;
1391 else
1392 check1--;
1393 }
1394
1395 check0 -= buffer[i];
1396 }
1397 }
1398
1399 if(check0 > 0xff || check1 > 0xff) { /* they shouldn't be able to do this. error! */
1400 faimdprintf(2, "check0 or check1 is too high: 0x%04x, 0x%04x\n", check0, check1);
1401 return -1;
1402 }
1403
1404 check0 &= 0xff; /* grab just the lowest byte */
1405 check1 &= 0xff; /* this should be clean, but just in case */
1406
1407 *checksum = ((check0 * 0x1000000) + (check1 * 0x10000));
1408
1409 return *checksum;
1410}
1411
1412
1413/*
1414 * aim_oft_buildheader:
1415 * fills a buffer with network-order fh data.
1416 * returns length written; -1 on error.
1417 * dest: buffer to fill -- pre-alloced
1418 * listingfh: fh to get data from
1419 *
1420 * DOES NOT DO BOUNDS CHECKING!
1421 */
1422
1423
1424faim_internal int aim_oft_buildheader(char *dest,struct aim_fileheader_t *listingfh)
1425{
1426 int i, curbyte;
1427
1428 if(!dest || !listingfh)
1429 return -1;
1430
1431 curbyte = 0;
1432 for(i = 0; i < 8; i++)
1433 curbyte += aimutil_put8(dest+curbyte, listingfh->bcookie[i]);
1434 curbyte += aimutil_put16(dest+curbyte, listingfh->encrypt);
1435 curbyte += aimutil_put16(dest+curbyte, listingfh->compress);
1436 curbyte += aimutil_put16(dest+curbyte, listingfh->totfiles);
1437 curbyte += aimutil_put16(dest+curbyte, listingfh->filesleft);
1438 curbyte += aimutil_put16(dest+curbyte, listingfh->totparts);
1439 curbyte += aimutil_put16(dest+curbyte, listingfh->partsleft);
1440 curbyte += aimutil_put32(dest+curbyte, listingfh->totsize);
1441 curbyte += aimutil_put32(dest+curbyte, listingfh->size);
1442 curbyte += aimutil_put32(dest+curbyte, listingfh->modtime);
1443 curbyte += aimutil_put32(dest+curbyte, listingfh->checksum);
1444 curbyte += aimutil_put32(dest+curbyte, listingfh->rfrcsum);
1445 curbyte += aimutil_put32(dest+curbyte, listingfh->rfsize);
1446 curbyte += aimutil_put32(dest+curbyte, listingfh->cretime);
1447 curbyte += aimutil_put32(dest+curbyte, listingfh->rfcsum);
1448 curbyte += aimutil_put32(dest+curbyte, listingfh->nrecvd);
1449 curbyte += aimutil_put32(dest+curbyte, listingfh->recvcsum);
1450
1451 memcpy(dest+curbyte, listingfh->idstring, 32);
1452 curbyte += 32;
1453
1454 curbyte += aimutil_put8(dest+curbyte, listingfh->flags);
1455 curbyte += aimutil_put8(dest+curbyte, listingfh->lnameoffset);
1456 curbyte += aimutil_put8(dest+curbyte, listingfh->lsizeoffset);
1457
1458 memcpy(dest+curbyte, listingfh->dummy, 69);
1459 curbyte += 69;
1460
1461 memcpy(dest+curbyte, listingfh->macfileinfo, 16);
1462 curbyte += 16;
1463
1464 curbyte += aimutil_put16(dest+curbyte, listingfh->nencode);
1465 curbyte += aimutil_put16(dest+curbyte, listingfh->nlanguage);
1466
1467 memcpy(dest+curbyte, listingfh->name, 64); /* XXX: Filenames longer than 64B */
1468 curbyte += 64;
1469
1470 return curbyte;
1471}
1472
1473/*
1474 * int aim_getfile_send(struct aim_conn_t *conn, FILE *tosend, struct aim_fileheader_t *fh)
1475 * conn is the OFT connection to shove the data down,
1476 * tosend is the FILE * for the file to send
1477 * fh is the filled-in fh value
1478 * returns -1 on error, 1 on success.
1479 */
1480
1481faim_export int aim_getfile_send(struct aim_conn_t *conn, FILE *tosend, struct aim_fileheader_t *fh)
1482{
1483 int pos, bufpos, i;
1484 const int bufsize = 4096;
1485 char *buf;
1486
1487 /* sanity checks */
1488 if(conn->type != AIM_CONN_TYPE_RENDEZVOUS || conn->subtype != AIM_CONN_SUBTYPE_OFT_GETFILE) {
1489 faimdprintf(1, "getfile_send: conn->type(0x%04x) != RENDEZVOUS or conn->subtype(0x%04x) != GETFILE\n", conn->type, conn->subtype);
1490 return -1;
1491 }
1492
1493 if(!tosend) {
1494 faimdprintf(1, "getfile_send: file pointer isn't valid\n");
1495 return -1;
1496 }
1497
1498 if(!fh) {
1499 faimdprintf(1, "getfile_send: fh isn't valid\n");
1500 return -1;
1501 }
1502
1503 /* real code */
1504
1505 if(!(buf = (char *)calloc(1, bufsize))) {
1506 perror("faim: getfile_send: calloc:");
1507 faimdprintf(2, "getfile_send calloc error\n");
1508 return -1;
1509 }
1510
1511 pos = 0;
1512
1513 if( fseek(tosend, 0, SEEK_SET) == -1) {
1514 perror("faim: getfile_send: fseek:");
1515 faimdprintf(2, "getfile_send fseek error\n");
1516 }
1517
1518 faimdprintf(2, "faim: getfile_send: using %i byte blocks\n", bufsize);
1519
1520 for(pos = 0; pos < fh->size; pos++) {
1521 bufpos = pos % bufsize;
1522
1523 if(bufpos == 0 && pos > 0) { /* filled our buffer. spit it across the wire */
1524 if ( (i = write(conn->fd, buf, bufsize)) != bufsize ) {
1525 perror("faim: getfile_send: write1: ");
1526 faimdprintf(1, "faim: getfile_send: whoopsy, didn't write it all...\n");
1527 free(buf);
1528 return -1;
1529 }
1530 }
1531 if( (buf[bufpos] = fgetc(tosend)) == EOF) {
1532 if(pos != fh->size) {
1533 printf("faim: getfile_send: hrm... apparent early EOF at pos 0x%x of 0x%lx\n", pos, fh->size);
1534 faimdprintf(1, "faim: getfile_send: hrm... apparent early EOF at pos 0x%lx of 0x%lx\n", pos, fh->size);
1535 free(buf);
1536 return -1;
1537 }
1538 }
1539
1540
1541 }
1542
1543 if( (i = write(conn->fd, buf, bufpos+1)) != (bufpos+1)) {
1544 perror("faim: getfile_send: write2: ");
1545 faimdprintf(1, "faim: getfile_send cleanup: whoopsy, didn't write it all...\n");
1546 free(buf);
1547 return -1;
1548 }
1549
1550 free(buf);
1551
1552 fclose(tosend);
1553 return 1;
1554}
1555
1556/*
1557 * int aim_getfile_send_chunk(struct aim_conn_t *conn, FILE *tosend, struct aim_fileheader_t *fh, int pos, int bufsize)
1558 * conn is the OFT connection to shove the data down,
1559 * tosend is the FILE * for the file to send
1560 * fh is the filled-in fh value
1561 * pos is the position to start at (at beginning should be 0, after 5
1562 * bytes are sent should be 5); -1 for "don't seek"
1563 * bufsize is the size of the chunk to send
1564 *
1565 * returns -1 on error, new pos on success.
1566 *
1567 *
1568 * Notes on usage:
1569 * You don't really have to keep track of pos if you don't want
1570 * to. just always call with -1 for pos, and it'll use the one
1571 * contained within the FILE *.
1572 *
1573 * if (pos + chunksize > fh->size), we only send as much data as we
1574 * can get (ie: up to fh->size.
1575 */
871e2fd0 1576faim_export int aim_getfile_send_chunk(struct aim_conn_t *conn, FILE *tosend, struct aim_fileheader_t *fh, int pos, int bufsize)
1577{
1578 int bufpos;
1579 char *buf;
1580
1581 /* sanity checks */
1582 if(conn->type != AIM_CONN_TYPE_RENDEZVOUS || conn->type != AIM_CONN_SUBTYPE_OFT_GETFILE) {
1583 faimdprintf(1, "faim: getfile_send_chunk: conn->type(0x%04x) != RENDEZVOUS or conn->subtype(0x%04x) != GETFILE\n", conn->type, conn->subtype);
1584 return -1;
1585 }
1586
1587 if(!tosend) {
1588 faimdprintf(1, "faim: getfile_send_chunk: file pointer isn't valid\n");
1589 return -1;
1590 }
1591
1592 if(!fh) {
1593 faimdprintf(1, "faim: getfile_send_chunk: fh isn't valid\n");
1594 return -1;
1595 }
1596
1597 /* real code */
1598
1599 if(!(buf = (char *)calloc(1, bufsize))) {
1600 perror("faim: getfile_send_chunk: calloc:");
1601 faimdprintf(2, "faim: getfile_send_chunk calloc error\n");
1602 return -1;
1603 }
1604
1605 if(pos != -1) {
1606 if( fseek(tosend, pos, SEEK_SET) == -1) {
1607 perror("faim: getfile_send_chunk: fseek:");
1608 faimdprintf(2, "faim: getfile_send_chunk fseek error\n");
1609 }
1610 }
1611
1612 faimdprintf(2, "faim: getfile_send_chunk: using %i byte blocks\n", bufsize);
1613
1614 for(bufpos = 0; pos < fh->size; bufpos++, pos++) {
1615 if( (buf[bufpos] = fgetc(tosend)) == EOF) {
1616 if(pos != fh->size) {
1617 faimdprintf(1, "faim: getfile_send_chunk: hrm... apparent early EOF at pos 0x%x of 0x%x\n", pos, fh->size);
1618 free(buf);
1619 return -1;
1620 }
1621 }
1622 }
1623
1624 if( write(conn->fd, buf, bufpos+1) != (bufpos+1)) {
1625 faimdprintf(1, "faim: getfile_send_chunk cleanup: whoopsy, didn't write it all...\n");
1626 free(buf);
1627 return -1;
1628 }
1629
1630 free(buf);
1631
1632 return (pos + bufpos);
1633}
1634
1635/*
1636 * aim_tx_destroy:
1637 * free's tx_command_t's. if command is locked, doesn't free.
1638 * returns -1 on error (locked struct); 0 on success.
1639 * command is the command to free
1640 */
1641
1642faim_internal int aim_tx_destroy(struct command_tx_struct *command)
1643{
1644 if(command->lock)
1645 return -1;
1646 if(command->data)
1647 free(command->data);
1648 free(command);
1649
1650 return 0;
1651}
1652
1653#if 0
1654/*
1655 * aim_getfile_intitiate:
1656 * For those times when we want to open up the directim channel ourselves.
1657 * sess is your session,
1658 * conn is the BOS conn,
1659 * priv is a dummy priv value (we'll let it get filled in later) (if
1660 * you pass a NULL, we alloc one)
1661 * destsn is the SN to connect to.
1662 */
1663
1664
1665faim_export struct aim_conn_t *aim_getfile_initiate(struct aim_session_t *sess,
1666 struct aim_conn_t *conn,
1667 struct aim_getfile_priv *priv,
1668 char *destsn)
1669{
1670 struct command_tx_struct *newpacket;
1671 struct aim_conn_t *newconn;
1672
1673 struct aim_msgcookie_t *cookie;
1674
1675 int curbyte, i, listenfd;
1676 short port = 4443;
1677
1678 struct hostent *hptr;
1679 struct utsname myname;
1680
1681 char cap[16];
1682 char d[4]; /* XXX: IPv6. *cough* */
1683
1684 /*
1685 * Open our socket
1686 */
1687
1688 if( (listenfd = aim_listenestablish(port)) == -1)
1689 return NULL;
1690
1691 /*
1692 * get our local IP
1693 */
1694
1695 if(uname(&myname) < 0)
1696 return NULL;
1697
1698 if( (hptr = gethostbyname(myname.nodename)) == NULL)
1699 return NULL;
1700
1701 memcpy(&d, hptr->h_addr_list[0], 4); /* XXX: this probably isn't quite kosher, but it works */
1702
1703 aim_putcap(cap, 16, AIM_CAPS_IMIMAGE);
1704
1705 /*
1706 * create the OSCAR packet
1707 */
1708
1709 if (!(newpacket = aim_tx_new(AIM_FRAMETYPE_OSCAR, 0x0002, conn, 10+8+2+1+strlen(destsn)+4+4+0x32)))
1710 return NULL;
1711
1712 newpacket->lock = 1; /* lock struct */
1713
1714 curbyte = 0;
1715 curbyte += aim_putsnac(newpacket->data+curbyte,
1716 0x0004, 0x0006, 0x0000, sess->snac_nextid);
1717
1718 /*
1719 * Generate a random message cookie
1720 * This cookie needs to be alphanumeric and NULL-terminated to be TOC-compatible.
1721 */
1722 for (i=0;i<7;i++)
1723 curbyte += aimutil_put8(newpacket->data+curbyte, 0x30 + ((u_char) random() % 20));
1724 curbyte += aimutil_put8(newpacket->data+curbyte, 0x00);
1725
1726 /*
1727 * grab all the data for cookie caching.
1728 */
1729 cookie = (struct aim_msgcookie_t *)calloc(1, sizeof(struct aim_msgcookie_t));
1730
1731 memcpy(cookie->cookie, newpacket->data+curbyte-8, 8);
1732 cookie->type = AIM_COOKIETYPE_OFTIM;
1733
1734 if(!priv)
1735 priv = (struct aim_directim_priv *)calloc(1, sizeof(struct aim_directim_priv));
1736
1737 memcpy(priv->cookie, cookie, 8);
1738 memcpy(priv->sn, destsn, sizeof(priv->sn));
1739
1740 cookie->data = priv;
1741
1742 aim_cachecookie(sess, cookie); /* cache da cookie */
1743
1744 /*
1745 * Channel ID
1746 */
1747 curbyte += aimutil_put16(newpacket->data+curbyte,0x0002);
1748
1749 /*
1750 * Destination SN (prepended with byte length)
1751 */
1752 curbyte += aimutil_put8(newpacket->data+curbyte,strlen(destsn));
1753 curbyte += aimutil_putstr(newpacket->data+curbyte, destsn, strlen(destsn));
1754
1755 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0003);
1756 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0000);
1757
1758 /*
1759 * enTLV start
1760 */
1761 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0005);
1762 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0032);
1763
1764 /*
1765 * Flag data / ICBM Parameters?
1766 */
1767 curbyte += aimutil_put8(newpacket->data+curbyte, 0x00);
1768 curbyte += aimutil_put8(newpacket->data+curbyte, 0x00);
1769
1770 /*
1771 * Cookie
1772 */
1773 curbyte += aimutil_putstr(newpacket->data+curbyte, (char *)cookie, 8);
1774
1775 /*
1776 * Capability String
1777 */
1778 curbyte += aimutil_putstr(newpacket->data+curbyte, (char *)cap, 0x10);
1779
1780 /*
1781 * 000a/0002 : 0001
1782 */
1783 curbyte += aimutil_put16(newpacket->data+curbyte, 0x000a);
1784 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0002);
1785 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0001);
1786
1787 /*
1788 * 0003/0004: IP address
1789 */
1790
1791 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0003);
1792 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0004);
1793
1794 for(i = 0; i < 4; i++)
1795 curbyte += aimutil_put8(newpacket->data+curbyte, d[i]); /* already in network byte order */
1796
1797 /*
1798 * 0005/0002: Port
1799 */
1800
1801 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0005);
1802 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0002);
1803 curbyte += aimutil_put16(newpacket->data+curbyte, port);
1804
1805 /*
1806 * 000f/0000: umm.. dunno. Zigamorph[1]?
1807 * [1]: see esr's TNHD.
1808 */
1809
1810 curbyte += aimutil_put16(newpacket->data+curbyte, 0x000f);
1811 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0000);
1812
1813 printf("curbyte: 0x%x\n",curbyte);
1814
1815 newpacket->commandlen = curbyte;
1816 newpacket->lock = 0;
1817
1818 aim_tx_enqueue(sess, newpacket);
1819
1820 /*
1821 * allocate and set up our connection
1822 */
1823
1824 i = fcntl(listenfd, F_GETFL, 0);
1825 fcntl(listenfd, F_SETFL, i | O_NONBLOCK);
1826
1827 newconn = aim_newconn(sess, AIM_CONN_TYPE_RENDEZVOUS_OUT, NULL);
1828 if (!newconn) {
1829 perror("aim_newconn");
1830 aim_conn_kill(sess, &newconn);
1831 return NULL;
1832 }
1833
1834 newconn->fd = listenfd;
1835 newconn->subtype = AIM_CONN_SUBTYPE_OFT_DIRECTIM;
1836 newconn->priv = priv;
1837 printf("faim: listening (fd = %d, unconnected)\n", newconn->fd);
1838
1839 /*
1840 * XXX We need some way of closing the listener socket after
1841 * n seconds of no connection. -- mid
1842 */
1843
871e2fd0 1844 return newconn;
1845}
1846
1847#endif
This page took 4.818513 seconds and 5 git commands to generate.