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