Mercurial > pidgin.yaz
comparison src/protocols/oscar/rxqueue.c @ 7806:c86f075b269a
[gaim-migrate @ 8453]
I modified some of the libfaim connection stuff. I dunno, it seems
cleaner this way. I like to be comfortable with what's going on.
It's possible that FT and DC won't work now (although, they should),
but I'll get to making them suck less pretty soon.
Also upgraded the Doxyfile to 1 version newer. It mostly just moved
some things around, but also removed the CGI_BLEH lines from the end.
committer: Tailor Script <tailor@pidgin.im>
author | Mark Doliner <mark@kingant.net> |
---|---|
date | Mon, 08 Dec 2003 05:41:04 +0000 |
parents | 04dc7fe68889 |
children | 92cbf9713795 |
comparison
equal
deleted
inserted
replaced
7805:5f0bb52c0609 | 7806:c86f075b269a |
---|---|
62 | 62 |
63 return red; | 63 return red; |
64 } | 64 } |
65 | 65 |
66 /** | 66 /** |
67 * aim_frame_destroy - free aim_frame_t | 67 * Free an aim_frame_t |
68 * @frame: the frame to free | 68 * |
69 * | 69 * @param frame The frame to free. |
70 * returns -1 on error; 0 on success. | 70 * @return -1 on error; 0 on success. |
71 * | |
72 */ | 71 */ |
73 faim_internal void aim_frame_destroy(aim_frame_t *frame) | 72 faim_internal void aim_frame_destroy(aim_frame_t *frame) |
74 { | 73 { |
75 | 74 |
76 free(frame->data.data); /* XXX aim_bstream_free */ | 75 free(frame->data.data); /* XXX aim_bstream_free */ |
78 | 77 |
79 return; | 78 return; |
80 } | 79 } |
81 | 80 |
82 /* | 81 /* |
83 * Read a FLAP header from conn into fr, and return the number of bytes in the payload. | 82 * Read a FLAP header from conn into fr, and return the number of |
83 * bytes in the payload. | |
84 * | |
85 * @return -1 on error, otherwise return the length of the payload. | |
84 */ | 86 */ |
85 static int aim_get_command_flap(aim_session_t *sess, aim_conn_t *conn, aim_frame_t *fr) | 87 static int aim_get_command_flap(aim_session_t *sess, aim_conn_t *conn, aim_frame_t *fr) |
86 { | 88 { |
87 fu8_t flaphdr_raw[6]; | 89 fu8_t hdr_raw[6]; |
88 aim_bstream_t flaphdr; | 90 aim_bstream_t hdr; |
89 fu16_t payloadlen; | |
90 | 91 |
91 aim_bstream_init(&flaphdr, flaphdr_raw, sizeof(flaphdr_raw)); | 92 fr->hdrtype = AIM_FRAMETYPE_FLAP; |
92 | 93 |
93 /* | 94 /* |
94 * Read FLAP header. Six bytes: | 95 * Read FLAP header. Six bytes total. |
95 * 0 char -- Always 0x2a | 96 * |
96 * 1 char -- Channel ID. Usually 2 -- 1 and 4 are used during login. | 97 * Byte # | Description |
97 * 2 short -- Sequence number | 98 * -------|------------- |
98 * 4 short -- Number of data bytes that follow. | 99 * 0x00 | Always 0x2a |
99 */ | 100 * 0x01 | Channel number, usually "2." "1" is used during login, |
100 if (aim_bstream_recv(&flaphdr, conn->fd, 6) < 6) { | 101 * | 4 is used during logoff. |
102 * 0x02 | Sequence number, 2 bytes. | |
103 * 0x04 | Number of data bytes that follow, 2 bytes. | |
104 */ | |
105 aim_bstream_init(&hdr, hdr_raw, sizeof(hdr_raw)); | |
106 if (aim_bstream_recv(&hdr, conn->fd, 6) < 6) { | |
101 aim_conn_close(conn); | 107 aim_conn_close(conn); |
102 return -1; | 108 return -1; |
103 } | 109 } |
104 | 110 |
105 aim_bstream_rewind(&flaphdr); | 111 aim_bstream_rewind(&hdr); |
106 | 112 |
107 /* | 113 /* |
108 * This shouldn't happen unless the socket breaks, the server breaks, | 114 * This shouldn't happen unless the socket breaks, the server breaks, |
109 * or we break. We must handle it just in case. | 115 * or we break. We must handle it just in case. |
110 */ | 116 */ |
111 if (aimbs_get8(&flaphdr) != 0x2a) { | 117 if (aimbs_get8(&hdr) != 0x2a) { |
112 fu8_t start; | 118 faimdprintf(sess, 0, "Invalid FLAP frame received on FLAP connection!"); |
113 | |
114 aim_bstream_rewind(&flaphdr); | |
115 start = aimbs_get8(&flaphdr); | |
116 faimdprintf(sess, 0, "FLAP framing disrupted (0x%02x)", start); | |
117 aim_conn_close(conn); | 119 aim_conn_close(conn); |
118 return -1; | 120 return -1; |
119 } | 121 } |
120 | 122 |
121 /* we're doing FLAP if we're here */ | 123 fr->hdr.flap.channel = aimbs_get8(&hdr); |
122 fr->hdrtype = AIM_FRAMETYPE_FLAP; | 124 fr->hdr.flap.seqnum = aimbs_get16(&hdr); |
123 | 125 |
124 fr->hdr.flap.type = aimbs_get8(&flaphdr); | 126 return aimbs_get16(&hdr); |
125 fr->hdr.flap.seqnum = aimbs_get16(&flaphdr); | 127 } |
126 payloadlen = aimbs_get16(&flaphdr); /* length of payload */ | 128 |
127 | 129 /* |
128 return payloadlen; | 130 * Read a rendezvous header from conn into fr, and return the number of |
129 } | 131 * bytes in the payload. |
130 | 132 * |
131 /* | 133 * @return -1 on error, otherwise return the length of the payload. |
132 * Read a rendezvous header from conn into fr, and return the number of bytes in the payload. | |
133 */ | 134 */ |
134 static int aim_get_command_rendezvous(aim_session_t *sess, aim_conn_t *conn, aim_frame_t *fr) | 135 static int aim_get_command_rendezvous(aim_session_t *sess, aim_conn_t *conn, aim_frame_t *fr) |
135 { | 136 { |
136 fu8_t rendhdr_raw[8]; | 137 fu8_t hdr_raw[8]; |
137 aim_bstream_t rendhdr; | 138 aim_bstream_t hdr; |
138 | 139 |
139 aim_bstream_init(&rendhdr, rendhdr_raw, sizeof(rendhdr_raw)); | 140 fr->hdrtype = AIM_FRAMETYPE_OFT; |
140 | 141 |
141 if (aim_bstream_recv(&rendhdr, conn->fd, 8) < 8) { | 142 /* |
143 * Read rendezvous header | |
144 */ | |
145 aim_bstream_init(&hdr, hdr_raw, sizeof(hdr_raw)); | |
146 if (aim_bstream_recv(&hdr, conn->fd, 8) < 8) { | |
142 aim_conn_close(conn); | 147 aim_conn_close(conn); |
143 return -1; | 148 return -1; |
144 } | 149 } |
145 | 150 |
146 aim_bstream_rewind(&rendhdr); | 151 aim_bstream_rewind(&hdr); |
147 | 152 |
148 fr->hdrtype = AIM_FRAMETYPE_OFT; /* a misnomer--rendezvous */ | 153 aimbs_getrawbuf(&hdr, fr->hdr.rend.magic, 4); |
149 | 154 fr->hdr.rend.hdrlen = aimbs_get16(&hdr); |
150 aimbs_getrawbuf(&rendhdr, fr->hdr.rend.magic, 4); | 155 fr->hdr.rend.type = aimbs_get16(&hdr); |
151 fr->hdr.rend.hdrlen = aimbs_get16(&rendhdr) - 8; | 156 |
152 fr->hdr.rend.type = aimbs_get16(&rendhdr); | 157 return fr->hdr.rend.hdrlen - 8; |
153 | |
154 return fr->hdr.rend.hdrlen; | |
155 } | 158 } |
156 | 159 |
157 /* | 160 /* |
158 * Grab a single command sequence off the socket, and enqueue it in the incoming event queue | 161 * Grab a single command sequence off the socket, and enqueue it in the incoming event queue |
159 * in a separate struct. | 162 * in a separate struct. |
163 * | |
164 * @return 0 on success, otherwise return the error number. | |
160 */ | 165 */ |
161 faim_export int aim_get_command(aim_session_t *sess, aim_conn_t *conn) | 166 faim_export int aim_get_command(aim_session_t *sess, aim_conn_t *conn) |
162 { | 167 { |
163 aim_frame_t *newrx; | 168 aim_frame_t *fr; |
164 fu16_t payloadlen; | 169 int payloadlen; |
165 | 170 |
166 if (!sess || !conn) | 171 if (!sess || !conn) |
167 return -EINVAL; | 172 return -EINVAL; |
168 | 173 |
169 if (conn->fd == -1) | 174 if (conn->fd == -1) |
173 return -1; | 178 return -1; |
174 | 179 |
175 if (conn->status & AIM_CONN_STATUS_INPROGRESS) | 180 if (conn->status & AIM_CONN_STATUS_INPROGRESS) |
176 return aim_conn_completeconnect(sess, conn); | 181 return aim_conn_completeconnect(sess, conn); |
177 | 182 |
178 if (!(newrx = (aim_frame_t *)calloc(sizeof(aim_frame_t), 1))) | 183 if (!(fr = (aim_frame_t *)calloc(sizeof(aim_frame_t), 1))) |
179 return -ENOMEM; | 184 return -ENOMEM; |
180 | 185 |
181 /* | 186 /* |
182 * Rendezvous (client to client) connections do not speak FLAP, so this | 187 * Rendezvous (client to client) connections do not speak FLAP, so this |
183 * function will break on them. | 188 * function will break on them. |
184 */ | 189 */ |
185 if (conn->type == AIM_CONN_TYPE_RENDEZVOUS) { | 190 if (conn->type == AIM_CONN_TYPE_RENDEZVOUS) |
186 int ret = aim_get_command_rendezvous(sess, conn, newrx); | 191 payloadlen = aim_get_command_rendezvous(sess, conn, fr); |
187 | 192 else if (conn->type == AIM_CONN_TYPE_LISTENER) { |
188 if (ret < 0) { | 193 faimdprintf(sess, 0, "AIM_CONN_TYPE_LISTENER on fd %d\n", conn->fd); |
189 free(newrx); | 194 free(fr); |
195 return -1; | |
196 } else | |
197 payloadlen = aim_get_command_flap(sess, conn, fr); | |
198 | |
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); | |
190 return -1; | 209 return -1; |
191 } | 210 } |
192 | 211 |
193 payloadlen = ret; | 212 aim_bstream_init(&fr->data, payload, payloadlen); |
194 } else if (conn->type == AIM_CONN_TYPE_LISTENER) { | |
195 faimdprintf(sess, 0, "AIM_CONN_TYPE_LISTENER on fd %d\n", conn->fd); | |
196 free(newrx); | |
197 return -1; | |
198 } else | |
199 payloadlen = aim_get_command_flap(sess, conn, newrx); | |
200 | |
201 newrx->nofree = 0; /* free by default */ | |
202 | |
203 if (payloadlen) { | |
204 fu8_t *payload = NULL; | |
205 | |
206 if (!(payload = (fu8_t *) malloc(payloadlen))) { | |
207 aim_frame_destroy(newrx); | |
208 return -1; | |
209 } | |
210 | |
211 aim_bstream_init(&newrx->data, payload, payloadlen); | |
212 | 213 |
213 /* read the payload */ | 214 /* read the payload */ |
214 if (aim_bstream_recv(&newrx->data, conn->fd, payloadlen) < payloadlen) { | 215 if (aim_bstream_recv(&fr->data, conn->fd, payloadlen) < payloadlen) { |
215 aim_frame_destroy(newrx); /* free's payload */ | 216 aim_frame_destroy(fr); /* free's payload */ |
216 aim_conn_close(conn); | 217 aim_conn_close(conn); |
217 return -1; | 218 return -1; |
218 } | 219 } |
219 } else | 220 } else |
220 aim_bstream_init(&newrx->data, NULL, 0); | 221 aim_bstream_init(&fr->data, NULL, 0); |
221 | 222 |
222 | 223 aim_bstream_rewind(&fr->data); |
223 aim_bstream_rewind(&newrx->data); | 224 |
224 | 225 fr->conn = conn; |
225 newrx->conn = conn; | 226 |
226 | 227 /* Enqueue this puppy */ |
227 newrx->next = NULL; /* this will always be at the bottom */ | 228 fr->next = NULL; /* this will always be at the bottom */ |
228 | 229 if (sess->queue_incoming == NULL) |
229 if (!sess->queue_incoming) | 230 sess->queue_incoming = fr; |
230 sess->queue_incoming = newrx; | |
231 else { | 231 else { |
232 aim_frame_t *cur; | 232 aim_frame_t *cur; |
233 | 233 for (cur = sess->queue_incoming; cur->next; cur = cur->next); |
234 for (cur = sess->queue_incoming; cur->next; cur = cur->next) | 234 cur->next = fr; |
235 ; | 235 } |
236 cur->next = newrx; | 236 |
237 } | 237 fr->conn->lastactivity = time(NULL); |
238 | |
239 newrx->conn->lastactivity = time(NULL); | |
240 | 238 |
241 return 0; | 239 return 0; |
242 } | 240 } |
243 | 241 |
244 /* | 242 /* |
245 * Purge recieve queue of all handled commands (->handled==1). Also | 243 * Purge recieve queue of all handled commands (->handled==1). |
246 * allows for selective freeing using ->nofree so that the client can | |
247 * keep the data for various purposes. | |
248 * | |
249 * If ->nofree is nonzero, the frame will be delinked from the global list, | |
250 * but will not be free'ed. The client _must_ keep a pointer to the | |
251 * data -- libfaim will not! If the client marks ->nofree but | |
252 * does not keep a pointer, it's lost forever. | |
253 * | 244 * |
254 */ | 245 */ |
255 faim_export void aim_purge_rxqueue(aim_session_t *sess) | 246 faim_export void aim_purge_rxqueue(aim_session_t *sess) |
256 { | 247 { |
257 aim_frame_t *cur, **prev; | 248 aim_frame_t *cur, **prev; |
258 | 249 |
259 for (prev = &sess->queue_incoming; (cur = *prev); ) { | 250 for (prev = &sess->queue_incoming; (cur = *prev); ) { |
260 if (cur->handled) { | 251 if (cur->handled) { |
261 | |
262 *prev = cur->next; | 252 *prev = cur->next; |
263 | 253 aim_frame_destroy(cur); |
264 if (!cur->nofree) | |
265 aim_frame_destroy(cur); | |
266 | |
267 } else | 254 } else |
268 prev = &cur->next; | 255 prev = &cur->next; |
269 } | 256 } |
270 | 257 |
271 return; | 258 return; |
284 | 271 |
285 for (currx = sess->queue_incoming; currx; currx = currx->next) { | 272 for (currx = sess->queue_incoming; currx; currx = currx->next) { |
286 if ((!currx->handled) && (currx->conn == conn)) | 273 if ((!currx->handled) && (currx->conn == conn)) |
287 currx->handled = 1; | 274 currx->handled = 1; |
288 } | 275 } |
276 | |
289 return; | 277 return; |
290 } | 278 } |