Mercurial > pidgin
comparison src/protocols/oscar/txqueue.c @ 7806:c86f075b269a
[gaim-migrate @ 8453]
I modified some of the libfaim connection stuff. I dunno, it seems
cleaner this way. I like to be comfortable with what's going on.
It's possible that FT and DC won't work now (although, they should),
but I'll get to making them suck less pretty soon.
Also upgraded the Doxyfile to 1 version newer. It mostly just moved
some things around, but also removed the CGI_BLEH lines from the end.
committer: Tailor Script <tailor@pidgin.im>
| author | Mark Doliner <mark@kingant.net> |
|---|---|
| date | Mon, 08 Dec 2003 05:41:04 +0000 |
| parents | 858979ab3867 |
| children | 0a0be07f066a |
comparison
equal
deleted
inserted
replaced
| 7805:5f0bb52c0609 | 7806:c86f075b269a |
|---|---|
| 28 */ | 28 */ |
| 29 faim_internal aim_frame_t *aim_tx_new(aim_session_t *sess, aim_conn_t *conn, fu8_t framing, fu16_t chan, int datalen) | 29 faim_internal aim_frame_t *aim_tx_new(aim_session_t *sess, aim_conn_t *conn, fu8_t framing, fu16_t chan, int datalen) |
| 30 { | 30 { |
| 31 aim_frame_t *fr; | 31 aim_frame_t *fr; |
| 32 | 32 |
| 33 if (!conn) { | 33 if (!sess || !conn) { |
| 34 faimdprintf(sess, 0, "aim_tx_new: ERROR: no connection specified\n"); | 34 faimdprintf(sess, 0, "aim_tx_new: No session or no connection specified!\n"); |
| 35 return NULL; | 35 return NULL; |
| 36 } | 36 } |
| 37 | 37 |
| 38 /* For sanity... */ | 38 /* For sanity... */ |
| 39 if ((conn->type == AIM_CONN_TYPE_RENDEZVOUS) || (conn->type == AIM_CONN_TYPE_LISTENER)) { | 39 if ((conn->type == AIM_CONN_TYPE_RENDEZVOUS) || (conn->type == AIM_CONN_TYPE_LISTENER)) { |
| 46 faimdprintf(sess, 0, "aim_tx_new: attempted to allocate inappropriate frame type for FLAP connection\n"); | 46 faimdprintf(sess, 0, "aim_tx_new: attempted to allocate inappropriate frame type for FLAP connection\n"); |
| 47 return NULL; | 47 return NULL; |
| 48 } | 48 } |
| 49 } | 49 } |
| 50 | 50 |
| 51 if (!(fr = (aim_frame_t *)malloc(sizeof(aim_frame_t)))) | 51 if (!(fr = (aim_frame_t *)calloc(1, sizeof(aim_frame_t)))) |
| 52 return NULL; | 52 return NULL; |
| 53 memset(fr, 0, sizeof(aim_frame_t)); | |
| 54 | 53 |
| 55 fr->conn = conn; | 54 fr->conn = conn; |
| 56 | |
| 57 fr->hdrtype = framing; | 55 fr->hdrtype = framing; |
| 58 | 56 if (fr->hdrtype == AIM_FRAMETYPE_FLAP) |
| 59 if (fr->hdrtype == AIM_FRAMETYPE_FLAP) { | 57 fr->hdr.flap.channel = chan; |
| 60 | 58 else if (fr->hdrtype == AIM_FRAMETYPE_OFT) |
| 61 fr->hdr.flap.type = chan; | |
| 62 | |
| 63 } else if (fr->hdrtype == AIM_FRAMETYPE_OFT) { | |
| 64 | |
| 65 fr->hdr.rend.type = chan; | 59 fr->hdr.rend.type = chan; |
| 66 | 60 else |
| 67 } else | |
| 68 faimdprintf(sess, 0, "tx_new: unknown framing\n"); | 61 faimdprintf(sess, 0, "tx_new: unknown framing\n"); |
| 69 | 62 |
| 70 if (datalen > 0) { | 63 if (datalen > 0) { |
| 71 fu8_t *data; | 64 fu8_t *data; |
| 72 | 65 |
| 79 } | 72 } |
| 80 | 73 |
| 81 return fr; | 74 return fr; |
| 82 } | 75 } |
| 83 | 76 |
| 77 /* | |
| 78 * This increments the tx command count, and returns the seqnum | |
| 79 * that should be stamped on the next FLAP packet sent. This is | |
| 80 * normally called during the final step of packet preparation | |
| 81 * before enqueuement (in aim_tx_enqueue()). | |
| 82 */ | |
| 83 static flap_seqnum_t aim_get_next_txseqnum(aim_conn_t *conn) | |
| 84 { | |
| 85 flap_seqnum_t ret; | |
| 86 | |
| 87 ret = ++conn->seqnum; | |
| 88 | |
| 89 return ret; | |
| 90 } | |
| 91 | |
| 84 /* | 92 /* |
| 85 * aim_tx_enqeue__queuebased() | |
| 86 * | |
| 87 * The overall purpose here is to enqueue the passed in command struct | 93 * The overall purpose here is to enqueue the passed in command struct |
| 88 * into the outgoing (tx) queue. Basically... | 94 * into the outgoing (tx) queue. Basically... |
| 89 * 1) Make a scope-irrelevent copy of the struct | 95 * 1) Make a scope-irrelevent copy of the struct |
| 90 * 3) Mark as not-sent-yet | 96 * 3) Mark as not-sent-yet |
| 91 * 4) Enqueue the struct into the list | 97 * 4) Enqueue the struct into the list |
| 113 /* see overhead note in aim_rxqueue counterpart */ | 119 /* see overhead note in aim_rxqueue counterpart */ |
| 114 if (!sess->queue_outgoing) | 120 if (!sess->queue_outgoing) |
| 115 sess->queue_outgoing = fr; | 121 sess->queue_outgoing = fr; |
| 116 else { | 122 else { |
| 117 aim_frame_t *cur; | 123 aim_frame_t *cur; |
| 118 | 124 for (cur = sess->queue_outgoing; cur->next; cur = cur->next); |
| 119 for (cur = sess->queue_outgoing; cur->next; cur = cur->next) | |
| 120 ; | |
| 121 cur->next = fr; | 125 cur->next = fr; |
| 122 } | 126 } |
| 123 | 127 |
| 124 return 0; | 128 return 0; |
| 125 } | 129 } |
| 126 | 130 |
| 127 /* | 131 /* |
| 128 * aim_tx_enqueue__immediate() | |
| 129 * | |
| 130 * Parallel to aim_tx_enqueue__queuebased, however, this bypasses | 132 * Parallel to aim_tx_enqueue__queuebased, however, this bypasses |
| 131 * the whole queue mess when you want immediate writes to happen. | 133 * the whole queue mess when you want immediate writes to happen. |
| 132 * | 134 * |
| 133 * Basically the same as its __queuebased couterpart, however | 135 * Basically the same as its __queuebased couterpart, however |
| 134 * instead of doing a list append, it just calls aim_tx_sendframe() | 136 * instead of doing a list append, it just calls aim_tx_sendframe() |
| 175 | 177 |
| 176 faim_internal int aim_tx_enqueue(aim_session_t *sess, aim_frame_t *fr) | 178 faim_internal int aim_tx_enqueue(aim_session_t *sess, aim_frame_t *fr) |
| 177 { | 179 { |
| 178 | 180 |
| 179 /* | 181 /* |
| 180 * If we want to send a connection thats inprogress, we have to force | 182 * If we want to send on a connection that is inprogress, we have to force |
| 181 * them to use the queue based version. Otherwise, use whatever they | 183 * them to use the queue based version. Otherwise, use whatever they |
| 182 * want. | 184 * want. |
| 183 */ | 185 */ |
| 184 if (fr && fr->conn && | 186 if (fr && fr->conn && |
| 185 (fr->conn->status & AIM_CONN_STATUS_INPROGRESS)) { | 187 (fr->conn->status & AIM_CONN_STATUS_INPROGRESS)) { |
| 187 } | 189 } |
| 188 | 190 |
| 189 return (*sess->tx_enqueue)(sess, fr); | 191 return (*sess->tx_enqueue)(sess, fr); |
| 190 } | 192 } |
| 191 | 193 |
| 192 /* | |
| 193 * aim_get_next_txseqnum() | |
| 194 * | |
| 195 * This increments the tx command count, and returns the seqnum | |
| 196 * that should be stamped on the next FLAP packet sent. This is | |
| 197 * normally called during the final step of packet preparation | |
| 198 * before enqueuement (in aim_tx_enqueue()). | |
| 199 * | |
| 200 */ | |
| 201 faim_internal flap_seqnum_t aim_get_next_txseqnum(aim_conn_t *conn) | |
| 202 { | |
| 203 flap_seqnum_t ret; | |
| 204 | |
| 205 ret = ++conn->seqnum; | |
| 206 | |
| 207 return ret; | |
| 208 } | |
| 209 | |
| 210 static int aim_send(int fd, const void *buf, size_t count) | 194 static int aim_send(int fd, const void *buf, size_t count) |
| 211 { | 195 { |
| 212 int left, cur; | 196 int left, cur; |
| 213 | 197 |
| 214 for (cur = 0, left = count; left; ) { | 198 for (cur = 0, left = count; left; ) { |
| 215 int ret; | 199 int ret; |
| 216 | 200 |
| 217 ret = send(fd, ((unsigned char *)buf)+cur, left, 0); | 201 ret = send(fd, ((unsigned char *)buf)+cur, left, 0); |
| 202 | |
| 218 if (ret == -1) | 203 if (ret == -1) |
| 219 return -1; | 204 return -1; |
| 220 else if (ret == 0) | 205 else if (ret == 0) |
| 221 return cur; | 206 return cur; |
| 222 | 207 |
| 228 } | 213 } |
| 229 | 214 |
| 230 static int aim_bstream_send(aim_bstream_t *bs, aim_conn_t *conn, size_t count) | 215 static int aim_bstream_send(aim_bstream_t *bs, aim_conn_t *conn, size_t count) |
| 231 { | 216 { |
| 232 int wrote = 0; | 217 int wrote = 0; |
| 218 | |
| 233 if (!bs || !conn || (count < 0)) | 219 if (!bs || !conn || (count < 0)) |
| 234 return -EINVAL; | 220 return -EINVAL; |
| 235 | 221 |
| 222 /* Make sure we don't send paste the end of the bs */ | |
| 236 if (count > aim_bstream_empty(bs)) | 223 if (count > aim_bstream_empty(bs)) |
| 237 count = aim_bstream_empty(bs); /* truncate to remaining space */ | 224 count = aim_bstream_empty(bs); /* truncate to remaining space */ |
| 238 | 225 |
| 239 if (count) { | 226 if (count) { |
| 227 /* | |
| 228 * If we're sending a large direct IM (maybe it contains an | |
| 229 * image or something), then we want to break it up into chunks | |
| 230 * of 1024 and update the UI between sending each one. This is | |
| 231 * kind of ugly. Ideally, if the client wants to send a large | |
| 232 * amount of data it should just write to the fd directly--we're | |
| 233 * not multithreaded and this is just a stop-gap thingy. | |
| 234 */ | |
| 240 if ((conn->type == AIM_CONN_TYPE_RENDEZVOUS) && | 235 if ((conn->type == AIM_CONN_TYPE_RENDEZVOUS) && |
| 241 (conn->subtype == AIM_CONN_SUBTYPE_OFT_DIRECTIM)) { | 236 (conn->subtype == AIM_CONN_SUBTYPE_OFT_DIRECTIM)) { |
| 242 /* I strongly suspect that this is a horrible thing to do | |
| 243 * and I feel really guilty doing it. */ | |
| 244 const char *sn = aim_odc_getsn(conn); | 237 const char *sn = aim_odc_getsn(conn); |
| 245 aim_rxcallback_t userfunc; | 238 aim_rxcallback_t userfunc; |
| 239 | |
| 246 while (count - wrote > 1024) { | 240 while (count - wrote > 1024) { |
| 247 wrote = wrote + aim_send(conn->fd, bs->data + bs->offset + wrote, 1024); | 241 wrote = wrote + aim_send(conn->fd, bs->data + bs->offset + wrote, 1024); |
| 248 if ((userfunc=aim_callhandler(conn->sessv, conn, | 242 if ((userfunc=aim_callhandler(conn->sessv, conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_IMAGETRANSFER))) |
| 249 AIM_CB_FAM_SPECIAL, | 243 userfunc(conn->sessv, NULL, sn, count-wrote>1024 ? ((double)wrote / count) : 1); |
| 250 AIM_CB_SPECIAL_IMAGETRANSFER))) | |
| 251 userfunc(conn->sessv, NULL, sn, | |
| 252 count-wrote>1024 ? ((double)wrote / count) : 1); | |
| 253 } | 244 } |
| 254 } | 245 } |
| 246 | |
| 255 if (count - wrote) { | 247 if (count - wrote) { |
| 256 wrote = wrote + aim_send(conn->fd, bs->data + bs->offset + wrote, count - wrote); | 248 wrote = wrote + aim_send(conn->fd, bs->data + bs->offset + wrote, count - wrote); |
| 257 } | 249 } |
| 258 | |
| 259 } | |
| 260 | |
| 261 if (((aim_session_t *)conn->sessv)->debug >= 2) { | |
| 262 int i; | |
| 263 aim_session_t *sess = (aim_session_t *)conn->sessv; | |
| 264 | |
| 265 faimdprintf(sess, 2, "\nOutgoing data: (%d bytes)", wrote); | |
| 266 for (i = 0; i < wrote; i++) { | |
| 267 if (!(i % 8)) | |
| 268 faimdprintf(sess, 2, "\n\t"); | |
| 269 faimdprintf(sess, 2, "0x%02x ", *(bs->data + bs->offset + i)); | |
| 270 } | |
| 271 faimdprintf(sess, 2, "\n"); | |
| 272 } | 250 } |
| 273 | 251 |
| 274 bs->offset += wrote; | 252 bs->offset += wrote; |
| 275 | 253 |
| 276 return wrote; | 254 return wrote; |
| 277 } | 255 } |
| 278 | 256 |
| 279 static int sendframe_flap(aim_session_t *sess, aim_frame_t *fr) | 257 static int sendframe_flap(aim_session_t *sess, aim_frame_t *fr) |
| 280 { | 258 { |
| 281 aim_bstream_t obs; | 259 aim_bstream_t bs; |
| 282 fu8_t *obs_raw; | 260 fu8_t *bs_raw; |
| 283 int payloadlen, err = 0, obslen; | 261 int payloadlen, err = 0, bslen; |
| 284 | 262 |
| 285 payloadlen = aim_bstream_curpos(&fr->data); | 263 payloadlen = aim_bstream_curpos(&fr->data); |
| 286 | 264 |
| 287 if (!(obs_raw = malloc(6 + payloadlen))) | 265 if (!(bs_raw = malloc(6 + payloadlen))) |
| 288 return -ENOMEM; | 266 return -ENOMEM; |
| 289 | 267 |
| 290 aim_bstream_init(&obs, obs_raw, 6 + payloadlen); | 268 aim_bstream_init(&bs, bs_raw, 6 + payloadlen); |
| 291 | 269 |
| 292 /* FLAP header */ | 270 /* FLAP header */ |
| 293 aimbs_put8(&obs, 0x2a); | 271 aimbs_put8(&bs, 0x2a); |
| 294 aimbs_put8(&obs, fr->hdr.flap.type); | 272 aimbs_put8(&bs, fr->hdr.flap.channel); |
| 295 aimbs_put16(&obs, fr->hdr.flap.seqnum); | 273 aimbs_put16(&bs, fr->hdr.flap.seqnum); |
| 296 aimbs_put16(&obs, payloadlen); | 274 aimbs_put16(&bs, payloadlen); |
| 297 | 275 |
| 298 /* payload */ | 276 /* payload */ |
| 299 aim_bstream_rewind(&fr->data); | 277 aim_bstream_rewind(&fr->data); |
| 300 aimbs_putbs(&obs, &fr->data, payloadlen); | 278 aimbs_putbs(&bs, &fr->data, payloadlen); |
| 301 | 279 |
| 302 obslen = aim_bstream_curpos(&obs); | 280 bslen = aim_bstream_curpos(&bs); |
| 303 aim_bstream_rewind(&obs); | 281 aim_bstream_rewind(&bs); |
| 304 if (aim_bstream_send(&obs, fr->conn, obslen) != obslen) | 282 if (aim_bstream_send(&bs, fr->conn, bslen) != bslen) |
| 305 err = -errno; | 283 err = -errno; |
| 306 | 284 |
| 307 free(obs_raw); /* XXX aim_bstream_free */ | 285 free(bs_raw); /* XXX aim_bstream_free */ |
| 308 | 286 |
| 309 fr->handled = 1; | 287 fr->handled = 1; |
| 310 fr->conn->lastactivity = time(NULL); | 288 fr->conn->lastactivity = time(NULL); |
| 311 | 289 |
| 312 return err; | 290 return err; |
| 314 | 292 |
| 315 static int sendframe_rendezvous(aim_session_t *sess, aim_frame_t *fr) | 293 static int sendframe_rendezvous(aim_session_t *sess, aim_frame_t *fr) |
| 316 { | 294 { |
| 317 aim_bstream_t bs; | 295 aim_bstream_t bs; |
| 318 fu8_t *bs_raw; | 296 fu8_t *bs_raw; |
| 319 int err = 0; | 297 int payloadlen, err = 0, bslen; |
| 320 int totlen = 8 + aim_bstream_curpos(&fr->data); | 298 |
| 321 | 299 payloadlen = aim_bstream_curpos(&fr->data); |
| 322 if (!(bs_raw = malloc(totlen))) | 300 |
| 323 return -1; | 301 if (!(bs_raw = malloc(8 + payloadlen))) |
| 324 | 302 return -ENOMEM; |
| 325 aim_bstream_init(&bs, bs_raw, totlen); | 303 |
| 326 | 304 aim_bstream_init(&bs, bs_raw, 8 + payloadlen); |
| 305 | |
| 306 /* Rendezvous header */ | |
| 327 aimbs_putraw(&bs, fr->hdr.rend.magic, 4); | 307 aimbs_putraw(&bs, fr->hdr.rend.magic, 4); |
| 328 aimbs_put16(&bs, 8 + fr->hdr.rend.hdrlen); | 308 aimbs_put16(&bs, fr->hdr.rend.hdrlen); |
| 329 aimbs_put16(&bs, fr->hdr.rend.type); | 309 aimbs_put16(&bs, fr->hdr.rend.type); |
| 330 | 310 |
| 331 /* payload */ | 311 /* payload */ |
| 332 aim_bstream_rewind(&fr->data); | 312 aim_bstream_rewind(&fr->data); |
| 333 aimbs_putbs(&bs, &fr->data, totlen - 8); | 313 aimbs_putbs(&bs, &fr->data, payloadlen); |
| 334 | 314 |
| 315 bslen = aim_bstream_curpos(&bs); | |
| 335 aim_bstream_rewind(&bs); | 316 aim_bstream_rewind(&bs); |
| 336 | 317 if (aim_bstream_send(&bs, fr->conn, bslen) != bslen) |
| 337 if (aim_bstream_send(&bs, fr->conn, totlen) != totlen) | |
| 338 err = -errno; | 318 err = -errno; |
| 339 | 319 |
| 340 free(bs_raw); /* XXX aim_bstream_free */ | 320 free(bs_raw); /* XXX aim_bstream_free */ |
| 341 | 321 |
| 342 fr->handled = 1; | 322 fr->handled = 1; |
| 349 { | 329 { |
| 350 if (fr->hdrtype == AIM_FRAMETYPE_FLAP) | 330 if (fr->hdrtype == AIM_FRAMETYPE_FLAP) |
| 351 return sendframe_flap(sess, fr); | 331 return sendframe_flap(sess, fr); |
| 352 else if (fr->hdrtype == AIM_FRAMETYPE_OFT) | 332 else if (fr->hdrtype == AIM_FRAMETYPE_OFT) |
| 353 return sendframe_rendezvous(sess, fr); | 333 return sendframe_rendezvous(sess, fr); |
| 334 | |
| 354 return -1; | 335 return -1; |
| 355 } | 336 } |
| 356 | 337 |
| 357 faim_export int aim_tx_flushqueue(aim_session_t *sess) | 338 faim_export int aim_tx_flushqueue(aim_session_t *sess) |
| 358 { | 339 { |
| 390 | 371 |
| 391 return 0; | 372 return 0; |
| 392 } | 373 } |
| 393 | 374 |
| 394 /* | 375 /* |
| 395 * aim_tx_purgequeue() | |
| 396 * | |
| 397 * This is responsable for removing sent commands from the transmit | 376 * This is responsable for removing sent commands from the transmit |
| 398 * queue. This is not a required operation, but it of course helps | 377 * queue. This is not a required operation, but it of course helps |
| 399 * reduce memory footprint at run time! | 378 * reduce memory footprint at run time! |
| 400 * | |
| 401 */ | 379 */ |
| 402 faim_export void aim_tx_purgequeue(aim_session_t *sess) | 380 faim_export void aim_tx_purgequeue(aim_session_t *sess) |
| 403 { | 381 { |
| 404 aim_frame_t *cur, **prev; | 382 aim_frame_t *cur, **prev; |
| 405 | 383 |
| 406 for (prev = &sess->queue_outgoing; (cur = *prev); ) { | 384 for (prev = &sess->queue_outgoing; (cur = *prev); ) { |
| 407 | |
| 408 if (cur->handled) { | 385 if (cur->handled) { |
| 409 *prev = cur->next; | 386 *prev = cur->next; |
| 410 | |
| 411 aim_frame_destroy(cur); | 387 aim_frame_destroy(cur); |
| 412 | |
| 413 } else | 388 } else |
| 414 prev = &cur->next; | 389 prev = &cur->next; |
| 415 } | 390 } |
| 416 | 391 |
| 417 return; | 392 return; |
| 418 } | 393 } |
| 419 | 394 |
| 420 /** | 395 /** |
| 421 * aim_tx_cleanqueue - get rid of packets waiting for tx on a dying conn | 396 * Get rid of packets waiting for tx on a dying conn. For now this |
| 422 * @sess: session | 397 * simply marks all packets as sent and lets them disappear without |
| 423 * @conn: connection that's dying | 398 * warning. |
| 424 * | 399 * |
| 425 * for now this simply marks all packets as sent and lets them | 400 * @param sess A session. |
| 426 * disappear without warning. | 401 * @param conn Connection that's dying. |
| 427 * | |
| 428 */ | 402 */ |
| 429 faim_internal void aim_tx_cleanqueue(aim_session_t *sess, aim_conn_t *conn) | 403 faim_internal void aim_tx_cleanqueue(aim_session_t *sess, aim_conn_t *conn) |
| 430 { | 404 { |
| 431 aim_frame_t *cur; | 405 aim_frame_t *cur; |
| 432 | 406 |
