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