]> andersk Git - libfaim.git/blame - aim_conn.c
- Preserve subtype and priv after aim_conn_close
[libfaim.git] / aim_conn.c
CommitLineData
9de3ca7e 1
2/*
3 * aim_conn.c
4 *
5 * Does all this gloriously nifty connection handling stuff...
6 *
7 */
8
a25832e6 9#include <faim/aim.h>
9de3ca7e 10
040457cc 11/*
12 * Clears out connection list, killing remaining connections.
13 */
a25832e6 14void aim_connrst(struct aim_session_t *sess)
9de3ca7e 15{
040457cc 16 faim_mutex_init(&sess->connlistlock, NULL);
17 if (sess->connlist) {
18 struct aim_conn_t *cur = sess->connlist, *tmp;
19
20 while(cur) {
21 tmp = cur->next;
22 aim_conn_close(cur);
23 free(cur);
24 cur = tmp;
25 }
e88ba395 26 }
040457cc 27 sess->connlist = NULL;
28 return;
9de3ca7e 29}
30
040457cc 31/*
32 * Gets a new connection structure.
33 */
a25832e6 34struct aim_conn_t *aim_conn_getnext(struct aim_session_t *sess)
9de3ca7e 35{
040457cc 36 struct aim_conn_t *newconn, *cur;
37
38 if (!(newconn = malloc(sizeof(struct aim_conn_t))))
39 return NULL;
40
41 memset(newconn, 0, sizeof(struct aim_conn_t));
42 aim_conn_close(newconn);
43 newconn->next = NULL;
44
45 faim_mutex_lock(&sess->connlistlock);
46 if (sess->connlist == NULL)
47 sess->connlist = newconn;
48 else {
49 for (cur = sess->connlist; cur->next; cur = cur->next)
50 ;
51 cur->next = newconn;
52 }
53 faim_mutex_unlock(&sess->connlistlock);
54
55 return newconn;
56}
57
4d7c1bfb 58static void aim_conn_init(struct aim_conn_t *deadconn)
59{
60 if (!deadconn)
61 return;
62
63 deadconn->fd = -1;
3369f8d4 64 deadconn->subtype = -1;
4d7c1bfb 65 deadconn->type = -1;
66 deadconn->seqnum = 0;
67 deadconn->lastactivity = 0;
68 deadconn->forcedlatency = 0;
69 deadconn->handlerlist = NULL;
70 deadconn->priv = NULL;
71 faim_mutex_init(&deadconn->active, NULL);
72 faim_mutex_init(&deadconn->seqnum_lock, NULL);
73
74 return;
75}
76
040457cc 77void aim_conn_kill(struct aim_session_t *sess, struct aim_conn_t **deadconn)
78{
79 struct aim_conn_t *cur;
80
81 if (!deadconn || !*deadconn)
82 return;
83
84 faim_mutex_lock(&sess->connlistlock);
85 if (sess->connlist == NULL)
86 ;
87 else if (sess->connlist->next == NULL) {
88 if (sess->connlist == *deadconn)
89 sess->connlist = NULL;
90 } else {
91 cur = sess->connlist;
92 while (cur->next) {
93 if (cur->next == *deadconn) {
94 cur->next = cur->next->next;
95 break;
96 }
97 cur = cur->next;
98 }
99 }
100 faim_mutex_unlock(&sess->connlistlock);
101
68ac63c2 102 /* XXX: do we need this for txqueue too? */
103 aim_rxqueue_cleanbyconn(sess, *deadconn);
104
4d7c1bfb 105 aim_conn_init(*deadconn);
040457cc 106 free(*deadconn);
107 deadconn = NULL;
108
109 return;
9de3ca7e 110}
111
112void aim_conn_close(struct aim_conn_t *deadconn)
113{
3369f8d4 114 int typesav = -1, subtypesav = -1;
115 void *privsav = NULL;
4d7c1bfb 116
117 faim_mutex_destroy(&deadconn->active);
118 faim_mutex_destroy(&deadconn->seqnum_lock);
9de3ca7e 119 if (deadconn->fd >= 3)
120 close(deadconn->fd);
0252e8c0 121 if (deadconn->handlerlist)
122 aim_clearhandlers(deadconn);
3369f8d4 123
124 typesav = deadconn->type;
125 subtypesav = deadconn->subtype;
126
127 if (deadconn->priv && (deadconn->type != AIM_CONN_TYPE_RENDEZVOUS)) {
0c20631f 128 free(deadconn->priv);
3369f8d4 129 deadconn->priv = NULL;
130 }
131 privsav = deadconn->priv;
132
4d7c1bfb 133 aim_conn_init(deadconn);
134
135 deadconn->type = typesav;
3369f8d4 136 deadconn->subtype = subtypesav;
137 deadconn->priv = privsav;
4d7c1bfb 138
139 return;
9de3ca7e 140}
141
a25832e6 142struct aim_conn_t *aim_getconn_type(struct aim_session_t *sess,
143 int type)
9de3ca7e 144{
040457cc 145 struct aim_conn_t *cur;
146
147 faim_mutex_lock(&sess->connlistlock);
148 for (cur = sess->connlist; cur; cur = cur->next) {
149 if (cur->type == type)
150 break;
151 }
152 faim_mutex_unlock(&sess->connlistlock);
153 return cur;
9de3ca7e 154}
155
156/*
157 * aim_newconn(type, dest)
158 *
159 * Opens a new connection to the specified dest host of type type.
160 *
161 * TODO: fix for proxies
162 * FIXME: Return errors in a more sane way.
163 *
164 */
a25832e6 165struct aim_conn_t *aim_newconn(struct aim_session_t *sess,
166 int type, char *dest)
9de3ca7e 167{
168 struct aim_conn_t *connstruct;
169 int ret;
170 struct sockaddr_in sa;
171 struct hostent *hp;
172 u_short port = FAIM_LOGIN_PORT;
a25832e6 173 char *host = NULL;
9de3ca7e 174 int i=0;
040457cc 175
e6b05d80 176 if ((connstruct=aim_conn_getnext(sess))==NULL)
9de3ca7e 177 return NULL;
178
040457cc 179 faim_mutex_lock(&connstruct->active);
180
9de3ca7e 181 connstruct->type = type;
182
e6b05d80 183 if (!dest) { /* just allocate a struct */
184 connstruct->fd = -1;
185 connstruct->status = 0;
040457cc 186 faim_mutex_unlock(&connstruct->active);
e6b05d80 187 return connstruct;
188 }
189
9de3ca7e 190 /*
191 * As of 23 Jul 1999, AOL now sends the port number, preceded by a
192 * colon, in the BOS redirect. This fatally breaks all previous
193 * libfaims. Bad, bad AOL.
194 *
195 * We put this here to catch every case.
196 *
197 */
198
e88ba395 199 for(i=0;i<strlen(dest);i++) {
200 if (dest[i] == ':') {
201 port = atoi(&(dest[i+1]));
202 break;
9de3ca7e 203 }
e88ba395 204 }
a25832e6 205 host = (char *)malloc(i+1);
206 strncpy(host, dest, i);
9ba272ca 207 host[i] = '\0';
208
040457cc 209 hp = gethostbyname(host);
a25832e6 210 free(host);
9de3ca7e 211
e88ba395 212 if (hp == NULL) {
213 connstruct->status = (h_errno | AIM_CONN_STATUS_RESOLVERR);
040457cc 214 faim_mutex_unlock(&connstruct->active);
e88ba395 215 return connstruct;
216 }
9de3ca7e 217
218 memset(&sa.sin_zero, 0, 8);
219 sa.sin_port = htons(port);
220 memcpy(&sa.sin_addr, hp->h_addr, hp->h_length);
221 sa.sin_family = hp->h_addrtype;
222
223 connstruct->fd = socket(hp->h_addrtype, SOCK_STREAM, 0);
224 ret = connect(connstruct->fd, (struct sockaddr *)&sa, sizeof(struct sockaddr_in));
e88ba395 225 if(ret < 0) {
226 connstruct->fd = -1;
227 connstruct->status = (errno | AIM_CONN_STATUS_CONNERR);
040457cc 228 faim_mutex_unlock(&connstruct->active);
e88ba395 229 return connstruct;
230 }
a25832e6 231
040457cc 232 faim_mutex_unlock(&connstruct->active);
233
9de3ca7e 234 return connstruct;
235}
236
a25832e6 237int aim_conngetmaxfd(struct aim_session_t *sess)
9de3ca7e 238{
040457cc 239 int j = 0;
240 struct aim_conn_t *cur;
241
242 faim_mutex_lock(&sess->connlistlock);
243 for (cur = sess->connlist; cur; cur = cur->next) {
244 if (cur->fd > j)
245 j = cur->fd;
246 }
247 faim_mutex_unlock(&sess->connlistlock);
e88ba395 248
9de3ca7e 249 return j;
250}
251
a25832e6 252int aim_countconn(struct aim_session_t *sess)
9de3ca7e 253{
040457cc 254 int cnt = 0;
255 struct aim_conn_t *cur;
256
257 faim_mutex_lock(&sess->connlistlock);
258 for (cur = sess->connlist; cur; cur = cur->next)
259 cnt++;
260 faim_mutex_unlock(&sess->connlistlock);
e88ba395 261
9de3ca7e 262 return cnt;
263}
264
265/*
266 * aim_select(timeout)
267 *
268 * Waits for a socket with data or for timeout, whichever comes first.
269 * See select(2).
270 *
b8d0da45 271 * Return codes in *status:
272 * -1 error in select() (NULL returned)
273 * 0 no events pending (NULL returned)
274 * 1 outgoing data pending (NULL returned)
275 * 2 incoming data pending (connection with pending data returned)
276 *
040457cc 277 * XXX: we could probably stand to do a little courser locking here.
278 *
9de3ca7e 279 */
a25832e6 280struct aim_conn_t *aim_select(struct aim_session_t *sess,
b8d0da45 281 struct timeval *timeout, int *status)
9de3ca7e 282{
040457cc 283 struct aim_conn_t *cur;
9de3ca7e 284 fd_set fds;
040457cc 285 int maxfd = 0;
9de3ca7e 286 int i;
287
040457cc 288 faim_mutex_lock(&sess->connlistlock);
289 if (sess->connlist == NULL) {
290 faim_mutex_unlock(&sess->connlistlock);
68ac63c2 291 *status = -1;
292 return NULL;
040457cc 293 }
294 faim_mutex_unlock(&sess->connlistlock);
f1a5efe0 295
9de3ca7e 296 /*
297 * If we have data waiting to be sent, return immediatly
298 */
b8d0da45 299 if (sess->queue_outgoing != NULL) {
300 *status = 1;
301 return NULL;
302 }
9de3ca7e 303
304 FD_ZERO(&fds);
040457cc 305 maxfd = 0;
306
307 faim_mutex_lock(&sess->connlistlock);
308 for (cur = sess->connlist; cur; cur = cur->next) {
309 FD_SET(cur->fd, &fds);
310 if (cur->fd > maxfd)
311 maxfd = cur->fd;
312 }
313 faim_mutex_unlock(&sess->connlistlock);
314
315 if ((i = select(maxfd+1, &fds, NULL, NULL, timeout))>=1) {
316 faim_mutex_lock(&sess->connlistlock);
317 for (cur = sess->connlist; cur; cur = cur->next) {
318 if (FD_ISSET(cur->fd, &fds)) {
319 *status = 2;
320 faim_mutex_unlock(&sess->connlistlock);
321 return cur;
322 }
323 }
b8d0da45 324 }
325
040457cc 326 faim_mutex_unlock(&sess->connlistlock);
b8d0da45 327 *status = i; /* may be 0 or -1 */
328 return NULL; /* no waiting or error, return */
9de3ca7e 329}
330
331int aim_conn_isready(struct aim_conn_t *conn)
332{
333 if (conn)
334 return (conn->status & 0x0001);
040457cc 335 return -1;
9de3ca7e 336}
337
338int aim_conn_setstatus(struct aim_conn_t *conn, int status)
339{
040457cc 340 int val;
341
342 if (!conn)
9de3ca7e 343 return -1;
040457cc 344
345 faim_mutex_lock(&conn->active);
346 val = conn->status ^= status;
347 faim_mutex_unlock(&conn->active);
348 return val;
9de3ca7e 349}
350
351int aim_conn_setlatency(struct aim_conn_t *conn, int newval)
352{
353 if (!conn)
354 return -1;
040457cc 355
356 faim_mutex_lock(&conn->active);
9de3ca7e 357 conn->forcedlatency = newval;
358 conn->lastactivity = 0; /* reset this just to make sure */
040457cc 359 faim_mutex_unlock(&conn->active);
9de3ca7e 360
361 return 0;
362}
a25832e6 363
364void aim_session_init(struct aim_session_t *sess)
365{
a25832e6 366 if (!sess)
367 return;
368
040457cc 369 memset(sess, 0, sizeof(struct aim_session_t));
e88ba395 370 aim_connrst(sess);
a25832e6 371 sess->queue_outgoing = NULL;
372 sess->queue_incoming = NULL;
0c20631f 373 sess->pendingjoin = NULL;
a25832e6 374 sess->outstanding_snacs = NULL;
375 sess->snac_nextid = 0x00000001;
376
e88ba395 377 /*
378 * This must always be set. Default to the queue-based
379 * version for back-compatibility.
380 */
381 sess->tx_enqueue = &aim_tx_enqueue__queuebased;
382
a25832e6 383 return;
384}
This page took 0.109308 seconds and 5 git commands to generate.