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