]> andersk Git - libfaim.git/blame - aim_txqueue.c
- Thu Mar 23 08:45:40 UTC 2000
[libfaim.git] / aim_txqueue.c
CommitLineData
9de3ca7e 1/*
24286d93 2 * aim_txqueue.c
3 *
4 * Herein lies all the mangement routines for the transmit (Tx) queue.
5 *
9de3ca7e 6 */
7
a25832e6 8#include <faim/aim.h>
9de3ca7e 9
10/*
24286d93 11 * aim_tx_enqeue()
12 *
13 * The overall purpose here is to enqueue the passed in command struct
14 * into the outgoing (tx) queue. Basically...
15 * 1) Make a scope-irrelevent copy of the struct
16 * 2) Lock the struct
17 * 3) Mark as not-sent-yet
18 * 4) Enqueue the struct into the list
19 * 5) Unlock the struct once it's linked in
20 * 6) Return
21 *
9de3ca7e 22 */
a25832e6 23int aim_tx_enqueue(struct aim_session_t *sess,
24 struct command_tx_struct *newpacket)
9de3ca7e 25{
b8d0da45 26 struct command_tx_struct *cur;
9de3ca7e 27 struct command_tx_struct *newpacket_copy = NULL;
28
b8d0da45 29 if (newpacket->conn == NULL) {
30 faimdprintf(1, "aim_tx_enqueue: WARNING: enqueueing packet with no connecetion, defaulting to BOS\n");
a25832e6 31 newpacket->conn = aim_getconn_type(sess, AIM_CONN_TYPE_BOS);
b8d0da45 32 }
9de3ca7e 33
34 newpacket_copy = (struct command_tx_struct *) malloc (sizeof(struct command_tx_struct));
35 memcpy(newpacket_copy, newpacket, sizeof(struct command_tx_struct));
36
37 /* assign seqnum */
38 newpacket_copy->seqnum = aim_get_next_txseqnum(newpacket_copy->conn);
39 /* set some more fields */
40 newpacket_copy->lock = 1; /* lock */
41 newpacket_copy->sent = 0; /* not sent yet */
42 newpacket_copy->next = NULL; /* always last */
43
b8d0da45 44 /* see overhead note in aim_rxqueue counterpart */
45 if (sess->queue_outgoing == NULL) {
46 sess->queue_outgoing = newpacket_copy;
47 } else {
48 for (cur = sess->queue_outgoing;
49 cur->next;
50 cur = cur->next)
51 ;
52 cur->next = newpacket_copy;
53 }
9de3ca7e 54
55 newpacket_copy->lock = 0; /* unlock so it can be sent */
56
b8d0da45 57#if debug == 2
58 faimdprintf(2, "calling aim_tx_printqueue()\n");
0c20631f 59 aim_tx_printqueue(sess);
b8d0da45 60 faimdprintf(2, "back from aim_tx_printqueue()\n");
9de3ca7e 61#endif
62
63 return 0;
64}
65
66/*
a25832e6 67 * aim_get_next_txseqnum()
68 *
69 * This increments the tx command count, and returns the seqnum
70 * that should be stamped on the next FLAP packet sent. This is
71 * normally called during the final step of packet preparation
72 * before enqueuement (in aim_tx_enqueue()).
73 *
9de3ca7e 74 */
75u_int aim_get_next_txseqnum(struct aim_conn_t *conn)
76{
77 return ( ++conn->seqnum );
78}
79
80/*
a25832e6 81 * aim_tx_printqueue()
82 *
83 * This is basically for debuging purposes only. It dumps all the
84 * records in the tx queue and their current status. Very helpful
85 * if the queue isn't working quite right.
86 *
9de3ca7e 87 */
b8d0da45 88#if debug == 2
0c20631f 89int aim_tx_printqueue(struct aim_session_t *sess)
9de3ca7e 90{
b8d0da45 91 struct command_tx_struct *cur;
9de3ca7e 92
b8d0da45 93 faimdprintf(2, "\ncurrent aim_queue_outgoing...\n");
94 faimdprintf(2, "\ttype seqnum len lock sent\n");
95
96 if (sess->queue_outgoing == NULL)
97 faimdprintf(2, "aim_tx_flushqueue(): queue empty");
98 else {
99 for (cur = sess->queue_outgoing; cur; cur = cur->next) {
100 faimdprintf(2, "\t %2x %4x %4x %1d %1d\n",
101 cur->type, cur->seqnum,
102 cur->commandlen, cur->lock,
103 cur->sent);
104 }
105 }
9de3ca7e 106
b8d0da45 107 faimdprintf(2, "\n(done printing queue)\n");
9de3ca7e 108
109 return 0;
110}
111#endif
112
113/*
a25832e6 114 * aim_tx_flushqueue()
115 *
116 * This the function is responsable for putting the queued commands
117 * onto the wire. This function is critical to the operation of
118 * the queue and therefore is the most prone to brokenness. It
119 * seems to be working quite well at this point.
120 *
121 * Procedure:
122 * 1) Traverse the list, only operate on commands that are unlocked
123 * and haven't been sent yet.
124 * 2) Lock the struct
125 * 3) Allocate a temporary buffer to store the finished, fully
126 * processed packet in.
127 * 4) Build the packet from the command_tx_struct data.
128 * 5) Write the packet to the socket.
129 * 6) If success, mark the packet sent, if fail report failure, do NOT
130 * mark the packet sent (so it will not get purged and therefore
131 * be attempted again on next call).
132 * 7) Unlock the struct.
133 * 8) Free the temp buffer
134 * 9) Step to next struct in list and go back to 1.
135 *
9de3ca7e 136 */
a25832e6 137int aim_tx_flushqueue(struct aim_session_t *sess)
9de3ca7e 138{
b8d0da45 139 struct command_tx_struct *cur;
9de3ca7e 140 u_char *curPacket = NULL;
141#if debug > 1
142 int i = 0;
143#endif
144
b8d0da45 145 if (sess->queue_outgoing == NULL)
146 return 0;
a25832e6 147
b8d0da45 148 faimdprintf(2, "beginning txflush...\n");
149 for (cur = sess->queue_outgoing; cur; cur = cur->next) {
150 /* only process if its unlocked and unsent */
151 if (!cur->lock && !cur->sent) {
a25832e6 152
b8d0da45 153 /*
154 * And now for the meager attempt to force transmit
155 * latency and avoid missed messages.
156 */
157 if ((cur->conn->lastactivity + cur->conn->forcedlatency) >= time(NULL)) {
158 /* FIXME FIXME -- should be a break! we dont want to block the upper layers */
159 sleep((cur->conn->lastactivity + cur->conn->forcedlatency) - time(NULL));
160 }
161
162 cur->lock = 1; /* lock the struct */
163
164 /* allocate full-packet buffer */
165 curPacket = (char *) malloc(cur->commandlen + 6);
166
167 /* command byte */
168 curPacket[0] = 0x2a;
169
170 /* type/family byte */
171 curPacket[1] = cur->type;
172
173 /* bytes 3+4: word: FLAP sequence number */
174 aimutil_put16(curPacket+2, cur->seqnum);
a25832e6 175
b8d0da45 176 /* bytes 5+6: word: SNAC len */
177 aimutil_put16(curPacket+4, cur->commandlen);
178
179 /* bytes 7 and on: raw: SNAC data */
180 memcpy(&(curPacket[6]), cur->data, cur->commandlen);
181
182 /* full image of raw packet data now in curPacket */
183 if ( (u_int)write(cur->conn->fd, curPacket, (cur->commandlen + 6)) != (cur->commandlen + 6)) {
184 printf("\nWARNING: Error in sending packet 0x%4x -- will try again next time\n\n", cur->seqnum);
185 cur->sent = 0; /* mark it unsent */
186 continue; /* bail out */
187 } else {
188 faimdprintf(2, "\nSENT 0x%4x\n\n", cur->seqnum);
a25832e6 189
b8d0da45 190 cur->sent = 1; /* mark the struct as sent */
191 cur->conn->lastactivity = time(NULL);
192 }
9de3ca7e 193#if debug > 2
b8d0da45 194 faimdprintf(2, "\nPacket:");
195 for (i = 0; i < (cur->commandlen + 6); i++) {
196 if ((i % 8) == 0) {
197 faimdprintf(2, "\n\t");
198 }
199 if (curPacket[i] >= ' ' && curPacket[i]<127) {
200 faimdprintf(2, "%c=%02x ", curPacket[i], curPacket[i]);
201 } else {
202 faimdprintf(2, "0x%2x ", curPacket[i]);
9de3ca7e 203 }
b8d0da45 204 }
205 faimdprintf(2, "\n");
206#endif
207 cur->lock = 0; /* unlock the struct */
208 free(curPacket); /* free up full-packet buffer */
9de3ca7e 209 }
b8d0da45 210 }
9de3ca7e 211
212 /* purge sent commands from queue */
a25832e6 213 aim_tx_purgequeue(sess);
9de3ca7e 214
215 return 0;
216}
217
218/*
a25832e6 219 * aim_tx_purgequeue()
220 *
221 * This is responsable for removing sent commands from the transmit
222 * queue. This is not a required operation, but it of course helps
223 * reduce memory footprint at run time!
224 *
9de3ca7e 225 */
b8d0da45 226void aim_tx_purgequeue(struct aim_session_t *sess)
9de3ca7e 227{
b8d0da45 228 struct command_tx_struct *cur = NULL;
229 struct command_tx_struct *tmp;
230
a25832e6 231 if (sess->queue_outgoing == NULL)
b8d0da45 232 return;
233
234 if (sess->queue_outgoing->next == NULL) {
235 if (!sess->queue_outgoing->lock && sess->queue_outgoing->sent) {
236 tmp = sess->queue_outgoing;
237 sess->queue_outgoing = NULL;
238 free(tmp->data);
239 free(tmp);
9de3ca7e 240 }
b8d0da45 241 return;
242 }
243
244 for(cur = sess->queue_outgoing; cur->next != NULL; ) {
245 if (!cur->next->lock && cur->next->sent) {
246 tmp = cur->next;
247 cur->next = tmp->next;
248 free(tmp->data);
249 free(tmp);
250 }
251 cur = cur->next;
9de3ca7e 252
b8d0da45 253 /*
254 * Be careful here. Because of the way we just
255 * manipulated the pointer, cur may be NULL and
256 * the for() will segfault doing the check unless
257 * we find this case first.
258 */
259 if (cur == NULL)
260 break;
261 }
262 return;
9de3ca7e 263}
This page took 0.840109 seconds and 5 git commands to generate.