Mercurial > pidgin.yaz
annotate src/protocols/oscar/rxqueue.c @ 12312:1c8ea8f3b84e
[gaim-migrate @ 14616]
forgot a line, and infamy
committer: Tailor Script <tailor@pidgin.im>
author | Christopher O'Brien <siege@pidgin.im> |
---|---|
date | Sun, 04 Dec 2005 05:04:39 +0000 |
parents | 7d31d61e6438 |
children | c5c0f714d8bc |
rev | line source |
---|---|
2086 | 1 /* |
2 * This file contains the management routines for the receive | |
3 * (incoming packet) queue. The actual packet handlers are in | |
8880 | 4 * rxhandlers.c. |
2086 | 5 */ |
6 | |
7 #define FAIM_INTERNAL | |
10267 | 8 #include <aim.h> |
2086 | 9 |
10 #ifndef _WIN32 | |
11 #include <sys/socket.h> | |
12 #endif | |
13 | |
14 /* | |
15 * | |
16 */ | |
17 faim_internal int aim_recv(int fd, void *buf, size_t count) | |
18 { | |
10267 | 19 int left, cur; |
2246
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
20 |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
21 for (cur = 0, left = count; left; ) { |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
22 int ret; |
10267 | 23 |
2246
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
24 ret = recv(fd, ((unsigned char *)buf)+cur, left, 0); |
2808
e79f30457998
[gaim-migrate @ 2821]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2706
diff
changeset
|
25 |
e79f30457998
[gaim-migrate @ 2821]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2706
diff
changeset
|
26 /* Of course EOF is an error, only morons disagree with that. */ |
e79f30457998
[gaim-migrate @ 2821]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2706
diff
changeset
|
27 if (ret <= 0) |
2246
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
28 return -1; |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
29 |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
30 cur += ret; |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
31 left -= ret; |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
32 } |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
33 |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
34 return cur; |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
35 } |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
36 |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
37 /* |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
38 * Read into a byte stream. Will not read more than count, but may read |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
39 * less if there is not enough room in the stream buffer. |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
40 */ |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
41 faim_internal int aim_bstream_recv(aim_bstream_t *bs, int fd, size_t count) |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
42 { |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
43 int red = 0; |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
44 |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
45 if (!bs || (fd < 0) || (count < 0)) |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
46 return -1; |
10267 | 47 |
2246
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
48 if (count > (bs->len - bs->offset)) |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
49 count = bs->len - bs->offset; /* truncate to remaining space */ |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
50 |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
51 if (count) { |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
52 |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
53 red = aim_recv(fd, bs->data + bs->offset, count); |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
54 |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
55 if (red <= 0) |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
56 return -1; |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
57 } |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
58 |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
59 bs->offset += red; |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
60 |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
61 return red; |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
62 } |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
63 |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
64 /** |
7806 | 65 * Free an aim_frame_t |
2246
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
66 * |
7806 | 67 * @param frame The frame to free. |
68 * @return -1 on error; 0 on success. | |
2246
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
69 */ |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
70 faim_internal void aim_frame_destroy(aim_frame_t *frame) |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
71 { |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
72 |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
73 free(frame->data.data); /* XXX aim_bstream_free */ |
3952 | 74 free(frame); |
2246
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
75 |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
76 return; |
3952 | 77 } |
2246
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
78 |
2086 | 79 /* |
7806 | 80 * Read a FLAP header from conn into fr, and return the number of |
81 * bytes in the payload. | |
82 * | |
83 * @return -1 on error, otherwise return the length of the payload. | |
2086 | 84 */ |
5414 | 85 static int aim_get_command_flap(aim_session_t *sess, aim_conn_t *conn, aim_frame_t *fr) |
2086 | 86 { |
7806 | 87 fu8_t hdr_raw[6]; |
88 aim_bstream_t hdr; | |
10267 | 89 |
7806 | 90 fr->hdrtype = AIM_FRAMETYPE_FLAP; |
2086 | 91 |
2246
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
92 /* |
7806 | 93 * Read FLAP header. Six bytes total. |
94 * | |
95 * Byte # | Description | |
96 * -------|------------- | |
97 * 0x00 | Always 0x2a | |
98 * 0x01 | Channel number, usually "2." "1" is used during login, | |
99 * | 4 is used during logoff. | |
100 * 0x02 | Sequence number, 2 bytes. | |
101 * 0x04 | Number of data bytes that follow, 2 bytes. | |
2246
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
102 */ |
7806 | 103 aim_bstream_init(&hdr, hdr_raw, sizeof(hdr_raw)); |
104 if (aim_bstream_recv(&hdr, conn->fd, 6) < 6) { | |
10271 | 105 aim_conn_close(conn); |
2246
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
106 return -1; |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
107 } |
2086 | 108 |
7806 | 109 aim_bstream_rewind(&hdr); |
2246
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
110 |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
111 /* |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
112 * This shouldn't happen unless the socket breaks, the server breaks, |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
113 * or we break. We must handle it just in case. |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
114 */ |
7806 | 115 if (aimbs_get8(&hdr) != 0x2a) { |
11253 | 116 gaim_debug_misc("oscar", "Invalid FLAP frame received on FLAP connection!"); |
10271 | 117 aim_conn_close(conn); |
2246
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
118 return -1; |
10267 | 119 } |
2086 | 120 |
7806 | 121 fr->hdr.flap.channel = aimbs_get8(&hdr); |
122 fr->hdr.flap.seqnum = aimbs_get16(&hdr); | |
3952 | 123 |
7806 | 124 return aimbs_get16(&hdr); |
3952 | 125 } |
126 | |
127 /* | |
7806 | 128 * Read a rendezvous header from conn into fr, and return the number of |
129 * bytes in the payload. | |
130 * | |
131 * @return -1 on error, otherwise return the length of the payload. | |
3952 | 132 */ |
133 static int aim_get_command_rendezvous(aim_session_t *sess, aim_conn_t *conn, aim_frame_t *fr) | |
134 { | |
7806 | 135 fu8_t hdr_raw[8]; |
136 aim_bstream_t hdr; | |
137 | |
138 fr->hdrtype = AIM_FRAMETYPE_OFT; | |
3952 | 139 |
7806 | 140 /* |
141 * Read rendezvous header | |
142 */ | |
143 aim_bstream_init(&hdr, hdr_raw, sizeof(hdr_raw)); | |
144 if (aim_bstream_recv(&hdr, conn->fd, 8) < 8) { | |
10271 | 145 aim_conn_close(conn); |
2246
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
146 return -1; |
3952 | 147 } |
148 | |
7806 | 149 aim_bstream_rewind(&hdr); |
3952 | 150 |
7806 | 151 aimbs_getrawbuf(&hdr, fr->hdr.rend.magic, 4); |
152 fr->hdr.rend.hdrlen = aimbs_get16(&hdr); | |
153 fr->hdr.rend.type = aimbs_get16(&hdr); | |
3952 | 154 |
7806 | 155 return fr->hdr.rend.hdrlen - 8; |
3952 | 156 } |
2086 | 157 |
3952 | 158 /* |
159 * Grab a single command sequence off the socket, and enqueue it in the incoming event queue | |
160 * in a separate struct. | |
7806 | 161 * |
162 * @return 0 on success, otherwise return the error number. | |
3952 | 163 */ |
164 faim_export int aim_get_command(aim_session_t *sess, aim_conn_t *conn) | |
165 { | |
7806 | 166 aim_frame_t *fr; |
167 int payloadlen; | |
3952 | 168 |
169 if (!sess || !conn) | |
4617 | 170 return -EINVAL; |
3952 | 171 |
172 if (conn->fd == -1) | |
173 return -1; /* it's an aim_conn_close()'d connection */ | |
174 | |
11214 | 175 /* If stdin is closed, then zero becomes a valid fd |
176 if (conn->fd < 3) | |
3952 | 177 return -1; |
11214 | 178 */ |
3952 | 179 |
180 if (conn->status & AIM_CONN_STATUS_INPROGRESS) | |
181 return aim_conn_completeconnect(sess, conn); | |
182 | |
7806 | 183 if (!(fr = (aim_frame_t *)calloc(sizeof(aim_frame_t), 1))) |
4617 | 184 return -ENOMEM; |
3952 | 185 |
186 /* | |
187 * Rendezvous (client to client) connections do not speak FLAP, so this | |
188 * function will break on them. | |
189 */ | |
7806 | 190 if (conn->type == AIM_CONN_TYPE_RENDEZVOUS) |
191 payloadlen = aim_get_command_rendezvous(sess, conn, fr); | |
192 else if (conn->type == AIM_CONN_TYPE_LISTENER) { | |
11253 | 193 gaim_debug_misc("oscar", "AIM_CONN_TYPE_LISTENER on fd %d\n", conn->fd); |
7806 | 194 free(fr); |
195 return -1; | |
196 } else | |
197 payloadlen = aim_get_command_flap(sess, conn, fr); | |
5927 | 198 |
7806 | 199 if (payloadlen < 0) { |
200 free(fr); | |
201 return -1; | |
202 } | |
203 | |
204 if (payloadlen > 0) { | |
205 fu8_t *payload = NULL; | |
206 | |
207 if (!(payload = (fu8_t *) malloc(payloadlen))) { | |
208 aim_frame_destroy(fr); | |
5927 | 209 return -1; |
210 } | |
211 | |
7806 | 212 aim_bstream_init(&fr->data, payload, payloadlen); |
2086 | 213 |
2246
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
214 /* read the payload */ |
7806 | 215 if (aim_bstream_recv(&fr->data, conn->fd, payloadlen) < payloadlen) { |
216 aim_frame_destroy(fr); /* free's payload */ | |
10271 | 217 aim_conn_close(conn); |
2246
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
218 return -1; |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
219 } |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
220 } else |
7806 | 221 aim_bstream_init(&fr->data, NULL, 0); |
2086 | 222 |
7806 | 223 aim_bstream_rewind(&fr->data); |
2086 | 224 |
7806 | 225 fr->conn = conn; |
2246
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
226 |
7806 | 227 /* Enqueue this puppy */ |
228 fr->next = NULL; /* this will always be at the bottom */ | |
229 if (sess->queue_incoming == NULL) | |
230 sess->queue_incoming = fr; | |
2246
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
231 else { |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
232 aim_frame_t *cur; |
7806 | 233 for (cur = sess->queue_incoming; cur->next; cur = cur->next); |
234 cur->next = fr; | |
2246
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
235 } |
2086 | 236 |
7806 | 237 fr->conn->lastactivity = time(NULL); |
2246
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
238 |
10267 | 239 return 0; |
2086 | 240 } |
241 | |
242 /* | |
8735
92cbf9713795
[gaim-migrate @ 9490]
Christian Hammond <chipx86@chipx86.com>
parents:
7806
diff
changeset
|
243 * Purge receive queue of all handled commands (->handled==1). |
2086 | 244 * |
245 */ | |
2246
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
246 faim_export void aim_purge_rxqueue(aim_session_t *sess) |
2086 | 247 { |
2246
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
248 aim_frame_t *cur, **prev; |
2086 | 249 |
2246
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
250 for (prev = &sess->queue_incoming; (cur = *prev); ) { |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
251 if (cur->handled) { |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
252 *prev = cur->next; |
7806 | 253 aim_frame_destroy(cur); |
2246
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
254 } else |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
255 prev = &cur->next; |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
256 } |
2086 | 257 |
2246
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
258 return; |
2086 | 259 } |
260 | |
261 /* | |
262 * Since aim_get_command will aim_conn_kill dead connections, we need | |
263 * to clean up the rxqueue of unprocessed connections on that socket. | |
264 * | |
265 * XXX: this is something that was handled better in the old connection | |
266 * handling method, but eh. | |
267 */ | |
2246
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
268 faim_internal void aim_rxqueue_cleanbyconn(aim_session_t *sess, aim_conn_t *conn) |
2086 | 269 { |
2246
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
270 aim_frame_t *currx; |
2086 | 271 |
2246
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
272 for (currx = sess->queue_incoming; currx; currx = currx->next) { |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
273 if ((!currx->handled) && (currx->conn == conn)) |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
274 currx->handled = 1; |
10267 | 275 } |
7806 | 276 |
2246
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
277 return; |
2086 | 278 } |