]> andersk Git - libfaim.git/blame - aim_rxqueue.c
- Sat Jun 24 02:14:07 UTC 2000
[libfaim.git] / aim_rxqueue.c
CommitLineData
9de3ca7e 1/*
f1a5efe0 2 * aim_rxqueue.c
3 *
4 * This file contains the management routines for the receive
5 * (incoming packet) queue. The actual packet handlers are in
6 * aim_rxhandlers.c.
9de3ca7e 7 */
8
a25832e6 9#include <faim/aim.h>
9de3ca7e 10
11/*
f1a5efe0 12 * Grab a single command sequence off the socket, and enqueue
13 * it in the incoming event queue in a seperate struct.
a25832e6 14 */
f1a5efe0 15int aim_get_command(struct aim_session_t *sess, struct aim_conn_t *conn)
9de3ca7e 16{
b69540e3 17 unsigned char generic[6];
f1a5efe0 18 struct command_rx_struct *newrx = NULL;
9de3ca7e 19
f1a5efe0 20 if (!sess || !conn)
21 return 0;
9de3ca7e 22
f1a5efe0 23 if (conn->fd < 3) /* can happen when people abuse the interface */
9de3ca7e 24 return 0;
25
040457cc 26 /*
27 * Rendezvous (client-client) connections do not speak
28 * FLAP, so this function will break on them.
29 */
b69540e3 30 if (conn->type == AIM_CONN_TYPE_RENDEZVOUS)
31 return aim_get_command_rendezvous(sess, conn);
040457cc 32
f1a5efe0 33 /*
34 * Read FLAP header. Six bytes:
35 *
36 * 0 char -- Always 0x2a
37 * 1 char -- Channel ID. Usually 2 -- 1 and 4 are used during login.
38 * 2 short -- Sequence number
39 * 4 short -- Number of data bytes that follow.
40 */
e88ba395 41 faim_mutex_lock(&conn->active);
f1a5efe0 42 if (read(conn->fd, generic, 6) < 6){
68ac63c2 43 aim_conn_kill(sess, &conn);
e88ba395 44 faim_mutex_unlock(&conn->active);
f1a5efe0 45 return -1;
46 }
9de3ca7e 47
b8d0da45 48 /*
49 * This shouldn't happen unless the socket breaks, the server breaks,
50 * or we break. We must handle it just in case.
51 */
52 if (generic[0] != 0x2a) {
f1a5efe0 53 faimdprintf(1, "Bad incoming data!");
b69540e3 54 faim_mutex_unlock(&conn->active);
b8d0da45 55 return -1;
56 }
9de3ca7e 57
9de3ca7e 58 /* allocate a new struct */
b69540e3 59 if (!(newrx = (struct command_rx_struct *)malloc(sizeof(struct command_rx_struct)))) {
60 faim_mutex_unlock(&conn->active);
f1a5efe0 61 return -1;
b69540e3 62 }
f1a5efe0 63 memset(newrx, 0x00, sizeof(struct command_rx_struct));
b8d0da45 64
f1a5efe0 65 newrx->lock = 1; /* lock the struct */
9de3ca7e 66
b69540e3 67 /* we're doing OSCAR if we're here */
68 newrx->hdrtype = AIM_FRAMETYPE_OSCAR;
69
a25832e6 70 /* store channel -- byte 2 */
b69540e3 71 newrx->hdr.oscar.type = (char) generic[1];
9de3ca7e 72
73 /* store seqnum -- bytes 3 and 4 */
b69540e3 74 newrx->hdr.oscar.seqnum = aimutil_get16(generic+2);
9de3ca7e 75
76 /* store commandlen -- bytes 5 and 6 */
f1a5efe0 77 newrx->commandlen = aimutil_get16(generic+4);
9de3ca7e 78
f1a5efe0 79 newrx->nofree = 0; /* free by default */
b8d0da45 80
9de3ca7e 81 /* malloc for data portion */
b69540e3 82 if (!(newrx->data = (u_char *) malloc(newrx->commandlen))) {
f1a5efe0 83 free(newrx);
b69540e3 84 faim_mutex_unlock(&conn->active);
f1a5efe0 85 return -1;
86 }
9de3ca7e 87
88 /* read the data portion of the packet */
f1a5efe0 89 if (read(conn->fd, newrx->data, newrx->commandlen) < newrx->commandlen){
90 free(newrx->data);
91 free(newrx);
68ac63c2 92 aim_conn_kill(sess, &conn);
e88ba395 93 faim_mutex_unlock(&conn->active);
b8d0da45 94 return -1;
95 }
e88ba395 96 faim_mutex_unlock(&conn->active);
9de3ca7e 97
f1a5efe0 98 newrx->conn = conn;
9de3ca7e 99
f1a5efe0 100 newrx->next = NULL; /* this will always be at the bottom */
101 newrx->lock = 0; /* unlock */
9de3ca7e 102
103 /* enqueue this packet */
b8d0da45 104 if (sess->queue_incoming == NULL) {
f1a5efe0 105 sess->queue_incoming = newrx;
b8d0da45 106 } else {
107 struct command_rx_struct *cur;
108
109 /*
110 * This append operation takes a while. It might be faster
111 * if we maintain a pointer to the last entry in the queue
112 * and just update that. Need to determine if the overhead
113 * to maintain that is lower than the overhead for this loop.
114 */
115 for (cur = sess->queue_incoming; cur->next; cur = cur->next)
116 ;
f1a5efe0 117 cur->next = newrx;
b8d0da45 118 }
9de3ca7e 119
f1a5efe0 120 newrx->conn->lastactivity = time(NULL);
9de3ca7e 121
122 return 0;
123}
124
b69540e3 125int aim_get_command_rendezvous(struct aim_session_t *sess, struct aim_conn_t *conn)
126{
127 unsigned char hdrbuf1[6];
128 unsigned char *hdr = NULL;
129 int hdrlen, hdrtype;
130 int payloadlength = 0;
131 int flags = 0;
132 char *snptr = NULL;
133
134 if (read(conn->fd, hdrbuf1, 6) < 6) {
135 perror("read");
136 printf("faim: rend: read error\n");
137 aim_conn_kill(sess, &conn);
138 return -1;
139 }
140
141 hdrlen = aimutil_get16(hdrbuf1+4);
142
143 hdrlen -= 6;
144 hdr = malloc(hdrlen);
145
146 faim_mutex_lock(&conn->active);
147 if (read(conn->fd, hdr, hdrlen) < hdrlen) {
148 perror("read");
149 printf("faim: rend: read2 error\n");
150 free(hdr);
151 faim_mutex_unlock(&conn->active);
152 aim_conn_kill(sess, &conn);
153 return -1;
154 }
155
156 hdrtype = aimutil_get16(hdr);
157
158 switch (hdrtype) {
159 case 0x0001: {
160 payloadlength = aimutil_get32(hdr+22);
161 flags = aimutil_get16(hdr+32);
162 snptr = hdr+38;
163
164 printf("OFT frame: %04x / %04x / %04x / %s\n", hdrtype, payloadlength, flags, snptr);
165
166 if (flags == 0x000e) {
167 printf("directim: %s has started typing\n", snptr);
168 } else if ((flags == 0x0000) && payloadlength) {
169 unsigned char *buf;
170 buf = malloc(payloadlength+1);
171
172 /* XXX theres got to be a better way */
173 faim_mutex_lock(&conn->active);
174 if (recv(conn->fd, buf, payloadlength, MSG_WAITALL) < payloadlength) {
175 perror("read");
176 printf("faim: rend: read3 error\n");
177 free(buf);
178 faim_mutex_unlock(&conn->active);
179 aim_conn_kill(sess, &conn);
180 return -1;
181 }
182 faim_mutex_unlock(&conn->active);
183 buf[payloadlength] = '\0';
184 printf("directim: %s/%04x/%04x/%s\n", snptr, payloadlength, flags, buf);
185 aim_send_im_direct(sess, conn, buf);
186 free(buf);
187 }
188 break;
189 }
190 default:
191 printf("OFT frame: type %04x\n", hdrtype);
192 /* data connection may be unreliable here */
193 break;
194 } /* switch */
195
196 free(hdr);
197
198 return 0;
199}
200
9de3ca7e 201/*
b8d0da45 202 * Purge recieve queue of all handled commands (->handled==1). Also
203 * allows for selective freeing using ->nofree so that the client can
204 * keep the data for various purposes.
a25832e6 205 *
b8d0da45 206 * If ->nofree is nonzero, the frame will be delinked from the global list,
207 * but will not be free'ed. The client _must_ keep a pointer to the
208 * data -- libfaim will not! If the client marks ->nofree but
209 * does not keep a pointer, it's lost forever.
a25832e6 210 *
9de3ca7e 211 */
b8d0da45 212void aim_purge_rxqueue(struct aim_session_t *sess)
9de3ca7e 213{
b8d0da45 214 struct command_rx_struct *cur = NULL;
215 struct command_rx_struct *tmp;
9de3ca7e 216
b8d0da45 217 if (sess->queue_incoming == NULL)
218 return;
219
220 if (sess->queue_incoming->next == NULL) {
221 if (sess->queue_incoming->handled) {
222 tmp = sess->queue_incoming;
223 sess->queue_incoming = NULL;
224
225 if (!tmp->nofree) {
b69540e3 226 if (tmp->hdrtype == AIM_FRAMETYPE_OFT)
227 free(tmp->hdr.oft.hdr2);
b8d0da45 228 free(tmp->data);
229 free(tmp);
230 } else
231 tmp->next = NULL;
9de3ca7e 232 }
b8d0da45 233 return;
234 }
235
236 for(cur = sess->queue_incoming; cur->next != NULL; ) {
237 if (cur->next->handled) {
238 tmp = cur->next;
239 cur->next = tmp->next;
240 if (!tmp->nofree) {
b69540e3 241 if (tmp->hdrtype == AIM_FRAMETYPE_OFT)
242 free(tmp->hdr.oft.hdr2);
b8d0da45 243 free(tmp->data);
244 free(tmp);
245 } else
246 tmp->next = NULL;
247 }
248 cur = cur->next;
249
250 /*
251 * Be careful here. Because of the way we just
252 * manipulated the pointer, cur may be NULL and
253 * the for() will segfault doing the check unless
254 * we find this case first.
255 */
256 if (cur == NULL)
257 break;
258 }
259
260 return;
9de3ca7e 261}
68ac63c2 262
263/*
264 * Since aim_get_command will aim_conn_kill dead connections, we need
265 * to clean up the rxqueue of unprocessed connections on that socket.
266 *
267 * XXX: this is something that was handled better in the old connection
268 * handling method, but eh.
269 */
270void aim_rxqueue_cleanbyconn(struct aim_session_t *sess, struct aim_conn_t *conn)
271{
272 struct command_rx_struct *currx;
273
274 for (currx = sess->queue_incoming; currx; currx = currx->next) {
275 if ((!currx->handled) && (currx->conn == conn))
276 currx->handled = 1;
277 }
278 return;
279}
This page took 0.102143 seconds and 5 git commands to generate.