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