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 }