]> andersk Git - libfaim.git/blame - aim_conn.c
Small fixes.
[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{
b13c9e13 16 faim_mutex_init(&sess->connlistlock);
040457cc 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;
b13c9e13 71 faim_mutex_init(&deadconn->active);
72 faim_mutex_init(&deadconn->seqnum_lock);
4d7c1bfb 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
f8ac5020 105 aim_conn_close(*deadconn);
106 if ((*deadconn)->priv)
107 free((*deadconn)->priv);
040457cc 108 free(*deadconn);
109 deadconn = NULL;
110
111 return;
9de3ca7e 112}
113
114void aim_conn_close(struct aim_conn_t *deadconn)
115{
3369f8d4 116 int typesav = -1, subtypesav = -1;
117 void *privsav = NULL;
4d7c1bfb 118
119 faim_mutex_destroy(&deadconn->active);
120 faim_mutex_destroy(&deadconn->seqnum_lock);
9de3ca7e 121 if (deadconn->fd >= 3)
122 close(deadconn->fd);
0252e8c0 123 if (deadconn->handlerlist)
124 aim_clearhandlers(deadconn);
3369f8d4 125
126 typesav = deadconn->type;
127 subtypesav = deadconn->subtype;
128
129 if (deadconn->priv && (deadconn->type != AIM_CONN_TYPE_RENDEZVOUS)) {
0c20631f 130 free(deadconn->priv);
3369f8d4 131 deadconn->priv = NULL;
132 }
133 privsav = deadconn->priv;
134
4d7c1bfb 135 aim_conn_init(deadconn);
136
137 deadconn->type = typesav;
3369f8d4 138 deadconn->subtype = subtypesav;
139 deadconn->priv = privsav;
4d7c1bfb 140
141 return;
9de3ca7e 142}
143
a25832e6 144struct aim_conn_t *aim_getconn_type(struct aim_session_t *sess,
145 int type)
9de3ca7e 146{
040457cc 147 struct aim_conn_t *cur;
148
149 faim_mutex_lock(&sess->connlistlock);
150 for (cur = sess->connlist; cur; cur = cur->next) {
151 if (cur->type == type)
152 break;
153 }
154 faim_mutex_unlock(&sess->connlistlock);
155 return cur;
9de3ca7e 156}
157
158/*
159 * aim_newconn(type, dest)
160 *
161 * Opens a new connection to the specified dest host of type type.
162 *
163 * TODO: fix for proxies
164 * FIXME: Return errors in a more sane way.
165 *
166 */
a25832e6 167struct aim_conn_t *aim_newconn(struct aim_session_t *sess,
168 int type, char *dest)
9de3ca7e 169{
170 struct aim_conn_t *connstruct;
171 int ret;
172 struct sockaddr_in sa;
173 struct hostent *hp;
174 u_short port = FAIM_LOGIN_PORT;
a25832e6 175 char *host = NULL;
9de3ca7e 176 int i=0;
040457cc 177
e6b05d80 178 if ((connstruct=aim_conn_getnext(sess))==NULL)
9de3ca7e 179 return NULL;
180
040457cc 181 faim_mutex_lock(&connstruct->active);
182
9de3ca7e 183 connstruct->type = type;
184
e6b05d80 185 if (!dest) { /* just allocate a struct */
186 connstruct->fd = -1;
187 connstruct->status = 0;
040457cc 188 faim_mutex_unlock(&connstruct->active);
e6b05d80 189 return connstruct;
190 }
191
9de3ca7e 192 /*
193 * As of 23 Jul 1999, AOL now sends the port number, preceded by a
194 * colon, in the BOS redirect. This fatally breaks all previous
195 * libfaims. Bad, bad AOL.
196 *
197 * We put this here to catch every case.
198 *
199 */
200
e88ba395 201 for(i=0;i<strlen(dest);i++) {
202 if (dest[i] == ':') {
203 port = atoi(&(dest[i+1]));
204 break;
9de3ca7e 205 }
e88ba395 206 }
a25832e6 207 host = (char *)malloc(i+1);
208 strncpy(host, dest, i);
9ba272ca 209 host[i] = '\0';
210
040457cc 211 hp = gethostbyname(host);
a25832e6 212 free(host);
9de3ca7e 213
e88ba395 214 if (hp == NULL) {
215 connstruct->status = (h_errno | AIM_CONN_STATUS_RESOLVERR);
040457cc 216 faim_mutex_unlock(&connstruct->active);
e88ba395 217 return connstruct;
218 }
9de3ca7e 219
220 memset(&sa.sin_zero, 0, 8);
221 sa.sin_port = htons(port);
222 memcpy(&sa.sin_addr, hp->h_addr, hp->h_length);
223 sa.sin_family = hp->h_addrtype;
224
225 connstruct->fd = socket(hp->h_addrtype, SOCK_STREAM, 0);
226 ret = connect(connstruct->fd, (struct sockaddr *)&sa, sizeof(struct sockaddr_in));
e88ba395 227 if(ret < 0) {
228 connstruct->fd = -1;
229 connstruct->status = (errno | AIM_CONN_STATUS_CONNERR);
040457cc 230 faim_mutex_unlock(&connstruct->active);
e88ba395 231 return connstruct;
232 }
a25832e6 233
040457cc 234 faim_mutex_unlock(&connstruct->active);
235
9de3ca7e 236 return connstruct;
237}
238
a25832e6 239int aim_conngetmaxfd(struct aim_session_t *sess)
9de3ca7e 240{
040457cc 241 int j = 0;
242 struct aim_conn_t *cur;
243
244 faim_mutex_lock(&sess->connlistlock);
245 for (cur = sess->connlist; cur; cur = cur->next) {
246 if (cur->fd > j)
247 j = cur->fd;
248 }
249 faim_mutex_unlock(&sess->connlistlock);
e88ba395 250
9de3ca7e 251 return j;
252}
253
a25832e6 254int aim_countconn(struct aim_session_t *sess)
9de3ca7e 255{
040457cc 256 int cnt = 0;
257 struct aim_conn_t *cur;
258
259 faim_mutex_lock(&sess->connlistlock);
260 for (cur = sess->connlist; cur; cur = cur->next)
261 cnt++;
262 faim_mutex_unlock(&sess->connlistlock);
e88ba395 263
9de3ca7e 264 return cnt;
265}
266
267/*
268 * aim_select(timeout)
269 *
270 * Waits for a socket with data or for timeout, whichever comes first.
271 * See select(2).
272 *
b8d0da45 273 * Return codes in *status:
274 * -1 error in select() (NULL returned)
275 * 0 no events pending (NULL returned)
276 * 1 outgoing data pending (NULL returned)
277 * 2 incoming data pending (connection with pending data returned)
278 *
040457cc 279 * XXX: we could probably stand to do a little courser locking here.
280 *
9de3ca7e 281 */
a25832e6 282struct aim_conn_t *aim_select(struct aim_session_t *sess,
b8d0da45 283 struct timeval *timeout, int *status)
9de3ca7e 284{
040457cc 285 struct aim_conn_t *cur;
9de3ca7e 286 fd_set fds;
040457cc 287 int maxfd = 0;
9de3ca7e 288 int i;
289
040457cc 290 faim_mutex_lock(&sess->connlistlock);
291 if (sess->connlist == NULL) {
292 faim_mutex_unlock(&sess->connlistlock);
68ac63c2 293 *status = -1;
294 return NULL;
040457cc 295 }
296 faim_mutex_unlock(&sess->connlistlock);
f1a5efe0 297
9de3ca7e 298 /*
299 * If we have data waiting to be sent, return immediatly
300 */
b8d0da45 301 if (sess->queue_outgoing != NULL) {
302 *status = 1;
303 return NULL;
304 }
9de3ca7e 305
306 FD_ZERO(&fds);
040457cc 307 maxfd = 0;
308
309 faim_mutex_lock(&sess->connlistlock);
310 for (cur = sess->connlist; cur; cur = cur->next) {
311 FD_SET(cur->fd, &fds);
312 if (cur->fd > maxfd)
313 maxfd = cur->fd;
314 }
315 faim_mutex_unlock(&sess->connlistlock);
316
317 if ((i = select(maxfd+1, &fds, NULL, NULL, timeout))>=1) {
318 faim_mutex_lock(&sess->connlistlock);
319 for (cur = sess->connlist; cur; cur = cur->next) {
320 if (FD_ISSET(cur->fd, &fds)) {
321 *status = 2;
322 faim_mutex_unlock(&sess->connlistlock);
323 return cur;
324 }
325 }
b8d0da45 326 }
327
040457cc 328 faim_mutex_unlock(&sess->connlistlock);
b8d0da45 329 *status = i; /* may be 0 or -1 */
330 return NULL; /* no waiting or error, return */
9de3ca7e 331}
332
333int aim_conn_isready(struct aim_conn_t *conn)
334{
335 if (conn)
336 return (conn->status & 0x0001);
040457cc 337 return -1;
9de3ca7e 338}
339
340int aim_conn_setstatus(struct aim_conn_t *conn, int status)
341{
040457cc 342 int val;
343
344 if (!conn)
9de3ca7e 345 return -1;
040457cc 346
347 faim_mutex_lock(&conn->active);
348 val = conn->status ^= status;
349 faim_mutex_unlock(&conn->active);
350 return val;
9de3ca7e 351}
352
353int aim_conn_setlatency(struct aim_conn_t *conn, int newval)
354{
355 if (!conn)
356 return -1;
040457cc 357
358 faim_mutex_lock(&conn->active);
9de3ca7e 359 conn->forcedlatency = newval;
360 conn->lastactivity = 0; /* reset this just to make sure */
040457cc 361 faim_mutex_unlock(&conn->active);
9de3ca7e 362
363 return 0;
364}
a25832e6 365
366void aim_session_init(struct aim_session_t *sess)
367{
a25832e6 368 if (!sess)
369 return;
370
040457cc 371 memset(sess, 0, sizeof(struct aim_session_t));
e88ba395 372 aim_connrst(sess);
a25832e6 373 sess->queue_outgoing = NULL;
374 sess->queue_incoming = NULL;
0c20631f 375 sess->pendingjoin = NULL;
b13c9e13 376 aim_initsnachash(sess);
a25832e6 377 sess->snac_nextid = 0x00000001;
378
e88ba395 379 /*
380 * This must always be set. Default to the queue-based
381 * version for back-compatibility.
382 */
383 sess->tx_enqueue = &aim_tx_enqueue__queuebased;
384
a25832e6 385 return;
386}
This page took 0.108389 seconds and 5 git commands to generate.