]> andersk Git - libfaim.git/blob - aim_ft.c
- Sun Jul 16 11:03:28 GMT 2000
[libfaim.git] / aim_ft.c
1 #include <faim/aim.h>
2
3 #include <sys/utsname.h> /* for aim_directim_initiate */
4 #include <arpa/inet.h> /* for inet_ntoa */
5
6 /* aim_msgcookies.c is mostly new. just look at the diff and replace yours, easiest. */
7
8 /* 
9    function name       where i had it
10    aim_send_im_direct aim_im.c
11    aim_directim_initiate aim_im.c
12    aim_filetransfer_accept aim_im.c
13    aim_getlisting aim_misc.c (?!) -- prototype function. can be ignored.
14    establish aim_misc.c
15    aim_get_command_rendezvous aim_rxqueue.c
16    oft_getfh aim_rxqueue.c
17 */
18
19 int aim_handlerendconnect(struct aim_session_t *sess, struct aim_conn_t *cur)
20 {
21   int acceptfd = 0;
22   rxcallback_t userfunc;
23   struct sockaddr cliaddr;
24   socklen_t clilen = sizeof(cliaddr);
25   int ret = 0;
26
27   /*
28    * Listener sockets only have incoming connections. No data.
29    */
30   if( (acceptfd = accept(cur->fd, &cliaddr, &clilen)) == -1)
31     return -1;
32
33   if (cliaddr.sa_family != AF_INET) /* just in case IPv6 really is happening */
34     return -1;
35
36   switch(cur->subtype) {
37   case AIM_CONN_SUBTYPE_OFT_DIRECTIM: {
38     struct aim_directim_priv *priv;
39     
40     priv = (struct aim_directim_priv *)calloc(1, sizeof(struct aim_directim_priv));
41
42     snprintf(priv->ip, sizeof(priv->ip), "%s:%u", inet_ntoa(((struct sockaddr_in *)&cliaddr)->sin_addr), ntohs(((struct sockaddr_in *)&cliaddr)->sin_port));
43
44     if(!cur->priv)
45       cur->priv = priv; /* what happens if there is one?! -- mid */
46
47     cur->type = AIM_CONN_TYPE_RENDEZVOUS;
48     close(cur->fd); /* should we really do this? seems like the client should decide. maybe clone the connection and keep the listener open. -- mid */
49     cur->fd = acceptfd;
50
51     if ( (userfunc = aim_callhandler(cur, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMINITIATE)))
52       ret = userfunc(sess, NULL, cur);
53                                    
54     break;
55   }
56   case AIM_CONN_SUBTYPE_OFT_GETFILE: {
57     struct aim_filetransfer_priv *priv;
58
59     priv->state = 0;
60
61     priv = (struct aim_filetransfer_priv *)calloc(1, sizeof(struct aim_filetransfer_priv));
62
63     snprintf(priv->ip, sizeof(priv->ip), "%s:%u", inet_ntoa(((struct sockaddr_in *)&cliaddr)->sin_addr), ntohs(((struct sockaddr_in *)&cliaddr)->sin_port));
64
65     if(!cur->priv)
66       cur->priv = priv;
67
68     if ( (userfunc = aim_callhandler(cur, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILEINITIATE)))
69       ret = userfunc(sess, NULL, cur);
70     break;
71   } 
72   default: {
73     /* XXX */
74   }
75   }
76   return ret;
77 }
78
79
80 /*
81  * aim_send_im_direct:
82  * sess - session
83  * conn - directim connection
84  * msg  - null-terminated string to send
85  */
86
87 int aim_send_im_direct(struct aim_session_t *sess, 
88                        struct aim_conn_t *conn,
89                        char *msg)
90 {
91   struct command_tx_struct *newpacket , *newpacket2; 
92
93   /* newpacket contains a real header with data, newpacket2 is just a
94      null packet, with a cookie and a lot of 0x00s. newpacket is the
95      "i'm sending", newpacket2 is the "i'm typing".*/
96
97   /* uhm. the client should send those as two seperate things -- mid */
98
99   struct aim_directim_priv *priv = NULL;
100   int i;
101
102   if (strlen(msg) >= MAXMSGLEN)
103     return -1;
104
105   if (!sess || !conn || !(conn->type) || (conn->type != AIM_CONN_TYPE_RENDEZVOUS) || !conn->priv) {
106     printf("faim: directim: invalid arguments\n");
107     return -1;
108   };
109
110   priv = (struct aim_directim_priv *)conn->priv;
111
112   /* NULLish Header */
113
114   if (!(newpacket2 = aim_tx_new(AIM_FRAMETYPE_OFT, 0x0001, conn, 0))) {
115     printf("faim: directim: tx_new2 failed\n");
116     return -1;
117   }                                                                           
118
119   newpacket2->lock = 1; /* lock struct */
120
121   memcpy(newpacket2->hdr.oft.magic, "ODC2", 4);
122   newpacket2->hdr.oft.hdr2len = 0x44;
123
124   if (!(newpacket2->hdr.oft.hdr2 = calloc(1,newpacket2->hdr.oft.hdr2len))) {
125     free(newpacket2);
126     return -1;
127   }
128
129   i = 0;
130   i += aimutil_put16(newpacket2->hdr.oft.hdr2+i, 0x0006);
131   i += aimutil_put16(newpacket2->hdr.oft.hdr2+i, 0x0000);
132
133   i += aimutil_putstr(newpacket2->hdr.oft.hdr2+i, priv->cookie, 8);
134
135   i += aimutil_put16(newpacket2->hdr.oft.hdr2+i, 0x0000);
136   i += aimutil_put16(newpacket2->hdr.oft.hdr2+i, 0x0000);
137   i += aimutil_put16(newpacket2->hdr.oft.hdr2+i, 0x0000);
138   i += aimutil_put16(newpacket2->hdr.oft.hdr2+i, 0x0000);
139
140   i += aimutil_put32(newpacket2->hdr.oft.hdr2+i, 0x00000000);
141
142   i += aimutil_put16(newpacket2->hdr.oft.hdr2+i, 0x0000);
143   i += aimutil_put16(newpacket2->hdr.oft.hdr2+i, 0x0000);
144   i += aimutil_put16(newpacket2->hdr.oft.hdr2+i, 0x0000);
145
146   i += aimutil_put16(newpacket2->hdr.oft.hdr2+i, 0x000e);
147
148   i += aimutil_put16(newpacket2->hdr.oft.hdr2+i, 0x0000);
149   i += aimutil_put16(newpacket2->hdr.oft.hdr2+i, 0x0000);
150
151   i += aimutil_putstr(newpacket2->hdr.oft.hdr2+i, sess->logininfo.screen_name, strlen(sess->logininfo.screen_name));
152   
153   i = 52; /* 0x34 */
154   i += aimutil_put8(newpacket2->hdr.oft.hdr2+i, 0x00); /* 53 */
155   i += aimutil_put16(newpacket2->hdr.oft.hdr2+i, 0x0000); /* 55 */
156   i += aimutil_put16(newpacket2->hdr.oft.hdr2+i, 0x0000);
157   i += aimutil_put16(newpacket2->hdr.oft.hdr2+i, 0x0000);
158   i += aimutil_put16(newpacket2->hdr.oft.hdr2+i, 0x0000);/* 61 */
159   i += aimutil_put16(newpacket2->hdr.oft.hdr2+i, 0x0000);
160   i += aimutil_put16(newpacket2->hdr.oft.hdr2+i, 0x0000);/* 65 */
161   i += aimutil_put16(newpacket2->hdr.oft.hdr2+i, 0x0000);/* end of hdr2 */
162
163   newpacket2->lock = 0;
164   newpacket2->data = NULL;
165   
166   aim_tx_enqueue(sess, newpacket2);
167
168   /* Header packet */
169
170   if (!(newpacket = aim_tx_new(AIM_FRAMETYPE_OFT, 0x0001, conn, strlen(msg)))) {
171     printf("faim: directim: tx_new failed\n");
172     return -1;
173   }
174
175   newpacket->lock = 1; /* lock struct */
176
177   memcpy(newpacket->hdr.oft.magic, "ODC2", 4);
178   newpacket->hdr.oft.hdr2len = 0x54;
179
180   if (!(newpacket->hdr.oft.hdr2 = calloc(1,newpacket->hdr.oft.hdr2len))) {
181     free(newpacket);
182     return -1;
183   }
184
185   i = 0;
186   i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0006);
187   i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0000);
188
189   i += aimutil_putstr(newpacket->hdr.oft.hdr2+i, priv->cookie, 8);
190
191   i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0000);
192   i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0000);
193   i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0000);
194   i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0000);
195
196   i += aimutil_put32(newpacket->hdr.oft.hdr2+i, strlen(msg));
197
198   i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0000);
199   i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0000);
200   i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0000);
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
205   i += aimutil_putstr(newpacket->hdr.oft.hdr2+i, sess->logininfo.screen_name, strlen(sess->logininfo.screen_name));
206   
207   i = 52; /* 0x34 */
208   i += aimutil_put8(newpacket->hdr.oft.hdr2+i, 0x00); /* 53 */
209   i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0000); /* 55 */
210   i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0000);
211   i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0000);
212   i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0000);/* 61 */
213   i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0000);
214   i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0000);/* 65 */
215   i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0000);/* end of hdr2 */
216
217   /* values grabbed from a dump */
218   i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0008); /* 69 */
219   i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x000c);
220   i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0000);/* 71 */
221   i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x1466);/* 73 */ 
222   i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x0001);/* 73 */ 
223   i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x2e0f);
224   i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0x393e);
225   i += aimutil_put16(newpacket->hdr.oft.hdr2+i, 0xcac8);
226
227   memcpy(newpacket->data, msg, strlen(msg));
228
229   newpacket->lock = 0;
230
231   aim_tx_enqueue(sess, newpacket);
232
233   return 0;
234 }
235
236 /*
237  * aim_directim_intitiate:
238  * For those times when we want to open up the directim channel ourselves.
239  * sess is your session,
240  * conn is the BOS conn,
241  * priv is a dummy priv value (we'll let it get filled in later) (if
242  * you pass a NULL, we alloc one) 
243  * destsn is the SN to connect to.  
244  */
245
246
247 struct aim_conn_t *aim_directim_initiate(struct aim_session_t *sess,
248                           struct aim_conn_t *conn,
249                           struct aim_directim_priv *priv,
250                           char *destsn)
251 {
252   struct command_tx_struct *newpacket;
253   struct aim_conn_t *newconn;
254
255   struct aim_msgcookie_t *cookie;
256
257   int curbyte, i, listenfd;
258   short port = 4443;
259
260   struct hostent *hptr;
261   struct utsname myname;
262
263   char cap[16];
264   char d[4]; /* XXX: IPv6. *cough* */
265
266   /*
267    * Open our socket
268    */
269
270   if( (listenfd = aim_listenestablish(port)) == -1)
271     return NULL;
272
273   /*
274    * get our local IP
275    */
276
277   if(uname(&myname) < 0)
278     return NULL;
279
280   if( (hptr = gethostbyname(myname.nodename)) == NULL)
281     return NULL;
282
283   memcpy(&d, hptr->h_addr_list[0], 4); /* XXX: this probably isn't quite kosher, but it works */
284
285   aim_putcap(cap, 16, AIM_CAPS_IMIMAGE);
286
287   /*
288    * create the OSCAR packet
289    */
290
291   if (!(newpacket = aim_tx_new(AIM_FRAMETYPE_OSCAR, 0x0002, conn, 10+8+2+1+strlen(destsn)+4+4+0x32)))
292     return NULL;
293
294   newpacket->lock = 1; /* lock struct */
295
296   curbyte  = 0;
297   curbyte += aim_putsnac(newpacket->data+curbyte, 
298                          0x0004, 0x0006, 0x0000, sess->snac_nextid);
299
300   /* 
301    * Generate a random message cookie 
302    * This cookie needs to be alphanumeric and NULL-terminated to be TOC-compatible.
303    */
304   for (i=0;i<7;i++)
305     curbyte += aimutil_put8(newpacket->data+curbyte, 0x30 + ((u_char) random() % 20));
306   curbyte += aimutil_put8(newpacket->data+curbyte, 0x00);
307
308   /*
309    * grab all the data for cookie caching.
310    */
311   cookie = (struct aim_msgcookie_t *)calloc(1, sizeof(struct aim_msgcookie_t));
312
313   memcpy(cookie->cookie, newpacket->data+curbyte-8, 8);
314   cookie->type = AIM_COOKIETYPE_OFTIM;
315   
316   if(!priv)
317     priv = (struct aim_directim_priv *)calloc(1, sizeof(struct aim_directim_priv));
318
319   memcpy(priv->cookie, cookie, 8);
320   memcpy(priv->sn, destsn, sizeof(priv->sn));
321  
322   cookie->data = priv;
323
324   aim_cachecookie(sess, cookie);  /* cache da cookie */
325
326   /*
327    * Channel ID
328    */
329   curbyte += aimutil_put16(newpacket->data+curbyte,0x0002);
330
331   /* 
332    * Destination SN (prepended with byte length)
333    */
334   curbyte += aimutil_put8(newpacket->data+curbyte,strlen(destsn));
335   curbyte += aimutil_putstr(newpacket->data+curbyte, destsn, strlen(destsn));
336
337   curbyte += aimutil_put16(newpacket->data+curbyte, 0x0003);
338   curbyte += aimutil_put16(newpacket->data+curbyte, 0x0000);
339
340   /* 
341    * enTLV start
342    */
343   curbyte += aimutil_put16(newpacket->data+curbyte, 0x0005);
344   curbyte += aimutil_put16(newpacket->data+curbyte, 0x0032);
345
346   /*
347    * Flag data / ICBM Parameters?
348    */
349   curbyte += aimutil_put8(newpacket->data+curbyte, 0x00);
350   curbyte += aimutil_put8(newpacket->data+curbyte, 0x00);
351
352   /*
353    * Cookie 
354    */
355   curbyte += aimutil_putstr(newpacket->data+curbyte, (char *)cookie, 8);
356
357   /*
358    * Capability String
359    */
360   curbyte += aimutil_putstr(newpacket->data+curbyte, (char *)cap, 0x10);
361
362   /*
363    * 000a/0002 : 0001
364    */
365   curbyte += aimutil_put16(newpacket->data+curbyte, 0x000a);
366   curbyte += aimutil_put16(newpacket->data+curbyte, 0x0002);
367   curbyte += aimutil_put16(newpacket->data+curbyte, 0x0001);
368
369   /*
370    * 0003/0004: IP address
371    */
372
373   curbyte += aimutil_put16(newpacket->data+curbyte, 0x0003);
374   curbyte += aimutil_put16(newpacket->data+curbyte, 0x0004);
375
376   for(i = 0; i < 4; i++)
377     curbyte += aimutil_put8(newpacket->data+curbyte, d[i]); /* already in network byte order */
378
379   /*
380    * 0005/0002: Port
381    */
382
383   curbyte += aimutil_put16(newpacket->data+curbyte, 0x0005);
384   curbyte += aimutil_put16(newpacket->data+curbyte, 0x0002);
385   curbyte += aimutil_put16(newpacket->data+curbyte, port);
386
387   /*
388    * 000f/0000: umm.. dunno. Zigamorph[1]?
389    * [1]: see esr's TNHD.
390    */
391
392   curbyte += aimutil_put16(newpacket->data+curbyte, 0x000f);
393   curbyte += aimutil_put16(newpacket->data+curbyte, 0x0000);
394
395   printf("curbyte: 0x%x\n",curbyte);
396
397   newpacket->commandlen = curbyte;
398   newpacket->lock = 0;
399
400   aim_tx_enqueue(sess, newpacket);
401
402   /*
403    * allocate and set up our connection
404    */
405
406   i = fcntl(listenfd, F_GETFL, 0);
407   fcntl(listenfd, F_SETFL, i | O_NONBLOCK);
408
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
426 #ifdef USE_SNAC_FOR_IMS
427  {
428     struct aim_snac_t snac;
429
430     snac.id = sess->snac_nextid;
431     snac.family = 0x0004;
432     snac.type = 0x0006;
433     snac.flags = 0x0000;
434
435     snac.data = malloc(strlen(destsn)+1);
436     memcpy(snac.data, destsn, strlen(destsn)+1);
437
438     aim_newsnac(sess, &snac);
439
440     aim_cleansnacs(sess, 60); /* clean out all SNACs over 60sec old */
441   }
442 #endif
443   
444   return (newconn);
445
446
447
448 struct aim_conn_t *aim_directim_connect(struct aim_session_t *sess,
449                                         struct aim_conn_t *conn,
450                                         struct aim_directim_priv *priv )
451 {
452   struct aim_conn_t *newconn = NULL;;
453
454   newconn = aim_newconn(sess, AIM_CONN_TYPE_RENDEZVOUS, priv->ip);
455   if (!newconn || (newconn->fd == -1)) { 
456     printf("could not connect to %s\n", priv->ip);
457     perror("aim_newconn");
458     aim_conn_kill(sess, &newconn);
459     return NULL;
460   } else {    
461     newconn->subtype = AIM_CONN_SUBTYPE_OFT_DIRECTIM;
462     newconn->priv = priv;
463     printf("faim: connected to peer (fd = %d)\n", newconn->fd);
464     return newconn;
465   }
466   return newconn;
467 }
468
469 u_long aim_accepttransfer(struct aim_session_t *sess,
470                           struct aim_conn_t *conn, 
471                           struct aim_conn_t *oftconn,
472                           char *sn,
473                           char *cookie,
474                           unsigned short rendid)
475 {
476   struct command_tx_struct *newpacket, *newoft;
477   struct aim_fileheader_t *listingfh;
478   int curbyte, i;
479   /* now for the oft bits */
480
481   if(rendid == AIM_CAPS_GETFILE) {
482     printf("jbm: getfile request accept\n");
483     if(!(newoft = aim_tx_new(AIM_FRAMETYPE_OFT, 0x1108, oftconn, 0))) {
484       printf("faim: accept_transfer: tx_new OFT failed\n");
485       return -1;
486     }
487     
488     newoft->lock = 1;
489     
490     memcpy(newoft->hdr.oft.magic, "OFT2", 4);
491     newoft->hdr.oft.hdr2len = 0xf8; /* 0x100 - 8 */
492     
493     if (!(newoft->hdr.oft.hdr2 = calloc(1,newoft->hdr.oft.hdr2len))) {
494       free(newoft);
495       return -1;
496     }  
497
498     listingfh = aim_getlisting(sess);
499
500     memcpy(listingfh->bcookie, cookie, 8);
501
502     curbyte = 0;
503     
504     for(i = 0; i < 8; i++)
505       curbyte += aimutil_put8(newoft->hdr.oft.hdr2+curbyte, cookie[i]);
506     curbyte += aimutil_put16(newoft->hdr.oft.hdr2+curbyte, listingfh->encrypt);
507     curbyte += aimutil_put16(newoft->hdr.oft.hdr2+curbyte, listingfh->compress);
508     curbyte += aimutil_put16(newoft->hdr.oft.hdr2+curbyte, listingfh->totfiles);
509     curbyte += aimutil_put16(newoft->hdr.oft.hdr2+curbyte, listingfh->filesleft);
510     curbyte += aimutil_put16(newoft->hdr.oft.hdr2+curbyte, listingfh->totparts);
511     curbyte += aimutil_put16(newoft->hdr.oft.hdr2+curbyte, listingfh->partsleft);
512     curbyte += aimutil_put32(newoft->hdr.oft.hdr2+curbyte, listingfh->totsize);
513     curbyte += aimutil_put32(newoft->hdr.oft.hdr2+curbyte, listingfh->size);
514     curbyte += aimutil_put32(newoft->hdr.oft.hdr2+curbyte, listingfh->modtime);
515     curbyte += aimutil_put32(newoft->hdr.oft.hdr2+curbyte, listingfh->checksum);
516     curbyte += aimutil_put32(newoft->hdr.oft.hdr2+curbyte, listingfh->rfrcsum);
517     curbyte += aimutil_put32(newoft->hdr.oft.hdr2+curbyte, listingfh->rfsize);
518     curbyte += aimutil_put32(newoft->hdr.oft.hdr2+curbyte, listingfh->cretime);
519     curbyte += aimutil_put32(newoft->hdr.oft.hdr2+curbyte, listingfh->rfcsum);
520     curbyte += aimutil_put32(newoft->hdr.oft.hdr2+curbyte, listingfh->nrecvd);
521     curbyte += aimutil_put32(newoft->hdr.oft.hdr2+curbyte, listingfh->recvcsum);
522
523     memcpy(newoft->hdr.oft.hdr2+curbyte, listingfh->idstring, 32);
524     curbyte += 32;
525
526     curbyte += aimutil_put8(newoft->hdr.oft.hdr2+curbyte, listingfh->flags);
527     curbyte += aimutil_put8(newoft->hdr.oft.hdr2+curbyte, listingfh->lnameoffset);
528     curbyte += aimutil_put8(newoft->hdr.oft.hdr2+curbyte, listingfh->lsizeoffset);
529
530     memcpy(newoft->hdr.oft.hdr2+curbyte, listingfh->dummy, 69);
531     curbyte += 69;
532     
533     memcpy(newoft->hdr.oft.hdr2+curbyte, listingfh->macfileinfo, 16);
534     curbyte += 16;
535
536     curbyte += aimutil_put16(newoft->hdr.oft.hdr2+curbyte, listingfh->nencode);
537     curbyte += aimutil_put16(newoft->hdr.oft.hdr2+curbyte, listingfh->nlanguage);
538
539     memcpy(newoft->hdr.oft.hdr2+curbyte, listingfh->name, 64);
540     curbyte += 64;
541
542     free(listingfh);
543
544     newoft->lock = 0;
545     aim_tx_enqueue(sess, newoft);
546     printf("faim: getfile: OFT listing enqueued.\n");
547     
548   }
549
550
551   if(!(newpacket = aim_tx_new(AIM_FRAMETYPE_OSCAR, 0x0002, conn, 10+8+2+1+strlen(sn)+4+2+8+16)))
552     return -1;
553   
554   newpacket->lock = 1;
555   
556   curbyte = aim_putsnac(newpacket->data, 0x0004, 0x0006, 0x0000, sess->snac_nextid);
557   for (i = 0; i < 8; i++)
558     curbyte += aimutil_put8(newpacket->data+curbyte, cookie[i]);
559   curbyte += aimutil_put16(newpacket->data+curbyte, 0x0002);
560   curbyte += aimutil_put8(newpacket->data+curbyte, strlen(sn));
561   curbyte += aimutil_putstr(newpacket->data+curbyte, sn, strlen(sn));
562   curbyte += aimutil_put16(newpacket->data+curbyte, 0x0005);
563   curbyte += aimutil_put16(newpacket->data+curbyte, 0x001a);
564   curbyte += aimutil_put16(newpacket->data+curbyte, 0x0002 /* accept */);
565   for (i = 0; i < 8; i++)
566     curbyte += aimutil_put8(newpacket->data+curbyte, cookie[i]);
567   curbyte += aim_putcap(newpacket->data+curbyte, 0x10, rendid);
568
569   newpacket->lock = 0;
570   aim_tx_enqueue(sess, newpacket);
571
572
573
574   return (sess->snac_nextid++);
575 }
576
577 /*
578  * aim_getlisting()
579  * 
580  * Get file listing.txt info. where else to put it? i
581  * dunno. client-side issue for sure tho. for now we just side-step
582  * the issue with a nice default. =)
583  *  
584  */
585
586 struct aim_fileheader_t *aim_getlisting(struct aim_session_t *sess) 
587 {
588   struct aim_fileheader_t *fh;
589
590   if(!(fh = (struct aim_fileheader_t*)calloc(1, sizeof(struct aim_fileheader_t))))
591     return NULL;
592
593   fh->encrypt     = 0x0000;
594   fh->compress    = 0x0000;
595   fh->totfiles    = 0x0001;
596   fh->filesleft   = 0x0001;
597   fh->totparts    = 0x0001;
598   fh->partsleft   = 0x0001;
599   fh->totsize     = 0x00000064;
600   fh->size        = 0x00000024; /* ls -l listing.txt */
601   fh->modtime     = (int)time(NULL); /*0x39441fb4; */
602   fh->checksum    = 0xb8350000;
603   fh->rfcsum      = 0x00000000;
604   fh->rfsize      = 0x00000000;
605   fh->cretime     = 0x00000000;
606   fh->rfcsum      = 0x00000000;
607   fh->nrecvd      = 0x00000000;
608   fh->recvcsum    = 0x00000000;
609
610   memset(fh->idstring, 0, 32/*sizeof(fh->idstring)*/);
611   memcpy(fh->idstring, "OFT_Windows ICBMFT V1.1 32", 32/*sizeof(fh->idstring)*/);
612   memset(fh->idstring+strlen(fh->idstring), 0, 32-strlen(fh->idstring)); /* jbm hack */ 
613
614   fh->flags       = 0x02;
615   fh->lnameoffset = 0x1a;
616   fh->lsizeoffset = 0x10;
617
618   memset(fh->dummy, 0, 69/*sizeof(fh->dummy)*/);
619   /*  fh->dummy = ;*/
620
621   memset(fh->macfileinfo, 0, 16/*sizeof(fh->macfileinfo)*/);
622   /*  fh->macfileinfo = ; */
623
624   fh->nencode     = 0x0000;
625   fh->nlanguage   = 0x0000;
626
627   memset(fh->name, 0, 64/*sizeof(fh->name)*/);
628   memcpy(fh->name, "listing.txt", 64 /*sizeof(fh->name)*/);
629   memset(fh->name+strlen(fh->name), 0, 64-strlen(fh->name)); /* jbm hack */
630
631   printf("jbm: fh name %s / %s\n", fh->name, (fh->name+(strlen(fh->name))));
632   return fh;
633 }
634
635 /*
636  * establish: create a listening socket on a port. you need to call
637  * accept() when it's connected.
638  * portnum is the port number to bind to.
639  * returns your fd
640  */
641
642 int aim_listenestablish(u_short portnum)
643 {
644   int listenfd;
645   const int on = 1;
646   struct addrinfo hints, *res, *ressave;
647   char serv[5];
648   sprintf(serv, "%d", portnum);
649   memset(&hints, 0, sizeof(struct addrinfo));
650   hints.ai_flags = AI_PASSIVE;
651   hints.ai_family = AF_UNSPEC;
652   hints.ai_socktype = SOCK_STREAM;
653   if (getaddrinfo(NULL/*any IP*/, serv, &hints, &res) != 0) {
654     perror("getaddrinfo");
655     return -1;
656   }
657   ressave = res;
658   do {
659     listenfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
660     if (listenfd < 0)
661       continue;
662     setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
663     if (bind(listenfd, res->ai_addr, res->ai_addrlen) == 0)
664       break; /* success */
665     close(listenfd);
666   } while ( (res = res->ai_next) );
667   if (!res)
668     return -1;
669   if (listen(listenfd, 1024)!=0) {
670     perror("listen");
671     return -1;
672   }
673   freeaddrinfo(ressave);
674   return listenfd;
675 }
676
677 int aim_get_command_rendezvous(struct aim_session_t *sess, struct aim_conn_t *conn)
678 {
679
680   /* XXX: NOT THREAD SAFE RIGHT NOW. the locks are acting up. deal. -- jbm */
681
682   unsigned char hdrbuf1[6];
683   unsigned char *hdr = NULL;
684   int hdrlen, hdrtype;
685   int flags = 0;
686   rxcallback_t userfunc = NULL;
687
688
689   memset(hdrbuf1, 0, sizeof(hdrbuf1));
690
691   if ( (hdrlen = read(conn->fd, hdrbuf1, 6)) < 6) {    
692     if(hdrlen < 0)
693       perror("read");
694     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);
695     aim_conn_kill(sess, &conn);
696     return -1; /* return -1 prematurely signal'd a bad read(). it's *
697                * direct, so we don't really care if the connection *
698                * falls apart.  -- jbm                              */
699   }
700
701   hdrlen = aimutil_get16(hdrbuf1+4);
702
703   hdrlen -= 6;
704   if (!(hdr = malloc(hdrlen)))
705     return -1;
706
707   //    faim_mutex_lock(&conn->active);
708   if (read(conn->fd, hdr, hdrlen) < hdrlen) {
709     perror("read");
710     printf("faim: rend: read2 error\n");
711     free(hdr);
712     //    faim_mutex_unlock(&conn->active);
713     aim_conn_kill(sess, &conn);
714     return 0; /* see comment on previous read check */
715   }
716
717   //  faim_mutex_unlock(&conn->active);
718
719   hdrtype = aimutil_get16(hdr);  
720
721   switch (hdrtype) {
722   case 0x0001: { /* directim */
723     int payloadlength = 0;
724     char *snptr = NULL;
725     struct aim_directim_priv *priv;
726     int i;
727
728     priv = (struct aim_directim_priv *)calloc(1, sizeof(struct aim_directim_priv));
729
730     payloadlength = aimutil_get32(hdr+22);
731     flags = aimutil_get16(hdr+32);
732     snptr = hdr+38;
733
734     strncpy(priv->sn, snptr, MAXSNLEN);
735
736     /*    printf("faim: OFT frame: %04x / %04x / %04x / %s\n", hdrtype, payloadlength, flags, snptr); */
737
738     if (flags == 0x000e) {
739       //      printf("faim: directim: %s has started typing. yippee.\n", snptr);
740       if ( (userfunc = aim_callhandler(conn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMTYPING)) )
741         return userfunc(sess, NULL, snptr);
742     } else if ((flags == 0x0000) && payloadlength) {
743       unsigned char *msg;
744       if(! (msg = calloc(1, payloadlength+1)) )
745         return 0;
746       
747       /* XXX: theres got to be a better way */
748       /* XXX: that's a moot point, as the locks never seem to be free. */
749       /*
750         faim_mutex_lock(&conn->active);
751       */
752
753       if (recv(conn->fd, msg, payloadlength, MSG_WAITALL) < payloadlength) {
754         perror("read");
755         printf("faim: rend: read3 error\n");
756         free(msg);
757         // faim_mutex_unlock(&conn->active);
758         aim_conn_kill(sess, &conn);
759         return 0;
760       }
761       //      faim_mutex_unlock(&conn->active);
762       msg[payloadlength] = '\0';
763       //   printf("faim: directim: %s/%04x/%04x/%s\n", snptr, payloadlength, flags, msg);
764
765       if ( (userfunc = aim_callhandler(conn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMINCOMING)) )
766         i = userfunc(sess, NULL, conn, snptr, msg);
767       
768       free(msg);
769       return i;
770     }
771     break;
772   } 
773   case 0x1209: { /* get file first */
774     struct aim_filetransfer_priv *ft;
775     struct aim_fileheader_t *fh;
776     struct aim_msgcookie_t *cook;
777
778
779     int commandlen;
780     char *data;
781
782     printf("faim: rend: fileget 0x1209\n");
783
784     if(hdrlen != 0x100)
785       printf("faim: fileget_command(1209): um. hdrlen != 0x100.. 0x%x\n", hdrlen);
786     
787     if(!(ft = (struct aim_filetransfer_priv *)calloc(1, sizeof(struct aim_filetransfer_priv)))) {
788       printf("faim: couldn't malloc ft. um. bad. bad bad. file transfer will likely fail, sorry.\n");
789       return 0;
790     }
791
792     fh = aim_oft_getfh(hdr);
793
794     memcpy(&(ft->fh), fh, sizeof(struct aim_fileheader_t));
795     
796     cook = aim_checkcookie(sess, ft->fh.bcookie, AIM_COOKIETYPE_OFTGET);
797
798     if(cook->data)
799       free(cook->data); /* XXX */
800   
801     cook->data = ft;
802     
803     aim_cachecookie(sess, cook);
804
805     commandlen = 36;
806
807     data = calloc(1, commandlen);
808     memcpy(data, "01/01/1999 00:00      100 file.txt\r\n", commandlen);
809
810     if (write(conn->fd, data, commandlen) != commandlen) {
811       perror("listing write error");
812     }
813
814     printf("jbm: hit end of 1209\n");
815
816     break;
817   }
818   case 0x120b: { /* get file second */
819     struct aim_filetransfer_priv *ft;
820     struct aim_msgcookie_t *cook;
821
822     struct aim_fileheader_t *fh;
823
824     printf("faim: rend: fileget 120b\n");
825
826     if(!(ft = (struct aim_filetransfer_priv *)calloc(1, sizeof(struct aim_filetransfer_priv)))) {
827       printf("faim: couldn't malloc ft. um. bad. bad bad. file transfer will likely fail, sorry.\n");
828       return 0;
829     }
830
831     if(hdrlen != 0x100)
832       printf("faim: fileget_command(120b): um. hdrlen != 0x100..\n");
833     
834     fh = aim_oft_getfh(hdr);
835
836     memcpy(&(ft->fh), fh, sizeof(struct aim_fileheader_t));
837     
838     cook = aim_checkcookie(sess, ft->fh.bcookie, AIM_COOKIETYPE_OFTGET);
839   
840     if(cook->data)
841       free(cook->data); /* XXX: integrate cookie caching */
842
843     cook->data = ft;
844     
845     aim_cachecookie(sess, cook);
846     
847     break;
848   }
849   case 0x120c: { /* yet more get file */
850     struct aim_filetransfer_priv *ft;
851     struct aim_msgcookie_t *cook;
852     struct aim_fileheader_t *listingfh;
853     struct command_tx_struct *newoft;
854     int curbyte, i;
855     
856     printf("faim: rend: fileget 120c\n");
857
858     if(!(ft = (struct aim_filetransfer_priv *)calloc(1, sizeof(struct aim_filetransfer_priv)))) {
859       printf("faim: couldn't malloc ft. um. bad. bad bad. file transfer will likely fail, sorry.\n");
860       return 0;
861     }
862
863     if(hdrlen != 0x100)
864       printf("faim: fileget_command(120c): um. hdrlen != 0x100..\n");
865
866     listingfh = aim_oft_getfh((char *)hdr);
867
868     memcpy(&(ft->fh), listingfh, sizeof(struct aim_fileheader_t));
869     
870     cook = aim_checkcookie(sess, ft->fh.bcookie, AIM_COOKIETYPE_OFTGET);
871   
872     if(cook->data)
873       free(cook->data); /* XXX */
874
875     cook->data = ft;
876     
877     aim_cachecookie(sess, cook);
878
879     printf("faim: fileget: %s seems to want %s\n", ft->sn, ft->fh.name);
880  
881     if(!(newoft = aim_tx_new(AIM_FRAMETYPE_OFT, 0x0101, conn, 0/*listingfh->size*/))) {
882       printf("faim: send_final_transfer: tx_new OFT failed\n");
883       return 0;
884     }
885     
886     /* XXX: actually implement Real Handling of all this */
887
888     printf("jbm: listingfh->size: 0x%lx\n", listingfh->size);
889
890     newoft->lock = 1;
891
892     /*    if(!(newoft->data = calloc(1, listingfh->size))) {
893       printf("newoft data malloc failed. bombing.\n");
894       return 0;
895       }*/
896
897     if(newoft->commandlen > 0) {
898       int i;
899       bzero(newoft->data, newoft->commandlen);
900       for(i = 0; i < newoft->commandlen; i++)
901         newoft->data[i] = 0x30 + (i%10);
902
903       //      memcpy(newoft->data, "This has been a Test\r\n-josh\r\n", newoft->commandlen);
904     }
905
906     memcpy(newoft->hdr.oft.magic, "OFT2", 4);
907     newoft->hdr.oft.hdr2len = 0xf8; /* 0x100 - 8 */
908     
909     if (!(newoft->hdr.oft.hdr2 = calloc(1,newoft->hdr.oft.hdr2len))) {
910       if(newoft->data)
911         free(newoft->data); /* XXX: make this into a destructor function */
912       free(newoft);
913       return 0;
914     }  
915
916     memcpy(listingfh->bcookie, ft->fh.bcookie, 8);
917
918     curbyte = 0;
919     
920     for(i = 0; i < 8; i++)
921       curbyte += aimutil_put8(newoft->hdr.oft.hdr2+curbyte, listingfh->bcookie[i]);
922     curbyte += aimutil_put16(newoft->hdr.oft.hdr2+curbyte, listingfh->encrypt);
923     curbyte += aimutil_put16(newoft->hdr.oft.hdr2+curbyte, listingfh->compress);
924     curbyte += aimutil_put16(newoft->hdr.oft.hdr2+curbyte, listingfh->totfiles);
925     curbyte += aimutil_put16(newoft->hdr.oft.hdr2+curbyte, listingfh->filesleft);
926     curbyte += aimutil_put16(newoft->hdr.oft.hdr2+curbyte, listingfh->totparts);
927     curbyte += aimutil_put16(newoft->hdr.oft.hdr2+curbyte, listingfh->partsleft);
928     curbyte += aimutil_put32(newoft->hdr.oft.hdr2+curbyte, listingfh->totsize);
929     curbyte += aimutil_put32(newoft->hdr.oft.hdr2+curbyte, listingfh->size);
930     curbyte += aimutil_put32(newoft->hdr.oft.hdr2+curbyte, listingfh->modtime);
931     curbyte += aimutil_put32(newoft->hdr.oft.hdr2+curbyte, listingfh->checksum);
932     curbyte += aimutil_put32(newoft->hdr.oft.hdr2+curbyte, listingfh->rfrcsum);
933     curbyte += aimutil_put32(newoft->hdr.oft.hdr2+curbyte, listingfh->rfsize);
934     curbyte += aimutil_put32(newoft->hdr.oft.hdr2+curbyte, listingfh->cretime);
935     curbyte += aimutil_put32(newoft->hdr.oft.hdr2+curbyte, listingfh->rfcsum);
936     curbyte += aimutil_put32(newoft->hdr.oft.hdr2+curbyte, 0 /*listingfh->nrecvd*/);
937     curbyte += aimutil_put32(newoft->hdr.oft.hdr2+curbyte, 0/*listingfh->recvcsum*/);
938
939     strncpy(newoft->hdr.oft.hdr2+curbyte, listingfh->idstring, 32);
940     curbyte += 32;
941
942     curbyte += aimutil_put8(newoft->hdr.oft.hdr2+curbyte, 0x20 /*listingfh->flags */);
943     curbyte += aimutil_put8(newoft->hdr.oft.hdr2+curbyte, listingfh->lnameoffset);
944     curbyte += aimutil_put8(newoft->hdr.oft.hdr2+curbyte, listingfh->lsizeoffset);
945
946     memcpy(newoft->hdr.oft.hdr2+curbyte, listingfh->dummy, 69);
947     curbyte += 69;
948     
949     memcpy(newoft->hdr.oft.hdr2+curbyte, listingfh->macfileinfo, 16);
950     curbyte += 16;
951
952     curbyte += aimutil_put16(newoft->hdr.oft.hdr2+curbyte, listingfh->nencode);
953     curbyte += aimutil_put16(newoft->hdr.oft.hdr2+curbyte, listingfh->nlanguage);
954
955     strncpy(newoft->hdr.oft.hdr2+curbyte, listingfh->name, 64);
956     curbyte += 64;
957
958     free(listingfh);
959
960     newoft->lock = 0;
961     aim_tx_enqueue(sess, newoft);
962     printf("jbm: OFT listing enqueued.\n");
963
964     break;
965   }
966   case 0x0202: { /* get file: ready to recieve data */
967     char *c;
968     int i;
969
970     struct aim_fileheader_t *fh;    
971     fh = aim_oft_getfh((char *)hdr);
972
973     c = (char *)calloc(1, fh->size);
974
975     printf("looks like we're ready to send data.(oft 0x0202)\n");
976
977
978     
979     for(i = 0; i < fh->size; i++)
980       c[i] = 0x30 + (i%10);
981
982     if ( (i = write(conn->fd, c, fh->size)) != fh->size ) {
983       printf("whoopsy, didn't write it all...\n");
984     }
985
986     break;
987   }
988   case 0x0204: { /* get file: finished. close it up */
989     printf("looks like we're done with a transfer (oft 0x0204)\n");
990     aim_conn_kill(sess, &conn);
991     break;
992   }
993   default: {
994     printf("OFT frame: type %04x\n", hdrtype);  
995     /* data connection may be unreliable here */
996     break;
997   }
998   } /* switch */
999
1000   free(hdr);
1001   
1002   return 0;
1003 }
1004
1005 /*
1006  * this currently feeds totally bogus data
1007  */
1008
1009 struct aim_fileheader_t *aim_oft_getfh(char *hdr) 
1010 {
1011   struct aim_fileheader_t *fh;
1012   int i, j;
1013
1014   if(!(fh = calloc(1, sizeof(struct aim_fileheader_t))))
1015     return NULL;
1016
1017   /* [0] and [1] are the type. we can ignore those here. */
1018
1019   i = 2;
1020
1021   for(j = 0; j < 8; j++, i++)
1022     fh->bcookie[j] = hdr[i];
1023   fh->encrypt = aimutil_get16(hdr+i);
1024   i += 2;
1025   fh->compress = aimutil_get16(hdr+i);
1026   i += 2;
1027   fh->totfiles = aimutil_get16(hdr+i);
1028   i += 2;
1029   fh->filesleft = aimutil_get16(hdr+i);
1030   i += 2;
1031   fh->totparts = aimutil_get16(hdr+i);
1032   i += 2;
1033   fh->partsleft = aimutil_get16(hdr+i);
1034   i += 2;
1035   fh->totsize = aimutil_get32(hdr+i);
1036   i += 4;
1037   fh->size = aimutil_get32(hdr+i);
1038   i += 4;
1039   fh->modtime = aimutil_get32(hdr+i);
1040   i += 4;
1041   fh->checksum = aimutil_get32(hdr+i);
1042   i += 4;
1043   fh->rfrcsum = aimutil_get32(hdr+i);
1044   i += 4;
1045   fh->rfsize = aimutil_get32(hdr+i);
1046   i += 4;
1047   fh->cretime = aimutil_get32(hdr+i);
1048   i += 4;
1049   fh->rfcsum = aimutil_get32(hdr+i);
1050   i += 4;
1051   fh->nrecvd = aimutil_get32(hdr+i);
1052   i += 4;
1053   fh->recvcsum = aimutil_get32(hdr+i);
1054   i += 4;
1055
1056   memcpy(fh->idstring, hdr+i, 32);
1057   i += 32;
1058
1059   fh->flags = aimutil_get8(hdr+i);
1060   i += 1;
1061   fh->lnameoffset = aimutil_get8(hdr+i);
1062   i += 1;
1063   fh->lsizeoffset = aimutil_get8(hdr+i);
1064   i += 1;
1065
1066   memcpy(fh->dummy, hdr+i, 69);
1067   i += 69;
1068
1069   memcpy(fh->macfileinfo, hdr+i, 16);
1070   i += 16;
1071
1072   fh->nencode = aimutil_get16(hdr+i);
1073   i += 2;
1074   fh->nlanguage = aimutil_get16(hdr+i);
1075   i += 2;
1076
1077   memcpy(fh->name, hdr+i, 64);
1078   i += 64;
1079
1080   return fh;
1081 }
This page took 0.134562 seconds and 5 git commands to generate.