5 * Does all this gloriously nifty connection handling stuff...
12 * Clears out connection list, killing remaining connections.
14 void aim_connrst(struct aim_session_t *sess)
16 faim_mutex_init(&sess->connlistlock);
18 struct aim_conn_t *cur = sess->connlist, *tmp;
27 sess->connlist = NULL;
32 * Gets a new connection structure.
34 struct aim_conn_t *aim_conn_getnext(struct aim_session_t *sess)
36 struct aim_conn_t *newconn, *cur;
38 if (!(newconn = malloc(sizeof(struct aim_conn_t))))
41 memset(newconn, 0, sizeof(struct aim_conn_t));
42 aim_conn_close(newconn);
45 faim_mutex_lock(&sess->connlistlock);
46 if (sess->connlist == NULL)
47 sess->connlist = newconn;
49 for (cur = sess->connlist; cur->next; cur = cur->next)
53 faim_mutex_unlock(&sess->connlistlock);
58 static void aim_conn_init(struct aim_conn_t *deadconn)
64 deadconn->subtype = -1;
67 deadconn->lastactivity = 0;
68 deadconn->forcedlatency = 0;
69 deadconn->handlerlist = NULL;
70 deadconn->priv = NULL;
71 faim_mutex_init(&deadconn->active);
72 faim_mutex_init(&deadconn->seqnum_lock);
77 void aim_conn_kill(struct aim_session_t *sess, struct aim_conn_t **deadconn)
79 struct aim_conn_t *cur;
81 if (!deadconn || !*deadconn)
84 faim_mutex_lock(&sess->connlistlock);
85 if (sess->connlist == NULL)
87 else if (sess->connlist->next == NULL) {
88 if (sess->connlist == *deadconn)
89 sess->connlist = NULL;
93 if (cur->next == *deadconn) {
94 cur->next = cur->next->next;
100 faim_mutex_unlock(&sess->connlistlock);
102 /* XXX: do we need this for txqueue too? */
103 aim_rxqueue_cleanbyconn(sess, *deadconn);
105 aim_conn_close(*deadconn);
106 if ((*deadconn)->priv)
107 free((*deadconn)->priv);
114 void aim_conn_close(struct aim_conn_t *deadconn)
116 int typesav = -1, subtypesav = -1;
117 void *privsav = NULL;
119 faim_mutex_destroy(&deadconn->active);
120 faim_mutex_destroy(&deadconn->seqnum_lock);
121 if (deadconn->fd >= 3)
123 if (deadconn->handlerlist)
124 aim_clearhandlers(deadconn);
126 typesav = deadconn->type;
127 subtypesav = deadconn->subtype;
129 if (deadconn->priv && (deadconn->type != AIM_CONN_TYPE_RENDEZVOUS)) {
130 free(deadconn->priv);
131 deadconn->priv = NULL;
133 privsav = deadconn->priv;
135 aim_conn_init(deadconn);
137 deadconn->type = typesav;
138 deadconn->subtype = subtypesav;
139 deadconn->priv = privsav;
144 struct aim_conn_t *aim_getconn_type(struct aim_session_t *sess,
147 struct aim_conn_t *cur;
149 faim_mutex_lock(&sess->connlistlock);
150 for (cur = sess->connlist; cur; cur = cur->next) {
151 if (cur->type == type)
154 faim_mutex_unlock(&sess->connlistlock);
159 * aim_newconn(type, dest)
161 * Opens a new connection to the specified dest host of type type.
163 * TODO: fix for proxies
164 * FIXME: Return errors in a more sane way.
167 struct aim_conn_t *aim_newconn(struct aim_session_t *sess,
168 int type, char *dest)
170 struct aim_conn_t *connstruct;
172 struct sockaddr_in sa;
174 u_short port = FAIM_LOGIN_PORT;
178 if ((connstruct=aim_conn_getnext(sess))==NULL)
181 faim_mutex_lock(&connstruct->active);
183 connstruct->type = type;
185 if (!dest) { /* just allocate a struct */
187 connstruct->status = 0;
188 faim_mutex_unlock(&connstruct->active);
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.
197 * We put this here to catch every case.
201 for(i=0;i<strlen(dest);i++) {
202 if (dest[i] == ':') {
203 port = atoi(&(dest[i+1]));
207 host = (char *)malloc(i+1);
208 strncpy(host, dest, i);
211 hp = gethostbyname(host);
215 connstruct->status = (h_errno | AIM_CONN_STATUS_RESOLVERR);
216 faim_mutex_unlock(&connstruct->active);
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;
225 connstruct->fd = socket(hp->h_addrtype, SOCK_STREAM, 0);
226 ret = connect(connstruct->fd, (struct sockaddr *)&sa, sizeof(struct sockaddr_in));
229 connstruct->status = (errno | AIM_CONN_STATUS_CONNERR);
230 faim_mutex_unlock(&connstruct->active);
234 faim_mutex_unlock(&connstruct->active);
239 int aim_conngetmaxfd(struct aim_session_t *sess)
242 struct aim_conn_t *cur;
244 faim_mutex_lock(&sess->connlistlock);
245 for (cur = sess->connlist; cur; cur = cur->next) {
249 faim_mutex_unlock(&sess->connlistlock);
254 int aim_countconn(struct aim_session_t *sess)
257 struct aim_conn_t *cur;
259 faim_mutex_lock(&sess->connlistlock);
260 for (cur = sess->connlist; cur; cur = cur->next)
262 faim_mutex_unlock(&sess->connlistlock);
268 * aim_select(timeout)
270 * Waits for a socket with data or for timeout, whichever comes first.
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)
279 * XXX: we could probably stand to do a little courser locking here.
282 struct aim_conn_t *aim_select(struct aim_session_t *sess,
283 struct timeval *timeout, int *status)
285 struct aim_conn_t *cur;
290 faim_mutex_lock(&sess->connlistlock);
291 if (sess->connlist == NULL) {
292 faim_mutex_unlock(&sess->connlistlock);
296 faim_mutex_unlock(&sess->connlistlock);
299 * If we have data waiting to be sent, return immediatly
301 if (sess->queue_outgoing != NULL) {
309 faim_mutex_lock(&sess->connlistlock);
310 for (cur = sess->connlist; cur; cur = cur->next) {
311 FD_SET(cur->fd, &fds);
315 faim_mutex_unlock(&sess->connlistlock);
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)) {
322 faim_mutex_unlock(&sess->connlistlock);
328 faim_mutex_unlock(&sess->connlistlock);
329 *status = i; /* may be 0 or -1 */
330 return NULL; /* no waiting or error, return */
333 int aim_conn_isready(struct aim_conn_t *conn)
336 return (conn->status & 0x0001);
340 int aim_conn_setstatus(struct aim_conn_t *conn, int status)
347 faim_mutex_lock(&conn->active);
348 val = conn->status ^= status;
349 faim_mutex_unlock(&conn->active);
353 int aim_conn_setlatency(struct aim_conn_t *conn, int newval)
358 faim_mutex_lock(&conn->active);
359 conn->forcedlatency = newval;
360 conn->lastactivity = 0; /* reset this just to make sure */
361 faim_mutex_unlock(&conn->active);
366 void aim_session_init(struct aim_session_t *sess)
371 memset(sess, 0, sizeof(struct aim_session_t));
373 sess->queue_outgoing = NULL;
374 sess->queue_incoming = NULL;
375 sess->pendingjoin = NULL;
376 aim_initsnachash(sess);
377 sess->snac_nextid = 0x00000001;
380 * This must always be set. Default to the queue-based
381 * version for back-compatibility.
383 sess->tx_enqueue = &aim_tx_enqueue__queuebased;