Mercurial > pidgin.yaz
annotate src/protocols/oscar/rxqueue.c @ 10563:3e2cd3fe8897
[gaim-migrate @ 11944]
Fix a problem Justin Wood noticed and supplied sf patch 920581 to fix
My fix is slightly difference.
The problem was that, if an iChat user had an available message up,
then they changed their buddy icon, Gaim would stop showing the
available message for the person.
committer: Tailor Script <tailor@pidgin.im>
author | Mark Doliner <mark@kingant.net> |
---|---|
date | Tue, 01 Feb 2005 05:19:27 +0000 |
parents | 361c9170d8af |
children | 751de30689ef |
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) { |
116 faimdprintf(sess, 0, "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 | |
175 if (conn->fd < 3) /* can happen when people abuse the interface */ | |
176 return -1; | |
177 | |
178 if (conn->status & AIM_CONN_STATUS_INPROGRESS) | |
179 return aim_conn_completeconnect(sess, conn); | |
180 | |
7806 | 181 if (!(fr = (aim_frame_t *)calloc(sizeof(aim_frame_t), 1))) |
4617 | 182 return -ENOMEM; |
3952 | 183 |
184 /* | |
185 * Rendezvous (client to client) connections do not speak FLAP, so this | |
186 * function will break on them. | |
187 */ | |
7806 | 188 if (conn->type == AIM_CONN_TYPE_RENDEZVOUS) |
189 payloadlen = aim_get_command_rendezvous(sess, conn, fr); | |
190 else if (conn->type == AIM_CONN_TYPE_LISTENER) { | |
191 faimdprintf(sess, 0, "AIM_CONN_TYPE_LISTENER on fd %d\n", conn->fd); | |
192 free(fr); | |
193 return -1; | |
194 } else | |
195 payloadlen = aim_get_command_flap(sess, conn, fr); | |
5927 | 196 |
7806 | 197 if (payloadlen < 0) { |
198 free(fr); | |
199 return -1; | |
200 } | |
201 | |
202 if (payloadlen > 0) { | |
203 fu8_t *payload = NULL; | |
204 | |
205 if (!(payload = (fu8_t *) malloc(payloadlen))) { | |
206 aim_frame_destroy(fr); | |
5927 | 207 return -1; |
208 } | |
209 | |
7806 | 210 aim_bstream_init(&fr->data, payload, payloadlen); |
2086 | 211 |
2246
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
212 /* read the payload */ |
7806 | 213 if (aim_bstream_recv(&fr->data, conn->fd, payloadlen) < payloadlen) { |
214 aim_frame_destroy(fr); /* free's payload */ | |
10271 | 215 aim_conn_close(conn); |
2246
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
216 return -1; |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
217 } |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
218 } else |
7806 | 219 aim_bstream_init(&fr->data, NULL, 0); |
2086 | 220 |
7806 | 221 aim_bstream_rewind(&fr->data); |
2086 | 222 |
7806 | 223 fr->conn = conn; |
2246
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
224 |
7806 | 225 /* Enqueue this puppy */ |
226 fr->next = NULL; /* this will always be at the bottom */ | |
227 if (sess->queue_incoming == NULL) | |
228 sess->queue_incoming = fr; | |
2246
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
229 else { |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
230 aim_frame_t *cur; |
7806 | 231 for (cur = sess->queue_incoming; cur->next; cur = cur->next); |
232 cur->next = fr; | |
2246
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
233 } |
2086 | 234 |
7806 | 235 fr->conn->lastactivity = time(NULL); |
2246
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
236 |
10267 | 237 return 0; |
2086 | 238 } |
239 | |
240 /* | |
8735
92cbf9713795
[gaim-migrate @ 9490]
Christian Hammond <chipx86@chipx86.com>
parents:
7806
diff
changeset
|
241 * Purge receive queue of all handled commands (->handled==1). |
2086 | 242 * |
243 */ | |
2246
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
244 faim_export void aim_purge_rxqueue(aim_session_t *sess) |
2086 | 245 { |
2246
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
246 aim_frame_t *cur, **prev; |
2086 | 247 |
2246
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
248 for (prev = &sess->queue_incoming; (cur = *prev); ) { |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
249 if (cur->handled) { |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
250 *prev = cur->next; |
7806 | 251 aim_frame_destroy(cur); |
2246
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
252 } else |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
253 prev = &cur->next; |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
254 } |
2086 | 255 |
2246
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
256 return; |
2086 | 257 } |
258 | |
259 /* | |
260 * Since aim_get_command will aim_conn_kill dead connections, we need | |
261 * to clean up the rxqueue of unprocessed connections on that socket. | |
262 * | |
263 * XXX: this is something that was handled better in the old connection | |
264 * handling method, but eh. | |
265 */ | |
2246
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
266 faim_internal void aim_rxqueue_cleanbyconn(aim_session_t *sess, aim_conn_t *conn) |
2086 | 267 { |
2246
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
268 aim_frame_t *currx; |
2086 | 269 |
2246
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
270 for (currx = sess->queue_incoming; currx; currx = currx->next) { |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
271 if ((!currx->handled) && (currx->conn == conn)) |
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
272 currx->handled = 1; |
10267 | 273 } |
7806 | 274 |
2246
933346315b9b
[gaim-migrate @ 2256]
Eric Warmenhoven <eric@warmenhoven.org>
parents:
2086
diff
changeset
|
275 return; |
2086 | 276 } |