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, NULL);
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 void aim_conn_kill(struct aim_session_t *sess, struct aim_conn_t **deadconn)
60 struct aim_conn_t *cur;
62 if (!deadconn || !*deadconn)
65 faim_mutex_lock(&sess->connlistlock);
66 if (sess->connlist == NULL)
68 else if (sess->connlist->next == NULL) {
69 if (sess->connlist == *deadconn)
70 sess->connlist = NULL;
74 if (cur->next == *deadconn) {
75 cur->next = cur->next->next;
81 faim_mutex_unlock(&sess->connlistlock);
83 aim_conn_close(*deadconn);
90 void aim_conn_close(struct aim_conn_t *deadconn)
92 if (deadconn->fd >= 3)
97 deadconn->lastactivity = 0;
98 deadconn->forcedlatency = 0;
99 if (deadconn->handlerlist)
100 aim_clearhandlers(deadconn);
101 deadconn->handlerlist = NULL;
103 free(deadconn->priv);
104 deadconn->priv = NULL;
105 faim_mutex_init(&deadconn->active, NULL);
106 faim_mutex_init(&deadconn->seqnum_lock, NULL);
109 struct aim_conn_t *aim_getconn_type(struct aim_session_t *sess,
112 struct aim_conn_t *cur;
114 faim_mutex_lock(&sess->connlistlock);
115 for (cur = sess->connlist; cur; cur = cur->next) {
116 if (cur->type == type)
119 faim_mutex_unlock(&sess->connlistlock);
124 * aim_newconn(type, dest)
126 * Opens a new connection to the specified dest host of type type.
128 * TODO: fix for proxies
129 * FIXME: Return errors in a more sane way.
132 struct aim_conn_t *aim_newconn(struct aim_session_t *sess,
133 int type, char *dest)
135 struct aim_conn_t *connstruct;
137 struct sockaddr_in sa;
139 u_short port = FAIM_LOGIN_PORT;
143 if ((connstruct=aim_conn_getnext(sess))==NULL)
146 faim_mutex_lock(&connstruct->active);
148 connstruct->type = type;
150 if (!dest) { /* just allocate a struct */
152 connstruct->status = 0;
153 faim_mutex_unlock(&connstruct->active);
158 * As of 23 Jul 1999, AOL now sends the port number, preceded by a
159 * colon, in the BOS redirect. This fatally breaks all previous
160 * libfaims. Bad, bad AOL.
162 * We put this here to catch every case.
166 for(i=0;i<strlen(dest);i++) {
167 if (dest[i] == ':') {
168 port = atoi(&(dest[i+1]));
172 host = (char *)malloc(i+1);
173 strncpy(host, dest, i);
176 hp = gethostbyname(host);
180 connstruct->status = (h_errno | AIM_CONN_STATUS_RESOLVERR);
181 faim_mutex_unlock(&connstruct->active);
185 memset(&sa.sin_zero, 0, 8);
186 sa.sin_port = htons(port);
187 memcpy(&sa.sin_addr, hp->h_addr, hp->h_length);
188 sa.sin_family = hp->h_addrtype;
190 connstruct->fd = socket(hp->h_addrtype, SOCK_STREAM, 0);
191 ret = connect(connstruct->fd, (struct sockaddr *)&sa, sizeof(struct sockaddr_in));
194 connstruct->status = (errno | AIM_CONN_STATUS_CONNERR);
195 faim_mutex_unlock(&connstruct->active);
199 faim_mutex_unlock(&connstruct->active);
204 int aim_conngetmaxfd(struct aim_session_t *sess)
207 struct aim_conn_t *cur;
209 faim_mutex_lock(&sess->connlistlock);
210 for (cur = sess->connlist; cur; cur = cur->next) {
214 faim_mutex_unlock(&sess->connlistlock);
219 int aim_countconn(struct aim_session_t *sess)
222 struct aim_conn_t *cur;
224 faim_mutex_lock(&sess->connlistlock);
225 for (cur = sess->connlist; cur; cur = cur->next)
227 faim_mutex_unlock(&sess->connlistlock);
233 * aim_select(timeout)
235 * Waits for a socket with data or for timeout, whichever comes first.
238 * Return codes in *status:
239 * -1 error in select() (NULL returned)
240 * 0 no events pending (NULL returned)
241 * 1 outgoing data pending (NULL returned)
242 * 2 incoming data pending (connection with pending data returned)
244 * XXX: we could probably stand to do a little courser locking here.
247 struct aim_conn_t *aim_select(struct aim_session_t *sess,
248 struct timeval *timeout, int *status)
250 struct aim_conn_t *cur;
255 faim_mutex_lock(&sess->connlistlock);
256 if (sess->connlist == NULL) {
257 faim_mutex_unlock(&sess->connlistlock);
260 faim_mutex_unlock(&sess->connlistlock);
263 * If we have data waiting to be sent, return immediatly
265 if (sess->queue_outgoing != NULL) {
273 faim_mutex_lock(&sess->connlistlock);
274 for (cur = sess->connlist; cur; cur = cur->next) {
275 FD_SET(cur->fd, &fds);
279 faim_mutex_unlock(&sess->connlistlock);
281 if ((i = select(maxfd+1, &fds, NULL, NULL, timeout))>=1) {
282 faim_mutex_lock(&sess->connlistlock);
283 for (cur = sess->connlist; cur; cur = cur->next) {
284 if (FD_ISSET(cur->fd, &fds)) {
286 faim_mutex_unlock(&sess->connlistlock);
292 faim_mutex_unlock(&sess->connlistlock);
293 *status = i; /* may be 0 or -1 */
294 return NULL; /* no waiting or error, return */
297 int aim_conn_isready(struct aim_conn_t *conn)
300 return (conn->status & 0x0001);
304 int aim_conn_setstatus(struct aim_conn_t *conn, int status)
311 faim_mutex_lock(&conn->active);
312 val = conn->status ^= status;
313 faim_mutex_unlock(&conn->active);
317 int aim_conn_setlatency(struct aim_conn_t *conn, int newval)
322 faim_mutex_lock(&conn->active);
323 conn->forcedlatency = newval;
324 conn->lastactivity = 0; /* reset this just to make sure */
325 faim_mutex_unlock(&conn->active);
330 void aim_session_init(struct aim_session_t *sess)
335 memset(sess, 0, sizeof(struct aim_session_t));
337 sess->queue_outgoing = NULL;
338 sess->queue_incoming = NULL;
339 sess->pendingjoin = NULL;
340 sess->outstanding_snacs = NULL;
341 sess->snac_nextid = 0x00000001;
344 * This must always be set. Default to the queue-based
345 * version for back-compatibility.
347 sess->tx_enqueue = &aim_tx_enqueue__queuebased;