comparison src/proxy.c @ 1840:00aef397a1fe

[gaim-migrate @ 1850] reworked some of the proxy stuff so that it's non-blocking now. next thing to do is to get IRC, MSN, Napster, and Jabber to use the new proxy_connect code. After that, Oscar and Yahoo (maybe Zephyr too? not likely) committer: Tailor Script <tailor@pidgin.im>
author Eric Warmenhoven <eric@warmenhoven.org>
date Sat, 12 May 2001 01:38:04 +0000
parents b4d454e5ee31
children 4dbd8533d209
comparison
equal deleted inserted replaced
1839:109cacf1ff97 1840:00aef397a1fe
32 #include <sys/types.h> 32 #include <sys/types.h>
33 #include <sys/socket.h> 33 #include <sys/socket.h>
34 #include <netdb.h> 34 #include <netdb.h>
35 #include <netinet/in.h> 35 #include <netinet/in.h>
36 #include <unistd.h> 36 #include <unistd.h>
37 #include <fcntl.h>
38 #include <errno.h>
37 #include <gtk/gtk.h> 39 #include <gtk/gtk.h>
38 #include "gaim.h" 40 #include "gaim.h"
39 #include "proxy.h" 41 #include "proxy.h"
40 42
41 static int proxy_connect_none(char *host, unsigned short port) 43 struct PHB {
44 GdkInputFunction func;
45 gpointer data;
46 char *host;
47 int port;
48 gint inpa;
49 };
50
51 static void no_one_calls(gpointer data, gint source, GdkInputCondition cond)
52 {
53 struct PHB *phb = data;
54 int len, error = ETIMEDOUT;
55 debug_printf("Connected\n");
56 len = sizeof(error);
57 if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
58 close(source);
59 gdk_input_remove(phb->inpa);
60 phb->func(phb->data, -1, GDK_INPUT_READ);
61 g_free(phb);
62 return;
63 }
64 fcntl(source, F_SETFL, 0);
65 gdk_input_remove(phb->inpa);
66 phb->func(phb->data, source, GDK_INPUT_READ);
67 g_free(phb);
68 }
69
70 static int proxy_connect_none(char *host, unsigned short port, struct PHB *phb)
42 { 71 {
43 struct sockaddr_in sin; 72 struct sockaddr_in sin;
44 struct hostent *hp; 73 struct hostent *hp;
45 int fd = -1; 74 int fd = -1;
46 75
47 debug_printf("connecting to %s:%d with no proxy\n", host, port); 76 debug_printf("connecting to %s:%d with no proxy\n", host, port);
48 77
49 if (!(hp = gethostbyname(host))) 78 if (!(hp = gethostbyname(host))) {
50 return -1; 79 g_free(phb);
80 return -1;
81 }
51 82
52 memset(&sin, 0, sizeof(struct sockaddr_in)); 83 memset(&sin, 0, sizeof(struct sockaddr_in));
53 memcpy(&sin.sin_addr.s_addr, hp->h_addr, hp->h_length); 84 memcpy(&sin.sin_addr.s_addr, hp->h_addr, hp->h_length);
54 sin.sin_family = hp->h_addrtype; 85 sin.sin_family = hp->h_addrtype;
55 sin.sin_port = htons(port); 86 sin.sin_port = htons(port);
56 87
57 if ((fd = socket(hp->h_addrtype, SOCK_STREAM, 0)) < 0) 88 if ((fd = socket(hp->h_addrtype, SOCK_STREAM, 0)) < 0) {
58 return -1; 89 g_free(phb);
59 90 return -1;
91 }
92
93 fcntl(fd, F_SETFL, O_NONBLOCK);
60 if (connect(fd, (struct sockaddr *)&sin, sizeof(sin)) < 0) { 94 if (connect(fd, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
61 close(fd); 95 if ((errno == EINPROGRESS) || (errno == EINTR)) {
62 return -1; 96 debug_printf("Connect would have blocked\n");
97 phb->inpa = gdk_input_add(fd, GDK_INPUT_WRITE, no_one_calls, phb);
98 } else {
99 close(fd);
100 g_free(phb);
101 return -1;
102 }
103 } else {
104 int len, error = ETIMEDOUT;
105 debug_printf("Connect didn't block\n");
106 len = sizeof(error);
107 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
108 close(fd);
109 g_free(phb);
110 return -1;
111 }
112 fcntl(fd, F_SETFL, 0);
113 phb->func(phb->data, fd, GDK_INPUT_READ);
114 g_free(phb);
63 } 115 }
64 116
65 return fd; 117 return fd;
66 } 118 }
67 119
68 #define HTTP_GOODSTRING "HTTP/1.0 200 Connection established" 120 #define HTTP_GOODSTRING "HTTP/1.0 200 Connection established"
69 #define HTTP_GOODSTRING2 "HTTP/1.1 200 Connection established" 121 #define HTTP_GOODSTRING2 "HTTP/1.1 200 Connection established"
70 122
71 static int proxy_connect_http(char *host, unsigned short port, char *proxyhost, unsigned short proxyport) 123 static void http_canread(gpointer data, gint source, GdkInputCondition cond)
124 {
125 int nlc = 0;
126 int pos = 0;
127 struct PHB *phb = data;
128 char inputline[8192];
129
130 gdk_input_remove(phb->inpa);
131
132 while ((nlc != 2) && (read(source, &inputline[pos++], 1) == 1)) {
133 if (inputline[pos-1] == '\n')
134 nlc++;
135 else if (inputline[pos-1] != '\r')
136 nlc = 0;
137 }
138 inputline[pos] = '\0';
139
140 debug_printf("Proxy says: %s\n", inputline);
141
142 if ((memcmp(HTTP_GOODSTRING , inputline, strlen(HTTP_GOODSTRING )) == 0) ||
143 (memcmp(HTTP_GOODSTRING2, inputline, strlen(HTTP_GOODSTRING2)) == 0)) {
144 phb->func(phb->data, source, GDK_INPUT_READ);
145 g_free(phb->host);
146 g_free(phb);
147 return;
148 }
149
150 close(source);
151 phb->func(phb->data, -1, GDK_INPUT_READ);
152 g_free(phb->host);
153 g_free(phb);
154 return;
155 }
156
157 static void http_canwrite(gpointer data, gint source, GdkInputCondition cond)
158 {
159 char cmd[384];
160 struct PHB *phb = data;
161 int len, error = ETIMEDOUT;
162 debug_printf("Connected\n");
163 if (phb->inpa > 0)
164 gdk_input_remove(phb->inpa);
165 len = sizeof(error);
166 if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
167 close(source);
168 phb->func(phb->data, -1, GDK_INPUT_READ);
169 g_free(phb->host);
170 g_free(phb);
171 return;
172 }
173 fcntl(source, F_SETFL, 0);
174
175 snprintf(cmd, sizeof(cmd), "CONNECT %s:%d HTTP/1.1\r\n\r\n", phb->host, phb->port);
176 if (send(source, cmd, strlen(cmd), 0) < 0) {
177 close(source);
178 phb->func(phb->data, -1, GDK_INPUT_READ);
179 g_free(phb->host);
180 g_free(phb);
181 return;
182 }
183
184 phb->inpa = gdk_input_add(source, GDK_INPUT_READ, http_canread, phb);
185 }
186
187 static int proxy_connect_http(char *host, unsigned short port,
188 char *proxyhost, unsigned short proxyport,
189 struct PHB *phb)
72 { 190 {
73 struct hostent *hp; 191 struct hostent *hp;
74 struct sockaddr_in sin; 192 struct sockaddr_in sin;
75 int fd = -1; 193 int fd = -1;
76 char cmd[384];
77 char inputline[8192];
78 int nlc = 0;
79 int pos = 0;
80 194
81 debug_printf("connecting to %s:%d via %s:%d using HTTP\n", host, port, proxyhost, proxyport); 195 debug_printf("connecting to %s:%d via %s:%d using HTTP\n", host, port, proxyhost, proxyport);
82 196
83 if (!(hp = gethostbyname(proxyhost))) 197 if (!(hp = gethostbyname(proxyhost))) {
84 return -1; 198 g_free(phb);
199 return -1;
200 }
85 201
86 memset(&sin, 0, sizeof(struct sockaddr_in)); 202 memset(&sin, 0, sizeof(struct sockaddr_in));
87 memcpy(&sin.sin_addr.s_addr, hp->h_addr, hp->h_length); 203 memcpy(&sin.sin_addr.s_addr, hp->h_addr, hp->h_length);
88 sin.sin_family = hp->h_addrtype; 204 sin.sin_family = hp->h_addrtype;
89 sin.sin_port = htons(proxyport); 205 sin.sin_port = htons(proxyport);
90 206
91 if ((fd = socket(hp->h_addrtype, SOCK_STREAM, 0)) < 0) 207 if ((fd = socket(hp->h_addrtype, SOCK_STREAM, 0)) < 0) {
92 return -1; 208 g_free(phb);
93 209 return -1;
210 }
211
212 phb->host = g_strdup(host);
213 phb->port = port;
214
215 fcntl(fd, F_SETFL, O_NONBLOCK);
94 if (connect(fd, (struct sockaddr *)&sin, sizeof(sin)) < 0) { 216 if (connect(fd, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
95 close(fd); 217 if ((errno == EINPROGRESS) || (errno == EINTR)) {
96 return -1; 218 debug_printf("Connect would have blocked\n");
97 } 219 phb->inpa = gdk_input_add(fd, GDK_INPUT_WRITE, http_canwrite, phb);
98 220 } else {
99 snprintf(cmd, sizeof(cmd), "CONNECT %s:%d HTTP/1.1\r\n\r\n", host, port); 221 close(fd);
100 222 g_free(phb->host);
101 if (send(fd, cmd, strlen(cmd), 0) < 0) { 223 g_free(phb);
102 close(fd); 224 return -1;
103 return -1; 225 }
104 } 226 } else {
105 while ((nlc != 2) && (read(fd, &inputline[pos++], 1) == 1)) { 227 int len, error = ETIMEDOUT;
106 if (inputline[pos-1] == '\n') 228 debug_printf("Connect didn't block\n");
107 nlc++; 229 len = sizeof(error);
108 else if (inputline[pos-1] != '\r') 230 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
109 nlc = 0; 231 close(fd);
110 } 232 g_free(phb->host);
111 233 g_free(phb);
112 debug_printf("Proxy says: %s\n", inputline); 234 return -1;
113 235 }
114 if ((memcmp(HTTP_GOODSTRING, inputline, strlen(HTTP_GOODSTRING)) == 0) || 236 fcntl(fd, F_SETFL, 0);
115 (memcmp(HTTP_GOODSTRING2, inputline, strlen(HTTP_GOODSTRING2)) == 0)) { 237 http_canwrite(phb, fd, GDK_INPUT_WRITE);
116 return fd; 238 }
117 } 239
118 240 return fd;
119 close(fd); 241 }
120 return -1; 242
121 } 243 static void s4_canread(gpointer data, gint source, GdkInputCondition cond)
122 244 {
123 static int proxy_connect_socks4(char *host, unsigned short port, 245 unsigned char packet[12];
124 char *proxyhost, unsigned short proxyport) 246 struct PHB *phb = data;
125 { 247
126 struct sockaddr_in sin; 248 gdk_input_remove(phb->inpa);
249
250 memset(packet, 0, sizeof(packet));
251 if (read(source, packet, 9) >= 4 && packet[1] == 90) {
252 phb->func(phb->data, source, GDK_INPUT_READ);
253 g_free(phb->host);
254 g_free(phb);
255 return;
256 }
257
258 close(source);
259 phb->func(phb->data, -1, GDK_INPUT_READ);
260 g_free(phb->host);
261 g_free(phb);
262 }
263
264 static void s4_canwrite(gpointer data, gint source, GdkInputCondition cond)
265 {
127 unsigned char packet[12]; 266 unsigned char packet[12];
128 struct hostent *hp; 267 struct hostent *hp;
129 int fd = -1; 268 struct PHB *phb = data;
130 269 int len, error = ETIMEDOUT;
131 debug_printf("connecting to %s:%d via %s:%d using SOCKS4\n", host, port, proxyhost, proxyport); 270 debug_printf("Connected\n");
132 271 if (phb->inpa > 0)
133 if (!(hp = gethostbyname(proxyhost))) 272 gdk_input_remove(phb->inpa);
134 return -1; 273 len = sizeof(error);
135 274 if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
136 memset(&sin, 0, sizeof(struct sockaddr_in)); 275 close(source);
137 memcpy(&sin.sin_addr.s_addr, hp->h_addr, hp->h_length); 276 phb->func(phb->data, -1, GDK_INPUT_READ);
138 sin.sin_family = hp->h_addrtype; 277 g_free(phb->host);
139 sin.sin_port = htons(proxyport); 278 g_free(phb);
140 279 return;
141 if ((fd = socket(hp->h_addrtype, SOCK_STREAM, 0)) < 0) 280 }
142 return -1; 281 fcntl(source, F_SETFL, 0);
143
144 if (connect(fd, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
145 close(fd);
146 return -1;
147 }
148 282
149 /* XXX does socks4 not support host name lookups by the proxy? */ 283 /* XXX does socks4 not support host name lookups by the proxy? */
150 if (!(hp = gethostbyname(host))) 284 if (!(hp = gethostbyname(phb->host))) {
151 return -1; 285 close(source);
286 phb->func(phb->data, -1, GDK_INPUT_READ);
287 g_free(phb->host);
288 g_free(phb);
289 return;
290 }
152 291
153 packet[0] = 4; 292 packet[0] = 4;
154 packet[1] = 1; 293 packet[1] = 1;
155 packet[2] = port >> 8; 294 packet[2] = phb->port >> 8;
156 packet[3] = port & 0xff; 295 packet[3] = phb->port & 0xff;
157 packet[4] = (unsigned char)(hp->h_addr_list[0])[0]; 296 packet[4] = (unsigned char)(hp->h_addr_list[0])[0];
158 packet[5] = (unsigned char)(hp->h_addr_list[0])[1]; 297 packet[5] = (unsigned char)(hp->h_addr_list[0])[1];
159 packet[6] = (unsigned char)(hp->h_addr_list[0])[2]; 298 packet[6] = (unsigned char)(hp->h_addr_list[0])[2];
160 packet[7] = (unsigned char)(hp->h_addr_list[0])[3]; 299 packet[7] = (unsigned char)(hp->h_addr_list[0])[3];
161 packet[8] = 0; 300 packet[8] = 0;
162 if (write(fd, packet, 9) == 9) { 301 if (write(source, packet, 9) != 9) {
163 memset(packet, 0, sizeof(packet)); 302 close(source);
164 if (read(fd, packet, 9) >= 4 && packet[1] == 90) 303 phb->func(phb->data, -1, GDK_INPUT_READ);
165 return fd; 304 g_free(phb->host);
166 } 305 g_free(phb);
167 close(fd); 306 return;
168 307 }
169 return -1; 308
170 } 309 phb->inpa = gdk_input_add(source, GDK_INPUT_READ, s4_canread, phb);
171 310 }
172 static int proxy_connect_socks5(char *host, unsigned short port, 311
173 char *proxyhost, unsigned short proxyport) 312 static int proxy_connect_socks4(char *host, unsigned short port,
174 { 313 char *proxyhost, unsigned short proxyport,
175 int i, fd = -1; 314 struct PHB *phb)
176 unsigned char buf[512]; 315 {
177 struct sockaddr_in sin; 316 struct sockaddr_in sin;
178 struct hostent *hp; 317 struct hostent *hp;
179 int hlen = strlen(host); 318 int fd = -1;
180 319
181 debug_printf("connecting to %s:%d via %s:%d using SOCKS5\n", host, port, proxyhost, proxyport); 320 debug_printf("connecting to %s:%d via %s:%d using SOCKS4\n", host, port, proxyhost, proxyport);
182 321
183 if (!(hp = gethostbyname(proxyhost))) 322 if (!(hp = gethostbyname(proxyhost))) {
184 return -1; 323 g_free(phb);
324 return -1;
325 }
185 326
186 memset(&sin, 0, sizeof(struct sockaddr_in)); 327 memset(&sin, 0, sizeof(struct sockaddr_in));
187 memcpy(&sin.sin_addr.s_addr, hp->h_addr, hp->h_length); 328 memcpy(&sin.sin_addr.s_addr, hp->h_addr, hp->h_length);
188 sin.sin_family = hp->h_addrtype; 329 sin.sin_family = hp->h_addrtype;
189 sin.sin_port = htons(proxyport); 330 sin.sin_port = htons(proxyport);
190 331
191 if ((fd = socket(hp->h_addrtype, SOCK_STREAM, 0)) < 0) 332 if ((fd = socket(hp->h_addrtype, SOCK_STREAM, 0)) < 0) {
192 return -1; 333 g_free(phb);
193 334 return -1;
335 }
336
337 phb->host = g_strdup(host);
338 phb->port = port;
339
340 fcntl(fd, F_SETFL, O_NONBLOCK);
194 if (connect(fd, (struct sockaddr *)&sin, sizeof(sin)) < 0) { 341 if (connect(fd, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
195 close(fd); 342 if ((errno == EINPROGRESS) || (errno == EINTR)) {
196 return -1; 343 debug_printf("Connect would have blocked\n");
197 } 344 phb->inpa = gdk_input_add(fd, GDK_INPUT_WRITE, s4_canwrite, phb);
345 } else {
346 close(fd);
347 g_free(phb->host);
348 g_free(phb);
349 return -1;
350 }
351 } else {
352 int len, error = ETIMEDOUT;
353 debug_printf("Connect didn't block\n");
354 len = sizeof(error);
355 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
356 close(fd);
357 g_free(phb->host);
358 g_free(phb);
359 return -1;
360 }
361 fcntl(fd, F_SETFL, 0);
362 s4_canwrite(phb, fd, GDK_INPUT_WRITE);
363 }
364
365 return fd;
366 }
367
368 static void s5_canread_again(gpointer data, gint source, GdkInputCondition cond)
369 {
370 unsigned char buf[512];
371 struct PHB *phb = data;
372
373 gdk_input_remove(phb->inpa);
374 debug_printf("able to read again\n");
375
376 if (read(source, buf, 10) < 10) {
377 debug_printf("or not...\n");
378 close(source);
379 phb->func(phb->data, -1, GDK_INPUT_READ);
380 g_free(phb->host);
381 g_free(phb);
382 return;
383 }
384 if ((buf[0] != 0x05) || (buf[1] != 0x00)) {
385 debug_printf("bad data\n");
386 close(source);
387 phb->func(phb->data, -1, GDK_INPUT_READ);
388 g_free(phb->host);
389 g_free(phb);
390 return;
391 }
392
393 phb->func(phb->data, source, GDK_INPUT_READ);
394 g_free(phb->host);
395 g_free(phb);
396 return;
397 }
398
399 static void s5_canread(gpointer data, gint source, GdkInputCondition cond)
400 {
401 unsigned char buf[512];
402 struct PHB *phb = data;
403 int hlen = strlen(phb->host);
404
405 gdk_input_remove(phb->inpa);
406 debug_printf("able to read\n");
407
408 if (read(source, buf, 2) < 2) {
409 close(source);
410 phb->func(phb->data, -1, GDK_INPUT_READ);
411 g_free(phb->host);
412 g_free(phb);
413 return;
414 }
415
416 if ((buf[0] != 0x05) || (buf[1] == 0xff)) {
417 close(source);
418 phb->func(phb->data, -1, GDK_INPUT_READ);
419 g_free(phb->host);
420 g_free(phb);
421 return;
422 }
423
424 buf[0] = 0x05;
425 buf[1] = 0x01; /* CONNECT */
426 buf[2] = 0x00; /* reserved */
427 buf[3] = 0x03; /* address type -- host name */
428 buf[4] = hlen;
429 memcpy(buf + 5, phb->host, hlen);
430 buf[5 + strlen(phb->host)] = phb->port >> 8;
431 buf[5 + strlen(phb->host) + 1] = phb->port & 0xff;
432
433 if (write(source, buf, (5 + strlen(phb->host) + 2)) < (5 + strlen(phb->host) + 2)) {
434 close(source);
435 phb->func(phb->data, -1, GDK_INPUT_READ);
436 g_free(phb->host);
437 g_free(phb);
438 return;
439 }
440
441 phb->inpa = gdk_input_add(source, GDK_INPUT_READ, s5_canread_again, phb);
442 }
443
444 static void s5_canwrite(gpointer data, gint source, GdkInputCondition cond)
445 {
446 unsigned char buf[512];
447 int i;
448 struct PHB *phb = data;
449 int len, error = ETIMEDOUT;
450 debug_printf("Connected\n");
451 if (phb->inpa > 0)
452 gdk_input_remove(phb->inpa);
453 len = sizeof(error);
454 if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
455 close(source);
456 phb->func(phb->data, -1, GDK_INPUT_READ);
457 g_free(phb->host);
458 g_free(phb);
459 return;
460 }
461 fcntl(source, F_SETFL, 0);
198 462
199 i = 0; 463 i = 0;
200 buf[0] = 0x05; /* SOCKS version 5 */ 464 buf[0] = 0x05; /* SOCKS version 5 */
201 buf[1] = 0x01; 465 buf[1] = 0x01;
202 buf[2] = 0x00; 466 buf[2] = 0x00;
203 i = 3; 467 i = 3;
204 468
205 if (write(fd, buf, i) < i) { 469 if (write(source, buf, i) < i) {
206 close(fd); 470 debug_printf("unable to write\n");
207 return -1; 471 close(source);
208 } 472 phb->func(phb->data, -1, GDK_INPUT_READ);
209 473 g_free(phb->host);
210 if (read(fd, buf, 2) < 2) { 474 g_free(phb);
211 close(fd); 475 return;
212 return -1; 476 }
213 } 477
214 478 phb->inpa = gdk_input_add(source, GDK_INPUT_READ, s5_canread, phb);
215 if ((buf[0] != 0x05) || (buf[1] == 0xff)) { 479 }
216 close(fd); 480
217 return -1; 481 static int proxy_connect_socks5(char *host, unsigned short port,
218 } 482 char *proxyhost, unsigned short proxyport,
219 483 struct PHB *phb)
220 buf[0] = 0x05; 484 {
221 buf[1] = 0x01; /* CONNECT */ 485 int fd = -1;
222 buf[2] = 0x00; /* reserved */ 486 struct sockaddr_in sin;
223 buf[3] = 0x03; /* address type -- host name */ 487 struct hostent *hp;
224 buf[4] = hlen; 488
225 memcpy(buf + 5, host, hlen); 489 debug_printf("connecting to %s:%d via %s:%d using SOCKS5\n", host, port, proxyhost, proxyport);
226 buf[5 + strlen(host)] = port >> 8; 490
227 buf[5 + strlen(host) + 1] = port & 0xff; 491 if (!(hp = gethostbyname(proxyhost))) {
228 492 g_free(phb);
229 if (write(fd, buf, (5 + strlen(host) + 2)) < (5 + strlen(host) + 2)) { 493 return -1;
230 close(fd); 494 }
231 return -1; 495
232 } 496 memset(&sin, 0, sizeof(struct sockaddr_in));
233 if (read(fd, buf, 10) < 10) { 497 memcpy(&sin.sin_addr.s_addr, hp->h_addr, hp->h_length);
234 close(fd); 498 sin.sin_family = hp->h_addrtype;
235 return -1; 499 sin.sin_port = htons(proxyport);
236 } 500
237 if ((buf[0] != 0x05) || (buf[1] != 0x00)) { 501 if ((fd = socket(hp->h_addrtype, SOCK_STREAM, 0)) < 0) {
238 close(fd); 502 g_free(phb);
239 return -1; 503 return -1;
504 }
505
506 phb->host = g_strdup(host);
507 phb->port = port;
508
509 fcntl(fd, F_SETFL, O_NONBLOCK);
510 if (connect(fd, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
511 if ((errno == EINPROGRESS) || (errno == EINTR)) {
512 debug_printf("Connect would have blocked\n");
513 phb->inpa = gdk_input_add(fd, GDK_INPUT_WRITE, s5_canwrite, phb);
514 } else {
515 close(fd);
516 g_free(phb->host);
517 g_free(phb);
518 return -1;
519 }
520 } else {
521 int len, error = ETIMEDOUT;
522 debug_printf("Connect didn't block\n");
523 len = sizeof(error);
524 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
525 close(fd);
526 g_free(phb->host);
527 g_free(phb);
528 return -1;
529 }
530 fcntl(fd, F_SETFL, 0);
531 s5_canwrite(phb, fd, GDK_INPUT_WRITE);
240 } 532 }
241 533
242 return fd; 534 return fd;
243 } 535 }
244 536
245 int proxy_connect(char *host, int port, char *proxyhost, int proxyport, int proxytype) 537 int proxy_connect(char *host, int port,
246 { 538 char *proxyhost, int proxyport, int proxytype,
247 if (!host || !port || (port == -1)) 539 GdkInputFunction func, gpointer data)
248 return -1; 540 {
249 else if ((proxytype == PROXY_NONE) || 541 struct PHB *phb = g_new0(struct PHB, 1);
542 phb->func = func;
543 phb->data = data;
544
545 if (!host || !port || (port == -1) || !func) {
546 g_free(phb);
547 return -1;
548 }
549
550 if ((proxytype == PROXY_NONE) ||
250 !proxyhost || !proxyhost[0] || 551 !proxyhost || !proxyhost[0] ||
251 !proxyport || (proxyport == -1)) return proxy_connect_none(host, port); 552 !proxyport || (proxyport == -1))
553 return proxy_connect_none(host, port, phb);
252 else if (proxytype == PROXY_HTTP) 554 else if (proxytype == PROXY_HTTP)
253 return proxy_connect_http(host, port, proxyhost, proxyport); 555 return proxy_connect_http(host, port, proxyhost, proxyport, phb);
254 else if (proxytype == PROXY_SOCKS4) 556 else if (proxytype == PROXY_SOCKS4)
255 return proxy_connect_socks4(host, port, proxyhost, proxyport); 557 return proxy_connect_socks4(host, port, proxyhost, proxyport, phb);
256 else if (proxytype == PROXY_SOCKS5) 558 else if (proxytype == PROXY_SOCKS5)
257 return proxy_connect_socks5(host, port, proxyhost, proxyport); 559 return proxy_connect_socks5(host, port, proxyhost, proxyport, phb);
560
561 g_free(phb);
258 return -1; 562 return -1;
259 } 563 }