]> andersk Git - libfaim.git/blame - aim_ft.c
- Tue Sep 5 03:47:26 GMT 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
105 if (strlen(msg) >= MAXMSGLEN)
106 return -1;
107
108 if (!sess || !conn || !(conn->type) || (conn->type != AIM_CONN_TYPE_RENDEZVOUS) || !conn->priv) {
109 printf("faim: directim: invalid arguments\n");
110 return -1;
111 };
112
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
154 i += aimutil_putstr(newpacket2->hdr.oft.hdr2+i, sess->logininfo.screen_name, strlen(sess->logininfo.screen_name));
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
208 i += aimutil_putstr(newpacket->hdr.oft.hdr2+i, sess->logininfo.screen_name, strlen(sess->logininfo.screen_name));
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
5ac21963 409#if 0
7392c79f 410 i = fcntl(listenfd, F_GETFL, 0);
411 fcntl(listenfd, F_SETFL, i | O_NONBLOCK);
5ac21963 412#endif
7392c79f 413
414 newconn = aim_newconn(sess, AIM_CONN_TYPE_RENDEZVOUS_OUT, NULL);
415 if (!newconn) {
416 perror("aim_newconn");
417 aim_conn_kill(sess, &newconn);
418 return NULL;
419 }
420
421 newconn->fd = listenfd;
422 newconn->subtype = AIM_CONN_SUBTYPE_OFT_DIRECTIM;
423 newconn->priv = priv;
424 printf("faim: listening (fd = %d, unconnected)\n", newconn->fd);
425
426 /*
427 * XXX We need some way of closing the listener socket after
428 * n seconds of no connection. -- mid
429 */
430
431#ifdef USE_SNAC_FOR_IMS
432 {
433 struct aim_snac_t snac;
434
435 snac.id = sess->snac_nextid;
436 snac.family = 0x0004;
437 snac.type = 0x0006;
438 snac.flags = 0x0000;
439
440 snac.data = malloc(strlen(destsn)+1);
441 memcpy(snac.data, destsn, strlen(destsn)+1);
442
443 aim_newsnac(sess, &snac);
444
445 aim_cleansnacs(sess, 60); /* clean out all SNACs over 60sec old */
446 }
447#endif
448
449 return (newconn);
450}
451
452
78b3fb13 453faim_export struct aim_conn_t *aim_directim_connect(struct aim_session_t *sess,
454 struct aim_conn_t *conn,
455 struct aim_directim_priv *priv )
7392c79f 456{
457 struct aim_conn_t *newconn = NULL;;
458
459 newconn = aim_newconn(sess, AIM_CONN_TYPE_RENDEZVOUS, priv->ip);
460 if (!newconn || (newconn->fd == -1)) {
461 printf("could not connect to %s\n", priv->ip);
462 perror("aim_newconn");
463 aim_conn_kill(sess, &newconn);
464 return NULL;
465 } else {
466 newconn->subtype = AIM_CONN_SUBTYPE_OFT_DIRECTIM;
467 newconn->priv = priv;
468 printf("faim: connected to peer (fd = %d)\n", newconn->fd);
469 return newconn;
470 }
471 return newconn;
472}
473
78b3fb13 474faim_export unsigned long aim_accepttransfer(struct aim_session_t *sess,
475 struct aim_conn_t *conn,
476 struct aim_conn_t *oftconn,
477 char *sn,
478 char *cookie,
479 unsigned short rendid)
7392c79f 480{
481 struct command_tx_struct *newpacket, *newoft;
482 struct aim_fileheader_t *listingfh;
483 int curbyte, i;
484 /* now for the oft bits */
485
486 if(rendid == AIM_CAPS_GETFILE) {
487 printf("jbm: getfile request accept\n");
488 if(!(newoft = aim_tx_new(AIM_FRAMETYPE_OFT, 0x1108, oftconn, 0))) {
489 printf("faim: accept_transfer: tx_new OFT failed\n");
490 return -1;
491 }
492
493 newoft->lock = 1;
494
495 memcpy(newoft->hdr.oft.magic, "OFT2", 4);
496 newoft->hdr.oft.hdr2len = 0xf8; /* 0x100 - 8 */
497
498 if (!(newoft->hdr.oft.hdr2 = calloc(1,newoft->hdr.oft.hdr2len))) {
499 free(newoft);
500 return -1;
501 }
502
503 listingfh = aim_getlisting(sess);
504
505 memcpy(listingfh->bcookie, cookie, 8);
506
507 curbyte = 0;
508
509 for(i = 0; i < 8; i++)
510 curbyte += aimutil_put8(newoft->hdr.oft.hdr2+curbyte, cookie[i]);
511 curbyte += aimutil_put16(newoft->hdr.oft.hdr2+curbyte, listingfh->encrypt);
512 curbyte += aimutil_put16(newoft->hdr.oft.hdr2+curbyte, listingfh->compress);
513 curbyte += aimutil_put16(newoft->hdr.oft.hdr2+curbyte, listingfh->totfiles);
514 curbyte += aimutil_put16(newoft->hdr.oft.hdr2+curbyte, listingfh->filesleft);
515 curbyte += aimutil_put16(newoft->hdr.oft.hdr2+curbyte, listingfh->totparts);
516 curbyte += aimutil_put16(newoft->hdr.oft.hdr2+curbyte, listingfh->partsleft);
517 curbyte += aimutil_put32(newoft->hdr.oft.hdr2+curbyte, listingfh->totsize);
518 curbyte += aimutil_put32(newoft->hdr.oft.hdr2+curbyte, listingfh->size);
519 curbyte += aimutil_put32(newoft->hdr.oft.hdr2+curbyte, listingfh->modtime);
520 curbyte += aimutil_put32(newoft->hdr.oft.hdr2+curbyte, listingfh->checksum);
521 curbyte += aimutil_put32(newoft->hdr.oft.hdr2+curbyte, listingfh->rfrcsum);
522 curbyte += aimutil_put32(newoft->hdr.oft.hdr2+curbyte, listingfh->rfsize);
523 curbyte += aimutil_put32(newoft->hdr.oft.hdr2+curbyte, listingfh->cretime);
524 curbyte += aimutil_put32(newoft->hdr.oft.hdr2+curbyte, listingfh->rfcsum);
525 curbyte += aimutil_put32(newoft->hdr.oft.hdr2+curbyte, listingfh->nrecvd);
526 curbyte += aimutil_put32(newoft->hdr.oft.hdr2+curbyte, listingfh->recvcsum);
527
528 memcpy(newoft->hdr.oft.hdr2+curbyte, listingfh->idstring, 32);
529 curbyte += 32;
530
531 curbyte += aimutil_put8(newoft->hdr.oft.hdr2+curbyte, listingfh->flags);
532 curbyte += aimutil_put8(newoft->hdr.oft.hdr2+curbyte, listingfh->lnameoffset);
533 curbyte += aimutil_put8(newoft->hdr.oft.hdr2+curbyte, listingfh->lsizeoffset);
534
535 memcpy(newoft->hdr.oft.hdr2+curbyte, listingfh->dummy, 69);
536 curbyte += 69;
537
538 memcpy(newoft->hdr.oft.hdr2+curbyte, listingfh->macfileinfo, 16);
539 curbyte += 16;
540
541 curbyte += aimutil_put16(newoft->hdr.oft.hdr2+curbyte, listingfh->nencode);
542 curbyte += aimutil_put16(newoft->hdr.oft.hdr2+curbyte, listingfh->nlanguage);
543
544 memcpy(newoft->hdr.oft.hdr2+curbyte, listingfh->name, 64);
545 curbyte += 64;
546
547 free(listingfh);
548
549 newoft->lock = 0;
550 aim_tx_enqueue(sess, newoft);
551 printf("faim: getfile: OFT listing enqueued.\n");
552
553 }
554
555
556 if(!(newpacket = aim_tx_new(AIM_FRAMETYPE_OSCAR, 0x0002, conn, 10+8+2+1+strlen(sn)+4+2+8+16)))
557 return -1;
558
559 newpacket->lock = 1;
560
561 curbyte = aim_putsnac(newpacket->data, 0x0004, 0x0006, 0x0000, sess->snac_nextid);
562 for (i = 0; i < 8; i++)
563 curbyte += aimutil_put8(newpacket->data+curbyte, cookie[i]);
564 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0002);
565 curbyte += aimutil_put8(newpacket->data+curbyte, strlen(sn));
566 curbyte += aimutil_putstr(newpacket->data+curbyte, sn, strlen(sn));
567 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0005);
568 curbyte += aimutil_put16(newpacket->data+curbyte, 0x001a);
569 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0002 /* accept */);
570 for (i = 0; i < 8; i++)
571 curbyte += aimutil_put8(newpacket->data+curbyte, cookie[i]);
572 curbyte += aim_putcap(newpacket->data+curbyte, 0x10, rendid);
573
574 newpacket->lock = 0;
575 aim_tx_enqueue(sess, newpacket);
576
577
578
579 return (sess->snac_nextid++);
580}
581
582/*
583 * aim_getlisting()
584 *
585 * Get file listing.txt info. where else to put it? i
586 * dunno. client-side issue for sure tho. for now we just side-step
587 * the issue with a nice default. =)
588 *
589 */
590
78b3fb13 591faim_internal struct aim_fileheader_t *aim_getlisting(struct aim_session_t *sess)
7392c79f 592{
593 struct aim_fileheader_t *fh;
594
595 if(!(fh = (struct aim_fileheader_t*)calloc(1, sizeof(struct aim_fileheader_t))))
596 return NULL;
597
598 fh->encrypt = 0x0000;
599 fh->compress = 0x0000;
600 fh->totfiles = 0x0001;
601 fh->filesleft = 0x0001;
602 fh->totparts = 0x0001;
603 fh->partsleft = 0x0001;
604 fh->totsize = 0x00000064;
605 fh->size = 0x00000024; /* ls -l listing.txt */
606 fh->modtime = (int)time(NULL); /*0x39441fb4; */
607 fh->checksum = 0xb8350000;
608 fh->rfcsum = 0x00000000;
609 fh->rfsize = 0x00000000;
610 fh->cretime = 0x00000000;
611 fh->rfcsum = 0x00000000;
612 fh->nrecvd = 0x00000000;
613 fh->recvcsum = 0x00000000;
614
615 memset(fh->idstring, 0, 32/*sizeof(fh->idstring)*/);
616 memcpy(fh->idstring, "OFT_Windows ICBMFT V1.1 32", 32/*sizeof(fh->idstring)*/);
617 memset(fh->idstring+strlen(fh->idstring), 0, 32-strlen(fh->idstring)); /* jbm hack */
618
619 fh->flags = 0x02;
620 fh->lnameoffset = 0x1a;
621 fh->lsizeoffset = 0x10;
622
623 memset(fh->dummy, 0, 69/*sizeof(fh->dummy)*/);
624 /* fh->dummy = ;*/
625
626 memset(fh->macfileinfo, 0, 16/*sizeof(fh->macfileinfo)*/);
627 /* fh->macfileinfo = ; */
628
629 fh->nencode = 0x0000;
630 fh->nlanguage = 0x0000;
631
632 memset(fh->name, 0, 64/*sizeof(fh->name)*/);
633 memcpy(fh->name, "listing.txt", 64 /*sizeof(fh->name)*/);
634 memset(fh->name+strlen(fh->name), 0, 64-strlen(fh->name)); /* jbm hack */
635
636 printf("jbm: fh name %s / %s\n", fh->name, (fh->name+(strlen(fh->name))));
637 return fh;
638}
639
640/*
641 * establish: create a listening socket on a port. you need to call
642 * accept() when it's connected.
643 * portnum is the port number to bind to.
644 * returns your fd
645 */
646
78b3fb13 647faim_internal int aim_listenestablish(u_short portnum)
7392c79f 648{
5ac21963 649#if defined(__linux__) /* XXX what other OS's support getaddrinfo? */
7392c79f 650 int listenfd;
651 const int on = 1;
652 struct addrinfo hints, *res, *ressave;
653 char serv[5];
654 sprintf(serv, "%d", portnum);
655 memset(&hints, 0, sizeof(struct addrinfo));
656 hints.ai_flags = AI_PASSIVE;
657 hints.ai_family = AF_UNSPEC;
658 hints.ai_socktype = SOCK_STREAM;
659 if (getaddrinfo(NULL/*any IP*/, serv, &hints, &res) != 0) {
660 perror("getaddrinfo");
661 return -1;
662 }
663 ressave = res;
664 do {
665 listenfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
666 if (listenfd < 0)
667 continue;
668 setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
669 if (bind(listenfd, res->ai_addr, res->ai_addrlen) == 0)
670 break; /* success */
671 close(listenfd);
672 } while ( (res = res->ai_next) );
673 if (!res)
674 return -1;
675 if (listen(listenfd, 1024)!=0) {
676 perror("listen");
677 return -1;
678 }
679 freeaddrinfo(ressave);
680 return listenfd;
5ac21963 681#else
682 int listenfd;
683 const int on = 1;
684 struct sockaddr_in sockin;
685
686 if ((listenfd = socket(PF_INET, SOCK_STREAM, AF_INET)) < 0) {
687 perror("socket(listenfd)");
688 return -1;
689 }
690 if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on) != 0)) {
691 perror("setsockopt(listenfd)");
692 close(listenfd);
693 return -1;
694 }
695 memset(&sockin, 0, sizeof(struct sockaddr_in));
696 sockin.sin_family = AF_INET;
697 sockin.sin_port = htons(portnum);
698 if (bind(listenfd, (struct sockaddr *)&sockin, sizeof(struct sockaddr_in)) != 0) {
699 perror("bind(listenfd)");
700 close(listenfd);
701 return -1;
702 }
703 if (listen(listenfd, 4) != 0) {
704 perror("listen(listenfd)");
705 close(listenfd);
706 return -1;
707 }
708
709 return listenfd;
710}
711#endif
7392c79f 712}
713
78b3fb13 714faim_internal int aim_get_command_rendezvous(struct aim_session_t *sess, struct aim_conn_t *conn)
7392c79f 715{
716
717 /* XXX: NOT THREAD SAFE RIGHT NOW. the locks are acting up. deal. -- jbm */
718
719 unsigned char hdrbuf1[6];
720 unsigned char *hdr = NULL;
721 int hdrlen, hdrtype;
722 int flags = 0;
723 rxcallback_t userfunc = NULL;
724
725
726 memset(hdrbuf1, 0, sizeof(hdrbuf1));
727
4dd56961 728 faim_mutex_lock(&conn->active); /* gets locked down for the entirety */
729
5ac21963 730 if ( (hdrlen = aim_recv(conn->fd, hdrbuf1, 6)) < 6) {
7392c79f 731 if(hdrlen < 0)
732 perror("read");
733 printf("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 734 faim_mutex_unlock(&conn->active);
1a8c261b 735 aim_conn_close(conn);
4dd56961 736 return -1;
7392c79f 737 }
738
739 hdrlen = aimutil_get16(hdrbuf1+4);
740
741 hdrlen -= 6;
742 if (!(hdr = malloc(hdrlen)))
743 return -1;
744
5ac21963 745 if (aim_recv(conn->fd, hdr, hdrlen) < hdrlen) {
7392c79f 746 perror("read");
747 printf("faim: rend: read2 error\n");
748 free(hdr);
4dd56961 749 faim_mutex_unlock(&conn->active);
1a8c261b 750 aim_conn_close(conn);
7392c79f 751 return 0; /* see comment on previous read check */
752 }
753
7392c79f 754 hdrtype = aimutil_get16(hdr);
755
756 switch (hdrtype) {
757 case 0x0001: { /* directim */
758 int payloadlength = 0;
759 char *snptr = NULL;
760 struct aim_directim_priv *priv;
761 int i;
762
763 priv = (struct aim_directim_priv *)calloc(1, sizeof(struct aim_directim_priv));
764
765 payloadlength = aimutil_get32(hdr+22);
766 flags = aimutil_get16(hdr+32);
78b3fb13 767 snptr = (char *)hdr+38;
7392c79f 768
769 strncpy(priv->sn, snptr, MAXSNLEN);
770
4dd56961 771#if 0
772 printf("faim: OFT frame: %04x / %04x / %04x / %s\n", hdrtype, payloadlength, flags, snptr);
773#endif
7392c79f 774
775 if (flags == 0x000e) {
4dd56961 776 faim_mutex_unlock(&conn->active);
7392c79f 777 if ( (userfunc = aim_callhandler(conn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMTYPING)) )
778 return userfunc(sess, NULL, snptr);
779 } else if ((flags == 0x0000) && payloadlength) {
780 unsigned char *msg;
4dd56961 781
782 if(! (msg = calloc(1, payloadlength+1)) ) {
783 faim_mutex_unlock(&conn->active);
7392c79f 784 return 0;
4dd56961 785 }
7392c79f 786
5ac21963 787 if (aim_recv(conn->fd, msg, payloadlength) < payloadlength) {
7392c79f 788 perror("read");
789 printf("faim: rend: read3 error\n");
790 free(msg);
4dd56961 791 faim_mutex_unlock(&conn->active);
1a8c261b 792 aim_conn_close(conn);
793 return -1;
7392c79f 794 }
4dd56961 795 faim_mutex_unlock(&conn->active);
7392c79f 796 msg[payloadlength] = '\0';
4dd56961 797#if 0
798 printf("faim: directim: %s/%04x/%04x/%s\n", snptr, payloadlength, flags, msg);
799#endif
7392c79f 800
801 if ( (userfunc = aim_callhandler(conn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMINCOMING)) )
802 i = userfunc(sess, NULL, conn, snptr, msg);
803
804 free(msg);
805 return i;
806 }
807 break;
808 }
809 case 0x1209: { /* get file first */
810 struct aim_filetransfer_priv *ft;
811 struct aim_fileheader_t *fh;
812 struct aim_msgcookie_t *cook;
813
7392c79f 814 int commandlen;
815 char *data;
816
817 printf("faim: rend: fileget 0x1209\n");
818
819 if(hdrlen != 0x100)
820 printf("faim: fileget_command(1209): um. hdrlen != 0x100.. 0x%x\n", hdrlen);
821
822 if(!(ft = (struct aim_filetransfer_priv *)calloc(1, sizeof(struct aim_filetransfer_priv)))) {
823 printf("faim: couldn't malloc ft. um. bad. bad bad. file transfer will likely fail, sorry.\n");
4dd56961 824 faim_mutex_unlock(&conn->active);
7392c79f 825 return 0;
826 }
827
828 fh = aim_oft_getfh(hdr);
829
830 memcpy(&(ft->fh), fh, sizeof(struct aim_fileheader_t));
831
78b3fb13 832 cook = aim_checkcookie(sess, (unsigned char *)ft->fh.bcookie, AIM_COOKIETYPE_OFTGET);
7392c79f 833
834 if(cook->data)
835 free(cook->data); /* XXX */
836
837 cook->data = ft;
838
839 aim_cachecookie(sess, cook);
840
841 commandlen = 36;
842
843 data = calloc(1, commandlen);
844 memcpy(data, "01/01/1999 00:00 100 file.txt\r\n", commandlen);
845
5ac21963 846 if (send(conn->fd, data, commandlen, 0) != commandlen) {
7392c79f 847 perror("listing write error");
848 }
4dd56961 849 faim_mutex_unlock(&conn->active);
7392c79f 850
851 printf("jbm: hit end of 1209\n");
852
853 break;
854 }
855 case 0x120b: { /* get file second */
856 struct aim_filetransfer_priv *ft;
857 struct aim_msgcookie_t *cook;
858
859 struct aim_fileheader_t *fh;
860
861 printf("faim: rend: fileget 120b\n");
862
863 if(!(ft = (struct aim_filetransfer_priv *)calloc(1, sizeof(struct aim_filetransfer_priv)))) {
864 printf("faim: couldn't malloc ft. um. bad. bad bad. file transfer will likely fail, sorry.\n");
4dd56961 865 faim_mutex_unlock(&conn->active);
7392c79f 866 return 0;
867 }
868
869 if(hdrlen != 0x100)
870 printf("faim: fileget_command(120b): um. hdrlen != 0x100..\n");
871
872 fh = aim_oft_getfh(hdr);
873
874 memcpy(&(ft->fh), fh, sizeof(struct aim_fileheader_t));
875
78b3fb13 876 cook = aim_checkcookie(sess, (unsigned char *)ft->fh.bcookie, AIM_COOKIETYPE_OFTGET);
7392c79f 877
878 if(cook->data)
879 free(cook->data); /* XXX: integrate cookie caching */
880
881 cook->data = ft;
882
883 aim_cachecookie(sess, cook);
4dd56961 884
885 faim_mutex_unlock(&conn->active);
7392c79f 886
887 break;
888 }
889 case 0x120c: { /* yet more get file */
890 struct aim_filetransfer_priv *ft;
891 struct aim_msgcookie_t *cook;
892 struct aim_fileheader_t *listingfh;
893 struct command_tx_struct *newoft;
894 int curbyte, i;
895
896 printf("faim: rend: fileget 120c\n");
897
898 if(!(ft = (struct aim_filetransfer_priv *)calloc(1, sizeof(struct aim_filetransfer_priv)))) {
899 printf("faim: couldn't malloc ft. um. bad. bad bad. file transfer will likely fail, sorry.\n");
4dd56961 900 faim_mutex_unlock(&conn->active);
7392c79f 901 return 0;
902 }
903
904 if(hdrlen != 0x100)
905 printf("faim: fileget_command(120c): um. hdrlen != 0x100..\n");
906
78b3fb13 907 listingfh = aim_oft_getfh(hdr);
7392c79f 908
909 memcpy(&(ft->fh), listingfh, sizeof(struct aim_fileheader_t));
910
78b3fb13 911 cook = aim_checkcookie(sess, (unsigned char *)ft->fh.bcookie, AIM_COOKIETYPE_OFTGET);
7392c79f 912
913 if(cook->data)
914 free(cook->data); /* XXX */
915
916 cook->data = ft;
917
918 aim_cachecookie(sess, cook);
919
4dd56961 920 faim_mutex_unlock(&conn->active);
921
7392c79f 922 printf("faim: fileget: %s seems to want %s\n", ft->sn, ft->fh.name);
923
924 if(!(newoft = aim_tx_new(AIM_FRAMETYPE_OFT, 0x0101, conn, 0/*listingfh->size*/))) {
925 printf("faim: send_final_transfer: tx_new OFT failed\n");
926 return 0;
927 }
928
929 /* XXX: actually implement Real Handling of all this */
930
931 printf("jbm: listingfh->size: 0x%lx\n", listingfh->size);
932
933 newoft->lock = 1;
934
935 /* if(!(newoft->data = calloc(1, listingfh->size))) {
936 printf("newoft data malloc failed. bombing.\n");
937 return 0;
938 }*/
939
940 if(newoft->commandlen > 0) {
941 int i;
5ac21963 942 memset(newoft->data, 0, newoft->commandlen);
943 for(i = 0; i < (signed)newoft->commandlen; i++)
7392c79f 944 newoft->data[i] = 0x30 + (i%10);
945
946 // memcpy(newoft->data, "This has been a Test\r\n-josh\r\n", newoft->commandlen);
947 }
948
949 memcpy(newoft->hdr.oft.magic, "OFT2", 4);
950 newoft->hdr.oft.hdr2len = 0xf8; /* 0x100 - 8 */
951
952 if (!(newoft->hdr.oft.hdr2 = calloc(1,newoft->hdr.oft.hdr2len))) {
953 if(newoft->data)
954 free(newoft->data); /* XXX: make this into a destructor function */
955 free(newoft);
956 return 0;
957 }
958
959 memcpy(listingfh->bcookie, ft->fh.bcookie, 8);
960
961 curbyte = 0;
962
963 for(i = 0; i < 8; i++)
964 curbyte += aimutil_put8(newoft->hdr.oft.hdr2+curbyte, listingfh->bcookie[i]);
965 curbyte += aimutil_put16(newoft->hdr.oft.hdr2+curbyte, listingfh->encrypt);
966 curbyte += aimutil_put16(newoft->hdr.oft.hdr2+curbyte, listingfh->compress);
967 curbyte += aimutil_put16(newoft->hdr.oft.hdr2+curbyte, listingfh->totfiles);
968 curbyte += aimutil_put16(newoft->hdr.oft.hdr2+curbyte, listingfh->filesleft);
969 curbyte += aimutil_put16(newoft->hdr.oft.hdr2+curbyte, listingfh->totparts);
970 curbyte += aimutil_put16(newoft->hdr.oft.hdr2+curbyte, listingfh->partsleft);
971 curbyte += aimutil_put32(newoft->hdr.oft.hdr2+curbyte, listingfh->totsize);
972 curbyte += aimutil_put32(newoft->hdr.oft.hdr2+curbyte, listingfh->size);
973 curbyte += aimutil_put32(newoft->hdr.oft.hdr2+curbyte, listingfh->modtime);
974 curbyte += aimutil_put32(newoft->hdr.oft.hdr2+curbyte, listingfh->checksum);
975 curbyte += aimutil_put32(newoft->hdr.oft.hdr2+curbyte, listingfh->rfrcsum);
976 curbyte += aimutil_put32(newoft->hdr.oft.hdr2+curbyte, listingfh->rfsize);
977 curbyte += aimutil_put32(newoft->hdr.oft.hdr2+curbyte, listingfh->cretime);
978 curbyte += aimutil_put32(newoft->hdr.oft.hdr2+curbyte, listingfh->rfcsum);
979 curbyte += aimutil_put32(newoft->hdr.oft.hdr2+curbyte, 0 /*listingfh->nrecvd*/);
980 curbyte += aimutil_put32(newoft->hdr.oft.hdr2+curbyte, 0/*listingfh->recvcsum*/);
981
78b3fb13 982 strncpy((char *)newoft->hdr.oft.hdr2+curbyte, listingfh->idstring, 32);
7392c79f 983 curbyte += 32;
984
985 curbyte += aimutil_put8(newoft->hdr.oft.hdr2+curbyte, 0x20 /*listingfh->flags */);
986 curbyte += aimutil_put8(newoft->hdr.oft.hdr2+curbyte, listingfh->lnameoffset);
987 curbyte += aimutil_put8(newoft->hdr.oft.hdr2+curbyte, listingfh->lsizeoffset);
988
989 memcpy(newoft->hdr.oft.hdr2+curbyte, listingfh->dummy, 69);
990 curbyte += 69;
991
992 memcpy(newoft->hdr.oft.hdr2+curbyte, listingfh->macfileinfo, 16);
993 curbyte += 16;
994
995 curbyte += aimutil_put16(newoft->hdr.oft.hdr2+curbyte, listingfh->nencode);
996 curbyte += aimutil_put16(newoft->hdr.oft.hdr2+curbyte, listingfh->nlanguage);
997
78b3fb13 998 strncpy((char *)newoft->hdr.oft.hdr2+curbyte, listingfh->name, 64);
7392c79f 999 curbyte += 64;
1000
1001 free(listingfh);
1002
1003 newoft->lock = 0;
1004 aim_tx_enqueue(sess, newoft);
1005 printf("jbm: OFT listing enqueued.\n");
1006
1007 break;
1008 }
1009 case 0x0202: { /* get file: ready to recieve data */
1010 char *c;
1011 int i;
1012
1013 struct aim_fileheader_t *fh;
78b3fb13 1014 fh = aim_oft_getfh(hdr);
7392c79f 1015
1016 c = (char *)calloc(1, fh->size);
1017
1018 printf("looks like we're ready to send data.(oft 0x0202)\n");
1019
1020
1021
1022 for(i = 0; i < fh->size; i++)
1023 c[i] = 0x30 + (i%10);
1024
5ac21963 1025 if ( (i = send(conn->fd, c, fh->size, 0)) != fh->size ) {
7392c79f 1026 printf("whoopsy, didn't write it all...\n");
1027 }
1028
4dd56961 1029 faim_mutex_unlock(&conn->active);
1030
7392c79f 1031 break;
1032 }
1033 case 0x0204: { /* get file: finished. close it up */
1034 printf("looks like we're done with a transfer (oft 0x0204)\n");
4dd56961 1035 faim_mutex_unlock(&conn->active);
1a8c261b 1036 aim_conn_close(conn);
7392c79f 1037 break;
1038 }
1039 default: {
1040 printf("OFT frame: type %04x\n", hdrtype);
1041 /* data connection may be unreliable here */
4dd56961 1042 faim_mutex_unlock(&conn->active);
7392c79f 1043 break;
1044 }
1045 } /* switch */
1046
1047 free(hdr);
1048
1049 return 0;
1050}
1051
1052/*
1053 * this currently feeds totally bogus data
1054 */
1055
78b3fb13 1056faim_internal struct aim_fileheader_t *aim_oft_getfh(unsigned char *hdr)
7392c79f 1057{
1058 struct aim_fileheader_t *fh;
1059 int i, j;
1060
1061 if(!(fh = calloc(1, sizeof(struct aim_fileheader_t))))
1062 return NULL;
1063
1064 /* [0] and [1] are the type. we can ignore those here. */
1065
1066 i = 2;
1067
1068 for(j = 0; j < 8; j++, i++)
1069 fh->bcookie[j] = hdr[i];
1070 fh->encrypt = aimutil_get16(hdr+i);
1071 i += 2;
1072 fh->compress = aimutil_get16(hdr+i);
1073 i += 2;
1074 fh->totfiles = aimutil_get16(hdr+i);
1075 i += 2;
1076 fh->filesleft = aimutil_get16(hdr+i);
1077 i += 2;
1078 fh->totparts = aimutil_get16(hdr+i);
1079 i += 2;
1080 fh->partsleft = aimutil_get16(hdr+i);
1081 i += 2;
1082 fh->totsize = aimutil_get32(hdr+i);
1083 i += 4;
1084 fh->size = aimutil_get32(hdr+i);
1085 i += 4;
1086 fh->modtime = aimutil_get32(hdr+i);
1087 i += 4;
1088 fh->checksum = aimutil_get32(hdr+i);
1089 i += 4;
1090 fh->rfrcsum = aimutil_get32(hdr+i);
1091 i += 4;
1092 fh->rfsize = aimutil_get32(hdr+i);
1093 i += 4;
1094 fh->cretime = aimutil_get32(hdr+i);
1095 i += 4;
1096 fh->rfcsum = aimutil_get32(hdr+i);
1097 i += 4;
1098 fh->nrecvd = aimutil_get32(hdr+i);
1099 i += 4;
1100 fh->recvcsum = aimutil_get32(hdr+i);
1101 i += 4;
1102
1103 memcpy(fh->idstring, hdr+i, 32);
1104 i += 32;
1105
1106 fh->flags = aimutil_get8(hdr+i);
1107 i += 1;
1108 fh->lnameoffset = aimutil_get8(hdr+i);
1109 i += 1;
1110 fh->lsizeoffset = aimutil_get8(hdr+i);
1111 i += 1;
1112
1113 memcpy(fh->dummy, hdr+i, 69);
1114 i += 69;
1115
1116 memcpy(fh->macfileinfo, hdr+i, 16);
1117 i += 16;
1118
1119 fh->nencode = aimutil_get16(hdr+i);
1120 i += 2;
1121 fh->nlanguage = aimutil_get16(hdr+i);
1122 i += 2;
1123
1124 memcpy(fh->name, hdr+i, 64);
1125 i += 64;
1126
1127 return fh;
1128}
This page took 0.202086 seconds and 5 git commands to generate.