]> andersk Git - libfaim.git/blob - aim_ft.c
close->closesocket for win32, and socket() stupidity in aim_ft.
[libfaim.git] / aim_ft.c
1 #include <faim/aim.h>
2
3 #ifndef _WIN32
4 #include <netdb.h>
5 #include <sys/socket.h>
6 #include <netinet/in.h>
7 #include <sys/utsname.h> /* for aim_directim_initiate */
8 #include <arpa/inet.h> /* for inet_ntoa */
9 #endif
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
20    aim_get_command_rendezvous aim_r
21    oft_getfh aim_rxqueue.c
22 */
23
24 faim_export int aim_handlerendconnect(struct aim_session_t *sess, struct aim_conn_t *cur)
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
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
90 faim_export int aim_send_im_direct(struct aim_session_t *sess, 
91                                    struct aim_conn_t *conn,
92                                    char *msg)
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
136   i += aimutil_putstr(newpacket2->hdr.oft.hdr2+i, (char *)priv->cookie, 8);
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
192   i += aimutil_putstr(newpacket->hdr.oft.hdr2+i, (char *)priv->cookie, 8);
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
250 faim_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)
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;
264   char localhost[129];
265
266   unsigned char cap[16];
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
280   if(gethostname(localhost, 128) < 0)
281     return NULL;
282
283   if( (hptr = gethostbyname(localhost)) == NULL)
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++)
308     curbyte += aimutil_put8(newpacket->data+curbyte, 0x30 + ((u_char) rand() % 20));
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
409 #if 0
410   i = fcntl(listenfd, F_GETFL, 0);
411   fcntl(listenfd, F_SETFL, i | O_NONBLOCK);
412 #endif
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
453 faim_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 )
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
474 faim_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)
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
591 faim_internal struct aim_fileheader_t *aim_getlisting(struct aim_session_t *sess) 
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
647 faim_internal int aim_listenestablish(u_short portnum)
648 {
649 #if defined(__linux__) /* XXX what other OS's support getaddrinfo? */
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;
681 #else 
682   int listenfd;
683   const int on = 1;
684   struct sockaddr_in sockin;
685   
686   if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 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 #endif
711 }
712
713 faim_internal int aim_get_command_rendezvous(struct aim_session_t *sess, struct aim_conn_t *conn)
714 {
715
716   /* XXX: NOT THREAD SAFE RIGHT NOW. the locks are acting up. deal. -- jbm */
717
718   unsigned char hdrbuf1[6];
719   unsigned char *hdr = NULL;
720   int hdrlen, hdrtype;
721   int flags = 0;
722   rxcallback_t userfunc = NULL;
723
724
725   memset(hdrbuf1, 0, sizeof(hdrbuf1));
726
727   faim_mutex_lock(&conn->active); /* gets locked down for the entirety */
728
729   if ( (hdrlen = aim_recv(conn->fd, hdrbuf1, 6)) < 6) {    
730     if(hdrlen < 0)
731       perror("read");
732     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);
733     faim_mutex_unlock(&conn->active);
734     aim_conn_close(conn);
735     return -1;
736   }
737
738   hdrlen = aimutil_get16(hdrbuf1+4);
739
740   hdrlen -= 6;
741   if (!(hdr = malloc(hdrlen)))
742     return -1;
743
744   if (aim_recv(conn->fd, hdr, hdrlen) < hdrlen) {
745     perror("read");
746     printf("faim: rend: read2 error\n");
747     free(hdr);
748     faim_mutex_unlock(&conn->active);
749     aim_conn_close(conn);
750     return 0; /* see comment on previous read check */
751   }
752
753   hdrtype = aimutil_get16(hdr);  
754
755   switch (hdrtype) {
756   case 0x0001: { /* directim */
757     int payloadlength = 0;
758     char *snptr = NULL;
759     struct aim_directim_priv *priv;
760     int i;
761
762     priv = (struct aim_directim_priv *)calloc(1, sizeof(struct aim_directim_priv));
763
764     payloadlength = aimutil_get32(hdr+22);
765     flags = aimutil_get16(hdr+32);
766     snptr = (char *)hdr+38;
767
768     strncpy(priv->sn, snptr, MAXSNLEN);
769
770 #if 0
771     printf("faim: OFT frame: %04x / %04x / %04x / %s\n", hdrtype, payloadlength, flags, snptr); 
772 #endif
773
774     if (flags == 0x000e) {
775       faim_mutex_unlock(&conn->active);
776       if ( (userfunc = aim_callhandler(conn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMTYPING)) )
777         return userfunc(sess, NULL, snptr);
778     } else if ((flags == 0x0000) && payloadlength) {
779       unsigned char *msg;
780
781       if(! (msg = calloc(1, payloadlength+1)) ) {
782         faim_mutex_unlock(&conn->active);
783         return 0;
784       }
785       
786       if (aim_recv(conn->fd, msg, payloadlength) < payloadlength) {
787         perror("read");
788         printf("faim: rend: read3 error\n");
789         free(msg);
790         faim_mutex_unlock(&conn->active);
791         aim_conn_close(conn);
792         return -1;
793       }
794       faim_mutex_unlock(&conn->active);
795       msg[payloadlength] = '\0';
796 #if 0     
797       printf("faim: directim: %s/%04x/%04x/%s\n", snptr, payloadlength, flags, msg);
798 #endif
799
800       if ( (userfunc = aim_callhandler(conn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMINCOMING)) )
801         i = userfunc(sess, NULL, conn, snptr, msg);
802       
803       free(msg);
804       return i;
805     }
806     break;
807   } 
808   case 0x1209: { /* get file first */
809     struct aim_filetransfer_priv *ft;
810     struct aim_fileheader_t *fh;
811     struct aim_msgcookie_t *cook;
812
813     int commandlen;
814     char *data;
815
816     printf("faim: rend: fileget 0x1209\n");
817
818     if(hdrlen != 0x100)
819       printf("faim: fileget_command(1209): um. hdrlen != 0x100.. 0x%x\n", hdrlen);
820     
821     if(!(ft = (struct aim_filetransfer_priv *)calloc(1, sizeof(struct aim_filetransfer_priv)))) {
822       printf("faim: couldn't malloc ft. um. bad. bad bad. file transfer will likely fail, sorry.\n");
823       faim_mutex_unlock(&conn->active);
824       return 0;
825     }
826
827     fh = aim_oft_getfh(hdr);
828
829     memcpy(&(ft->fh), fh, sizeof(struct aim_fileheader_t));
830     
831     cook = aim_checkcookie(sess, (unsigned char *)ft->fh.bcookie, AIM_COOKIETYPE_OFTGET);
832
833     if(cook->data)
834       free(cook->data); /* XXX */
835   
836     cook->data = ft;
837     
838     aim_cachecookie(sess, cook);
839
840     commandlen = 36;
841
842     data = calloc(1, commandlen);
843     memcpy(data, "01/01/1999 00:00      100 file.txt\r\n", commandlen);
844
845     if (send(conn->fd, data, commandlen, 0) != commandlen) {
846       perror("listing write error");
847     }
848     faim_mutex_unlock(&conn->active);
849
850     printf("jbm: hit end of 1209\n");
851
852     break;
853   }
854   case 0x120b: { /* get file second */
855     struct aim_filetransfer_priv *ft;
856     struct aim_msgcookie_t *cook;
857
858     struct aim_fileheader_t *fh;
859
860     printf("faim: rend: fileget 120b\n");
861
862     if(!(ft = (struct aim_filetransfer_priv *)calloc(1, sizeof(struct aim_filetransfer_priv)))) {
863       printf("faim: couldn't malloc ft. um. bad. bad bad. file transfer will likely fail, sorry.\n");
864       faim_mutex_unlock(&conn->active);
865       return 0;
866     }
867
868     if(hdrlen != 0x100)
869       printf("faim: fileget_command(120b): um. hdrlen != 0x100..\n");
870     
871     fh = aim_oft_getfh(hdr);
872
873     memcpy(&(ft->fh), fh, sizeof(struct aim_fileheader_t));
874     
875     cook = aim_checkcookie(sess, (unsigned char *)ft->fh.bcookie, AIM_COOKIETYPE_OFTGET);
876   
877     if(cook->data)
878       free(cook->data); /* XXX: integrate cookie caching */
879
880     cook->data = ft;
881     
882     aim_cachecookie(sess, cook);
883
884     faim_mutex_unlock(&conn->active);
885     
886     break;
887   }
888   case 0x120c: { /* yet more get file */
889     struct aim_filetransfer_priv *ft;
890     struct aim_msgcookie_t *cook;
891     struct aim_fileheader_t *listingfh;
892     struct command_tx_struct *newoft;
893     int curbyte, i;
894     
895     printf("faim: rend: fileget 120c\n");
896
897     if(!(ft = (struct aim_filetransfer_priv *)calloc(1, sizeof(struct aim_filetransfer_priv)))) {
898       printf("faim: couldn't malloc ft. um. bad. bad bad. file transfer will likely fail, sorry.\n");
899       faim_mutex_unlock(&conn->active);
900       return 0;
901     }
902
903     if(hdrlen != 0x100)
904       printf("faim: fileget_command(120c): um. hdrlen != 0x100..\n");
905
906     listingfh = aim_oft_getfh(hdr);
907
908     memcpy(&(ft->fh), listingfh, sizeof(struct aim_fileheader_t));
909     
910     cook = aim_checkcookie(sess, (unsigned char *)ft->fh.bcookie, AIM_COOKIETYPE_OFTGET);
911   
912     if(cook->data)
913       free(cook->data); /* XXX */
914
915     cook->data = ft;
916     
917     aim_cachecookie(sess, cook);
918
919     faim_mutex_unlock(&conn->active);
920
921     printf("faim: fileget: %s seems to want %s\n", ft->sn, ft->fh.name);
922  
923     if(!(newoft = aim_tx_new(AIM_FRAMETYPE_OFT, 0x0101, conn, 0/*listingfh->size*/))) {
924       printf("faim: send_final_transfer: tx_new OFT failed\n");
925       return 0;
926     }
927     
928     /* XXX: actually implement Real Handling of all this */
929
930     printf("jbm: listingfh->size: 0x%lx\n", listingfh->size);
931
932     newoft->lock = 1;
933
934     /*    if(!(newoft->data = calloc(1, listingfh->size))) {
935       printf("newoft data malloc failed. bombing.\n");
936       return 0;
937       }*/
938
939     if(newoft->commandlen > 0) {
940       int i;
941       memset(newoft->data, 0, newoft->commandlen);
942       for(i = 0; i < (signed)newoft->commandlen; i++)
943         newoft->data[i] = 0x30 + (i%10);
944
945       //      memcpy(newoft->data, "This has been a Test\r\n-josh\r\n", newoft->commandlen);
946     }
947
948     memcpy(newoft->hdr.oft.magic, "OFT2", 4);
949     newoft->hdr.oft.hdr2len = 0xf8; /* 0x100 - 8 */
950     
951     if (!(newoft->hdr.oft.hdr2 = calloc(1,newoft->hdr.oft.hdr2len))) {
952       if(newoft->data)
953         free(newoft->data); /* XXX: make this into a destructor function */
954       free(newoft);
955       return 0;
956     }  
957
958     memcpy(listingfh->bcookie, ft->fh.bcookie, 8);
959
960     curbyte = 0;
961     
962     for(i = 0; i < 8; i++)
963       curbyte += aimutil_put8(newoft->hdr.oft.hdr2+curbyte, listingfh->bcookie[i]);
964     curbyte += aimutil_put16(newoft->hdr.oft.hdr2+curbyte, listingfh->encrypt);
965     curbyte += aimutil_put16(newoft->hdr.oft.hdr2+curbyte, listingfh->compress);
966     curbyte += aimutil_put16(newoft->hdr.oft.hdr2+curbyte, listingfh->totfiles);
967     curbyte += aimutil_put16(newoft->hdr.oft.hdr2+curbyte, listingfh->filesleft);
968     curbyte += aimutil_put16(newoft->hdr.oft.hdr2+curbyte, listingfh->totparts);
969     curbyte += aimutil_put16(newoft->hdr.oft.hdr2+curbyte, listingfh->partsleft);
970     curbyte += aimutil_put32(newoft->hdr.oft.hdr2+curbyte, listingfh->totsize);
971     curbyte += aimutil_put32(newoft->hdr.oft.hdr2+curbyte, listingfh->size);
972     curbyte += aimutil_put32(newoft->hdr.oft.hdr2+curbyte, listingfh->modtime);
973     curbyte += aimutil_put32(newoft->hdr.oft.hdr2+curbyte, listingfh->checksum);
974     curbyte += aimutil_put32(newoft->hdr.oft.hdr2+curbyte, listingfh->rfrcsum);
975     curbyte += aimutil_put32(newoft->hdr.oft.hdr2+curbyte, listingfh->rfsize);
976     curbyte += aimutil_put32(newoft->hdr.oft.hdr2+curbyte, listingfh->cretime);
977     curbyte += aimutil_put32(newoft->hdr.oft.hdr2+curbyte, listingfh->rfcsum);
978     curbyte += aimutil_put32(newoft->hdr.oft.hdr2+curbyte, 0 /*listingfh->nrecvd*/);
979     curbyte += aimutil_put32(newoft->hdr.oft.hdr2+curbyte, 0/*listingfh->recvcsum*/);
980
981     strncpy((char *)newoft->hdr.oft.hdr2+curbyte, listingfh->idstring, 32);
982     curbyte += 32;
983
984     curbyte += aimutil_put8(newoft->hdr.oft.hdr2+curbyte, 0x20 /*listingfh->flags */);
985     curbyte += aimutil_put8(newoft->hdr.oft.hdr2+curbyte, listingfh->lnameoffset);
986     curbyte += aimutil_put8(newoft->hdr.oft.hdr2+curbyte, listingfh->lsizeoffset);
987
988     memcpy(newoft->hdr.oft.hdr2+curbyte, listingfh->dummy, 69);
989     curbyte += 69;
990     
991     memcpy(newoft->hdr.oft.hdr2+curbyte, listingfh->macfileinfo, 16);
992     curbyte += 16;
993
994     curbyte += aimutil_put16(newoft->hdr.oft.hdr2+curbyte, listingfh->nencode);
995     curbyte += aimutil_put16(newoft->hdr.oft.hdr2+curbyte, listingfh->nlanguage);
996
997     strncpy((char *)newoft->hdr.oft.hdr2+curbyte, listingfh->name, 64);
998     curbyte += 64;
999
1000     free(listingfh);
1001
1002     newoft->lock = 0;
1003     aim_tx_enqueue(sess, newoft);
1004     printf("jbm: OFT listing enqueued.\n");
1005
1006     break;
1007   }
1008   case 0x0202: { /* get file: ready to recieve data */
1009     char *c;
1010     int i;
1011
1012     struct aim_fileheader_t *fh;    
1013     fh = aim_oft_getfh(hdr);
1014
1015     c = (char *)calloc(1, fh->size);
1016
1017     printf("looks like we're ready to send data.(oft 0x0202)\n");
1018
1019
1020     
1021     for(i = 0; i < fh->size; i++)
1022       c[i] = 0x30 + (i%10);
1023
1024     if ( (i = send(conn->fd, c, fh->size, 0)) != fh->size ) {
1025       printf("whoopsy, didn't write it all...\n");
1026     }
1027
1028     faim_mutex_unlock(&conn->active);
1029
1030     break;
1031   }
1032   case 0x0204: { /* get file: finished. close it up */
1033     printf("looks like we're done with a transfer (oft 0x0204)\n");
1034     faim_mutex_unlock(&conn->active);
1035     aim_conn_close(conn);
1036     break;
1037   }
1038   default: {
1039     printf("OFT frame: type %04x\n", hdrtype);  
1040     /* data connection may be unreliable here */
1041     faim_mutex_unlock(&conn->active);
1042     break;
1043   }
1044   } /* switch */
1045
1046   free(hdr);
1047   
1048   return 0;
1049 }
1050
1051 /*
1052  * this currently feeds totally bogus data
1053  */
1054
1055 faim_internal struct aim_fileheader_t *aim_oft_getfh(unsigned char *hdr) 
1056 {
1057   struct aim_fileheader_t *fh;
1058   int i, j;
1059
1060   if(!(fh = calloc(1, sizeof(struct aim_fileheader_t))))
1061     return NULL;
1062
1063   /* [0] and [1] are the type. we can ignore those here. */
1064
1065   i = 2;
1066
1067   for(j = 0; j < 8; j++, i++)
1068     fh->bcookie[j] = hdr[i];
1069   fh->encrypt = aimutil_get16(hdr+i);
1070   i += 2;
1071   fh->compress = aimutil_get16(hdr+i);
1072   i += 2;
1073   fh->totfiles = aimutil_get16(hdr+i);
1074   i += 2;
1075   fh->filesleft = aimutil_get16(hdr+i);
1076   i += 2;
1077   fh->totparts = aimutil_get16(hdr+i);
1078   i += 2;
1079   fh->partsleft = aimutil_get16(hdr+i);
1080   i += 2;
1081   fh->totsize = aimutil_get32(hdr+i);
1082   i += 4;
1083   fh->size = aimutil_get32(hdr+i);
1084   i += 4;
1085   fh->modtime = aimutil_get32(hdr+i);
1086   i += 4;
1087   fh->checksum = aimutil_get32(hdr+i);
1088   i += 4;
1089   fh->rfrcsum = aimutil_get32(hdr+i);
1090   i += 4;
1091   fh->rfsize = aimutil_get32(hdr+i);
1092   i += 4;
1093   fh->cretime = aimutil_get32(hdr+i);
1094   i += 4;
1095   fh->rfcsum = aimutil_get32(hdr+i);
1096   i += 4;
1097   fh->nrecvd = aimutil_get32(hdr+i);
1098   i += 4;
1099   fh->recvcsum = aimutil_get32(hdr+i);
1100   i += 4;
1101
1102   memcpy(fh->idstring, hdr+i, 32);
1103   i += 32;
1104
1105   fh->flags = aimutil_get8(hdr+i);
1106   i += 1;
1107   fh->lnameoffset = aimutil_get8(hdr+i);
1108   i += 1;
1109   fh->lsizeoffset = aimutil_get8(hdr+i);
1110   i += 1;
1111
1112   memcpy(fh->dummy, hdr+i, 69);
1113   i += 69;
1114
1115   memcpy(fh->macfileinfo, hdr+i, 16);
1116   i += 16;
1117
1118   fh->nencode = aimutil_get16(hdr+i);
1119   i += 2;
1120   fh->nlanguage = aimutil_get16(hdr+i);
1121   i += 2;
1122
1123   memcpy(fh->name, hdr+i, 64);
1124   i += 64;
1125
1126   return fh;
1127 }
This page took 0.205478 seconds and 5 git commands to generate.