]> andersk Git - libfaim.git/blame - aim_conn.c
Last few changes left in my inbox.
[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
9#include "aim.h"
10
11void aim_connrst(void)
12{
13 int i;
14 for (i = 0; i < AIM_CONN_MAX; i++)
15 {
16 aim_conns[i].fd = -1;
17 aim_conns[i].type = -1;
18 aim_conns[i].status = 0;
19 aim_conns[i].seqnum = 0;
20 aim_conns[i].lastactivity = 0;
21 aim_conns[i].forcedlatency = 0;
22 aim_clearhandlers(&aim_conns[i]);
23 aim_conns[i].handlerlist = NULL;
24 }
25
26}
27
28struct aim_conn_t *aim_conn_getnext(void)
29{
30 int i;
31 for (i=0;i<AIM_CONN_MAX;i++)
32 if (aim_conns[i].fd == -1)
33 return &(aim_conns[i]);
34 return NULL;
35}
36
37void aim_conn_close(struct aim_conn_t *deadconn)
38{
39 if (deadconn->fd >= 3)
40 close(deadconn->fd);
41 deadconn->fd = -1;
42 deadconn->type = -1;
43 deadconn->seqnum = 0;
44 deadconn->lastactivity = 0;
45 deadconn->forcedlatency = 0;
46 aim_clearhandlers(deadconn);
47 deadconn->handlerlist = NULL;
48}
49
50struct aim_conn_t *aim_getconn_type(int type)
51{
52 int i;
53 for (i=0; i<AIM_CONN_MAX; i++)
54 if (aim_conns[i].type == type)
55 return &(aim_conns[i]);
56 return NULL;
57}
58
59/*
60 * aim_newconn(type, dest)
61 *
62 * Opens a new connection to the specified dest host of type type.
63 *
64 * TODO: fix for proxies
65 * FIXME: Return errors in a more sane way.
66 *
67 */
68struct aim_conn_t *aim_newconn(int type, char *dest)
69{
70 struct aim_conn_t *connstruct;
71 int ret;
72 struct sockaddr_in sa;
73 struct hostent *hp;
74 u_short port = FAIM_LOGIN_PORT;
75 int i=0;
76
77 if (!dest || ((connstruct=aim_conn_getnext())==NULL))
78 return NULL;
79
80 connstruct->type = type;
81
82 /*
83 * As of 23 Jul 1999, AOL now sends the port number, preceded by a
84 * colon, in the BOS redirect. This fatally breaks all previous
85 * libfaims. Bad, bad AOL.
86 *
87 * We put this here to catch every case.
88 *
89 */
90
91 for(i=0;(i<strlen(dest));i++)
92 if (dest[i] == ':') {
93 port = atoi(&(dest[i+1]));
94 dest[i]=0;
95 break;
96 }
97
98 hp = gethostbyname2(dest, AF_INET);
99 if (hp == NULL)
100 {
101 connstruct->status = (h_errno | AIM_CONN_STATUS_RESOLVERR);
102 return connstruct;
103 }
104
105 memset(&sa.sin_zero, 0, 8);
106 sa.sin_port = htons(port);
107 memcpy(&sa.sin_addr, hp->h_addr, hp->h_length);
108 sa.sin_family = hp->h_addrtype;
109
110 connstruct->fd = socket(hp->h_addrtype, SOCK_STREAM, 0);
111 ret = connect(connstruct->fd, (struct sockaddr *)&sa, sizeof(struct sockaddr_in));
112 if( ret < 0)
113 {
114 connstruct->fd = -1;
115 connstruct->status = (errno | AIM_CONN_STATUS_CONNERR);
116 return connstruct;
117 }
118
119 return connstruct;
120}
121
122int aim_conngetmaxfd(void)
123{
124 int i,j;
125 j=0;
126 for (i=0;i<AIM_CONN_MAX;i++)
127 if(aim_conns[i].fd > j)
128 j = aim_conns[i].fd;
129 return j;
130}
131
132int aim_countconn(void)
133{
134 int i,cnt;
135 cnt = 0;
136 for (i=0;i<AIM_CONN_MAX;i++)
137 if (aim_conns[i].fd > -1)
138 cnt++;
139 return cnt;
140}
141
142/*
143 * aim_select(timeout)
144 *
145 * Waits for a socket with data or for timeout, whichever comes first.
146 * See select(2).
147 *
148 */
149struct aim_conn_t *aim_select(struct timeval *timeout)
150{
151 fd_set fds;
152 fd_set errfds;
153 int i;
154
155 if (aim_countconn() <= 0)
156 return 0;
157
158 /*
159 * If we have data waiting to be sent, return immediatly
160 */
161 if (aim_queue_outgoing)
162 return (struct aim_conn_t *)1;
163
164 FD_ZERO(&fds);
165 FD_ZERO(&errfds);
166
167 for(i=0;i<AIM_CONN_MAX;i++)
168 if (aim_conns[i].fd>-1)
169 {
170 FD_SET(aim_conns[i].fd, &fds);
171 FD_SET(aim_conns[i].fd, &errfds);
172 }
173
174 i = select(aim_conngetmaxfd()+1, &fds, NULL, &errfds, timeout);
175 if (i>=1)
176 {
177 int j;
178 for (j=0;j<AIM_CONN_MAX;j++)
179 {
180 if (aim_conns[j].fd > -1)
181 {
182 if ((FD_ISSET(aim_conns[j].fd, &errfds)))
183 {
184 /* got an exception; close whats left of it up */
185 aim_conn_close(&(aim_conns[j]));
186 return (struct aim_conn_t *)-1;
187 }
188 else if ((FD_ISSET(aim_conns[j].fd, &fds)))
189 return &(aim_conns[j]); /* return the first waiting struct */
190 }
191 }
192 /* should never get here */
193 }
194 else
195 return (struct aim_conn_t *)i; /* no waiting or error, return -- FIXME: return type funnies */
196 return NULL; /* NO REACH */
197}
198
199int aim_conn_isready(struct aim_conn_t *conn)
200{
201 if (conn)
202 return (conn->status & 0x0001);
203 else
204 return -1;
205}
206
207int aim_conn_setstatus(struct aim_conn_t *conn, int status)
208{
209 if (conn)
210 return (conn->status ^= status);
211 else
212 return -1;
213}
214
215int aim_conn_setlatency(struct aim_conn_t *conn, int newval)
216{
217 if (!conn)
218 return -1;
219
220 conn->forcedlatency = newval;
221 conn->lastactivity = 0; /* reset this just to make sure */
222
223 return 0;
224}
This page took 0.079763 seconds and 5 git commands to generate.