comparison libpurple/protocols/qq/udp_proxy_s5.c @ 15822:32c366eeeb99

sed -ie 's/gaim/purple/g'
author Sean Egan <seanegan@gmail.com>
date Mon, 19 Mar 2007 07:01:17 +0000
parents 5fe8042783c1
children 44b4e8bd759b
comparison
equal deleted inserted replaced
15821:84b0f9b23ede 15822:32c366eeeb99
1 /** 1 /**
2 * @file udp_proxy_s5.c 2 * @file udp_proxy_s5.c
3 * 3 *
4 * gaim 4 * purple
5 * 5 *
6 * Gaim is the legal property of its developers, whose names are too numerous 6 * Purple is the legal property of its developers, whose names are too numerous
7 * to list here. Please refer to the COPYRIGHT file distributed with this 7 * to list here. Please refer to the COPYRIGHT file distributed with this
8 * source distribution. 8 * source distribution.
9 * 9 *
10 * This program is free software; you can redistribute it and/or modify 10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by 11 * it under the terms of the GNU General Public License as published by
24 24
25 #include "debug.h" 25 #include "debug.h"
26 26
27 #include "udp_proxy_s5.h" 27 #include "udp_proxy_s5.h"
28 28
29 static void _qq_s5_canread_again(gpointer data, gint source, GaimInputCondition cond) 29 static void _qq_s5_canread_again(gpointer data, gint source, PurpleInputCondition cond)
30 { 30 {
31 unsigned char buf[512]; 31 unsigned char buf[512];
32 struct PHB *phb = data; 32 struct PHB *phb = data;
33 struct sockaddr_in sin; 33 struct sockaddr_in sin;
34 int len, error; 34 int len, error;
35 socklen_t errlen; 35 socklen_t errlen;
36 36
37 gaim_input_remove(phb->inpa); 37 purple_input_remove(phb->inpa);
38 gaim_debug(GAIM_DEBUG_INFO, "socks5 proxy", "Able to read again.\n"); 38 purple_debug(PURPLE_DEBUG_INFO, "socks5 proxy", "Able to read again.\n");
39 39
40 len = read(source, buf, 10); 40 len = read(source, buf, 10);
41 if (len < 10) { 41 if (len < 10) {
42 gaim_debug(GAIM_DEBUG_WARNING, "socks5 proxy", "or not...\n"); 42 purple_debug(PURPLE_DEBUG_WARNING, "socks5 proxy", "or not...\n");
43 close(source); 43 close(source);
44 44
45 if (phb->account == NULL || gaim_account_get_connection(phb->account) != NULL) { 45 if (phb->account == NULL || purple_account_get_connection(phb->account) != NULL) {
46 46
47 phb->func(phb->data, source, NULL); 47 phb->func(phb->data, source, NULL);
48 } 48 }
49 49
50 g_free(phb->host); 50 g_free(phb->host);
51 g_free(phb); 51 g_free(phb);
52 return; 52 return;
53 } 53 }
54 if ((buf[0] != 0x05) || (buf[1] != 0x00)) { 54 if ((buf[0] != 0x05) || (buf[1] != 0x00)) {
55 if ((buf[0] == 0x05) && (buf[1] < 0x09)) 55 if ((buf[0] == 0x05) && (buf[1] < 0x09))
56 gaim_debug(GAIM_DEBUG_ERROR, "socks5 proxy", "socks5 error: %x\n", buf[1]); 56 purple_debug(PURPLE_DEBUG_ERROR, "socks5 proxy", "socks5 error: %x\n", buf[1]);
57 else 57 else
58 gaim_debug(GAIM_DEBUG_ERROR, "socks5 proxy", "Bad data.\n"); 58 purple_debug(PURPLE_DEBUG_ERROR, "socks5 proxy", "Bad data.\n");
59 close(source); 59 close(source);
60 60
61 if (phb->account == NULL || gaim_account_get_connection(phb->account) != NULL) { 61 if (phb->account == NULL || purple_account_get_connection(phb->account) != NULL) {
62 62
63 phb->func(phb->data, -1, _("Unable to connect")); 63 phb->func(phb->data, -1, _("Unable to connect"));
64 } 64 }
65 65
66 g_free(phb->host); 66 g_free(phb->host);
71 sin.sin_family = AF_INET; 71 sin.sin_family = AF_INET;
72 memcpy(&sin.sin_addr.s_addr, buf + 4, 4); 72 memcpy(&sin.sin_addr.s_addr, buf + 4, 4);
73 memcpy(&sin.sin_port, buf + 8, 2); 73 memcpy(&sin.sin_port, buf + 8, 2);
74 74
75 if (connect(phb->udpsock, (struct sockaddr *) &sin, sizeof(struct sockaddr_in)) < 0) { 75 if (connect(phb->udpsock, (struct sockaddr *) &sin, sizeof(struct sockaddr_in)) < 0) {
76 gaim_debug(GAIM_DEBUG_INFO, "s5_canread_again", "connect failed: %s\n", strerror(errno)); 76 purple_debug(PURPLE_DEBUG_INFO, "s5_canread_again", "connect failed: %s\n", strerror(errno));
77 close(phb->udpsock); 77 close(phb->udpsock);
78 close(source); 78 close(source);
79 g_free(phb->host); 79 g_free(phb->host);
80 g_free(phb); 80 g_free(phb);
81 return; 81 return;
82 } 82 }
83 83
84 error = ETIMEDOUT; 84 error = ETIMEDOUT;
85 gaim_debug(GAIM_DEBUG_INFO, "QQ", "Connect didn't block\n"); 85 purple_debug(PURPLE_DEBUG_INFO, "QQ", "Connect didn't block\n");
86 errlen = sizeof(error); 86 errlen = sizeof(error);
87 if (getsockopt(phb->udpsock, SOL_SOCKET, SO_ERROR, &error, &errlen) < 0) { 87 if (getsockopt(phb->udpsock, SOL_SOCKET, SO_ERROR, &error, &errlen) < 0) {
88 gaim_debug(GAIM_DEBUG_ERROR, "QQ", "getsockopt failed.\n"); 88 purple_debug(PURPLE_DEBUG_ERROR, "QQ", "getsockopt failed.\n");
89 close(phb->udpsock); 89 close(phb->udpsock);
90 return; 90 return;
91 } 91 }
92 fcntl(phb->udpsock, F_SETFL, 0); 92 fcntl(phb->udpsock, F_SETFL, 0);
93 93
94 if (phb->account == NULL || gaim_account_get_connection(phb->account) != NULL) { 94 if (phb->account == NULL || purple_account_get_connection(phb->account) != NULL) {
95 phb->func(phb->data, phb->udpsock, NULL); 95 phb->func(phb->data, phb->udpsock, NULL);
96 } 96 }
97 97
98 g_free(phb->host); 98 g_free(phb->host);
99 g_free(phb); 99 g_free(phb);
105 struct PHB *phb = data; 105 struct PHB *phb = data;
106 struct sockaddr_in sin, ctlsin; 106 struct sockaddr_in sin, ctlsin;
107 int port; 107 int port;
108 socklen_t ctllen; 108 socklen_t ctllen;
109 109
110 gaim_debug(GAIM_DEBUG_INFO, "s5_sendconnect", "remote host is %s:%d\n", phb->host, phb->port); 110 purple_debug(PURPLE_DEBUG_INFO, "s5_sendconnect", "remote host is %s:%d\n", phb->host, phb->port);
111 111
112 buf[0] = 0x05; 112 buf[0] = 0x05;
113 buf[1] = 0x03; /* udp relay */ 113 buf[1] = 0x03; /* udp relay */
114 buf[2] = 0x00; /* reserved */ 114 buf[2] = 0x00; /* reserved */
115 buf[3] = 0x01; /* address type -- ipv4 */ 115 buf[3] = 0x01; /* address type -- ipv4 */
116 memset(buf + 4, 0, 0x04); 116 memset(buf + 4, 0, 0x04);
117 117
118 ctllen = sizeof(ctlsin); 118 ctllen = sizeof(ctlsin);
119 if (getsockname(source, (struct sockaddr *) &ctlsin, &ctllen) < 0) { 119 if (getsockname(source, (struct sockaddr *) &ctlsin, &ctllen) < 0) {
120 gaim_debug(GAIM_DEBUG_INFO, "QQ", "getsockname: %s\n", strerror(errno)); 120 purple_debug(PURPLE_DEBUG_INFO, "QQ", "getsockname: %s\n", strerror(errno));
121 close(source); 121 close(source);
122 g_free(phb->host); 122 g_free(phb->host);
123 g_free(phb); 123 g_free(phb);
124 return; 124 return;
125 } 125 }
126 126
127 phb->udpsock = socket(PF_INET, SOCK_DGRAM, 0); 127 phb->udpsock = socket(PF_INET, SOCK_DGRAM, 0);
128 gaim_debug(GAIM_DEBUG_INFO, "s5_sendconnect", "UDP socket=%d\n", phb->udpsock); 128 purple_debug(PURPLE_DEBUG_INFO, "s5_sendconnect", "UDP socket=%d\n", phb->udpsock);
129 if (phb->udpsock < 0) { 129 if (phb->udpsock < 0) {
130 close(source); 130 close(source);
131 g_free(phb->host); 131 g_free(phb->host);
132 g_free(phb); 132 g_free(phb);
133 return; 133 return;
155 memset(buf + 4, 0, 0x04); 155 memset(buf + 4, 0, 0x04);
156 memcpy(buf + 8, &(sin.sin_port), 0x02); 156 memcpy(buf + 8, &(sin.sin_port), 0x02);
157 157
158 if (write(source, buf, 10) < 10) { 158 if (write(source, buf, 10) < 10) {
159 close(source); 159 close(source);
160 gaim_debug(GAIM_DEBUG_INFO, "s5_sendconnect", "packet too small\n"); 160 purple_debug(PURPLE_DEBUG_INFO, "s5_sendconnect", "packet too small\n");
161 161
162 if (phb->account == NULL || gaim_account_get_connection(phb->account) != NULL) { 162 if (phb->account == NULL || purple_account_get_connection(phb->account) != NULL) {
163 phb->func(phb->data, -1, _("Unable to connect")); 163 phb->func(phb->data, -1, _("Unable to connect"));
164 } 164 }
165 165
166 g_free(phb->host); 166 g_free(phb->host);
167 g_free(phb); 167 g_free(phb);
168 return; 168 return;
169 } 169 }
170 170
171 phb->inpa = gaim_input_add(source, GAIM_INPUT_READ, _qq_s5_canread_again, phb); 171 phb->inpa = purple_input_add(source, PURPLE_INPUT_READ, _qq_s5_canread_again, phb);
172 } 172 }
173 173
174 static void _qq_s5_readauth(gpointer data, gint source, GaimInputCondition cond) 174 static void _qq_s5_readauth(gpointer data, gint source, PurpleInputCondition cond)
175 { 175 {
176 unsigned char buf[512]; 176 unsigned char buf[512];
177 struct PHB *phb = data; 177 struct PHB *phb = data;
178 178
179 gaim_input_remove(phb->inpa); 179 purple_input_remove(phb->inpa);
180 gaim_debug(GAIM_DEBUG_INFO, "socks5 proxy", "Got auth response.\n"); 180 purple_debug(PURPLE_DEBUG_INFO, "socks5 proxy", "Got auth response.\n");
181 181
182 if (read(source, buf, 2) < 2) { 182 if (read(source, buf, 2) < 2) {
183 close(source); 183 close(source);
184 184
185 if (phb->account == NULL || gaim_account_get_connection(phb->account) != NULL) { 185 if (phb->account == NULL || purple_account_get_connection(phb->account) != NULL) {
186 186
187 phb->func(phb->data, -1, _("Unable to connect")); 187 phb->func(phb->data, -1, _("Unable to connect"));
188 } 188 }
189 189
190 g_free(phb->host); 190 g_free(phb->host);
193 } 193 }
194 194
195 if ((buf[0] != 0x01) || (buf[1] != 0x00)) { 195 if ((buf[0] != 0x01) || (buf[1] != 0x00)) {
196 close(source); 196 close(source);
197 197
198 if (phb->account == NULL || gaim_account_get_connection(phb->account) != NULL) { 198 if (phb->account == NULL || purple_account_get_connection(phb->account) != NULL) {
199 199
200 phb->func(phb->data, -1, _("Unable to connect")); 200 phb->func(phb->data, -1, _("Unable to connect"));
201 } 201 }
202 202
203 g_free(phb->host); 203 g_free(phb->host);
206 } 206 }
207 207
208 _qq_s5_sendconnect(phb, source); 208 _qq_s5_sendconnect(phb, source);
209 } 209 }
210 210
211 static void _qq_s5_canread(gpointer data, gint source, GaimInputCondition cond) 211 static void _qq_s5_canread(gpointer data, gint source, PurpleInputCondition cond)
212 { 212 {
213 unsigned char buf[512]; 213 unsigned char buf[512];
214 struct PHB *phb; 214 struct PHB *phb;
215 int ret; 215 int ret;
216 216
217 phb = data; 217 phb = data;
218 218
219 gaim_input_remove(phb->inpa); 219 purple_input_remove(phb->inpa);
220 gaim_debug(GAIM_DEBUG_INFO, "socks5 proxy", "Able to read.\n"); 220 purple_debug(PURPLE_DEBUG_INFO, "socks5 proxy", "Able to read.\n");
221 221
222 ret = read(source, buf, 2); 222 ret = read(source, buf, 2);
223 if (ret < 2) { 223 if (ret < 2) {
224 gaim_debug(GAIM_DEBUG_INFO, "s5_canread", "packet smaller than 2 octet\n"); 224 purple_debug(PURPLE_DEBUG_INFO, "s5_canread", "packet smaller than 2 octet\n");
225 close(source); 225 close(source);
226 226
227 if (phb->account == NULL || gaim_account_get_connection(phb->account) != NULL) { 227 if (phb->account == NULL || purple_account_get_connection(phb->account) != NULL) {
228 228
229 phb->func(phb->data, -1, _("Unable to connect")); 229 phb->func(phb->data, -1, _("Unable to connect"));
230 } 230 }
231 231
232 g_free(phb->host); 232 g_free(phb->host);
233 g_free(phb); 233 g_free(phb);
234 return; 234 return;
235 } 235 }
236 236
237 if ((buf[0] != 0x05) || (buf[1] == 0xff)) { 237 if ((buf[0] != 0x05) || (buf[1] == 0xff)) {
238 gaim_debug(GAIM_DEBUG_INFO, "s5_canread", "unsupport\n"); 238 purple_debug(PURPLE_DEBUG_INFO, "s5_canread", "unsupport\n");
239 close(source); 239 close(source);
240 240
241 if (phb->account == NULL || gaim_account_get_connection(phb->account) != NULL) { 241 if (phb->account == NULL || purple_account_get_connection(phb->account) != NULL) {
242 242
243 phb->func(phb->data, -1, _("Unable to connect")); 243 phb->func(phb->data, -1, _("Unable to connect"));
244 } 244 }
245 245
246 g_free(phb->host); 246 g_free(phb->host);
249 } 249 }
250 250
251 if (buf[1] == 0x02) { 251 if (buf[1] == 0x02) {
252 unsigned int i, j; 252 unsigned int i, j;
253 253
254 i = strlen(gaim_proxy_info_get_username(phb->gpi)); 254 i = strlen(purple_proxy_info_get_username(phb->gpi));
255 j = strlen(gaim_proxy_info_get_password(phb->gpi)); 255 j = strlen(purple_proxy_info_get_password(phb->gpi));
256 256
257 buf[0] = 0x01; /* version 1 */ 257 buf[0] = 0x01; /* version 1 */
258 buf[1] = i; 258 buf[1] = i;
259 memcpy(buf + 2, gaim_proxy_info_get_username(phb->gpi), i); 259 memcpy(buf + 2, purple_proxy_info_get_username(phb->gpi), i);
260 buf[2 + i] = j; 260 buf[2 + i] = j;
261 memcpy(buf + 2 + i + 1, gaim_proxy_info_get_password(phb->gpi), j); 261 memcpy(buf + 2 + i + 1, purple_proxy_info_get_password(phb->gpi), j);
262 262
263 if (write(source, buf, 3 + i + j) < 3 + i + j) { 263 if (write(source, buf, 3 + i + j) < 3 + i + j) {
264 close(source); 264 close(source);
265 265
266 if (phb->account == NULL || gaim_account_get_connection(phb->account) != NULL) { 266 if (phb->account == NULL || purple_account_get_connection(phb->account) != NULL) {
267 267
268 phb->func(phb->data, -1, _("Unable to connect")); 268 phb->func(phb->data, -1, _("Unable to connect"));
269 } 269 }
270 270
271 g_free(phb->host); 271 g_free(phb->host);
272 g_free(phb); 272 g_free(phb);
273 return; 273 return;
274 } 274 }
275 275
276 phb->inpa = gaim_input_add(source, GAIM_INPUT_READ, _qq_s5_readauth, phb); 276 phb->inpa = purple_input_add(source, PURPLE_INPUT_READ, _qq_s5_readauth, phb);
277 } else { 277 } else {
278 gaim_debug(GAIM_DEBUG_INFO, "s5_canread", "calling s5_sendconnect\n"); 278 purple_debug(PURPLE_DEBUG_INFO, "s5_canread", "calling s5_sendconnect\n");
279 _qq_s5_sendconnect(phb, source); 279 _qq_s5_sendconnect(phb, source);
280 } 280 }
281 } 281 }
282 282
283 static void _qq_s5_canwrite(gpointer data, gint source, GaimInputCondition cond) 283 static void _qq_s5_canwrite(gpointer data, gint source, PurpleInputCondition cond)
284 { 284 {
285 unsigned char buf[512]; 285 unsigned char buf[512];
286 int i; 286 int i;
287 struct PHB *phb = data; 287 struct PHB *phb = data;
288 unsigned int len; 288 unsigned int len;
289 int error = ETIMEDOUT; 289 int error = ETIMEDOUT;
290 290
291 gaim_debug(GAIM_DEBUG_INFO, "socks5 proxy", "Connected.\n"); 291 purple_debug(PURPLE_DEBUG_INFO, "socks5 proxy", "Connected.\n");
292 292
293 if (phb->inpa > 0) 293 if (phb->inpa > 0)
294 gaim_input_remove(phb->inpa); 294 purple_input_remove(phb->inpa);
295 295
296 len = sizeof(error); 296 len = sizeof(error);
297 if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { 297 if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
298 gaim_debug(GAIM_DEBUG_INFO, "getsockopt", "%s\n", strerror(errno)); 298 purple_debug(PURPLE_DEBUG_INFO, "getsockopt", "%s\n", strerror(errno));
299 close(source); 299 close(source);
300 if (phb->account == NULL || gaim_account_get_connection(phb->account) != NULL) { 300 if (phb->account == NULL || purple_account_get_connection(phb->account) != NULL) {
301 301
302 phb->func(phb->data, -1, _("Unable to connect")); 302 phb->func(phb->data, -1, _("Unable to connect"));
303 } 303 }
304 304
305 g_free(phb->host); 305 g_free(phb->host);
309 fcntl(source, F_SETFL, 0); 309 fcntl(source, F_SETFL, 0);
310 310
311 i = 0; 311 i = 0;
312 buf[0] = 0x05; /* SOCKS version 5 */ 312 buf[0] = 0x05; /* SOCKS version 5 */
313 313
314 if (gaim_proxy_info_get_username(phb->gpi) != NULL) { 314 if (purple_proxy_info_get_username(phb->gpi) != NULL) {
315 buf[1] = 0x02; /* two methods */ 315 buf[1] = 0x02; /* two methods */
316 buf[2] = 0x00; /* no authentication */ 316 buf[2] = 0x00; /* no authentication */
317 buf[3] = 0x02; /* username/password authentication */ 317 buf[3] = 0x02; /* username/password authentication */
318 i = 4; 318 i = 4;
319 } else { 319 } else {
321 buf[2] = 0x00; 321 buf[2] = 0x00;
322 i = 3; 322 i = 3;
323 } 323 }
324 324
325 if (write(source, buf, i) < i) { 325 if (write(source, buf, i) < i) {
326 gaim_debug(GAIM_DEBUG_INFO, "write", "%s\n", strerror(errno)); 326 purple_debug(PURPLE_DEBUG_INFO, "write", "%s\n", strerror(errno));
327 gaim_debug(GAIM_DEBUG_ERROR, "socks5 proxy", "Unable to write\n"); 327 purple_debug(PURPLE_DEBUG_ERROR, "socks5 proxy", "Unable to write\n");
328 close(source); 328 close(source);
329 329
330 if (phb->account == NULL || gaim_account_get_connection(phb->account) != NULL) { 330 if (phb->account == NULL || purple_account_get_connection(phb->account) != NULL) {
331 331
332 phb->func(phb->data, -1, _("Unable to connect")); 332 phb->func(phb->data, -1, _("Unable to connect"));
333 } 333 }
334 334
335 g_free(phb->host); 335 g_free(phb->host);
336 g_free(phb); 336 g_free(phb);
337 return; 337 return;
338 } 338 }
339 339
340 phb->inpa = gaim_input_add(source, GAIM_INPUT_READ, _qq_s5_canread, phb); 340 phb->inpa = purple_input_add(source, PURPLE_INPUT_READ, _qq_s5_canread, phb);
341 } 341 }
342 342
343 gint qq_proxy_socks5(struct PHB *phb, struct sockaddr *addr, socklen_t addrlen) 343 gint qq_proxy_socks5(struct PHB *phb, struct sockaddr *addr, socklen_t addrlen)
344 { 344 {
345 gint fd; 345 gint fd;
346 gaim_debug(GAIM_DEBUG_INFO, "QQ", 346 purple_debug(PURPLE_DEBUG_INFO, "QQ",
347 "Connecting to %s:%d via %s:%d using SOCKS5\n", 347 "Connecting to %s:%d via %s:%d using SOCKS5\n",
348 phb->host, phb->port, gaim_proxy_info_get_host(phb->gpi), gaim_proxy_info_get_port(phb->gpi)); 348 phb->host, phb->port, purple_proxy_info_get_host(phb->gpi), purple_proxy_info_get_port(phb->gpi));
349 349
350 if ((fd = socket(addr->sa_family, SOCK_STREAM, 0)) < 0) 350 if ((fd = socket(addr->sa_family, SOCK_STREAM, 0)) < 0)
351 return -1; 351 return -1;
352 352
353 gaim_debug(GAIM_DEBUG_INFO, "QQ", "proxy_sock5 return fd=%d\n", fd); 353 purple_debug(PURPLE_DEBUG_INFO, "QQ", "proxy_sock5 return fd=%d\n", fd);
354 354
355 fcntl(fd, F_SETFL, O_NONBLOCK); 355 fcntl(fd, F_SETFL, O_NONBLOCK);
356 if (connect(fd, addr, addrlen) < 0) { 356 if (connect(fd, addr, addrlen) < 0) {
357 if ((errno == EINPROGRESS) || (errno == EINTR)) { 357 if ((errno == EINPROGRESS) || (errno == EINTR)) {
358 gaim_debug(GAIM_DEBUG_WARNING, "QQ", "Connect in asynchronous mode.\n"); 358 purple_debug(PURPLE_DEBUG_WARNING, "QQ", "Connect in asynchronous mode.\n");
359 phb->inpa = gaim_input_add(fd, GAIM_INPUT_WRITE, _qq_s5_canwrite, phb); 359 phb->inpa = purple_input_add(fd, PURPLE_INPUT_WRITE, _qq_s5_canwrite, phb);
360 } else { 360 } else {
361 close(fd); 361 close(fd);
362 return -1; 362 return -1;
363 } 363 }
364 } else { 364 } else {
365 gaim_debug(GAIM_DEBUG_MISC, "QQ", "Connect in blocking mode.\n"); 365 purple_debug(PURPLE_DEBUG_MISC, "QQ", "Connect in blocking mode.\n");
366 fcntl(fd, F_SETFL, 0); 366 fcntl(fd, F_SETFL, 0);
367 _qq_s5_canwrite(phb, fd, GAIM_INPUT_WRITE); 367 _qq_s5_canwrite(phb, fd, PURPLE_INPUT_WRITE);
368 } 368 }
369 369
370 return fd; 370 return fd;
371 } 371 }