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