Mercurial > pidgin
comparison src/protocols/oscar/txqueue.c @ 13253:87a7c3077c19
[gaim-migrate @ 15619]
More cleaning up of oscar. Renamed some functions to be more clear.
Got rid of some stuff that wasn't used. Inlined some small things
in conn.c that were only used once.
The goals of all this are
1. Non-blocking I/O for all connections
2. p2p stuff won't use the same struct as oscar connections, because
that's stupid
3. The oscar PRPL should be less scary
committer: Tailor Script <tailor@pidgin.im>
author | Mark Doliner <mark@kingant.net> |
---|---|
date | Sun, 12 Feb 2006 21:27:04 +0000 |
parents | f260d319bbbc |
children | 7ead7b8aea63 |
comparison
equal
deleted
inserted
replaced
13252:2871c385c45a | 13253:87a7c3077c19 |
---|---|
44 * | 44 * |
45 * framing = AIM_FRAMETYPE_OFT/FLAP | 45 * framing = AIM_FRAMETYPE_OFT/FLAP |
46 * chan = channel for FLAP, hdrtype for OFT | 46 * chan = channel for FLAP, hdrtype for OFT |
47 * | 47 * |
48 */ | 48 */ |
49 faim_internal FlapFrame *aim_tx_new(OscarSession *sess, OscarConnection *conn, guint8 framing, guint16 chan, int datalen) | 49 FlapFrame * |
50 flap_frame_new(OscarSession *sess, OscarConnection *conn, guint8 framing, guint16 chan, int datalen) | |
50 { | 51 { |
51 FlapFrame *fr; | 52 FlapFrame *fr; |
52 | 53 |
53 if (!sess || !conn) { | 54 if (!sess || !conn) { |
54 gaim_debug_misc("oscar", "aim_tx_new: No session or no connection specified!\n"); | 55 gaim_debug_misc("oscar", "flap_frame_new: No session or no connection specified!\n"); |
55 return NULL; | 56 return NULL; |
56 } | 57 } |
57 | 58 |
58 /* For sanity... */ | 59 /* For sanity... */ |
59 if ((conn->type == AIM_CONN_TYPE_RENDEZVOUS) || (conn->type == AIM_CONN_TYPE_LISTENER)) { | 60 if ((conn->type == AIM_CONN_TYPE_RENDEZVOUS) || (conn->type == AIM_CONN_TYPE_LISTENER)) { |
60 if (framing != AIM_FRAMETYPE_OFT) { | 61 if (framing != AIM_FRAMETYPE_OFT) { |
61 gaim_debug_misc("oscar", "aim_tx_new: attempted to allocate inappropriate frame type for rendezvous connection\n"); | 62 gaim_debug_misc("oscar", "flap_frame_new: attempted to allocate inappropriate frame type for rendezvous connection\n"); |
62 return NULL; | 63 return NULL; |
63 } | 64 } |
64 } else { | 65 } else { |
65 if (framing != AIM_FRAMETYPE_FLAP) { | 66 if (framing != AIM_FRAMETYPE_FLAP) { |
66 gaim_debug_misc("oscar", "aim_tx_new: attempted to allocate inappropriate frame type for FLAP connection\n"); | 67 gaim_debug_misc("oscar", "flap_frame_new: attempted to allocate inappropriate frame type for FLAP connection\n"); |
67 return NULL; | 68 return NULL; |
68 } | 69 } |
69 } | 70 } |
70 | 71 |
71 if (!(fr = (FlapFrame *)calloc(1, sizeof(FlapFrame)))) | 72 fr = g_new0(FlapFrame, 1); |
72 return NULL; | |
73 | |
74 fr->conn = conn; | 73 fr->conn = conn; |
75 fr->hdrtype = framing; | 74 fr->hdrtype = framing; |
76 if (fr->hdrtype == AIM_FRAMETYPE_FLAP) | 75 if (fr->hdrtype == AIM_FRAMETYPE_FLAP) |
77 fr->hdr.flap.channel = chan; | 76 fr->hdr.flap.channel = chan; |
78 else if (fr->hdrtype == AIM_FRAMETYPE_OFT) | 77 else if (fr->hdrtype == AIM_FRAMETYPE_OFT) |
92 } | 91 } |
93 | 92 |
94 return fr; | 93 return fr; |
95 } | 94 } |
96 | 95 |
97 /* | 96 static int |
98 * This increments the tx command count, and returns the seqnum | 97 aim_send(int fd, const void *buf, size_t count) |
99 * that should be stamped on the next FLAP packet sent. This is | |
100 * normally called during the final step of packet preparation | |
101 * before enqueuement (in aim_tx_enqueue()). | |
102 */ | |
103 static flap_seqnum_t aim_get_next_txseqnum(OscarConnection *conn) | |
104 { | |
105 flap_seqnum_t ret; | |
106 | |
107 ret = ++conn->seqnum; | |
108 | |
109 return ret; | |
110 } | |
111 | |
112 /* | |
113 * The overall purpose here is to enqueue the passed in command struct | |
114 * into the outgoing (tx) queue. Basically... | |
115 * 1) Make a scope-irrelevant copy of the struct | |
116 * 3) Mark as not-sent-yet | |
117 * 4) Enqueue the struct into the list | |
118 * 6) Return | |
119 * | |
120 * Note that this is only used when doing queue-based transmitting; | |
121 * that is, when sess->tx_enqueue is set to &aim_tx_enqueue__queuebased. | |
122 * | |
123 */ | |
124 static int aim_tx_enqueue__queuebased(OscarSession *sess, FlapFrame *fr) | |
125 { | |
126 | |
127 if (!fr->conn) { | |
128 gaim_debug_warning("oscar", "aim_tx_enqueue: enqueueing packet with no connecetion\n"); | |
129 fr->conn = aim_getconn_type(sess, AIM_CONN_TYPE_BOS); | |
130 } | |
131 | |
132 if (fr->hdrtype == AIM_FRAMETYPE_FLAP) { | |
133 /* assign seqnum -- XXX should really not assign until hardxmit */ | |
134 fr->hdr.flap.seqnum = aim_get_next_txseqnum(fr->conn); | |
135 } | |
136 | |
137 fr->handled = 0; /* not sent yet */ | |
138 | |
139 /* see overhead note in aim_rxqueue counterpart */ | |
140 if (!sess->queue_outgoing) | |
141 sess->queue_outgoing = fr; | |
142 else { | |
143 FlapFrame *cur; | |
144 for (cur = sess->queue_outgoing; cur->next; cur = cur->next); | |
145 cur->next = fr; | |
146 } | |
147 | |
148 return 0; | |
149 } | |
150 | |
151 /* | |
152 * Parallel to aim_tx_enqueue__queuebased, however, this bypasses | |
153 * the whole queue mess when you want immediate writes to happen. | |
154 * | |
155 * Basically the same as its __queuebased couterpart, however | |
156 * instead of doing a list append, it just calls aim_tx_sendframe() | |
157 * right here. | |
158 * | |
159 */ | |
160 static int aim_tx_enqueue__immediate(OscarSession *sess, FlapFrame *fr) | |
161 { | |
162 int ret; | |
163 | |
164 if (!fr->conn) { | |
165 gaim_debug_error("oscar", "aim_tx_enqueue: packet has no connection\n"); | |
166 aim_frame_destroy(fr); | |
167 return 0; | |
168 } | |
169 | |
170 if (fr->hdrtype == AIM_FRAMETYPE_FLAP) | |
171 fr->hdr.flap.seqnum = aim_get_next_txseqnum(fr->conn); | |
172 | |
173 fr->handled = 0; /* not sent yet */ | |
174 | |
175 ret = aim_tx_sendframe(sess, fr); | |
176 | |
177 aim_frame_destroy(fr); | |
178 | |
179 return ret; | |
180 } | |
181 | |
182 faim_export int aim_tx_setenqueue(OscarSession *sess, int what, int (*func)(OscarSession *, FlapFrame *)) | |
183 { | |
184 | |
185 if (what == AIM_TX_QUEUED) | |
186 sess->tx_enqueue = &aim_tx_enqueue__queuebased; | |
187 else if (what == AIM_TX_IMMEDIATE) | |
188 sess->tx_enqueue = &aim_tx_enqueue__immediate; | |
189 else if (what == AIM_TX_USER) { | |
190 if (!func) | |
191 return -EINVAL; | |
192 sess->tx_enqueue = func; | |
193 } else | |
194 return -EINVAL; /* unknown action */ | |
195 | |
196 return 0; | |
197 } | |
198 | |
199 faim_internal int aim_tx_enqueue(OscarSession *sess, FlapFrame *fr) | |
200 { | |
201 | |
202 /* | |
203 * If we want to send on a connection that is in progress, we have to force | |
204 * them to use the queue based version. Otherwise, use whatever they | |
205 * want. | |
206 */ | |
207 if (fr && fr->conn && | |
208 (fr->conn->status & AIM_CONN_STATUS_INPROGRESS)) { | |
209 return aim_tx_enqueue__queuebased(sess, fr); | |
210 } | |
211 | |
212 return (*sess->tx_enqueue)(sess, fr); | |
213 } | |
214 | |
215 static int aim_send(int fd, const void *buf, size_t count) | |
216 { | 98 { |
217 int left, cur; | 99 int left, cur; |
218 | 100 |
219 for (cur = 0, left = count; left; ) { | 101 for (cur = 0, left = count; left; ) { |
220 int ret; | 102 int ret; |
231 } | 113 } |
232 | 114 |
233 return cur; | 115 return cur; |
234 } | 116 } |
235 | 117 |
236 faim_internal int aim_bstream_send(ByteStream *bs, OscarConnection *conn, size_t count) | 118 int |
119 aim_bstream_send(ByteStream *bs, OscarConnection *conn, size_t count) | |
237 { | 120 { |
238 int wrote = 0; | 121 int wrote = 0; |
239 | 122 |
240 if (!bs || !conn) | 123 if (!bs || !conn) |
241 return -EINVAL; | 124 return -EINVAL; |
277 bs->offset += wrote; | 160 bs->offset += wrote; |
278 | 161 |
279 return wrote; | 162 return wrote; |
280 } | 163 } |
281 | 164 |
282 static int sendframe_flap(OscarSession *sess, FlapFrame *fr) | 165 static int |
166 sendframe_flap(OscarSession *sess, FlapFrame *fr) | |
283 { | 167 { |
284 ByteStream bs; | 168 ByteStream bs; |
285 guint8 *bs_raw; | 169 guint8 *bs_raw; |
286 int payloadlen, err = 0, bslen; | 170 int payloadlen, err = 0, bslen; |
287 | 171 |
313 fr->conn->lastactivity = time(NULL); | 197 fr->conn->lastactivity = time(NULL); |
314 | 198 |
315 return err; | 199 return err; |
316 } | 200 } |
317 | 201 |
318 static int sendframe_rendezvous(OscarSession *sess, FlapFrame *fr) | 202 static int |
203 sendframe_rendezvous(OscarSession *sess, FlapFrame *fr) | |
319 { | 204 { |
320 ByteStream bs; | 205 ByteStream bs; |
321 guint8 *bs_raw; | 206 guint8 *bs_raw; |
322 int payloadlen, err = 0, bslen; | 207 int payloadlen, err = 0, bslen; |
323 | 208 |
348 fr->conn->lastactivity = time(NULL); | 233 fr->conn->lastactivity = time(NULL); |
349 | 234 |
350 return err; | 235 return err; |
351 } | 236 } |
352 | 237 |
353 faim_internal int aim_tx_sendframe(OscarSession *sess, FlapFrame *fr) | 238 static int |
239 aim_tx_sendframe(OscarSession *sess, FlapFrame *fr) | |
354 { | 240 { |
355 if (fr->hdrtype == AIM_FRAMETYPE_FLAP) | 241 if (fr->hdrtype == AIM_FRAMETYPE_FLAP) |
356 return sendframe_flap(sess, fr); | 242 return sendframe_flap(sess, fr); |
357 else if (fr->hdrtype == AIM_FRAMETYPE_OFT) | 243 else if (fr->hdrtype == AIM_FRAMETYPE_OFT) |
358 return sendframe_rendezvous(sess, fr); | 244 return sendframe_rendezvous(sess, fr); |
359 | 245 |
360 return -1; | 246 return -1; |
361 } | 247 } |
362 | 248 |
363 faim_export int aim_tx_flushqueue(OscarSession *sess) | 249 int |
250 aim_tx_flushqueue(OscarSession *sess) | |
364 { | 251 { |
365 FlapFrame *cur; | 252 FlapFrame *cur; |
366 | 253 |
367 for (cur = sess->queue_outgoing; cur; cur = cur->next) { | 254 for (cur = sess->queue_outgoing; cur; cur = cur->next) { |
368 | 255 |
396 | 283 |
397 return 0; | 284 return 0; |
398 } | 285 } |
399 | 286 |
400 /* | 287 /* |
401 * This is responsible for removing sent commands from the transmit | 288 * This is responsible for removing sent commands from the transmit |
402 * queue. This is not a required operation, but it of course helps | 289 * queue. This is not a required operation, but it of course helps |
403 * reduce memory footprint at run time! | 290 * reduce memory footprint at run time! |
404 */ | 291 */ |
405 faim_export void aim_tx_purgequeue(OscarSession *sess) | 292 void |
293 aim_tx_purgequeue(OscarSession *sess) | |
406 { | 294 { |
407 FlapFrame *cur, **prev; | 295 FlapFrame *cur, **prev; |
408 | 296 |
409 for (prev = &sess->queue_outgoing; (cur = *prev); ) { | 297 for (prev = &sess->queue_outgoing; (cur = *prev); ) { |
410 if (cur->handled) { | 298 if (cur->handled) { |
416 | 304 |
417 return; | 305 return; |
418 } | 306 } |
419 | 307 |
420 /** | 308 /** |
421 * Get rid of packets waiting for tx on a dying conn. For now this | 309 * Get rid of packets waiting for tx on a dying conn. For now this |
422 * simply marks all packets as sent and lets them disappear without | 310 * simply marks all packets as sent and lets them disappear without |
423 * warning. | 311 * warning. |
424 * | 312 * |
425 * @param sess A session. | 313 * @param sess A session. |
426 * @param conn Connection that's dying. | 314 * @param conn Connection that's dying. |
427 */ | 315 */ |
428 faim_internal void aim_tx_cleanqueue(OscarSession *sess, OscarConnection *conn) | 316 void |
317 aim_tx_cleanqueue(OscarSession *sess, OscarConnection *conn) | |
429 { | 318 { |
430 FlapFrame *cur; | 319 FlapFrame *cur; |
431 | 320 |
432 for (cur = sess->queue_outgoing; cur; cur = cur->next) { | 321 for (cur = sess->queue_outgoing; cur; cur = cur->next) { |
433 if (cur->conn == conn) | 322 if (cur->conn == conn) |
434 cur->handled = 1; | 323 cur->handled = 1; |
435 } | 324 } |
436 | 325 |
437 return; | 326 return; |
438 } | 327 } |
328 | |
329 /* | |
330 * This increments the tx command count, and returns the seqnum | |
331 * that should be stamped on the next FLAP packet sent. This is | |
332 * normally called during the final step of packet preparation | |
333 * before enqueuement (in aim_tx_enqueue()). | |
334 */ | |
335 static flap_seqnum_t | |
336 aim_get_next_txseqnum(OscarConnection *conn) | |
337 { | |
338 flap_seqnum_t ret; | |
339 | |
340 ret = ++conn->seqnum; | |
341 | |
342 return ret; | |
343 } | |
344 | |
345 /* | |
346 * The overall purpose here is to enqueue the passed in command struct | |
347 * into the outgoing (tx) queue. Basically... | |
348 * 1) Make a scope-irrelevant copy of the struct | |
349 * 3) Mark as not-sent-yet | |
350 * 4) Enqueue the struct into the list | |
351 * 6) Return | |
352 * | |
353 * Note that this is only used when doing queue-based transmitting; | |
354 * that is, when sess->tx_enqueue is set to &aim_tx_enqueue__queuebased. | |
355 * | |
356 */ | |
357 static int | |
358 aim_tx_enqueue__queuebased(OscarSession *sess, FlapFrame *fr) | |
359 { | |
360 | |
361 if (!fr->conn) { | |
362 gaim_debug_warning("oscar", "aim_tx_enqueue: enqueueing packet with no connecetion\n"); | |
363 fr->conn = aim_getconn_type(sess, AIM_CONN_TYPE_BOS); | |
364 } | |
365 | |
366 if (fr->hdrtype == AIM_FRAMETYPE_FLAP) { | |
367 /* assign seqnum -- XXX should really not assign until hardxmit */ | |
368 fr->hdr.flap.seqnum = aim_get_next_txseqnum(fr->conn); | |
369 } | |
370 | |
371 fr->handled = 0; /* not sent yet */ | |
372 | |
373 /* see overhead note in aim_rxqueue counterpart */ | |
374 if (!sess->queue_outgoing) | |
375 sess->queue_outgoing = fr; | |
376 else { | |
377 FlapFrame *cur; | |
378 for (cur = sess->queue_outgoing; cur->next; cur = cur->next); | |
379 cur->next = fr; | |
380 } | |
381 | |
382 return 0; | |
383 } | |
384 | |
385 /* | |
386 * Parallel to aim_tx_enqueue__queuebased, however, this bypasses | |
387 * the whole queue mess when you want immediate writes to happen. | |
388 * | |
389 * Basically the same as its __queuebased couterpart, however | |
390 * instead of doing a list append, it just calls aim_tx_sendframe() | |
391 * right here. | |
392 * | |
393 */ | |
394 static int | |
395 aim_tx_enqueue__immediate(OscarSession *sess, FlapFrame *fr) | |
396 { | |
397 int ret; | |
398 | |
399 if (!fr->conn) { | |
400 gaim_debug_error("oscar", "aim_tx_enqueue: packet has no connection\n"); | |
401 aim_frame_destroy(fr); | |
402 return 0; | |
403 } | |
404 | |
405 if (fr->hdrtype == AIM_FRAMETYPE_FLAP) | |
406 fr->hdr.flap.seqnum = aim_get_next_txseqnum(fr->conn); | |
407 | |
408 fr->handled = 0; /* not sent yet */ | |
409 | |
410 ret = aim_tx_sendframe(sess, fr); | |
411 | |
412 aim_frame_destroy(fr); | |
413 | |
414 return ret; | |
415 } | |
416 | |
417 int | |
418 aim_tx_setenqueue(OscarSession *sess, int what, int (*func)(OscarSession *, FlapFrame *)) | |
419 { | |
420 | |
421 if (what == AIM_TX_QUEUED) | |
422 sess->tx_enqueue = &aim_tx_enqueue__queuebased; | |
423 else if (what == AIM_TX_IMMEDIATE) | |
424 sess->tx_enqueue = &aim_tx_enqueue__immediate; | |
425 else | |
426 return -EINVAL; /* unknown action */ | |
427 | |
428 return 0; | |
429 } | |
430 | |
431 int | |
432 aim_tx_enqueue(OscarSession *sess, FlapFrame *fr) | |
433 { | |
434 /* | |
435 * If we want to send on a connection that is in progress, we have to force | |
436 * them to use the queue based version. Otherwise, use whatever they | |
437 * want. | |
438 */ | |
439 if (fr && fr->conn && | |
440 (fr->conn->status & AIM_CONN_STATUS_INPROGRESS)) { | |
441 return aim_tx_enqueue__queuebased(sess, fr); | |
442 } | |
443 | |
444 return (*sess->tx_enqueue)(sess, fr); | |
445 } |