Mercurial > pidgin.yaz
comparison src/protocols/oscar/conn.c @ 2246:933346315b9b
[gaim-migrate @ 2256]
heh.
committer: Tailor Script <tailor@pidgin.im>
author | Eric Warmenhoven <eric@warmenhoven.org> |
---|---|
date | Sun, 09 Sep 2001 10:07:14 +0000 |
parents | 424a40f12a6c |
children | d82efea341ef |
comparison
equal
deleted
inserted
replaced
2245:31157c54fe6e | 2246:933346315b9b |
---|---|
13 #include <netdb.h> | 13 #include <netdb.h> |
14 #include <sys/socket.h> | 14 #include <sys/socket.h> |
15 #include <netinet/in.h> | 15 #include <netinet/in.h> |
16 #endif | 16 #endif |
17 | 17 |
18 static void connkill_real(aim_session_t *sess, aim_conn_t **deadconn) | |
19 { | |
20 | |
21 aim_rxqueue_cleanbyconn(sess, *deadconn); | |
22 aim_tx_cleanqueue(sess, *deadconn); | |
23 | |
24 if ((*deadconn)->fd != -1) | |
25 aim_conn_close(*deadconn); | |
26 | |
27 /* | |
28 * XXX ->priv should never be touched by the library. I know | |
29 * it used to be, but I'm getting rid of all that. Use | |
30 * ->internal instead. | |
31 */ | |
32 if ((*deadconn)->priv) | |
33 free((*deadconn)->priv); | |
34 | |
35 /* | |
36 * This will free ->internal if it necessary... | |
37 */ | |
38 if ((*deadconn)->type == AIM_CONN_TYPE_RENDEZVOUS) | |
39 aim_conn_kill_rend(sess, *deadconn); | |
40 | |
41 free(*deadconn); | |
42 deadconn = NULL; | |
43 | |
44 return; | |
45 } | |
46 | |
18 /** | 47 /** |
19 * aim_connrst - Clears out connection list, killing remaining connections. | 48 * aim_connrst - Clears out connection list, killing remaining connections. |
20 * @sess: Session to be cleared | 49 * @sess: Session to be cleared |
21 * | 50 * |
22 * Clears out the connection list and kills any connections left. | 51 * Clears out the connection list and kills any connections left. |
23 * | 52 * |
24 */ | 53 */ |
25 static void aim_connrst(struct aim_session_t *sess) | 54 static void aim_connrst(aim_session_t *sess) |
26 { | 55 { |
27 faim_mutex_init(&sess->connlistlock); | 56 |
28 if (sess->connlist) { | 57 faim_mutex_init(&sess->connlistlock); |
29 struct aim_conn_t *cur = sess->connlist, *tmp; | 58 |
30 | 59 if (sess->connlist) { |
31 while(cur) { | 60 aim_conn_t *cur = sess->connlist, *tmp; |
32 tmp = cur->next; | 61 |
33 aim_conn_close(cur); | 62 while (cur) { |
34 free(cur); | 63 tmp = cur->next; |
35 cur = tmp; | 64 aim_conn_close(cur); |
36 } | 65 connkill_real(sess, &cur); |
37 } | 66 cur = tmp; |
38 sess->connlist = NULL; | 67 } |
39 return; | 68 } |
69 | |
70 sess->connlist = NULL; | |
71 | |
72 return; | |
40 } | 73 } |
41 | 74 |
42 /** | 75 /** |
43 * aim_conn_init - Reset a connection to default values. | 76 * aim_conn_init - Reset a connection to default values. |
44 * @deadconn: Connection to be reset | 77 * @deadconn: Connection to be reset |
45 * | 78 * |
46 * Initializes and/or resets a connection structure. | 79 * Initializes and/or resets a connection structure. |
47 * | 80 * |
48 */ | 81 */ |
49 static void aim_conn_init(struct aim_conn_t *deadconn) | 82 static void aim_conn_init(aim_conn_t *deadconn) |
50 { | 83 { |
51 if (!deadconn) | 84 |
52 return; | 85 if (!deadconn) |
53 | 86 return; |
54 deadconn->fd = -1; | 87 |
55 deadconn->subtype = -1; | 88 deadconn->fd = -1; |
56 deadconn->type = -1; | 89 deadconn->subtype = -1; |
57 deadconn->seqnum = 0; | 90 deadconn->type = -1; |
58 deadconn->lastactivity = 0; | 91 deadconn->seqnum = 0; |
59 deadconn->forcedlatency = 0; | 92 deadconn->lastactivity = 0; |
60 deadconn->handlerlist = NULL; | 93 deadconn->forcedlatency = 0; |
61 deadconn->priv = NULL; | 94 deadconn->handlerlist = NULL; |
62 faim_mutex_init(&deadconn->active); | 95 deadconn->priv = NULL; |
63 faim_mutex_init(&deadconn->seqnum_lock); | 96 faim_mutex_init(&deadconn->active); |
64 | 97 faim_mutex_init(&deadconn->seqnum_lock); |
65 return; | 98 |
99 return; | |
66 } | 100 } |
67 | 101 |
68 /** | 102 /** |
69 * aim_conn_getnext - Gets a new connection structure. | 103 * aim_conn_getnext - Gets a new connection structure. |
70 * @sess: Session | 104 * @sess: Session |
71 * | 105 * |
72 * Allocate a new empty connection structure. | 106 * Allocate a new empty connection structure. |
73 * | 107 * |
74 */ | 108 */ |
75 static struct aim_conn_t *aim_conn_getnext(struct aim_session_t *sess) | 109 static aim_conn_t *aim_conn_getnext(aim_session_t *sess) |
76 { | 110 { |
77 struct aim_conn_t *newconn, *cur; | 111 aim_conn_t *newconn; |
78 | 112 |
79 if (!(newconn = malloc(sizeof(struct aim_conn_t)))) | 113 if (!(newconn = malloc(sizeof(aim_conn_t)))) |
80 return NULL; | 114 return NULL; |
81 | 115 memset(newconn, 0, sizeof(aim_conn_t)); |
82 memset(newconn, 0, sizeof(struct aim_conn_t)); | 116 |
83 aim_conn_init(newconn); | 117 aim_conn_init(newconn); |
84 newconn->next = NULL; | 118 |
85 | 119 newconn->next = sess->connlist; |
86 faim_mutex_lock(&sess->connlistlock); | 120 sess->connlist = newconn; |
87 if (sess->connlist == NULL) | 121 |
88 sess->connlist = newconn; | 122 return newconn; |
89 else { | |
90 for (cur = sess->connlist; cur->next; cur = cur->next) | |
91 ; | |
92 cur->next = newconn; | |
93 } | |
94 faim_mutex_unlock(&sess->connlistlock); | |
95 | |
96 return newconn; | |
97 } | 123 } |
98 | 124 |
99 /** | 125 /** |
100 * aim_conn_kill - Close and free a connection. | 126 * aim_conn_kill - Close and free a connection. |
101 * @sess: Session for the connection | 127 * @sess: Session for the connection |
103 * | 129 * |
104 * Close, clear, and free a connection structure. Should never be | 130 * Close, clear, and free a connection structure. Should never be |
105 * called from within libfaim. | 131 * called from within libfaim. |
106 * | 132 * |
107 */ | 133 */ |
108 faim_export void aim_conn_kill(struct aim_session_t *sess, struct aim_conn_t **deadconn) | 134 faim_export void aim_conn_kill(aim_session_t *sess, aim_conn_t **deadconn) |
109 { | 135 { |
110 struct aim_conn_t *cur; | 136 aim_conn_t *cur, **prev; |
111 | 137 |
112 if (!deadconn || !*deadconn) | 138 if (!deadconn || !*deadconn) |
113 return; | 139 return; |
114 | 140 |
115 aim_tx_cleanqueue(sess, *deadconn); | 141 for (prev = &sess->connlist; (cur = *prev); ) { |
116 | 142 if (cur == *deadconn) { |
117 faim_mutex_lock(&sess->connlistlock); | 143 *prev = cur->next; |
118 if (sess->connlist == NULL) | 144 break; |
119 ; | 145 } |
120 else if (sess->connlist->next == NULL) { | 146 prev = &cur->next; |
121 if (sess->connlist == *deadconn) | 147 } |
122 sess->connlist = NULL; | 148 |
123 } else { | 149 if (!cur) |
124 cur = sess->connlist; | 150 return; /* oops */ |
125 while (cur->next) { | 151 |
126 if (cur->next == *deadconn) { | 152 connkill_real(sess, &cur); |
127 cur->next = cur->next->next; | 153 |
128 break; | 154 return; |
129 } | |
130 cur = cur->next; | |
131 } | |
132 } | |
133 faim_mutex_unlock(&sess->connlistlock); | |
134 | |
135 /* XXX: do we need this for txqueue too? */ | |
136 aim_rxqueue_cleanbyconn(sess, *deadconn); | |
137 | |
138 if ((*deadconn)->fd != -1) | |
139 aim_conn_close(*deadconn); | |
140 if ((*deadconn)->priv) | |
141 free((*deadconn)->priv); | |
142 free(*deadconn); | |
143 deadconn = NULL; | |
144 | |
145 return; | |
146 } | 155 } |
147 | 156 |
148 /** | 157 /** |
149 * aim_conn_close - Close a connection | 158 * aim_conn_close - Close a connection |
150 * @deadconn: Connection to close | 159 * @deadconn: Connection to close |
151 * | 160 * |
152 * Close (but not free) a connection. | 161 * Close (but not free) a connection. |
153 * | 162 * |
154 * This leaves everything untouched except for clearing the | 163 * This leaves everything untouched except for clearing the |
155 * handler list and setting the fd to -1 (used to recognize | 164 * handler list and setting the fd to -1 (used to recognize |
156 * dead connections). | 165 * dead connections). It will also remove cookies if necessary. |
157 * | 166 * |
158 */ | 167 */ |
159 faim_export void aim_conn_close(struct aim_conn_t *deadconn) | 168 faim_export void aim_conn_close(aim_conn_t *deadconn) |
160 { | 169 { |
161 | 170 |
162 faim_mutex_destroy(&deadconn->active); | 171 faim_mutex_destroy(&deadconn->active); |
163 faim_mutex_destroy(&deadconn->seqnum_lock); | 172 faim_mutex_destroy(&deadconn->seqnum_lock); |
164 if (deadconn->fd >= 3) | 173 if (deadconn->fd >= 3) |
165 close(deadconn->fd); | 174 close(deadconn->fd); |
166 deadconn->fd = -1; | 175 deadconn->fd = -1; |
167 if (deadconn->handlerlist) | 176 if (deadconn->handlerlist) |
168 aim_clearhandlers(deadconn); | 177 aim_clearhandlers(deadconn); |
169 | 178 if (deadconn->type == AIM_CONN_TYPE_RENDEZVOUS) |
170 return; | 179 aim_conn_close_rend((aim_session_t *)deadconn->sessv, deadconn); |
180 | |
181 | |
182 return; | |
171 } | 183 } |
172 | 184 |
173 /** | 185 /** |
174 * aim_getconn_type - Find a connection of a specific type | 186 * aim_getconn_type - Find a connection of a specific type |
175 * @sess: Session to search | 187 * @sess: Session to search |
178 * Searches for a connection of the specified type in the | 190 * Searches for a connection of the specified type in the |
179 * specified session. Returns the first connection of that | 191 * specified session. Returns the first connection of that |
180 * type found. | 192 * type found. |
181 * | 193 * |
182 */ | 194 */ |
183 faim_export struct aim_conn_t *aim_getconn_type(struct aim_session_t *sess, | 195 faim_export aim_conn_t *aim_getconn_type(aim_session_t *sess, int type) |
184 int type) | 196 { |
185 { | 197 aim_conn_t *cur; |
186 struct aim_conn_t *cur; | 198 |
187 | 199 faim_mutex_lock(&sess->connlistlock); |
188 faim_mutex_lock(&sess->connlistlock); | 200 for (cur = sess->connlist; cur; cur = cur->next) { |
189 for (cur = sess->connlist; cur; cur = cur->next) { | 201 if ((cur->type == type) && |
190 if ((cur->type == type) && !(cur->status & AIM_CONN_STATUS_INPROGRESS)) | 202 !(cur->status & AIM_CONN_STATUS_INPROGRESS)) |
191 break; | 203 break; |
192 } | 204 } |
193 faim_mutex_unlock(&sess->connlistlock); | 205 faim_mutex_unlock(&sess->connlistlock); |
194 | 206 |
195 return cur; | 207 return cur; |
196 } | 208 } |
197 | 209 |
198 faim_export struct aim_conn_t *aim_getconn_type_all(struct aim_session_t *sess, | 210 faim_export aim_conn_t *aim_getconn_type_all(aim_session_t *sess, int type) |
199 int type) | 211 { |
200 { | 212 aim_conn_t *cur; |
201 struct aim_conn_t *cur; | 213 |
202 | 214 faim_mutex_lock(&sess->connlistlock); |
203 faim_mutex_lock(&sess->connlistlock); | 215 for (cur = sess->connlist; cur; cur = cur->next) { |
204 for (cur = sess->connlist; cur; cur = cur->next) { | 216 if (cur->type == type) |
205 if (cur->type == type) | 217 break; |
206 break; | 218 } |
207 } | 219 faim_mutex_unlock(&sess->connlistlock); |
208 faim_mutex_unlock(&sess->connlistlock); | 220 |
209 | 221 return cur; |
210 return cur; | |
211 } | 222 } |
212 | 223 |
213 /* If you pass -1 for the fd, you'll get what you ask for. Gibberish. */ | 224 /* If you pass -1 for the fd, you'll get what you ask for. Gibberish. */ |
214 faim_export struct aim_conn_t *aim_getconn_fd(struct aim_session_t *sess, | 225 faim_export aim_conn_t *aim_getconn_fd(aim_session_t *sess, int fd) |
215 int fd) | 226 { |
216 { | 227 aim_conn_t *cur; |
217 struct aim_conn_t *cur; | 228 |
218 | 229 faim_mutex_lock(&sess->connlistlock); |
219 faim_mutex_lock(&sess->connlistlock); | 230 for (cur = sess->connlist; cur; cur = cur->next) { |
220 for (cur = sess->connlist; cur; cur = cur->next) { | 231 if (cur->fd == fd) |
221 if (cur->fd == fd) | 232 break; |
222 break; | 233 } |
223 } | 234 faim_mutex_unlock(&sess->connlistlock); |
224 faim_mutex_unlock(&sess->connlistlock); | 235 |
225 | 236 return cur; |
226 return cur; | |
227 } | 237 } |
228 | 238 |
229 /** | 239 /** |
230 * aim_proxyconnect - An extrememly quick and dirty SOCKS5 interface. | 240 * aim_proxyconnect - An extrememly quick and dirty SOCKS5 interface. |
231 * @sess: Session to connect | 241 * @sess: Session to connect |
235 * | 245 * |
236 * Attempts to connect to the specified host via the configured | 246 * Attempts to connect to the specified host via the configured |
237 * proxy settings, if present. If no proxy is configured for | 247 * proxy settings, if present. If no proxy is configured for |
238 * this session, the connection is done directly. | 248 * this session, the connection is done directly. |
239 * | 249 * |
240 */ | 250 * XXX this is really awful. |
241 static int aim_proxyconnect(struct aim_session_t *sess, | 251 * |
242 char *host, unsigned short port, | 252 */ |
243 int *statusret) | 253 static int aim_proxyconnect(aim_session_t *sess, const char *host, fu16_t port, fu32_t *statusret) |
244 { | 254 { |
245 int fd = -1; | 255 int fd = -1; |
246 | 256 |
247 if (strlen(sess->socksproxy.server)) { /* connecting via proxy */ | 257 if (strlen(sess->socksproxy.server)) { /* connecting via proxy */ |
248 int i; | 258 int i; |
249 unsigned char buf[512]; | 259 unsigned char buf[512]; |
250 struct sockaddr_in sa; | 260 struct sockaddr_in sa; |
251 struct hostent *hp; | 261 struct hostent *hp; |
252 char *proxy; | 262 char *proxy; |
253 unsigned short proxyport = 1080; | 263 unsigned short proxyport = 1080; |
254 | 264 |
255 for(i=0;i<(int)strlen(sess->socksproxy.server);i++) { | 265 for(i=0;i<(int)strlen(sess->socksproxy.server);i++) { |
256 if (sess->socksproxy.server[i] == ':') { | 266 if (sess->socksproxy.server[i] == ':') { |
257 proxyport = atoi(&(sess->socksproxy.server[i+1])); | 267 proxyport = atoi(&(sess->socksproxy.server[i+1])); |
258 break; | 268 break; |
259 } | 269 } |
260 } | 270 } |
261 proxy = (char *)malloc(i+1); | 271 |
262 strncpy(proxy, sess->socksproxy.server, i); | 272 proxy = (char *)malloc(i+1); |
263 proxy[i] = '\0'; | 273 strncpy(proxy, sess->socksproxy.server, i); |
264 | 274 proxy[i] = '\0'; |
265 if (!(hp = gethostbyname(proxy))) { | 275 |
266 faimdprintf(sess, 0, "proxyconnect: unable to resolve proxy name\n"); | 276 if (!(hp = gethostbyname(proxy))) { |
267 *statusret = (h_errno | AIM_CONN_STATUS_RESOLVERR); | 277 faimdprintf(sess, 0, "proxyconnect: unable to resolve proxy name\n"); |
268 return -1; | 278 *statusret = (h_errno | AIM_CONN_STATUS_RESOLVERR); |
269 } | 279 return -1; |
270 free(proxy); | 280 } |
271 | 281 free(proxy); |
272 memset(&sa.sin_zero, 0, 8); | 282 |
273 sa.sin_port = htons(proxyport); | 283 memset(&sa.sin_zero, 0, 8); |
274 memcpy(&sa.sin_addr, hp->h_addr, hp->h_length); | 284 sa.sin_port = htons(proxyport); |
275 sa.sin_family = hp->h_addrtype; | 285 memcpy(&sa.sin_addr, hp->h_addr, hp->h_length); |
276 | 286 sa.sin_family = hp->h_addrtype; |
277 fd = socket(hp->h_addrtype, SOCK_STREAM, 0); | 287 |
278 if (connect(fd, (struct sockaddr *)&sa, sizeof(struct sockaddr_in)) < 0) { | 288 fd = socket(hp->h_addrtype, SOCK_STREAM, 0); |
279 faimdprintf(sess, 0, "proxyconnect: unable to connect to proxy\n"); | 289 if (connect(fd, (struct sockaddr *)&sa, sizeof(struct sockaddr_in)) < 0) { |
280 close(fd); | 290 faimdprintf(sess, 0, "proxyconnect: unable to connect to proxy\n"); |
281 return -1; | 291 close(fd); |
282 } | 292 return -1; |
283 | 293 } |
284 i = 0; | 294 |
285 buf[0] = 0x05; /* SOCKS version 5 */ | 295 i = 0; |
286 if (strlen(sess->socksproxy.username)) { | 296 buf[0] = 0x05; /* SOCKS version 5 */ |
287 buf[1] = 0x02; /* two methods */ | 297 if (strlen(sess->socksproxy.username)) { |
288 buf[2] = 0x00; /* no authentication */ | 298 buf[1] = 0x02; /* two methods */ |
289 buf[3] = 0x02; /* username/password authentication */ | 299 buf[2] = 0x00; /* no authentication */ |
290 i = 4; | 300 buf[3] = 0x02; /* username/password authentication */ |
291 } else { | 301 i = 4; |
292 buf[1] = 0x01; | 302 } else { |
293 buf[2] = 0x00; | 303 buf[1] = 0x01; |
294 i = 3; | 304 buf[2] = 0x00; |
295 } | 305 i = 3; |
296 | 306 } |
297 if (write(fd, buf, i) < i) { | 307 |
298 *statusret = errno; | 308 if (write(fd, buf, i) < i) { |
299 close(fd); | 309 *statusret = errno; |
300 return -1; | 310 close(fd); |
301 } | 311 return -1; |
302 | 312 } |
303 if (read(fd, buf, 2) < 2) { | 313 |
304 *statusret = errno; | 314 if (read(fd, buf, 2) < 2) { |
305 close(fd); | 315 *statusret = errno; |
306 return -1; | 316 close(fd); |
307 } | 317 return -1; |
308 | 318 } |
309 if ((buf[0] != 0x05) || (buf[1] == 0xff)) { | 319 |
310 *statusret = EINVAL; | 320 if ((buf[0] != 0x05) || (buf[1] == 0xff)) { |
311 close(fd); | 321 *statusret = EINVAL; |
312 return -1; | 322 close(fd); |
313 } | 323 return -1; |
314 | 324 } |
315 /* check if we're doing username authentication */ | 325 |
316 if (buf[1] == 0x02) { | 326 /* check if we're doing username authentication */ |
317 i = aimutil_put8(buf, 0x01); /* version 1 */ | 327 if (buf[1] == 0x02) { |
318 i += aimutil_put8(buf+i, strlen(sess->socksproxy.username)); | 328 i = aimutil_put8(buf, 0x01); /* version 1 */ |
319 i += aimutil_putstr(buf+i, sess->socksproxy.username, strlen(sess->socksproxy.username)); | 329 i += aimutil_put8(buf+i, strlen(sess->socksproxy.username)); |
320 i += aimutil_put8(buf+i, strlen(sess->socksproxy.password)); | 330 i += aimutil_putstr(buf+i, sess->socksproxy.username, strlen(sess->socksproxy.username)); |
321 i += aimutil_putstr(buf+i, sess->socksproxy.password, strlen(sess->socksproxy.password)); | 331 i += aimutil_put8(buf+i, strlen(sess->socksproxy.password)); |
322 if (write(fd, buf, i) < i) { | 332 i += aimutil_putstr(buf+i, sess->socksproxy.password, strlen(sess->socksproxy.password)); |
323 *statusret = errno; | 333 if (write(fd, buf, i) < i) { |
324 close(fd); | 334 *statusret = errno; |
325 return -1; | 335 close(fd); |
326 } | 336 return -1; |
327 if (read(fd, buf, 2) < 2) { | 337 } |
328 *statusret = errno; | 338 if (read(fd, buf, 2) < 2) { |
329 close(fd); | 339 *statusret = errno; |
330 return -1; | 340 close(fd); |
331 } | 341 return -1; |
332 if ((buf[0] != 0x01) || (buf[1] != 0x00)) { | 342 } |
333 *statusret = EINVAL; | 343 if ((buf[0] != 0x01) || (buf[1] != 0x00)) { |
334 close(fd); | 344 *statusret = EINVAL; |
335 return -1; | 345 close(fd); |
336 } | 346 return -1; |
337 } | 347 } |
338 | 348 } |
339 i = aimutil_put8(buf, 0x05); | 349 |
340 i += aimutil_put8(buf+i, 0x01); /* CONNECT */ | 350 i = aimutil_put8(buf, 0x05); |
341 i += aimutil_put8(buf+i, 0x00); /* reserved */ | 351 i += aimutil_put8(buf+i, 0x01); /* CONNECT */ |
342 i += aimutil_put8(buf+i, 0x03); /* address type: host name */ | 352 i += aimutil_put8(buf+i, 0x00); /* reserved */ |
343 i += aimutil_put8(buf+i, strlen(host)); | 353 i += aimutil_put8(buf+i, 0x03); /* address type: host name */ |
344 i += aimutil_putstr(buf+i, host, strlen(host)); | 354 i += aimutil_put8(buf+i, strlen(host)); |
345 i += aimutil_put16(buf+i, port); | 355 i += aimutil_putstr(buf+i, host, strlen(host)); |
346 | 356 i += aimutil_put16(buf+i, port); |
347 if (write(fd, buf, i) < i) { | 357 |
348 *statusret = errno; | 358 if (write(fd, buf, i) < i) { |
349 close(fd); | 359 *statusret = errno; |
350 return -1; | 360 close(fd); |
351 } | 361 return -1; |
352 if (read(fd, buf, 10) < 10) { | 362 } |
353 *statusret = errno; | 363 if (read(fd, buf, 10) < 10) { |
354 close(fd); | 364 *statusret = errno; |
355 return -1; | 365 close(fd); |
356 } | 366 return -1; |
357 if ((buf[0] != 0x05) || (buf[1] != 0x00)) { | 367 } |
358 *statusret = EINVAL; | 368 if ((buf[0] != 0x05) || (buf[1] != 0x00)) { |
359 close(fd); | 369 *statusret = EINVAL; |
360 return -1; | 370 close(fd); |
361 } | 371 return -1; |
362 | 372 } |
363 } else { /* connecting directly */ | 373 |
364 struct sockaddr_in sa; | 374 } else { /* connecting directly */ |
365 struct hostent *hp; | 375 struct sockaddr_in sa; |
366 | 376 struct hostent *hp; |
367 if (!(hp = gethostbyname(host))) { | 377 |
368 *statusret = (h_errno | AIM_CONN_STATUS_RESOLVERR); | 378 if (!(hp = gethostbyname(host))) { |
369 return -1; | 379 *statusret = (h_errno | AIM_CONN_STATUS_RESOLVERR); |
370 } | 380 return -1; |
371 | 381 } |
372 memset(&sa, 0, sizeof(struct sockaddr_in)); | 382 |
373 sa.sin_port = htons(port); | 383 memset(&sa, 0, sizeof(struct sockaddr_in)); |
374 memcpy(&sa.sin_addr, hp->h_addr, hp->h_length); | 384 sa.sin_port = htons(port); |
375 sa.sin_family = hp->h_addrtype; | 385 memcpy(&sa.sin_addr, hp->h_addr, hp->h_length); |
376 | 386 sa.sin_family = hp->h_addrtype; |
377 fd = socket(hp->h_addrtype, SOCK_STREAM, 0); | 387 |
378 | 388 fd = socket(hp->h_addrtype, SOCK_STREAM, 0); |
379 if (sess->flags & AIM_SESS_FLAGS_NONBLOCKCONNECT) | 389 |
380 fcntl(fd, F_SETFL, O_NONBLOCK); /* XXX save flags */ | 390 if (sess->flags & AIM_SESS_FLAGS_NONBLOCKCONNECT) |
381 | 391 fcntl(fd, F_SETFL, O_NONBLOCK); /* XXX save flags */ |
382 if (connect(fd, (struct sockaddr *)&sa, sizeof(struct sockaddr_in)) < 0) { | 392 |
383 if (sess->flags & AIM_SESS_FLAGS_NONBLOCKCONNECT) { | 393 if (connect(fd, (struct sockaddr *)&sa, sizeof(struct sockaddr_in)) < 0) { |
384 if ((errno == EINPROGRESS) || (errno == EINTR)) { | 394 if (sess->flags & AIM_SESS_FLAGS_NONBLOCKCONNECT) { |
385 if (statusret) | 395 if ((errno == EINPROGRESS) || (errno == EINTR)) { |
386 *statusret |= AIM_CONN_STATUS_INPROGRESS; | 396 if (statusret) |
387 return fd; | 397 *statusret |= AIM_CONN_STATUS_INPROGRESS; |
388 } | 398 return fd; |
389 } | 399 } |
390 close(fd); | 400 } |
391 fd = -1; | 401 close(fd); |
392 } | 402 fd = -1; |
393 } | 403 } |
394 return fd; | 404 } |
405 return fd; | |
395 } | 406 } |
396 | 407 |
397 /** | 408 /** |
398 * aim_cloneconn - clone an aim_conn_t | 409 * aim_cloneconn - clone an aim_conn_t |
399 * @sess: session containing parent | 410 * @sess: session containing parent |
405 * is copied, not the data it points to. | 416 * is copied, not the data it points to. |
406 * | 417 * |
407 * This function returns a pointer to the new aim_conn_t, or %NULL on | 418 * This function returns a pointer to the new aim_conn_t, or %NULL on |
408 * error | 419 * error |
409 */ | 420 */ |
410 faim_internal struct aim_conn_t *aim_cloneconn(struct aim_session_t *sess, | 421 faim_internal aim_conn_t *aim_cloneconn(aim_session_t *sess, aim_conn_t *src) |
411 struct aim_conn_t *src) | 422 { |
412 { | 423 aim_conn_t *conn; |
413 struct aim_conn_t *conn; | 424 |
414 struct aim_rxcblist_t *cur; | 425 if (!(conn = aim_conn_getnext(sess))) |
415 | 426 return NULL; |
416 if (!(conn = aim_conn_getnext(sess))) | 427 |
417 return NULL; | 428 faim_mutex_lock(&conn->active); |
418 | 429 |
419 faim_mutex_lock(&conn->active); | 430 conn->fd = src->fd; |
420 | 431 conn->type = src->type; |
421 conn->fd = src->fd; | 432 conn->subtype = src->subtype; |
422 conn->type = src->type; | 433 conn->seqnum = src->seqnum; |
423 conn->subtype = src->subtype; | 434 conn->priv = src->priv; |
424 conn->seqnum = src->seqnum; | 435 conn->internal = src->internal; |
425 conn->priv = src->priv; | 436 conn->lastactivity = src->lastactivity; |
426 conn->lastactivity = src->lastactivity; | 437 conn->forcedlatency = src->forcedlatency; |
427 conn->forcedlatency = src->forcedlatency; | 438 conn->sessv = src->sessv; |
428 conn->sessv = src->sessv; | 439 aim_clonehandlers(sess, conn, src); |
429 | 440 |
430 /* clone handler list */ | 441 faim_mutex_unlock(&conn->active); |
431 for (cur = src->handlerlist; cur; cur = cur->next) { | 442 |
432 aim_conn_addhandler(sess, conn, cur->family, cur->type, | 443 return conn; |
433 cur->handler, cur->flags); | |
434 } | |
435 | |
436 faim_mutex_unlock(&conn->active); | |
437 | |
438 return conn; | |
439 } | 444 } |
440 | 445 |
441 /** | 446 /** |
442 * aim_newconn - Open a new connection | 447 * aim_newconn - Open a new connection |
443 * @sess: Session to create connection in | 448 * @sess: Session to create connection in |
450 * is made. | 455 * is made. |
451 * | 456 * |
452 * FIXME: Return errors in a more sane way. | 457 * FIXME: Return errors in a more sane way. |
453 * | 458 * |
454 */ | 459 */ |
455 faim_export struct aim_conn_t *aim_newconn(struct aim_session_t *sess, | 460 faim_export aim_conn_t *aim_newconn(aim_session_t *sess, int type, const char *dest) |
456 int type, char *dest) | 461 { |
457 { | 462 aim_conn_t *connstruct; |
458 struct aim_conn_t *connstruct; | 463 fu16_t port = FAIM_LOGIN_PORT; |
459 int ret; | 464 char *host; |
460 u_short port = FAIM_LOGIN_PORT; | 465 int i, ret; |
461 char *host = NULL; | 466 |
462 int i=0; | 467 if (!(connstruct = aim_conn_getnext(sess))) |
463 | 468 return NULL; |
464 if ((connstruct=aim_conn_getnext(sess))==NULL) | 469 |
465 return NULL; | 470 faim_mutex_lock(&connstruct->active); |
466 | 471 |
467 faim_mutex_lock(&connstruct->active); | 472 connstruct->sessv = (void *)sess; |
468 | 473 connstruct->type = type; |
469 connstruct->sessv = (void *)sess; | 474 |
470 connstruct->type = type; | 475 if (!dest) { /* just allocate a struct */ |
471 | 476 connstruct->fd = -1; |
472 if (!dest) { /* just allocate a struct */ | 477 connstruct->status = 0; |
473 connstruct->fd = -1; | 478 faim_mutex_unlock(&connstruct->active); |
474 connstruct->status = 0; | 479 return connstruct; |
475 faim_mutex_unlock(&connstruct->active); | 480 } |
476 return connstruct; | 481 |
477 } | 482 /* |
478 | 483 * As of 23 Jul 1999, AOL now sends the port number, preceded by a |
479 /* | 484 * colon, in the BOS redirect. This fatally breaks all previous |
480 * As of 23 Jul 1999, AOL now sends the port number, preceded by a | 485 * libfaims. Bad, bad AOL. |
481 * colon, in the BOS redirect. This fatally breaks all previous | 486 * |
482 * libfaims. Bad, bad AOL. | 487 * We put this here to catch every case. |
483 * | 488 * |
484 * We put this here to catch every case. | 489 */ |
485 * | 490 |
486 */ | 491 for(i = 0; i < (int)strlen(dest); i++) { |
487 | 492 if (dest[i] == ':') { |
488 for(i=0;i<(int)strlen(dest);i++) { | 493 port = atoi(&(dest[i+1])); |
489 if (dest[i] == ':') { | 494 break; |
490 port = atoi(&(dest[i+1])); | 495 } |
491 break; | 496 } |
492 } | 497 |
493 } | 498 host = (char *)malloc(i+1); |
494 host = (char *)malloc(i+1); | 499 strncpy(host, dest, i); |
495 strncpy(host, dest, i); | 500 host[i] = '\0'; |
496 host[i] = '\0'; | 501 |
497 | 502 if ((ret = aim_proxyconnect(sess, host, port, &connstruct->status)) < 0) { |
498 if ((ret = aim_proxyconnect(sess, host, port, &connstruct->status)) < 0) { | 503 connstruct->fd = -1; |
499 connstruct->fd = -1; | 504 connstruct->status = (errno | AIM_CONN_STATUS_CONNERR); |
500 connstruct->status = (errno | AIM_CONN_STATUS_CONNERR); | 505 free(host); |
501 free(host); | 506 faim_mutex_unlock(&connstruct->active); |
502 faim_mutex_unlock(&connstruct->active); | 507 return connstruct; |
503 return connstruct; | 508 } else |
504 } else | 509 connstruct->fd = ret; |
505 connstruct->fd = ret; | 510 |
506 | 511 faim_mutex_unlock(&connstruct->active); |
507 faim_mutex_unlock(&connstruct->active); | 512 |
508 | 513 free(host); |
509 free(host); | 514 |
510 | 515 return connstruct; |
511 return connstruct; | |
512 } | 516 } |
513 | 517 |
514 /** | 518 /** |
515 * aim_conngetmaxfd - Return the highest valued file discriptor in session | 519 * aim_conngetmaxfd - Return the highest valued file discriptor in session |
516 * @sess: Session to search | 520 * @sess: Session to search |
517 * | 521 * |
518 * Returns the highest valued filed descriptor of all open | 522 * Returns the highest valued filed descriptor of all open |
519 * connections in @sess. | 523 * connections in @sess. |
520 * | 524 * |
521 */ | 525 */ |
522 faim_export int aim_conngetmaxfd(struct aim_session_t *sess) | 526 faim_export int aim_conngetmaxfd(aim_session_t *sess) |
523 { | 527 { |
524 int j = 0; | 528 int j; |
525 struct aim_conn_t *cur; | 529 aim_conn_t *cur; |
526 | 530 |
527 faim_mutex_lock(&sess->connlistlock); | 531 faim_mutex_lock(&sess->connlistlock); |
528 for (cur = sess->connlist; cur; cur = cur->next) { | 532 for (cur = sess->connlist, j = 0; cur; cur = cur->next) { |
529 if (cur->fd > j) | 533 if (cur->fd > j) |
530 j = cur->fd; | 534 j = cur->fd; |
531 } | 535 } |
532 faim_mutex_unlock(&sess->connlistlock); | 536 faim_mutex_unlock(&sess->connlistlock); |
533 | 537 |
534 return j; | 538 return j; |
535 } | 539 } |
536 | 540 |
537 /** | 541 /** |
538 * aim_conn_in_sess - Predicate to test the precense of a connection in a sess | 542 * aim_conn_in_sess - Predicate to test the precense of a connection in a sess |
539 * @sess: Session to look in | 543 * @sess: Session to look in |
541 * | 545 * |
542 * Searches @sess for the passed connection. Returns 1 if its present, | 546 * Searches @sess for the passed connection. Returns 1 if its present, |
543 * zero otherwise. | 547 * zero otherwise. |
544 * | 548 * |
545 */ | 549 */ |
546 faim_export int aim_conn_in_sess(struct aim_session_t *sess, struct aim_conn_t *conn) | 550 faim_export int aim_conn_in_sess(aim_session_t *sess, aim_conn_t *conn) |
547 { | 551 { |
548 struct aim_conn_t *cur; | 552 aim_conn_t *cur; |
549 | 553 |
550 faim_mutex_lock(&sess->connlistlock); | 554 faim_mutex_lock(&sess->connlistlock); |
551 for(cur = sess->connlist; cur; cur = cur->next) | 555 for (cur = sess->connlist; cur; cur = cur->next) { |
552 if(cur == conn) { | 556 if (cur == conn) { |
553 faim_mutex_unlock(&sess->connlistlock); | 557 faim_mutex_unlock(&sess->connlistlock); |
554 return 1; | 558 return 1; |
555 } | 559 } |
556 faim_mutex_unlock(&sess->connlistlock); | 560 } |
557 return 0; | 561 faim_mutex_unlock(&sess->connlistlock); |
562 | |
563 return 0; | |
558 } | 564 } |
559 | 565 |
560 /** | 566 /** |
561 * aim_select - Wait for a socket with data or timeout | 567 * aim_select - Wait for a socket with data or timeout |
562 * @sess: Session to wait on | 568 * @sess: Session to wait on |
573 * 2 incoming data pending (connection with pending data returned) | 579 * 2 incoming data pending (connection with pending data returned) |
574 * | 580 * |
575 * XXX: we could probably stand to do a little courser locking here. | 581 * XXX: we could probably stand to do a little courser locking here. |
576 * | 582 * |
577 */ | 583 */ |
578 faim_export struct aim_conn_t *aim_select(struct aim_session_t *sess, | 584 faim_export aim_conn_t *aim_select(aim_session_t *sess, struct timeval *timeout, int *status) |
579 struct timeval *timeout, | 585 { |
580 int *status) | 586 aim_conn_t *cur; |
581 { | 587 fd_set fds, wfds; |
582 struct aim_conn_t *cur; | 588 int maxfd, i, haveconnecting = 0; |
583 fd_set fds, wfds; | 589 |
584 int maxfd = 0; | 590 faim_mutex_lock(&sess->connlistlock); |
585 int i, haveconnecting = 0; | 591 if (!sess->connlist) { |
586 | 592 faim_mutex_unlock(&sess->connlistlock); |
587 faim_mutex_lock(&sess->connlistlock); | 593 *status = -1; |
588 if (sess->connlist == NULL) { | 594 return NULL; |
589 faim_mutex_unlock(&sess->connlistlock); | 595 } |
590 *status = -1; | |
591 return NULL; | |
592 } | |
593 faim_mutex_unlock(&sess->connlistlock); | |
594 | |
595 FD_ZERO(&fds); | |
596 FD_ZERO(&wfds); | |
597 maxfd = 0; | |
598 | |
599 faim_mutex_lock(&sess->connlistlock); | |
600 for (cur = sess->connlist; cur; cur = cur->next) { | |
601 if (cur->fd == -1) { | |
602 /* don't let invalid/dead connections sit around */ | |
603 *status = 2; | |
604 faim_mutex_unlock(&sess->connlistlock); | |
605 return cur; | |
606 } else if (cur->status & AIM_CONN_STATUS_INPROGRESS) { | |
607 FD_SET(cur->fd, &wfds); | |
608 | |
609 haveconnecting++; | |
610 } | |
611 FD_SET(cur->fd, &fds); | |
612 if (cur->fd > maxfd) | |
613 maxfd = cur->fd; | |
614 } | |
615 faim_mutex_unlock(&sess->connlistlock); | |
616 | |
617 /* | |
618 * If we have data waiting to be sent, return | |
619 * | |
620 * We have to not do this if theres at least one | |
621 * connection thats still connecting, since that connection | |
622 * may have queued data and this return would prevent | |
623 * the connection from ever completing! This is a major | |
624 * inadequacy of the libfaim way of doing things. It means | |
625 * that nothing can transmit as long as there's connecting | |
626 * sockets. Evil. | |
627 * | |
628 * But its still better than having blocking connects. | |
629 * | |
630 */ | |
631 if (!haveconnecting && (sess->queue_outgoing != NULL)) { | |
632 *status = 1; | |
633 return NULL; | |
634 } | |
635 | |
636 if ((i = select(maxfd+1, &fds, &wfds, NULL, timeout))>=1) { | |
637 faim_mutex_lock(&sess->connlistlock); | |
638 for (cur = sess->connlist; cur; cur = cur->next) { | |
639 if ((FD_ISSET(cur->fd, &fds)) || | |
640 ((cur->status & AIM_CONN_STATUS_INPROGRESS) && | |
641 FD_ISSET(cur->fd, &wfds))) { | |
642 *status = 2; | |
643 faim_mutex_unlock(&sess->connlistlock); | 596 faim_mutex_unlock(&sess->connlistlock); |
644 return cur; /* XXX race condition here -- shouldnt unlock connlist */ | 597 |
645 } | 598 FD_ZERO(&fds); |
646 } | 599 FD_ZERO(&wfds); |
647 *status = 0; /* shouldn't happen */ | 600 |
648 } else if ((i == -1) && (errno == EINTR)) /* treat interrupts as a timeout */ | 601 faim_mutex_lock(&sess->connlistlock); |
649 *status = 0; | 602 for (cur = sess->connlist, maxfd = 0; cur; cur = cur->next) { |
650 else | 603 if (cur->fd == -1) { |
651 *status = i; /* can be 0 or -1 */ | 604 /* don't let invalid/dead connections sit around */ |
652 | 605 *status = 2; |
653 faim_mutex_unlock(&sess->connlistlock); | 606 faim_mutex_unlock(&sess->connlistlock); |
654 | 607 return cur; |
655 return NULL; /* no waiting or error, return */ | 608 } else if (cur->status & AIM_CONN_STATUS_INPROGRESS) { |
656 } | 609 FD_SET(cur->fd, &wfds); |
657 | 610 |
658 /** | 611 haveconnecting++; |
659 * aim_conn_isready - Test if a connection is marked ready | 612 } |
660 * @conn: Connection to test | 613 FD_SET(cur->fd, &fds); |
661 * | 614 if (cur->fd > maxfd) |
662 * Returns true if the connection is ready, false otherwise. | 615 maxfd = cur->fd; |
663 * Returns -1 if the connection is invalid. | 616 } |
664 * | 617 faim_mutex_unlock(&sess->connlistlock); |
665 * XXX: This is deprecated. | 618 |
666 * | 619 /* |
667 */ | 620 * If we have data waiting to be sent, return |
668 faim_export int aim_conn_isready(struct aim_conn_t *conn) | 621 * |
669 { | 622 * We have to not do this if theres at least one |
670 if (conn) | 623 * connection thats still connecting, since that connection |
671 return (conn->status & 0x0001); | 624 * may have queued data and this return would prevent |
672 return -1; | 625 * the connection from ever completing! This is a major |
673 } | 626 * inadequacy of the libfaim way of doing things. It means |
674 | 627 * that nothing can transmit as long as there's connecting |
675 /** | 628 * sockets. Evil. |
676 * aim_conn_setstatus - Set the status of a connection | 629 * |
677 * @conn: Connection | 630 * But its still better than having blocking connects. |
678 * @status: New status | 631 * |
679 * | 632 */ |
680 * @newstatus is %XOR'd with the previous value of the connection | 633 if (!haveconnecting && sess->queue_outgoing) { |
681 * status and returned. Returns -1 if the connection is invalid. | 634 *status = 1; |
682 * | 635 return NULL; |
683 * This isn't real useful. | 636 } |
684 * | 637 |
685 */ | 638 if ((i = select(maxfd+1, &fds, &wfds, NULL, timeout))>=1) { |
686 faim_export int aim_conn_setstatus(struct aim_conn_t *conn, int status) | 639 faim_mutex_lock(&sess->connlistlock); |
687 { | 640 for (cur = sess->connlist; cur; cur = cur->next) { |
688 int val; | 641 if ((FD_ISSET(cur->fd, &fds)) || |
689 | 642 ((cur->status & AIM_CONN_STATUS_INPROGRESS) && |
690 if (!conn) | 643 FD_ISSET(cur->fd, &wfds))) { |
691 return -1; | 644 *status = 2; |
692 | 645 faim_mutex_unlock(&sess->connlistlock); |
693 faim_mutex_lock(&conn->active); | 646 return cur; /* XXX race condition here -- shouldnt unlock connlist */ |
694 val = conn->status ^= status; | 647 } |
695 faim_mutex_unlock(&conn->active); | 648 } |
696 | 649 *status = 0; /* shouldn't happen */ |
697 return val; | 650 } else if ((i == -1) && (errno == EINTR)) /* treat interrupts as a timeout */ |
651 *status = 0; | |
652 else | |
653 *status = i; /* can be 0 or -1 */ | |
654 | |
655 faim_mutex_unlock(&sess->connlistlock); | |
656 | |
657 return NULL; /* no waiting or error, return */ | |
698 } | 658 } |
699 | 659 |
700 /** | 660 /** |
701 * aim_conn_setlatency - Set a forced latency value for connection | 661 * aim_conn_setlatency - Set a forced latency value for connection |
702 * @conn: Conn to set latency for | 662 * @conn: Conn to set latency for |
709 * | 669 * |
710 * XXX: This should really be replaced with something that scales and | 670 * XXX: This should really be replaced with something that scales and |
711 * backs off like the real rate limiting does. | 671 * backs off like the real rate limiting does. |
712 * | 672 * |
713 */ | 673 */ |
714 faim_export int aim_conn_setlatency(struct aim_conn_t *conn, int newval) | 674 faim_export int aim_conn_setlatency(aim_conn_t *conn, int newval) |
715 { | 675 { |
716 if (!conn) | 676 |
717 return -1; | 677 if (!conn) |
718 | 678 return -1; |
719 faim_mutex_lock(&conn->active); | 679 |
720 conn->forcedlatency = newval; | 680 faim_mutex_lock(&conn->active); |
721 conn->lastactivity = 0; /* reset this just to make sure */ | 681 conn->forcedlatency = newval; |
722 faim_mutex_unlock(&conn->active); | 682 conn->lastactivity = 0; /* reset this just to make sure */ |
723 | 683 faim_mutex_unlock(&conn->active); |
724 return 0; | 684 |
685 return 0; | |
725 } | 686 } |
726 | 687 |
727 /** | 688 /** |
728 * aim_setupproxy - Configure a proxy for this session | 689 * aim_setupproxy - Configure a proxy for this session |
729 * @sess: Session to set proxy for | 690 * @sess: Session to set proxy for |
736 * args, it will clear out a previously set proxy. | 697 * args, it will clear out a previously set proxy. |
737 * | 698 * |
738 * Set username and password to %NULL if not applicable. | 699 * Set username and password to %NULL if not applicable. |
739 * | 700 * |
740 */ | 701 */ |
741 faim_export void aim_setupproxy(struct aim_session_t *sess, char *server, char *username, char *password) | 702 faim_export void aim_setupproxy(aim_session_t *sess, const char *server, const char *username, const char *password) |
742 { | 703 { |
743 /* clear out the proxy info */ | 704 /* clear out the proxy info */ |
744 if (!server || !strlen(server)) { | 705 if (!server || !strlen(server)) { |
745 memset(sess->socksproxy.server, 0, sizeof(sess->socksproxy.server)); | 706 memset(sess->socksproxy.server, 0, sizeof(sess->socksproxy.server)); |
746 memset(sess->socksproxy.username, 0, sizeof(sess->socksproxy.username)); | 707 memset(sess->socksproxy.username, 0, sizeof(sess->socksproxy.username)); |
747 memset(sess->socksproxy.password, 0, sizeof(sess->socksproxy.password)); | 708 memset(sess->socksproxy.password, 0, sizeof(sess->socksproxy.password)); |
748 return; | 709 return; |
749 } | 710 } |
750 | 711 |
751 strncpy(sess->socksproxy.server, server, sizeof(sess->socksproxy.server)); | 712 strncpy(sess->socksproxy.server, server, sizeof(sess->socksproxy.server)); |
752 if (username && strlen(username)) | 713 if (username && strlen(username)) |
753 strncpy(sess->socksproxy.username, username, sizeof(sess->socksproxy.username)); | 714 strncpy(sess->socksproxy.username, username, sizeof(sess->socksproxy.username)); |
754 if (password && strlen(password)) | 715 if (password && strlen(password)) |
755 strncpy(sess->socksproxy.password, password, sizeof(sess->socksproxy.password)); | 716 strncpy(sess->socksproxy.password, password, sizeof(sess->socksproxy.password)); |
756 return; | 717 |
757 } | 718 return; |
758 | 719 } |
759 static void defaultdebugcb(struct aim_session_t *sess, int level, const char *format, va_list va) | 720 |
760 { | 721 static void defaultdebugcb(aim_session_t *sess, int level, const char *format, va_list va) |
761 vfprintf(stderr, format, va); | 722 { |
723 | |
724 vfprintf(stderr, format, va); | |
725 | |
726 return; | |
762 } | 727 } |
763 | 728 |
764 /** | 729 /** |
765 * aim_session_init - Initializes a session structure | 730 * aim_session_init - Initializes a session structure |
766 * @sess: Session to initialize | 731 * @sess: Session to initialize |
768 * @debuglevel: Level of debugging output (zero is least) | 733 * @debuglevel: Level of debugging output (zero is least) |
769 * | 734 * |
770 * Sets up the initial values for a session. | 735 * Sets up the initial values for a session. |
771 * | 736 * |
772 */ | 737 */ |
773 faim_export void aim_session_init(struct aim_session_t *sess, unsigned long flags, int debuglevel) | 738 faim_export void aim_session_init(aim_session_t *sess, fu32_t flags, int debuglevel) |
774 { | 739 { |
775 if (!sess) | 740 |
776 return; | 741 if (!sess) |
777 | 742 return; |
778 memset(sess, 0, sizeof(struct aim_session_t)); | 743 |
779 aim_connrst(sess); | 744 memset(sess, 0, sizeof(aim_session_t)); |
780 sess->queue_outgoing = NULL; | 745 aim_connrst(sess); |
781 sess->queue_incoming = NULL; | 746 sess->queue_outgoing = NULL; |
782 sess->pendingjoin = NULL; | 747 sess->queue_incoming = NULL; |
783 sess->pendingjoinexchange = 0; | 748 sess->pendingjoin = NULL; |
784 aim_initsnachash(sess); | 749 sess->pendingjoinexchange = 0; |
785 sess->msgcookies = NULL; | 750 aim_initsnachash(sess); |
786 sess->snac_nextid = 0x00000001; | 751 sess->msgcookies = NULL; |
787 | 752 sess->snacid_next = 0x00000001; |
788 sess->flags = 0; | 753 |
789 sess->debug = debuglevel; | 754 sess->flags = 0; |
790 sess->debugcb = defaultdebugcb; | 755 sess->debug = debuglevel; |
791 | 756 sess->debugcb = defaultdebugcb; |
792 sess->modlistv = NULL; | 757 |
793 | 758 sess->modlistv = NULL; |
794 /* | 759 |
795 * Default to SNAC login unless XORLOGIN is explicitly set. | 760 /* |
796 */ | 761 * Default to SNAC login unless XORLOGIN is explicitly set. |
797 if (!(flags & AIM_SESS_FLAGS_XORLOGIN)) | 762 */ |
798 sess->flags |= AIM_SESS_FLAGS_SNACLOGIN; | 763 if (!(flags & AIM_SESS_FLAGS_XORLOGIN)) |
799 sess->flags |= flags; | 764 sess->flags |= AIM_SESS_FLAGS_SNACLOGIN; |
800 | 765 sess->flags |= flags; |
801 /* | 766 |
802 * This must always be set. Default to the queue-based | 767 /* |
803 * version for back-compatibility. | 768 * This must always be set. Default to the queue-based |
804 */ | 769 * version for back-compatibility. |
805 aim_tx_setenqueue(sess, AIM_TX_QUEUED, NULL); | 770 */ |
806 | 771 aim_tx_setenqueue(sess, AIM_TX_QUEUED, NULL); |
807 | 772 |
808 /* | 773 |
809 * Register all the modules for this session... | 774 /* |
810 */ | 775 * Register all the modules for this session... |
811 aim__registermodule(sess, misc_modfirst); /* load the catch-all first */ | 776 */ |
812 aim__registermodule(sess, buddylist_modfirst); | 777 aim__registermodule(sess, misc_modfirst); /* load the catch-all first */ |
813 aim__registermodule(sess, admin_modfirst); | 778 aim__registermodule(sess, buddylist_modfirst); |
814 aim__registermodule(sess, bos_modfirst); | 779 aim__registermodule(sess, admin_modfirst); |
815 aim__registermodule(sess, search_modfirst); | 780 aim__registermodule(sess, bos_modfirst); |
816 aim__registermodule(sess, stats_modfirst); | 781 aim__registermodule(sess, search_modfirst); |
817 aim__registermodule(sess, auth_modfirst); | 782 aim__registermodule(sess, stats_modfirst); |
818 aim__registermodule(sess, msg_modfirst); | 783 aim__registermodule(sess, auth_modfirst); |
819 aim__registermodule(sess, chatnav_modfirst); | 784 aim__registermodule(sess, msg_modfirst); |
820 aim__registermodule(sess, chat_modfirst); | 785 aim__registermodule(sess, chatnav_modfirst); |
821 aim__registermodule(sess, locate_modfirst); | 786 aim__registermodule(sess, chat_modfirst); |
822 aim__registermodule(sess, general_modfirst); | 787 aim__registermodule(sess, locate_modfirst); |
823 | 788 aim__registermodule(sess, general_modfirst); |
824 return; | 789 |
790 return; | |
825 } | 791 } |
826 | 792 |
827 /** | 793 /** |
828 * aim_session_kill - Deallocate a session | 794 * aim_session_kill - Deallocate a session |
829 * @sess: Session to kill | 795 * @sess: Session to kill |
830 * | 796 * |
831 * | 797 */ |
832 */ | 798 faim_export void aim_session_kill(aim_session_t *sess) |
833 faim_export void aim_session_kill(struct aim_session_t *sess) | 799 { |
834 { | 800 |
835 | 801 aim_logoff(sess); |
836 aim_logoff(sess); | 802 |
837 | 803 aim__shutdownmodules(sess); |
838 aim__shutdownmodules(sess); | 804 |
839 | 805 return; |
840 return; | |
841 } | 806 } |
842 | 807 |
843 /** | 808 /** |
844 * aim_setdebuggingcb - Set the function to call when outputting debugging info | 809 * aim_setdebuggingcb - Set the function to call when outputting debugging info |
845 * @sess: Session to change | 810 * @sess: Session to change |
848 * The function specified is called whenever faimdprintf() is used within | 813 * The function specified is called whenever faimdprintf() is used within |
849 * libfaim, and the session's debugging level is greater tha nor equal to | 814 * libfaim, and the session's debugging level is greater tha nor equal to |
850 * the value faimdprintf was called with. | 815 * the value faimdprintf was called with. |
851 * | 816 * |
852 */ | 817 */ |
853 faim_export int aim_setdebuggingcb(struct aim_session_t *sess, faim_debugging_callback_t cb) | 818 faim_export int aim_setdebuggingcb(aim_session_t *sess, faim_debugging_callback_t cb) |
854 { | 819 { |
855 | 820 |
856 if (!sess) | 821 if (!sess) |
857 return -1; | 822 return -1; |
858 | 823 |
859 sess->debugcb = cb; | 824 sess->debugcb = cb; |
860 | 825 |
861 return 0; | 826 return 0; |
862 } | 827 } |
863 | 828 |
864 /** | 829 /** |
865 * aim_conn_isconnecting - Determine if a connection is connecting | 830 * aim_conn_isconnecting - Determine if a connection is connecting |
866 * @conn: Connection to examine | 831 * @conn: Connection to examine |
868 * Returns nonzero if the connection is in the process of | 833 * Returns nonzero if the connection is in the process of |
869 * connecting (or if it just completed and aim_conn_completeconnect() | 834 * connecting (or if it just completed and aim_conn_completeconnect() |
870 * has yet to be called on it). | 835 * has yet to be called on it). |
871 * | 836 * |
872 */ | 837 */ |
873 faim_export int aim_conn_isconnecting(struct aim_conn_t *conn) | 838 faim_export int aim_conn_isconnecting(aim_conn_t *conn) |
874 { | 839 { |
875 if (!conn) | 840 |
876 return 0; | 841 if (!conn) |
877 return (conn->status & AIM_CONN_STATUS_INPROGRESS)?1:0; | 842 return 0; |
878 } | 843 |
879 | 844 return !!(conn->status & AIM_CONN_STATUS_INPROGRESS); |
880 faim_export int aim_conn_completeconnect(struct aim_session_t *sess, struct aim_conn_t *conn) | 845 } |
881 { | 846 |
882 fd_set fds, wfds; | 847 /* |
883 struct timeval tv; | 848 * XXX this is nearly as ugly as proxyconnect(). |
884 int res, error = ETIMEDOUT; | 849 */ |
885 aim_rxcallback_t userfunc; | 850 faim_export int aim_conn_completeconnect(aim_session_t *sess, aim_conn_t *conn) |
886 | 851 { |
887 if (!conn || (conn->fd == -1)) | 852 fd_set fds, wfds; |
888 return -1; | 853 struct timeval tv; |
889 | 854 int res, error = ETIMEDOUT; |
890 if (!(conn->status & AIM_CONN_STATUS_INPROGRESS)) | 855 aim_rxcallback_t userfunc; |
891 return -1; | 856 |
892 | 857 if (!conn || (conn->fd == -1)) |
893 FD_ZERO(&fds); | 858 return -1; |
894 FD_SET(conn->fd, &fds); | 859 |
895 FD_ZERO(&wfds); | 860 if (!(conn->status & AIM_CONN_STATUS_INPROGRESS)) |
896 FD_SET(conn->fd, &wfds); | 861 return -1; |
897 tv.tv_sec = 0; | 862 |
898 tv.tv_usec = 0; | 863 FD_ZERO(&fds); |
899 | 864 FD_SET(conn->fd, &fds); |
900 if ((res = select(conn->fd+1, &fds, &wfds, NULL, &tv)) == -1) { | 865 FD_ZERO(&wfds); |
901 error = errno; | 866 FD_SET(conn->fd, &wfds); |
902 aim_conn_close(conn); | 867 tv.tv_sec = 0; |
903 errno = error; | 868 tv.tv_usec = 0; |
904 return -1; | 869 |
905 } else if (res == 0) { | 870 if ((res = select(conn->fd+1, &fds, &wfds, NULL, &tv)) == -1) { |
906 faimdprintf(sess, 0, "aim_conn_completeconnect: false alarm on %d\n", conn->fd); | 871 error = errno; |
907 return 0; /* hasn't really completed yet... */ | 872 aim_conn_close(conn); |
908 } | 873 errno = error; |
909 | 874 return -1; |
910 if (FD_ISSET(conn->fd, &fds) || FD_ISSET(conn->fd, &wfds)) { | 875 } else if (res == 0) { |
911 int len = sizeof(error); | 876 faimdprintf(sess, 0, "aim_conn_completeconnect: false alarm on %d\n", conn->fd); |
912 | 877 return 0; /* hasn't really completed yet... */ |
913 if (getsockopt(conn->fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) | 878 } |
914 error = errno; | 879 |
915 } | 880 if (FD_ISSET(conn->fd, &fds) || FD_ISSET(conn->fd, &wfds)) { |
916 | 881 int len = sizeof(error); |
917 if (error) { | 882 |
918 aim_conn_close(conn); | 883 if (getsockopt(conn->fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) |
919 errno = error; | 884 error = errno; |
920 return -1; | 885 } |
921 } | 886 |
922 | 887 if (error) { |
923 fcntl(conn->fd, F_SETFL, 0); /* XXX should restore original flags */ | 888 aim_conn_close(conn); |
924 | 889 errno = error; |
925 conn->status &= ~AIM_CONN_STATUS_INPROGRESS; | 890 return -1; |
926 | 891 } |
927 if ((userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE))) | 892 |
928 userfunc(sess, NULL, conn); | 893 fcntl(conn->fd, F_SETFL, 0); /* XXX should restore original flags */ |
929 | 894 |
930 /* Flush out the queues if there was something waiting for this conn */ | 895 conn->status &= ~AIM_CONN_STATUS_INPROGRESS; |
931 aim_tx_flushqueue(sess); | 896 |
932 | 897 if ((userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE))) |
933 return 0; | 898 userfunc(sess, NULL, conn); |
934 } | 899 |
935 | 900 /* Flush out the queues if there was something waiting for this conn */ |
936 faim_export struct aim_session_t *aim_conn_getsess(struct aim_conn_t *conn) | 901 aim_tx_flushqueue(sess); |
937 { | 902 |
938 | 903 return 0; |
939 if (!conn) | 904 } |
940 return NULL; | 905 |
941 | 906 faim_export aim_session_t *aim_conn_getsess(aim_conn_t *conn) |
942 return (struct aim_session_t *)conn->sessv; | 907 { |
908 | |
909 if (!conn) | |
910 return NULL; | |
911 | |
912 return (aim_session_t *)conn->sessv; | |
943 } | 913 } |
944 | 914 |
945 /* | 915 /* |
946 * aim_logoff() | 916 * aim_logoff() |
947 * | 917 * |
948 * Closes -ALL- open connections. | 918 * Closes -ALL- open connections. |
949 * | 919 * |
950 */ | 920 */ |
951 faim_export int aim_logoff(struct aim_session_t *sess) | 921 faim_export int aim_logoff(aim_session_t *sess) |
952 { | 922 { |
953 | 923 |
954 aim_connrst(sess); /* in case we want to connect again */ | 924 aim_connrst(sess); /* in case we want to connect again */ |
955 | 925 |
956 return 0; | 926 return 0; |
957 | 927 |
958 } | 928 } |
959 | 929 |