comparison src/protocols/oscar/peer.c @ 13239:f260d319bbbc

[gaim-migrate @ 15605] Renaming a bunch of structs and typedefs to use the same naming scheme as the rest of Gaim committer: Tailor Script <tailor@pidgin.im>
author Mark Doliner <mark@kingant.net>
date Sun, 12 Feb 2006 16:02:05 +0000
parents f2431a7e33aa
children 2871c385c45a
comparison
equal deleted inserted replaced
13238:1e855032d7bc 13239:f260d319bbbc
20 20
21 /* 21 /*
22 * Oscar File transfer (OFT) and Oscar Direct Connect (ODC). 22 * Oscar File transfer (OFT) and Oscar Direct Connect (ODC).
23 * (ODC is also referred to as DirectIM and IM Image.) 23 * (ODC is also referred to as DirectIM and IM Image.)
24 * 24 *
25 * There are a few static helper functions at the top, then 25 * There are a few static helper functions at the top, then
26 * ODC stuff, then ft stuff. 26 * ODC stuff, then ft stuff.
27 * 27 *
28 * I feel like this is a good place to explain OFT, so I'm going to 28 * I feel like this is a good place to explain OFT, so I'm going to
29 * do just that. Each OFT packet has a header type. I guess this 29 * do just that. Each OFT packet has a header type. I guess this
30 * is pretty similar to the subtype of a SNAC packet. The type 30 * is pretty similar to the subtype of a SNAC packet. The type
31 * basically tells the other client the meaning of the OFT packet. 31 * basically tells the other client the meaning of the OFT packet.
32 * There are two distinct types of file transfer, which I usually 32 * There are two distinct types of file transfer, which I usually
33 * call "sendfile" and "getfile." Sendfile is when you send a file 33 * call "sendfile" and "getfile." Sendfile is when you send a file
34 * to another AIM user. Getfile is when you share a group of files, 34 * to another AIM user. Getfile is when you share a group of files,
35 * and other users request that you send them the files. 35 * and other users request that you send them the files.
36 * 36 *
37 * A typical sendfile file transfer goes like this: 37 * A typical sendfile file transfer goes like this:
38 * 1) Sender sends a channel 2 ICBM telling the other user that 38 * 1) Sender sends a channel 2 ICBM telling the other user that
39 * we want to send them a file. At the same time, we open a 39 * we want to send them a file. At the same time, we open a
40 * listener socket (this should be done before sending the 40 * listener socket (this should be done before sending the
41 * ICBM) on some port, and wait for them to connect to us. 41 * ICBM) on some port, and wait for them to connect to us.
42 * The ICBM we sent should contain our IP address and the port 42 * The ICBM we sent should contain our IP address and the port
43 * number that we're listening on. 43 * number that we're listening on.
44 * 2) The receiver connects to the sender on the given IP address 44 * 2) The receiver connects to the sender on the given IP address
45 * and port. After the connection is established, the receiver 45 * and port. After the connection is established, the receiver
46 * sends an ICBM signifying that we are ready and waiting. 46 * sends an ICBM signifying that we are ready and waiting.
47 * 3) The sender sends an OFT PROMPT message over the OFT 47 * 3) The sender sends an OFT PROMPT message over the OFT
48 * connection. 48 * connection.
49 * 4) The receiver of the file sends back an exact copy of this 49 * 4) The receiver of the file sends back an exact copy of this
50 * OFT packet, except the cookie is filled in with the cookie 50 * OFT packet, except the cookie is filled in with the cookie
51 * from the ICBM. I think this might be an attempt to verify 51 * from the ICBM. I think this might be an attempt to verify
52 * that the user that is connected is actually the guy that 52 * that the user that is connected is actually the guy that
53 * we sent the ICBM to. Oh, I've been calling this the ACK. 53 * we sent the ICBM to. Oh, I've been calling this the ACK.
54 * 5) The sender starts sending raw data across the connection 54 * 5) The sender starts sending raw data across the connection
55 * until the entire file has been sent. 55 * until the entire file has been sent.
56 * 6) The receiver knows the file is finished because the sender 56 * 6) The receiver knows the file is finished because the sender
57 * sent the file size in an earlier OFT packet. So then the 57 * sent the file size in an earlier OFT packet. So then the
58 * receiver sends the DONE thingy (after filling in the 58 * receiver sends the DONE thingy (after filling in the
59 * "received" checksum and size) and closes the connection. 59 * "received" checksum and size) and closes the connection.
60 */ 60 */
61 61
62 #ifdef HAVE_CONFIG_H 62 #ifdef HAVE_CONFIG_H
63 #include <config.h> 63 #include <config.h>
104 /** 104 /**
105 * Convert the directory separator from / (0x2f) to ^A (0x01) 105 * Convert the directory separator from / (0x2f) to ^A (0x01)
106 * 106 *
107 * @param name The filename to convert. 107 * @param name The filename to convert.
108 */ 108 */
109 static void aim_oft_dirconvert_tostupid(char *name) 109 static void
110 aim_oft_dirconvert_tostupid(char *name)
110 { 111 {
111 while (name[0]) { 112 while (name[0]) {
112 if (name[0] == 0x01) 113 if (name[0] == 0x01)
113 name[0] = G_DIR_SEPARATOR; 114 name[0] = G_DIR_SEPARATOR;
114 name++; 115 name++;
118 /** 119 /**
119 * Convert the directory separator from ^A (0x01) to / (0x2f) 120 * Convert the directory separator from ^A (0x01) to / (0x2f)
120 * 121 *
121 * @param name The filename to convert. 122 * @param name The filename to convert.
122 */ 123 */
123 static void aim_oft_dirconvert_fromstupid(char *name) 124 static void
125 aim_oft_dirconvert_fromstupid(char *name)
124 { 126 {
125 while (name[0]) { 127 while (name[0]) {
126 if (name[0] == G_DIR_SEPARATOR) 128 if (name[0] == G_DIR_SEPARATOR)
127 name[0] = 0x01; 129 name[0] = 0x01;
128 name++; 130 name++;
130 } 132 }
131 133
132 /** 134 /**
133 * Calculate oft checksum of buffer 135 * Calculate oft checksum of buffer
134 * 136 *
135 * Prevcheck should be 0xFFFF0000 when starting a checksum of a file. The 137 * Prevcheck should be 0xFFFF0000 when starting a checksum of a file. The
136 * checksum is kind of a rolling checksum thing, so each time you get bytes 138 * checksum is kind of a rolling checksum thing, so each time you get bytes
137 * of a file you just call this puppy and it updates the checksum. You can 139 * of a file you just call this puppy and it updates the checksum. You can
138 * calculate the checksum of an entire file by calling this in a while or a 140 * calculate the checksum of an entire file by calling this in a while or a
139 * for loop, or something. 141 * for loop, or something.
140 * 142 *
141 * Thanks to Graham Booker for providing this improved checksum routine, 143 * Thanks to Graham Booker for providing this improved checksum routine,
142 * which is simpler and should be more accurate than Josh Myer's original 144 * which is simpler and should be more accurate than Josh Myer's original
143 * code. -- wtm 145 * code. -- wtm
144 * 146 *
145 * This algorithm works every time I have tried it. The other fails 147 * This algorithm works every time I have tried it. The other fails
146 * sometimes. So, AOL who thought this up? It has got to be the weirdest 148 * sometimes. So, AOL who thought this up? It has got to be the weirdest
147 * checksum I have ever seen. 149 * checksum I have ever seen.
148 * 150 *
149 * @param buffer Buffer of data to checksum. Man I'd like to buff her... 151 * @param buffer Buffer of data to checksum. Man I'd like to buff her...
150 * @param bufsize Size of buffer. 152 * @param bufsize Size of buffer.
151 * @param prevcheck Previous checksum. 153 * @param prevcheck Previous checksum.
152 */ 154 */
153 faim_export guint32 aim_oft_checksum_chunk(const guint8 *buffer, int bufferlen, guint32 prevcheck) 155 guint32
156 aim_oft_checksum_chunk(const guint8 *buffer, int bufferlen, guint32 prevcheck)
154 { 157 {
155 guint32 check = (prevcheck >> 16) & 0xffff, oldcheck; 158 guint32 check = (prevcheck >> 16) & 0xffff, oldcheck;
156 int i; 159 int i;
157 unsigned short val; 160 unsigned short val;
158 161
162 val = buffer[i]; 165 val = buffer[i];
163 else 166 else
164 val = buffer[i] << 8; 167 val = buffer[i] << 8;
165 check -= val; 168 check -= val;
166 /* 169 /*
167 * The following appears to be necessary.... It happens 170 * The following appears to be necessary.... It happens
168 * every once in a while and the checksum doesn't fail. 171 * every once in a while and the checksum doesn't fail.
169 */ 172 */
170 if (check > oldcheck) 173 if (check > oldcheck)
171 check--; 174 check--;
172 } 175 }
173 check = ((check & 0x0000ffff) + (check >> 16)); 176 check = ((check & 0x0000ffff) + (check >> 16));
174 check = ((check & 0x0000ffff) + (check >> 16)); 177 check = ((check & 0x0000ffff) + (check >> 16));
175 return check << 16; 178 return check << 16;
176 } 179 }
177 180
178 faim_export guint32 aim_oft_checksum_file(char *filename) { 181 guint32
182 aim_oft_checksum_file(char *filename)
183 {
179 FILE *fd; 184 FILE *fd;
180 guint32 checksum = 0xffff0000; 185 guint32 checksum = 0xffff0000;
181 186
182 if ((fd = fopen(filename, "rb"))) { 187 if ((fd = fopen(filename, "rb"))) {
183 int bytes; 188 int bytes;
199 * 204 *
200 * @param sess The session. 205 * @param sess The session.
201 * @param cur The conn the incoming connection is on. 206 * @param cur The conn the incoming connection is on.
202 * @return Return 0 if no errors, otherwise return the error number. 207 * @return Return 0 if no errors, otherwise return the error number.
203 */ 208 */
204 faim_export int aim_handlerendconnect(aim_session_t *sess, aim_conn_t *cur) 209 int
210 aim_handlerendconnect(OscarSession *sess, OscarConnection *cur)
205 { 211 {
206 int acceptfd = 0; 212 int acceptfd = 0;
207 struct sockaddr addr; 213 struct sockaddr addr;
208 socklen_t addrlen = sizeof(addr); 214 socklen_t addrlen = sizeof(addr);
209 int ret = 0; 215 int ret = 0;
210 aim_conn_t *newconn; 216 OscarConnection *newconn;
211 char ip[20]; 217 char ip[20];
212 unsigned short port; 218 unsigned short port;
213 219
214 if ((acceptfd = accept(cur->fd, &addr, &addrlen)) == -1) 220 if ((acceptfd = accept(cur->fd, &addr, &addrlen)) == -1)
215 return 0; /* not an error */ 221 return 0; /* not an error */
238 244
239 priv = (struct aim_odc_intdata *)(newconn->internal = cur->internal); 245 priv = (struct aim_odc_intdata *)(newconn->internal = cur->internal);
240 cur->internal = NULL; 246 cur->internal = NULL;
241 snprintf(priv->ip, sizeof(priv->ip), "%s:%hu", ip, port); 247 snprintf(priv->ip, sizeof(priv->ip), "%s:%hu", ip, port);
242 248
243 if ((userfunc = aim_callhandler(sess, newconn, AIM_CB_FAM_OFT, OFT_TYPE_DIRECTIM_ESTABLISHED))) 249 if ((userfunc = aim_callhandler(sess, newconn, AIM_CB_FAM_OFT, PEER_TYPE_DIRECTIM_ESTABLISHED)))
244 ret = userfunc(sess, NULL, newconn, cur); 250 ret = userfunc(sess, NULL, newconn, cur);
245 251
246 } else if (newconn->subtype == AIM_CONN_SUBTYPE_OFT_GETFILE) { 252 } else if (newconn->subtype == AIM_CONN_SUBTYPE_OFT_GETFILE) {
247 } else if (newconn->subtype == AIM_CONN_SUBTYPE_OFT_SENDFILE) { 253 } else if (newconn->subtype == AIM_CONN_SUBTYPE_OFT_SENDFILE) {
248 aim_rxcallback_t userfunc; 254 aim_rxcallback_t userfunc;
249 255
250 if ((userfunc = aim_callhandler(sess, newconn, AIM_CB_FAM_OFT, OFT_TYPE_ESTABLISHED))) 256 if ((userfunc = aim_callhandler(sess, newconn, AIM_CB_FAM_OFT, PEER_TYPE_ESTABLISHED)))
251 ret = userfunc(sess, NULL, newconn, cur); 257 ret = userfunc(sess, NULL, newconn, cur);
252 258
253 } else { 259 } else {
254 gaim_debug_warning("oscar", "Got a connection on a listener that's not rendezvous. Closing connection.\n"); 260 gaim_debug_warning("oscar", "Got a connection on a listener that's not rendezvous. Closing connection.\n");
255 aim_conn_close(newconn); 261 aim_conn_close(newconn);
262 /** 268 /**
263 * Send client-to-client typing notification over an established direct connection. 269 * Send client-to-client typing notification over an established direct connection.
264 * 270 *
265 * @param sess The session. 271 * @param sess The session.
266 * @param conn The already-connected ODC connection. 272 * @param conn The already-connected ODC connection.
267 * @param typing If 0x0002, sends a "typing" message, 0x0001 sends "typed," and 273 * @param typing If 0x0002, sends a "typing" message, 0x0001 sends "typed," and
268 * 0x0000 sends "stopped." 274 * 0x0000 sends "stopped."
269 * @return Return 0 if no errors, otherwise return the error number. 275 * @return Return 0 if no errors, otherwise return the error number.
270 */ 276 */
271 faim_export int aim_odc_send_typing(aim_session_t *sess, aim_conn_t *conn, int typing) 277 int
278 aim_odc_send_typing(OscarSession *sess, OscarConnection *conn, int typing)
272 { 279 {
273 struct aim_odc_intdata *intdata = (struct aim_odc_intdata *)conn->internal; 280 struct aim_odc_intdata *intdata = (struct aim_odc_intdata *)conn->internal;
274 aim_frame_t *fr; 281 FlapFrame *fr;
275 aim_bstream_t *hdrbs; 282 ByteStream *hdrbs;
276 guint8 *hdr; 283 guint8 *hdr;
277 int hdrlen = 0x44; 284 int hdrlen = 0x44;
278 285
279 if (!sess || !conn || (conn->type != AIM_CONN_TYPE_RENDEZVOUS)) 286 if (!sess || !conn || (conn->type != AIM_CONN_TYPE_RENDEZVOUS))
280 return -EINVAL; 287 return -EINVAL;
335 } 342 }
336 343
337 /** 344 /**
338 * Send client-to-client IM over an established direct connection. 345 * Send client-to-client IM over an established direct connection.
339 * Call this just like you would aim_send_im, to send a directim. 346 * Call this just like you would aim_send_im, to send a directim.
340 * 347 *
341 * @param sess The session. 348 * @param sess The session.
342 * @param conn The already-connected ODC connection. 349 * @param conn The already-connected ODC connection.
343 * @param msg Null-terminated string to send. 350 * @param msg Null-terminated string to send.
344 * @param len The length of the message to send, including binary data. 351 * @param len The length of the message to send, including binary data.
345 * @param encoding See the AIM_CHARSET_* defines in oscar.h 352 * @param encoding See the AIM_CHARSET_* defines in oscar.h
346 * @param isawaymsg 0 if this is not an auto-response, 1 if it is. 353 * @param isawaymsg 0 if this is not an auto-response, 1 if it is.
347 * @return Return 0 if no errors, otherwise return the error number. 354 * @return Return 0 if no errors, otherwise return the error number.
348 */ 355 */
349 faim_export int aim_odc_send_im(aim_session_t *sess, aim_conn_t *conn, const char *msg, int len, int encoding, int isawaymsg) 356 int
350 { 357 aim_odc_send_im(OscarSession *sess, OscarConnection *conn, const char *msg, int len, int encoding, int isawaymsg)
351 aim_frame_t *fr; 358 {
352 aim_bstream_t *hdrbs; 359 FlapFrame *fr;
360 ByteStream *hdrbs;
353 struct aim_odc_intdata *intdata = (struct aim_odc_intdata *)conn->internal; 361 struct aim_odc_intdata *intdata = (struct aim_odc_intdata *)conn->internal;
354 int hdrlen = 0x44; 362 int hdrlen = 0x44;
355 guint8 *hdr; 363 guint8 *hdr;
356 364
357 if (!sess || !conn || (conn->type != AIM_CONN_TYPE_RENDEZVOUS) || !msg) 365 if (!sess || !conn || (conn->type != AIM_CONN_TYPE_RENDEZVOUS) || !msg)
402 aimbs_put16(hdrbs, 0x0000); 410 aimbs_put16(hdrbs, 0x0000);
403 aimbs_put8(hdrbs, 0x00); 411 aimbs_put8(hdrbs, 0x00);
404 412
405 /* end of hdr2 */ 413 /* end of hdr2 */
406 414
407 #if 0 /* XXX - this is how you send buddy icon info... */ 415 #if 0 /* XXX - this is how you send buddy icon info... */
408 aimbs_put16(hdrbs, 0x0008); 416 aimbs_put16(hdrbs, 0x0008);
409 aimbs_put16(hdrbs, 0x000c); 417 aimbs_put16(hdrbs, 0x000c);
410 aimbs_put16(hdrbs, 0x0000); 418 aimbs_put16(hdrbs, 0x0000);
411 aimbs_put16(hdrbs, 0x1466); 419 aimbs_put16(hdrbs, 0x1466);
412 aimbs_put16(hdrbs, 0x0001); 420 aimbs_put16(hdrbs, 0x0001);
425 * Get the screen name of the peer of a direct connection. 433 * Get the screen name of the peer of a direct connection.
426 * 434 *
427 * @param conn The ODC connection. 435 * @param conn The ODC connection.
428 * @return The screen name of the dude, or NULL if there was an anomaly. 436 * @return The screen name of the dude, or NULL if there was an anomaly.
429 */ 437 */
430 faim_export const char *aim_odc_getsn(aim_conn_t *conn) 438 const char *
439 aim_odc_getsn(OscarConnection *conn)
431 { 440 {
432 struct aim_odc_intdata *intdata; 441 struct aim_odc_intdata *intdata;
433 442
434 if (!conn || !conn->internal) 443 if (!conn || !conn->internal)
435 return NULL; 444 return NULL;
447 * Get the cookie of a direct connection. 456 * Get the cookie of a direct connection.
448 * 457 *
449 * @param conn The ODC connection. 458 * @param conn The ODC connection.
450 * @return The cookie, an 8 byte unterminated string, or NULL if there was an anomaly. 459 * @return The cookie, an 8 byte unterminated string, or NULL if there was an anomaly.
451 */ 460 */
452 faim_export const guchar *aim_odc_getcookie(aim_conn_t *conn) 461 const guchar *
462 aim_odc_getcookie(OscarConnection *conn)
453 { 463 {
454 struct aim_odc_intdata *intdata; 464 struct aim_odc_intdata *intdata;
455 465
456 if (!conn || !conn->internal) 466 if (!conn || !conn->internal)
457 return NULL; 467 return NULL;
464 /** 474 /**
465 * Find the conn of a direct connection with the given buddy. 475 * Find the conn of a direct connection with the given buddy.
466 * 476 *
467 * @param sess The session. 477 * @param sess The session.
468 * @param sn The screen name of the buddy whose direct connection you want to find. 478 * @param sn The screen name of the buddy whose direct connection you want to find.
469 * @return The conn for the direct connection with the given buddy, or NULL if no 479 * @return The conn for the direct connection with the given buddy, or NULL if no
470 * connection was found. 480 * connection was found.
471 */ 481 */
472 faim_export aim_conn_t *aim_odc_getconn(aim_session_t *sess, const char *sn) 482 OscarConnection *
473 { 483 aim_odc_getconn(OscarSession *sess, const char *sn)
474 aim_conn_t *cur; 484 {
485 OscarConnection *cur;
475 struct aim_odc_intdata *intdata; 486 struct aim_odc_intdata *intdata;
476 487
477 if (!sess || !sn || !strlen(sn)) 488 if (!sess || !sn || !strlen(sn))
478 return NULL; 489 return NULL;
479 490
498 * 509 *
499 * @param sess The session 510 * @param sess The session
500 * @param sn The screen name to connect to. 511 * @param sn The screen name to connect to.
501 * @return The new connection. 512 * @return The new connection.
502 */ 513 */
503 faim_export aim_conn_t *aim_odc_initiate(aim_session_t *sess, const char *sn, int listenfd, 514 OscarConnection *
504 const guint8 *localip, guint16 port, const guint8 *mycookie) 515 aim_odc_initiate(OscarSession *sess, const char *sn, int listenfd,
505 { 516 const guint8 *localip, guint16 port, const guint8 *mycookie)
506 aim_conn_t *newconn; 517 {
507 aim_msgcookie_t *cookie; 518 OscarConnection *newconn;
519 IcbmCookie *cookie;
508 struct aim_odc_intdata *priv; 520 struct aim_odc_intdata *priv;
509 guint8 ck[8]; 521 guint8 ck[8];
510 522
511 if (!localip) 523 if (!localip)
512 return NULL; 524 return NULL;
515 memcpy(ck, mycookie, 8); 527 memcpy(ck, mycookie, 8);
516 aim_im_sendch2_odcrequest(sess, ck, TRUE, sn, localip, port); 528 aim_im_sendch2_odcrequest(sess, ck, TRUE, sn, localip, port);
517 } else 529 } else
518 aim_im_sendch2_odcrequest(sess, ck, FALSE, sn, localip, port); 530 aim_im_sendch2_odcrequest(sess, ck, FALSE, sn, localip, port);
519 531
520 cookie = (aim_msgcookie_t *)calloc(1, sizeof(aim_msgcookie_t)); 532 cookie = (IcbmCookie *)calloc(1, sizeof(IcbmCookie));
521 memcpy(cookie->cookie, ck, 8); 533 memcpy(cookie->cookie, ck, 8);
522 cookie->type = AIM_COOKIETYPE_OFTIM; 534 cookie->type = AIM_COOKIETYPE_OFTIM;
523 535
524 /* this one is for the cookie */ 536 /* this one is for the cookie */
525 priv = (struct aim_odc_intdata *)calloc(1, sizeof(struct aim_odc_intdata)); 537 priv = (struct aim_odc_intdata *)calloc(1, sizeof(struct aim_odc_intdata));
552 /** 564 /**
553 * Connect directly to the given buddy for directim. 565 * Connect directly to the given buddy for directim.
554 * 566 *
555 * This is a wrapper for aim_newconn. 567 * This is a wrapper for aim_newconn.
556 * 568 *
557 * If addr is NULL, the socket is not created, but the connection is 569 * If addr is NULL, the socket is not created, but the connection is
558 * allocated and setup to connect. 570 * allocated and setup to connect.
559 * 571 *
560 * @param sess The Godly session. 572 * @param sess The Godly session.
561 * @param sn The screen name we're connecting to. I hope it's a girl... 573 * @param sn The screen name we're connecting to. I hope it's a girl...
562 * @param addr Address to connect to. 574 * @param addr Address to connect to.
563 * @return The new connection. 575 * @return The new connection.
564 */ 576 */
565 faim_export aim_conn_t *aim_odc_connect(aim_session_t *sess, const char *sn, const char *addr, const guint8 *cookie) 577 OscarConnection *
566 { 578 aim_odc_connect(OscarSession *sess, const char *sn, const char *addr, const guint8 *cookie)
567 aim_conn_t *newconn; 579 {
580 OscarConnection *newconn;
568 struct aim_odc_intdata *intdata; 581 struct aim_odc_intdata *intdata;
569 582
570 if (!sess || !sn) 583 if (!sess || !sn)
571 return NULL; 584 return NULL;
572 585
596 * @param conn The ODC connection of the incoming data. 609 * @param conn The ODC connection of the incoming data.
597 * @param frr The frame allocated for the incoming data. 610 * @param frr The frame allocated for the incoming data.
598 * @param bs It stands for "bologna sandwich." 611 * @param bs It stands for "bologna sandwich."
599 * @return Return 0 if no errors, otherwise return the error number. 612 * @return Return 0 if no errors, otherwise return the error number.
600 */ 613 */
601 static int handlehdr_odc(aim_session_t *sess, aim_conn_t *conn, aim_frame_t *frr, aim_bstream_t *bs) 614 static int
602 { 615 handlehdr_odc(OscarSession *sess, OscarConnection *conn, FlapFrame *frr, ByteStream *bs)
603 aim_frame_t fr; 616 {
617 FlapFrame fr;
604 int ret = 0; 618 int ret = 0;
605 aim_rxcallback_t userfunc; 619 aim_rxcallback_t userfunc;
606 guint32 payloadlength; 620 guint32 payloadlength;
607 guint16 flags, encoding; 621 guint16 flags, encoding;
608 char *snptr = NULL; 622 char *snptr = NULL;
624 snptr = aimbs_getstr(bs, 32); /* Next 32 bytes contain the sn, padded with null chars */ 638 snptr = aimbs_getstr(bs, 32); /* Next 32 bytes contain the sn, padded with null chars */
625 639
626 gaim_debug_misc("oscar", "faim: OFT frame: handlehdr_odc: %04x / %04x / %s\n", payloadlength, flags, snptr); 640 gaim_debug_misc("oscar", "faim: OFT frame: handlehdr_odc: %04x / %04x / %s\n", payloadlength, flags, snptr);
627 641
628 if (flags & 0x0008) { 642 if (flags & 0x0008) {
629 if ((userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, OFT_TYPE_DIRECTIMTYPING))) 643 if ((userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, PEER_TYPE_DIRECTIMTYPING)))
630 ret = userfunc(sess, &fr, snptr, 2); 644 ret = userfunc(sess, &fr, snptr, 2);
631 } else if (flags & 0x0004) { 645 } else if (flags & 0x0004) {
632 if ((userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, OFT_TYPE_DIRECTIMTYPING))) 646 if ((userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, PEER_TYPE_DIRECTIMTYPING)))
633 ret = userfunc(sess, &fr, snptr, 1); 647 ret = userfunc(sess, &fr, snptr, 1);
634 } else { 648 } else {
635 if ((userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, OFT_TYPE_DIRECTIMTYPING))) 649 if ((userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, PEER_TYPE_DIRECTIMTYPING)))
636 ret = userfunc(sess, &fr, snptr, 0); 650 ret = userfunc(sess, &fr, snptr, 0);
637 } 651 }
638 652
639 if ((payloadlength != 0) && (payloadlength != UINT_MAX)) { 653 if ((payloadlength != 0) && (payloadlength != UINT_MAX)) {
640 char *msg; 654 char *msg;
649 } 663 }
650 664
651 while (payloadlength - recvd) { 665 while (payloadlength - recvd) {
652 if (payloadlength - recvd >= 1024) 666 if (payloadlength - recvd >= 1024)
653 i = aim_recv(conn->fd, &msg[recvd], 1024); 667 i = aim_recv(conn->fd, &msg[recvd], 1024);
654 else 668 else
655 i = aim_recv(conn->fd, &msg[recvd], payloadlength - recvd); 669 i = aim_recv(conn->fd, &msg[recvd], payloadlength - recvd);
656 if (i <= 0) { 670 if (i <= 0) {
657 free(msg); 671 free(msg);
658 free(snptr); 672 free(snptr);
659 return -1; 673 return -1;
660 } 674 }
661 recvd = recvd + i; 675 recvd = recvd + i;
662 if ((userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_IMAGETRANSFER))) 676 if ((userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_IMAGETRANSFER)))
663 ret = userfunc(sess, &fr, snptr, (double)recvd / payloadlength); 677 ret = userfunc(sess, &fr, snptr, (double)recvd / payloadlength);
664 } 678 }
665 679
666 if ((userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, OFT_TYPE_DIRECTIMINCOMING))) 680 if ((userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, PEER_TYPE_DIRECTIMINCOMING)))
667 ret = userfunc(sess, &fr, snptr, msg, payloadlength, encoding, isawaymsg); 681 ret = userfunc(sess, &fr, snptr, msg, payloadlength, encoding, isawaymsg);
668 682
669 free(msg); 683 free(msg);
670 } 684 }
671 685
672 free(snptr); 686 free(snptr);
673 687
674 return ret; 688 return ret;
675 } 689 }
676 690
677 faim_export struct aim_oft_info *aim_oft_createinfo(aim_session_t *sess, const guint8 *cookie, const char *sn, const char *ip, guint16 port, guint32 size, guint32 modtime, char *filename, int send_or_recv, int method, int stage) 691 PeerInfo *
678 { 692 aim_oft_createinfo(OscarSession *sess, const guint8 *cookie, const char *sn, const char *ip, guint16 port, guint32 size, guint32 modtime, char *filename, int send_or_recv, int method, int stage)
679 struct aim_oft_info *new; 693 {
694 PeerInfo *new;
680 695
681 if (!sess) 696 if (!sess)
682 return NULL; 697 return NULL;
683 698
684 if (!(new = (struct aim_oft_info *)calloc(1, sizeof(struct aim_oft_info)))) 699 if (!(new = (PeerInfo *)calloc(1, sizeof(PeerInfo))))
685 return NULL; 700 return NULL;
686 701
687 new->sess = sess; 702 new->sess = sess;
688 if (cookie) 703 if (cookie)
689 memcpy(new->cookie, cookie, 8); 704 memcpy(new->cookie, cookie, 8);
724 sess->oft_info = new; 739 sess->oft_info = new;
725 740
726 return new; 741 return new;
727 } 742 }
728 743
729 faim_export struct aim_rv_proxy_info *aim_rv_proxy_createinfo(aim_session_t *sess, const guint8 *cookie, 744 PeerProxyInfo *aim_rv_proxy_createinfo(OscarSession *sess, const guint8 *cookie,
730 guint16 port) 745 guint16 port)
731 { 746 {
732 struct aim_rv_proxy_info *proxy_info; 747 PeerProxyInfo *proxy_info;
733 748
734 if (!(proxy_info = (struct aim_rv_proxy_info*)calloc(1, sizeof(struct aim_rv_proxy_info)))) 749 if (!(proxy_info = (PeerProxyInfo*)calloc(1, sizeof(PeerProxyInfo))))
735 return NULL; 750 return NULL;
736 751
737 proxy_info->sess = sess; 752 proxy_info->sess = sess;
738 proxy_info->port = port; 753 proxy_info->port = port;
739 proxy_info->packet_ver = AIM_RV_PROXY_PACKETVER_DFLT; 754 proxy_info->packet_ver = AIM_RV_PROXY_PACKETVER_DFLT;
740 proxy_info->unknownA = AIM_RV_PROXY_UNKNOWNA_DFLT; 755 proxy_info->unknownA = AIM_RV_PROXY_UNKNOWNA_DFLT;
741 756
742 if (cookie) 757 if (cookie)
743 memcpy(proxy_info->cookie, cookie, 8); 758 memcpy(proxy_info->cookie, cookie, 8);
744 759
745 return proxy_info; 760 return proxy_info;
746 } 761 }
747 762
748 /** 763 /**
749 * Remove the given oft_info struct from the oft_info linked list, and 764 * Remove the given oft_info struct from the oft_info linked list, and
750 * then free its memory. 765 * then free its memory.
751 * 766 *
752 * @param sess The session. 767 * @param sess The session.
753 * @param oft_info The aim_oft_info struct that we're destroying. 768 * @param oft_info The PeerInfo that we're destroying.
754 * @return Return 0 if no errors, otherwise return the error number. 769 * @return Return 0 if no errors, otherwise return the error number.
755 */ 770 */
756 faim_export int aim_oft_destroyinfo(struct aim_oft_info *oft_info) 771 int
757 { 772 aim_oft_destroyinfo(PeerInfo *oft_info)
758 aim_session_t *sess; 773 {
774 OscarSession *sess;
759 775
760 if (!oft_info || !(sess = oft_info->sess)) 776 if (!oft_info || !(sess = oft_info->sess))
761 return -EINVAL; 777 return -EINVAL;
762 778
763 if (sess->oft_info && (sess->oft_info == oft_info)) { 779 if (sess->oft_info && (sess->oft_info == oft_info)) {
764 sess->oft_info = sess->oft_info->next; 780 sess->oft_info = sess->oft_info->next;
765 } else { 781 } else {
766 struct aim_oft_info *cur; 782 PeerInfo *cur;
767 for (cur=sess->oft_info; (cur->next && (cur->next!=oft_info)); cur=cur->next); 783 for (cur=sess->oft_info; (cur->next && (cur->next!=oft_info)); cur=cur->next);
768 if (cur->next) 784 if (cur->next)
769 cur->next = cur->next->next; 785 cur->next = cur->next->next;
770 } 786 }
771 787
779 } 795 }
780 796
781 /** 797 /**
782 * Creates a listener socket so the other dude can connect to us. 798 * Creates a listener socket so the other dude can connect to us.
783 * 799 *
784 * You'll want to set up some kind of watcher on this socket. 800 * You'll want to set up some kind of watcher on this socket.
785 * When the state changes, call aim_handlerendconnection with 801 * When the state changes, call aim_handlerendconnection with
786 * the connection returned by this. aim_handlerendconnection 802 * the connection returned by this. aim_handlerendconnection
787 * will accept the pending connection and stop listening. 803 * will accept the pending connection and stop listening.
788 * 804 *
789 * @param sess The session. 805 * @param sess The session.
790 * @param oft_info File transfer information associated with this 806 * @param oft_info File transfer information associated with this
791 * connection. 807 * connection.
792 * @return Return 0 if no errors, otherwise return the error number. 808 * @return Return 0 if no errors, otherwise return the error number.
793 */ 809 */
794 faim_export int aim_sendfile_listen(aim_session_t *sess, struct aim_oft_info *oft_info, int listenfd) 810 int
811 aim_sendfile_listen(OscarSession *sess, PeerInfo *oft_info, int listenfd)
795 { 812 {
796 if (!oft_info) 813 if (!oft_info)
797 return -EINVAL; 814 return -EINVAL;
798 815
799 if (!(oft_info->conn = aim_newconn(sess, AIM_CONN_TYPE_LISTENER))) { 816 if (!(oft_info->conn = aim_newconn(sess, AIM_CONN_TYPE_LISTENER))) {
812 * Extract an &aim_fileheader_t from the given buffer. 829 * Extract an &aim_fileheader_t from the given buffer.
813 * 830 *
814 * @param bs The should be from an incoming rendezvous packet. 831 * @param bs The should be from an incoming rendezvous packet.
815 * @return A pointer to new struct on success, or NULL on error. 832 * @return A pointer to new struct on success, or NULL on error.
816 */ 833 */
817 static struct aim_fileheader_t *aim_oft_getheader(aim_bstream_t *bs) 834 static PeerFrame *
818 { 835 aim_oft_getheader(ByteStream *bs)
819 struct aim_fileheader_t *fh; 836 {
820 837 PeerFrame *fh;
821 if (!(fh = calloc(1, sizeof(struct aim_fileheader_t)))) 838
839 if (!(fh = calloc(1, sizeof(PeerFrame))))
822 return NULL; 840 return NULL;
823 841
824 /* The bstream should be positioned after the hdrtype. */ 842 /* The bstream should be positioned after the hdrtype. */
825 aimbs_getrawbuf(bs, fh->bcookie, 8); 843 aimbs_getrawbuf(bs, fh->bcookie, 8);
826 fh->encrypt = aimbs_get16(bs); 844 fh->encrypt = aimbs_get16(bs);
849 fh->nlanguage = aimbs_get16(bs); 867 fh->nlanguage = aimbs_get16(bs);
850 aimbs_getrawbuf(bs, (guchar *)fh->name, 64); /* XXX - filenames longer than 64B */ 868 aimbs_getrawbuf(bs, (guchar *)fh->name, 64); /* XXX - filenames longer than 64B */
851 fh->name[63] = '\0'; 869 fh->name[63] = '\0';
852 870
853 return fh; 871 return fh;
854 } 872 }
855 873
856 /** 874 /**
857 * Fills a buffer with network-order fh data 875 * Fills a buffer with network-order fh data
858 * 876 *
859 * @param bs A bstream to fill -- automatically initialized 877 * @param bs A bstream to fill -- automatically initialized
860 * @param fh A struct aim_fileheader_t to get data from. 878 * @param fh A PeerFrame to get data from.
861 * @return Return non-zero on error. 879 * @return Return non-zero on error.
862 */ 880 */
863 static int aim_oft_buildheader(aim_bstream_t *bs, struct aim_fileheader_t *fh) 881 static int
864 { 882 aim_oft_buildheader(ByteStream *bs, PeerFrame *fh)
883 {
865 guint8 *hdr; 884 guint8 *hdr;
866 885
867 if (!bs || !fh) 886 if (!bs || !fh)
868 return -EINVAL; 887 return -EINVAL;
869 888
904 /** 923 /**
905 * Create an OFT packet based on the given information, and send it on its merry way. 924 * Create an OFT packet based on the given information, and send it on its merry way.
906 * 925 *
907 * @param sess The session. 926 * @param sess The session.
908 * @param type The subtype of the OFT packet we're sending. 927 * @param type The subtype of the OFT packet we're sending.
909 * @param oft_info The aim_oft_info struct with the connection and OFT 928 * @param oft_info The PeerInfo with the connection and OFT
910 * info we're sending. 929 * info we're sending.
911 * @return Return 0 if no errors, otherwise return the error number. 930 * @return Return 0 if no errors, otherwise return the error number.
912 */ 931 */
913 faim_export int aim_oft_sendheader(aim_session_t *sess, guint16 type, struct aim_oft_info *oft_info) 932 int aim_oft_sendheader(OscarSession *sess, guint16 type, PeerInfo *oft_info)
914 { 933 {
915 aim_frame_t *fr; 934 FlapFrame *fr;
916 935
917 if (!sess || !oft_info || !oft_info->conn || (oft_info->conn->type != AIM_CONN_TYPE_RENDEZVOUS)) 936 if (!sess || !oft_info || !oft_info->conn || (oft_info->conn->type != AIM_CONN_TYPE_RENDEZVOUS))
918 return -EINVAL; 937 return -EINVAL;
919 938
920 #if 0 939 #if 0
921 /* 940 /*
922 * If you are receiving a file, the cookie should be null, if you are sending a 941 * If you are receiving a file, the cookie should be null, if you are sending a
923 * file, the cookie should be the same as the one used in the ICBM negotiation 942 * file, the cookie should be the same as the one used in the ICBM negotiation
924 * SNACs. 943 * SNACs.
925 */ 944 */
926 fh->lnameoffset = 0x1a; 945 fh->lnameoffset = 0x1a;
927 fh->lsizeoffset = 0x10; 946 fh->lsizeoffset = 0x10;
928 947
956 * 975 *
957 * @param sess The session. 976 * @param sess The session.
958 * @param proxy_info Changable pieces of data for this packet 977 * @param proxy_info Changable pieces of data for this packet
959 * @return Return 0 if no errors, otherwise return the error number. 978 * @return Return 0 if no errors, otherwise return the error number.
960 */ 979 */
961 faim_export int aim_rv_proxy_init_recv(struct aim_rv_proxy_info *proxy_info) 980 int
981 aim_rv_proxy_init_recv(PeerProxyInfo *proxy_info)
962 { 982 {
963 #if 0 983 #if 0
964 aim_tlvlist_t *tlvlist_sendfile; 984 aim_tlvlist_t *tlvlist_sendfile;
965 #endif 985 #endif
966 aim_bstream_t bs; 986 ByteStream bs;
967 guint8 *bs_raw; 987 guint8 *bs_raw;
968 guint16 packet_len; 988 guint16 packet_len;
969 guint8 sn_len; 989 guint8 sn_len;
970 int err; 990 int err;
971 991
1029 * 1049 *
1030 * @param sess The session. 1050 * @param sess The session.
1031 * @param proxy_info Changable pieces of data for this packet 1051 * @param proxy_info Changable pieces of data for this packet
1032 * @return Return 0 if no errors, otherwise return the error number. 1052 * @return Return 0 if no errors, otherwise return the error number.
1033 */ 1053 */
1034 faim_export int aim_rv_proxy_init_send(struct aim_rv_proxy_info *proxy_info) 1054 int
1055 aim_rv_proxy_init_send(PeerProxyInfo *proxy_info)
1035 { 1056 {
1036 #if 0 1057 #if 0
1037 aim_tlvlist_t *tlvlist_sendfile; 1058 aim_tlvlist_t *tlvlist_sendfile;
1038 #endif 1059 #endif
1039 aim_bstream_t bs; 1060 ByteStream bs;
1040 guint8 *bs_raw; 1061 guint8 *bs_raw;
1041 guint16 packet_len; 1062 guint16 packet_len;
1042 guint8 sn_len; 1063 guint8 sn_len;
1043 int err; 1064 int err;
1044 1065
1099 * @param sess The session. 1120 * @param sess The session.
1100 * @param fr The frame allocated for the incoming data. 1121 * @param fr The frame allocated for the incoming data.
1101 * @return Return 0 if the packet was handled correctly, otherwise return the 1122 * @return Return 0 if the packet was handled correctly, otherwise return the
1102 * error number. 1123 * error number.
1103 */ 1124 */
1104 faim_internal int aim_rxdispatch_rendezvous(aim_session_t *sess, aim_frame_t *fr) 1125 int
1105 { 1126 aim_rxdispatch_rendezvous(OscarSession *sess, FlapFrame *fr)
1106 aim_conn_t *conn = fr->conn; 1127 {
1128 OscarConnection *conn = fr->conn;
1107 int ret = 1; 1129 int ret = 1;
1108 1130
1109 if (conn->subtype == AIM_CONN_SUBTYPE_OFT_DIRECTIM) { 1131 if (conn->subtype == AIM_CONN_SUBTYPE_OFT_DIRECTIM) {
1110 if (fr->hdr.rend.type == 0x0001) 1132 if (fr->hdr.rend.type == 0x0001)
1111 ret = handlehdr_odc(sess, conn, fr, &fr->data); 1133 ret = handlehdr_odc(sess, conn, fr, &fr->data);
1112 else 1134 else
1113 gaim_debug_info("oscar", "ODC directim frame unknown, type is %04x\n", fr->hdr.rend.type); 1135 gaim_debug_info("oscar", "ODC directim frame unknown, type is %04x\n", fr->hdr.rend.type);
1114 1136
1115 } else { 1137 } else {
1116 aim_rxcallback_t userfunc; 1138 aim_rxcallback_t userfunc;
1117 struct aim_fileheader_t *header = aim_oft_getheader(&fr->data); 1139 PeerFrame *header = aim_oft_getheader(&fr->data);
1118 aim_oft_dirconvert_fromstupid(header->name); /* XXX - This should be client-side */ 1140 aim_oft_dirconvert_fromstupid(header->name); /* XXX - This should be client-side */
1119 1141
1120 if ((userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, fr->hdr.rend.type))) 1142 if ((userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, fr->hdr.rend.type)))
1121 ret = userfunc(sess, fr, conn, header->bcookie, header); 1143 ret = userfunc(sess, fr, conn, header->bcookie, header);
1122 1144
1133 * Handle incoming data on a rendezvous proxy connection. This is similar to 1155 * Handle incoming data on a rendezvous proxy connection. This is similar to
1134 * aim_rxdispatch_rendezvous above and should probably be kept with that function. 1156 * aim_rxdispatch_rendezvous above and should probably be kept with that function.
1135 * 1157 *
1136 * @param sess The session. 1158 * @param sess The session.
1137 * @param fr The frame allocated for the incoming data. 1159 * @param fr The frame allocated for the incoming data.
1138 * @return Return 0 if the packet was handled correctly, otherwise return the 1160 * @return Return 0 if the packet was handled correctly, otherwise return the
1139 * error number. 1161 * error number.
1140 */ 1162 */
1141 faim_internal struct aim_rv_proxy_info *aim_rv_proxy_read(aim_session_t *sess, aim_conn_t *conn) 1163 PeerProxyInfo *
1142 { 1164 aim_rv_proxy_read(OscarSession *sess, OscarConnection *conn)
1143 aim_bstream_t bs_hdr; 1165 {
1166 ByteStream bs_hdr;
1144 guint8 hdr_buf[AIM_RV_PROXY_HDR_LEN]; 1167 guint8 hdr_buf[AIM_RV_PROXY_HDR_LEN];
1145 aim_bstream_t bs_body; /* The body (everything but the header) of the packet */ 1168 ByteStream bs_body; /* The body (everything but the header) of the packet */
1146 guint8 *body_buf = NULL; 1169 guint8 *body_buf = NULL;
1147 guint8 body_len; 1170 guint8 body_len;
1148 1171
1149 char str_ip[30] = {""}; 1172 char str_ip[30] = {""};
1150 guint8 ip_temp[4]; 1173 guint8 ip_temp[4];
1151 1174
1152 guint16 len; 1175 guint16 len;
1153 struct aim_rv_proxy_info *proxy_info; 1176 PeerProxyInfo *proxy_info;
1154 1177
1155 if(!(proxy_info = malloc(sizeof(struct aim_rv_proxy_info)))) 1178 if(!(proxy_info = malloc(sizeof(PeerProxyInfo))))
1156 return NULL; 1179 return NULL;
1157 1180
1158 aim_bstream_init(&bs_hdr, hdr_buf, AIM_RV_PROXY_HDR_LEN); 1181 aim_bstream_init(&bs_hdr, hdr_buf, AIM_RV_PROXY_HDR_LEN);
1159 if (aim_bstream_recv(&bs_hdr, conn->fd, AIM_RV_PROXY_HDR_LEN) == AIM_RV_PROXY_HDR_LEN) { 1182 if (aim_bstream_recv(&bs_hdr, conn->fd, AIM_RV_PROXY_HDR_LEN) == AIM_RV_PROXY_HDR_LEN) {
1160 aim_bstream_rewind(&bs_hdr); 1183 aim_bstream_rewind(&bs_hdr);
1211 free(proxy_info); 1234 free(proxy_info);
1212 proxy_info = NULL; 1235 proxy_info = NULL;
1213 } 1236 }
1214 } else { 1237 } else {
1215 gaim_debug_warning("oscar","unknown type for aim rendezvous proxy packet\n"); 1238 gaim_debug_warning("oscar","unknown type for aim rendezvous proxy packet\n");
1216 } 1239 }
1217 } else { 1240 } else {
1218 gaim_debug_warning("oscar","error reading header of rv proxy packet\n"); 1241 gaim_debug_warning("oscar","error reading header of rv proxy packet\n");
1219 aim_conn_close(conn); 1242 aim_conn_close(conn);
1220 free(proxy_info); 1243 free(proxy_info);
1221 proxy_info = NULL; 1244 proxy_info = NULL;