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 }