]> andersk Git - libfaim.git/blame - aim_rxqueue.c
Lots of minor cleanups. Adds new (disabled) SNAC-based login.
[libfaim.git] / aim_rxqueue.c
CommitLineData
9de3ca7e 1/*
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.
7
8 */
9
a25832e6 10#include <faim/aim.h>
9de3ca7e 11
12/*
adca9dcf 13 * This is a modified read() to make SURE we get the number
14 * of bytes we are told to, otherwise block.
15 *
16 * Modified to count errno (Sébastien Carpe <scarpe@atos-group.com>)
17 *
18*/
9de3ca7e 19int Read(int fd, u_char *buf, int len)
20{
21 int i = 0;
22 int j = 0;
adca9dcf 23 int err_count=0;
24
9de3ca7e 25 while ((i < len) && (!(i < 0)))
26 {
27 j = read(fd, &(buf[i]), len-i);
28 if ( (j < 0) && (errno != EAGAIN))
adca9dcf 29 return -errno; /* fail */
30 else if (j==0)
31 {
32 err_count++;
33 if (err_count> MAX_READ_ERROR) {
34 /*
35 * Reached maximum number of allowed read errors.
36 *
37 * Lets suppose the connection is lost and errno didn't
38 * know it.
39 *
40 */
41 return (-1);
42 }
43 }
9de3ca7e 44 else
adca9dcf 45 i += j; /* success, continue */
9de3ca7e 46 }
9de3ca7e 47 return i;
48}
49
a25832e6 50/*
51 * Grab as many command sequences as we can off the socket, and enqueue
52 * each command in the incoming event queue in a seperate struct.
53 */
54int aim_get_command(struct aim_session_t *sess)
9de3ca7e 55{
56 int i, readgood, j, isav, err;
57 int s;
58 fd_set fds;
59 struct timeval tv;
60 char generic[6];
61 struct command_rx_struct *workingStruct = NULL;
62 struct command_rx_struct *workingPtr = NULL;
63 struct aim_conn_t *conn = NULL;
64#if debug > 0
65 printf("Reading generic/unknown response...");
66#endif
67
68
69 /* dont wait at all (ie, never call this unless something is there) */
70 tv.tv_sec = 0;
71 tv.tv_usec = 0;
a25832e6 72 conn = aim_select(sess, &tv);
9de3ca7e 73
74 if (conn==NULL)
75 return 0; /* nothing waiting */
76
77 s = conn->fd;
78
79 if (s < 3)
80 return 0;
81
82 FD_ZERO(&fds);
83 FD_SET(s, &fds);
84 tv.tv_sec = 0; /* wait, but only for 10us */
85 tv.tv_usec = 10;
86
87 generic[0] = 0x00;
88
89 readgood = 0;
90 i = 0;
91 j = 0;
92 /* read first 6 bytes (the FLAP header only) off the socket */
93 while ( (select(s+1, &fds, NULL, NULL, &tv) == 1) && (i < 6))
94 {
95 if ((err = Read(s, &(generic[i]), 1)) < 0)
96 {
97 /* error is probably not recoverable...(must be a pessimistic day) */
98 aim_conn_close(conn);
99 return err;
100 }
101
102 if (readgood == 0)
103 {
104 if (generic[i] == 0x2a)
105 {
106 readgood = 1;
107#if debug > 1
108 printf("%x ", generic[i]);
109 fflush(stdout);
110#endif
111 i++;
112 }
113 else
114 {
115#if debug > 1
116 printf("skipping 0x%d ", generic[i]);
117 fflush(stdout);
118#endif
119 j++;
120 }
121 }
122 else
123 {
124#if debug > 1
125 printf("%x ", generic[i]);
126#endif
127 i++;
128 }
129 FD_ZERO(&fds);
130 FD_SET(s, &fds);
131 tv.tv_sec= 2;
132 tv.tv_usec= 2;
133 }
134
135 if (generic[0] != 0x2a)
136 {
137 /* this really shouldn't happen, since the main loop
138 select() should protect us from entering this function
139 without data waiting */
140 printf("Bad incoming data!");
141 return -1;
142 }
143
144 isav = i;
145
146 /* allocate a new struct */
147 workingStruct = (struct command_rx_struct *) malloc(sizeof(struct command_rx_struct));
148 workingStruct->lock = 1; /* lock the struct */
149
a25832e6 150 /* store channel -- byte 2 */
9de3ca7e 151 workingStruct->type = (char) generic[1];
152
153 /* store seqnum -- bytes 3 and 4 */
a25832e6 154 workingStruct->seqnum = aimutil_get16(generic+2);
9de3ca7e 155
156 /* store commandlen -- bytes 5 and 6 */
a25832e6 157 workingStruct->commandlen = aimutil_get16(generic+4);
9de3ca7e 158
159 /* malloc for data portion */
a25832e6 160 workingStruct->data = (u_char *) malloc(workingStruct->commandlen);
9de3ca7e 161
162 /* read the data portion of the packet */
163 i = Read(s, workingStruct->data, workingStruct->commandlen);
164 if (i < 0)
165 {
166 aim_conn_close(conn);
167 return i;
168 }
169
170#if debug > 0
171 printf(" done. (%db+%db read, %db skipped)\n", isav, i, j);
172#endif
173
174 workingStruct->conn = conn;
175
176 workingStruct->next = NULL; /* this will always be at the bottom */
177 workingStruct->lock = 0; /* unlock */
178
179 /* enqueue this packet */
a25832e6 180 if (sess->queue_incoming == NULL)
9de3ca7e 181 {
a25832e6 182 sess->queue_incoming = workingStruct;
9de3ca7e 183 }
184 else
185 {
a25832e6 186 workingPtr = sess->queue_incoming;
9de3ca7e 187 while (workingPtr->next != NULL)
188 workingPtr = workingPtr->next;
189 workingPtr->next = workingStruct;
190 }
191
192
193 workingStruct->conn->lastactivity = time(NULL);
194
195 return 0;
196}
197
198/*
a25832e6 199 * purge_rxqueue()
200 *
201 * This is just what it sounds. It purges the receive (rx) queue of
202 * all handled commands. This is normally called from inside
203 * aim_rxdispatch() after it's processed all the commands in the queue.
204 *
9de3ca7e 205 */
206struct command_rx_struct *aim_purge_rxqueue(struct command_rx_struct *queue)
207{
208 struct command_rx_struct *workingPtr = NULL;
209 struct command_rx_struct *workingPtr2 = NULL;
210
211 if (queue == (struct command_rx_struct *)NULL)
212 {
213 /* do nothing */
214 }
215 else if (queue->next == (struct command_rx_struct *)NULL)
216 {
217 if (queue->handled == 1) {
218 workingPtr = queue;
219 queue = NULL;
220 free(workingPtr->data);
221 free(workingPtr);
222 }
223 }
224 else
225 {
226 while (queue->handled == 1)
227 {
228 workingPtr = queue;
229 queue = queue->next;
230 free(workingPtr->data);
231 free(workingPtr);
232 }
233
234 workingPtr = queue;
235
236 while (workingPtr->next != (struct command_rx_struct *)NULL)
237 {
238 if (workingPtr->next->handled == 1)
239 {
240 workingPtr2 = workingPtr->next;
241 workingPtr->next = workingPtr->next->next;
242 free(workingPtr2->data);
243 free(workingPtr2);
244 }
245 else /* TODO: rework this so the additional if isn't needed */
246 {
247 if (workingPtr->next == (struct command_rx_struct *)NULL)
248 {
249 if (workingPtr->handled == 1)
250 {
251 workingPtr2 = workingPtr;
252 workingPtr = NULL;
253 free(workingPtr2->data);
254 free(workingPtr2);
255 return queue;
256 }
257 }
258 else
259 {
260 workingPtr = workingPtr->next;
261 }
262 }
263 }
264 }
265 return queue;
266}
This page took 0.085738 seconds and 5 git commands to generate.