Mercurial > pidgin.yaz
comparison src/proxy.c @ 14089:10e8eb6a4910
[gaim-migrate @ 16712]
Pretty large commit here. Basically I got sick of having to verify
that gc is still valid on all the callback functions for
gaim_proxy_connect(). The fix for this for gaim_proxy_connect() to
return something that allows the connection attempt to be canceled.
It's not quite there yet, but this is a good first step. I changed
gaim_proxy_connect() to return a reference to a new
GaimProxyConnectInfo (this used to be called PHB). Eventually this
can be passed to a function that'll cancel the connection attempt.
I also decided to add an error_cb instead of using connect_cb and
passing a file descriptor of -1. And proxy.c will also pass an
error message to callers which should explain the reason that the
connection attempt failed.
Oh, and proxy.c now never calls gaim_connection_error()
committer: Tailor Script <tailor@pidgin.im>
author | Mark Doliner <mark@kingant.net> |
---|---|
date | Sat, 12 Aug 2006 10:12:43 +0000 |
parents | 8bda65b88e49 |
children | 983fbec46eb0 |
comparison
equal
deleted
inserted
replaced
14088:223570831b0b | 14089:10e8eb6a4910 |
---|---|
36 #include "ntlm.h" | 36 #include "ntlm.h" |
37 #include "prefs.h" | 37 #include "prefs.h" |
38 #include "proxy.h" | 38 #include "proxy.h" |
39 #include "util.h" | 39 #include "util.h" |
40 | 40 |
41 static GaimProxyInfo *global_proxy_info = NULL; | 41 /* Does anyone know what PHB stands for? */ |
42 | |
43 struct PHB { | 42 struct PHB { |
44 GaimInputFunction func; | 43 GaimProxyConnectFunction connect_cb; |
44 GaimProxyErrorFunction error_cb; | |
45 gpointer data; | 45 gpointer data; |
46 char *host; | 46 char *host; |
47 int port; | 47 int port; |
48 gint inpa; | 48 guint inpa; |
49 GaimProxyInfo *gpi; | 49 GaimProxyInfo *gpi; |
50 GaimAccount *account; | |
51 GSList *hosts; | 50 GSList *hosts; |
52 guchar *write_buffer; | 51 guchar *write_buffer; |
53 gsize write_buf_len; | 52 gsize write_buf_len; |
54 gsize written_len; | 53 gsize written_len; |
55 GaimInputFunction read_cb; | 54 GaimInputFunction read_cb; |
56 guchar *read_buffer; | 55 guchar *read_buffer; |
57 gsize read_buf_len; | 56 gsize read_buf_len; |
58 gsize read_len; | 57 gsize read_len; |
59 }; | 58 }; |
60 | |
61 static void try_connect(struct PHB *); | |
62 | 59 |
63 static const char *socks5errors[] = { | 60 static const char *socks5errors[] = { |
64 "succeeded\n", | 61 "succeeded\n", |
65 "general SOCKS server failure\n", | 62 "general SOCKS server failure\n", |
66 "connection not allowed by ruleset\n", | 63 "connection not allowed by ruleset\n", |
70 "TTL expired\n", | 67 "TTL expired\n", |
71 "Command not supported\n", | 68 "Command not supported\n", |
72 "Address type not supported\n" | 69 "Address type not supported\n" |
73 }; | 70 }; |
74 | 71 |
72 static GaimProxyInfo *global_proxy_info = NULL; | |
73 static GSList *phbs = NULL; | |
74 | |
75 static void try_connect(struct PHB *); | |
76 | |
75 /************************************************************************** | 77 /************************************************************************** |
76 * Proxy structure API | 78 * Proxy structure API |
77 **************************************************************************/ | 79 **************************************************************************/ |
78 GaimProxyInfo * | 80 GaimProxyInfo * |
79 gaim_proxy_info_new(void) | 81 gaim_proxy_info_new(void) |
253 } | 255 } |
254 /************************************************************************** | 256 /************************************************************************** |
255 * Proxy API | 257 * Proxy API |
256 **************************************************************************/ | 258 **************************************************************************/ |
257 | 259 |
260 static void | |
261 gaim_proxy_phb_destroy(struct PHB *phb) | |
262 { | |
263 phbs = g_slist_remove(phbs, phb); | |
264 | |
265 if (phb->inpa > 0) | |
266 gaim_input_remove(phb->inpa); | |
267 | |
268 while (phb->hosts != NULL) | |
269 { | |
270 /* Discard the length... */ | |
271 phb->hosts = g_slist_remove(phb->hosts, phb->hosts->data); | |
272 /* Free the address... */ | |
273 g_free(phb->hosts->data); | |
274 phb->hosts = g_slist_remove(phb->hosts, phb->hosts->data); | |
275 } | |
276 | |
277 g_free(phb->host); | |
278 g_free(phb->write_buffer); | |
279 g_free(phb->read_buffer); | |
280 g_free(phb); | |
281 } | |
282 | |
283 static void | |
284 gaim_proxy_phb_connected(struct PHB *phb, int fd) | |
285 { | |
286 phb->connect_cb(phb->data, fd); | |
287 gaim_proxy_phb_destroy(phb); | |
288 } | |
289 | |
290 /** | |
291 * @param error An error message explaining why the connection | |
292 * failed. This will be passed to the callback function | |
293 * specified in the call to gaim_proxy_connect(). | |
294 */ | |
295 static void | |
296 gaim_proxy_phb_error(struct PHB *phb, const gchar *error_message) | |
297 { | |
298 if (phb->error_cb == NULL) | |
299 { | |
300 /* | |
301 * TODO | |
302 * While we're transitioning to the new gaim_proxy_connect() | |
303 * code, not all callers supply an error_cb. If this is the | |
304 * case then they're expecting connect_cb to be called with | |
305 * an fd of -1 in the case of an error. Once all callers have | |
306 * been changed this whole if statement should be removed. | |
307 */ | |
308 phb->connect_cb(phb->data, -1); | |
309 gaim_proxy_phb_destroy(phb); | |
310 return; | |
311 } | |
312 | |
313 phb->error_cb(phb->data, error_message); | |
314 gaim_proxy_phb_destroy(phb); | |
315 } | |
316 | |
258 #if defined(__unix__) || defined(__APPLE__) | 317 #if defined(__unix__) || defined(__APPLE__) |
259 | 318 |
260 /* | 319 /* |
261 * This structure represents both a pending DNS request and | 320 * This structure represents both a pending DNS request and |
262 * a free child process. | 321 * a free child process. |
263 */ | 322 */ |
264 typedef struct { | 323 typedef struct { |
265 char *host; | 324 char *host; |
266 int port; | 325 int port; |
267 dns_callback_t callback; | 326 GaimProxyDnsConnectFunction callback; |
268 gpointer data; | 327 gpointer data; |
269 gint inpa; | 328 guint inpa; |
270 int fd_in, fd_out; | 329 int fd_in, fd_out; |
271 pid_t dns_pid; | 330 pid_t dns_pid; |
272 } pending_dns_request_t; | 331 } pending_dns_request_t; |
273 | 332 |
274 static GSList *free_dns_children = NULL; | 333 static GSList *free_dns_children = NULL; |
283 int port; | 342 int port; |
284 } dns_params_t; | 343 } dns_params_t; |
285 | 344 |
286 typedef struct { | 345 typedef struct { |
287 dns_params_t params; | 346 dns_params_t params; |
288 dns_callback_t callback; | 347 GaimProxyDnsConnectFunction callback; |
289 gpointer data; | 348 gpointer data; |
290 } queued_dns_request_t; | 349 } queued_dns_request_t; |
291 | 350 |
292 /* | 351 /* |
293 * Begin the DNS resolver child process functions. | 352 * Begin the DNS resolver child process functions. |
692 /* | 751 /* |
693 * End the functions for dealing with the DNS child processes. | 752 * End the functions for dealing with the DNS child processes. |
694 */ | 753 */ |
695 | 754 |
696 int | 755 int |
697 gaim_gethostbyname_async(const char *hostname, int port, dns_callback_t callback, gpointer data) | 756 gaim_gethostbyname_async(const char *hostname, int port, GaimProxyDnsConnectFunction callback, gpointer data) |
698 { | 757 { |
699 pending_dns_request_t *req = NULL; | 758 pending_dns_request_t *req = NULL; |
700 dns_params_t dns_params; | 759 dns_params_t dns_params; |
701 gchar *host_temp; | 760 gchar *host_temp; |
702 gboolean show_debug; | 761 gboolean show_debug; |
765 #elif defined _WIN32 /* end __unix__ || __APPLE__ */ | 824 #elif defined _WIN32 /* end __unix__ || __APPLE__ */ |
766 | 825 |
767 typedef struct _dns_tdata { | 826 typedef struct _dns_tdata { |
768 char *hostname; | 827 char *hostname; |
769 int port; | 828 int port; |
770 dns_callback_t callback; | 829 GaimProxyDnsConnectFunction callback; |
771 gpointer data; | 830 gpointer data; |
772 GSList *hosts; | 831 GSList *hosts; |
773 char *errmsg; | 832 char *errmsg; |
774 } dns_tdata; | 833 } dns_tdata; |
775 | 834 |
841 return 0; | 900 return 0; |
842 } | 901 } |
843 | 902 |
844 int | 903 int |
845 gaim_gethostbyname_async(const char *hostname, int port, | 904 gaim_gethostbyname_async(const char *hostname, int port, |
846 dns_callback_t callback, gpointer data) | 905 GaimProxyDnsConnectFunction callback, gpointer data) |
847 { | 906 { |
848 dns_tdata *td; | 907 dns_tdata *td; |
849 struct sockaddr_in sin; | 908 struct sockaddr_in sin; |
850 GError* err = NULL; | 909 GError* err = NULL; |
851 | 910 |
880 | 939 |
881 typedef struct { | 940 typedef struct { |
882 gpointer data; | 941 gpointer data; |
883 size_t addrlen; | 942 size_t addrlen; |
884 struct sockaddr *addr; | 943 struct sockaddr *addr; |
885 dns_callback_t callback; | 944 GaimProxyDnsConnectFunction callback; |
886 } pending_dns_request_t; | 945 } pending_dns_request_t; |
887 | 946 |
888 static gboolean host_resolved(gpointer data) | 947 static gboolean host_resolved(gpointer data) |
889 { | 948 { |
890 pending_dns_request_t *req = (pending_dns_request_t*)data; | 949 pending_dns_request_t *req = (pending_dns_request_t*)data; |
896 return FALSE; | 955 return FALSE; |
897 } | 956 } |
898 | 957 |
899 int | 958 int |
900 gaim_gethostbyname_async(const char *hostname, int port, | 959 gaim_gethostbyname_async(const char *hostname, int port, |
901 dns_callback_t callback, gpointer data) | 960 GaimProxyDnsConnectFunction callback, gpointer data) |
902 { | 961 { |
903 struct sockaddr_in sin; | 962 struct sockaddr_in sin; |
904 pending_dns_request_t *req; | 963 pending_dns_request_t *req; |
905 | 964 |
906 if (!inet_aton(hostname, &sin.sin_addr)) { | 965 if (!inet_aton(hostname, &sin.sin_addr)) { |
953 */ | 1012 */ |
954 ret = getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len); | 1013 ret = getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len); |
955 if (ret == 0 && error == EINPROGRESS) | 1014 if (ret == 0 && error == EINPROGRESS) |
956 return; /* we'll be called again later */ | 1015 return; /* we'll be called again later */ |
957 if (ret < 0 || error != 0) { | 1016 if (ret < 0 || error != 0) { |
958 if(ret!=0) error = errno; | 1017 if (ret!=0) |
1018 error = errno; | |
959 close(source); | 1019 close(source); |
960 gaim_input_remove(phb->inpa); | 1020 gaim_input_remove(phb->inpa); |
1021 phb->inpa = 0; | |
961 | 1022 |
962 gaim_debug_error("proxy", | 1023 gaim_debug_error("proxy", |
963 "getsockopt SO_ERROR check: %s\n", strerror(error)); | 1024 "getsockopt SO_ERROR check: %s\n", strerror(error)); |
964 | 1025 |
965 try_connect(phb); | 1026 try_connect(phb); |
966 return; | 1027 return; |
967 } | 1028 } |
968 | 1029 |
969 gaim_input_remove(phb->inpa); | 1030 gaim_input_remove(phb->inpa); |
970 | 1031 phb->inpa = 0; |
971 if (phb->account == NULL || | 1032 |
972 gaim_account_get_connection(phb->account) != NULL) { | 1033 gaim_proxy_phb_connected(phb, source); |
973 | |
974 phb->func(phb->data, source, GAIM_INPUT_READ); | |
975 } | |
976 | |
977 g_free(phb->host); | |
978 g_free(phb); | |
979 } | 1034 } |
980 | 1035 |
981 static gboolean clean_connect(gpointer data) | 1036 static gboolean clean_connect(gpointer data) |
982 { | 1037 { |
983 struct PHB *phb = data; | 1038 struct PHB *phb = data; |
984 | 1039 |
985 if (phb->account == NULL || | 1040 gaim_proxy_phb_connected(phb, phb->port); |
986 gaim_account_get_connection(phb->account) != NULL) { | |
987 | |
988 phb->func(phb->data, phb->port, GAIM_INPUT_READ); | |
989 } | |
990 | |
991 g_free(phb->host); | |
992 g_free(phb); | |
993 | 1041 |
994 return FALSE; | 1042 return FALSE; |
995 } | 1043 } |
996 | 1044 |
997 | 1045 |
1035 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { | 1083 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { |
1036 gaim_debug_error("proxy", "getsockopt failed.\n"); | 1084 gaim_debug_error("proxy", "getsockopt failed.\n"); |
1037 close(fd); | 1085 close(fd); |
1038 return -1; | 1086 return -1; |
1039 } | 1087 } |
1088 /* TODO: Why is the following line so strange? */ | |
1040 phb->port = fd; /* bleh */ | 1089 phb->port = fd; /* bleh */ |
1041 gaim_timeout_add(50, clean_connect, phb); /* we do this because we never | 1090 gaim_timeout_add(10, clean_connect, phb); /* we do this because we never |
1042 want to call our callback | 1091 want to call our callback |
1043 before we return. */ | 1092 before we return. */ |
1044 } | 1093 } |
1045 | 1094 |
1046 return fd; | 1095 return fd; |
1057 | 1106 |
1058 if(ret < 0 && errno == EAGAIN) | 1107 if(ret < 0 && errno == EAGAIN) |
1059 return; | 1108 return; |
1060 else if(ret < 0) { | 1109 else if(ret < 0) { |
1061 gaim_input_remove(phb->inpa); | 1110 gaim_input_remove(phb->inpa); |
1111 phb->inpa = 0; | |
1062 close(source); | 1112 close(source); |
1063 g_free(phb->write_buffer); | 1113 g_free(phb->write_buffer); |
1064 phb->write_buffer = NULL; | 1114 phb->write_buffer = NULL; |
1065 try_connect(phb); | 1115 try_connect(phb); |
1066 return; | 1116 return; |
1077 phb->inpa = gaim_input_add(source, GAIM_INPUT_READ, phb->read_cb, phb); | 1127 phb->inpa = gaim_input_add(source, GAIM_INPUT_READ, phb->read_cb, phb); |
1078 } | 1128 } |
1079 | 1129 |
1080 #define HTTP_GOODSTRING "HTTP/1.0 200" | 1130 #define HTTP_GOODSTRING "HTTP/1.0 200" |
1081 #define HTTP_GOODSTRING2 "HTTP/1.1 200" | 1131 #define HTTP_GOODSTRING2 "HTTP/1.1 200" |
1082 | |
1083 static void | |
1084 http_complete(struct PHB *phb, gint source) | |
1085 { | |
1086 gaim_debug_info("http proxy", "proxy connection established\n"); | |
1087 if(!phb->account || phb->account->gc) { | |
1088 phb->func(phb->data, source, GAIM_INPUT_READ); | |
1089 } | |
1090 g_free(phb->host); | |
1091 g_free(phb); | |
1092 } | |
1093 | |
1094 | 1132 |
1095 /* read the response to the CONNECT request, if we are requesting a non-port-80 tunnel */ | 1133 /* read the response to the CONNECT request, if we are requesting a non-port-80 tunnel */ |
1096 static void | 1134 static void |
1097 http_canread(gpointer data, gint source, GaimInputCondition cond) | 1135 http_canread(gpointer data, gint source, GaimInputCondition cond) |
1098 { | 1136 { |
1099 int len, headers_len, status = 0; | 1137 int len, headers_len, status = 0; |
1100 gboolean error; | 1138 gboolean error; |
1101 struct PHB *phb = data; | 1139 struct PHB *phb = data; |
1102 guchar *p; | 1140 guchar *p; |
1103 gsize max_read; | 1141 gsize max_read; |
1142 gchar *msg; | |
1104 | 1143 |
1105 if(phb->read_buffer == NULL) { | 1144 if(phb->read_buffer == NULL) { |
1106 phb->read_buf_len = 8192; | 1145 phb->read_buf_len = 8192; |
1107 phb->read_buffer = g_malloc(phb->read_buf_len); | 1146 phb->read_buffer = g_malloc(phb->read_buf_len); |
1108 phb->read_len = 0; | 1147 phb->read_len = 0; |
1114 len = read(source, p, max_read); | 1153 len = read(source, p, max_read); |
1115 if(len < 0 && errno == EAGAIN) | 1154 if(len < 0 && errno == EAGAIN) |
1116 return; | 1155 return; |
1117 else if(len <= 0) { | 1156 else if(len <= 0) { |
1118 close(source); | 1157 close(source); |
1119 source = -1; | 1158 gaim_proxy_phb_error(phb, _("Lost connection with server for an unknown reason.")); |
1120 g_free(phb->read_buffer); | |
1121 phb->read_buffer = NULL; | |
1122 gaim_input_remove(phb->inpa); | |
1123 phb->inpa = 0; | |
1124 http_complete(phb, source); | |
1125 return; | 1159 return; |
1126 } else { | 1160 } else { |
1127 phb->read_len += len; | 1161 phb->read_len += len; |
1128 } | 1162 } |
1129 p[len] = '\0'; | 1163 p[len] = '\0'; |
1135 headers_len = len; | 1169 headers_len = len; |
1136 else | 1170 else |
1137 return; | 1171 return; |
1138 | 1172 |
1139 error = strncmp((const char *)phb->read_buffer, "HTTP/", 5) != 0; | 1173 error = strncmp((const char *)phb->read_buffer, "HTTP/", 5) != 0; |
1140 if(!error) { | 1174 if (!error) |
1175 { | |
1141 int major; | 1176 int major; |
1142 p = phb->read_buffer + 5; | 1177 p = phb->read_buffer + 5; |
1143 major = strtol((const char *)p, (char **)&p, 10); | 1178 major = strtol((const char *)p, (char **)&p, 10); |
1144 error = (major == 0) || (*p != '.'); | 1179 error = (major == 0) || (*p != '.'); |
1145 if(!error) { | 1180 if(!error) { |
1155 } | 1190 } |
1156 } | 1191 } |
1157 | 1192 |
1158 /* Read the contents */ | 1193 /* Read the contents */ |
1159 p = (guchar *)g_strrstr((const gchar *)phb->read_buffer, "Content-Length: "); | 1194 p = (guchar *)g_strrstr((const gchar *)phb->read_buffer, "Content-Length: "); |
1160 if(p != NULL) { | 1195 if (p != NULL) |
1196 { | |
1161 gchar *tmp; | 1197 gchar *tmp; |
1162 int len = 0; | 1198 int len = 0; |
1163 char tmpc; | 1199 char tmpc; |
1164 p += strlen("Content-Length: "); | 1200 p += strlen("Content-Length: "); |
1165 tmp = strchr((const char *)p, '\r'); | 1201 tmp = strchr((const char *)p, '\r'); |
1178 if (read(source, &tmpc, 1) < 0 && errno != EAGAIN) | 1214 if (read(source, &tmpc, 1) < 0 && errno != EAGAIN) |
1179 break; | 1215 break; |
1180 } | 1216 } |
1181 } | 1217 } |
1182 | 1218 |
1183 if(error) { | 1219 if (error) |
1184 gaim_debug_error("proxy", | 1220 { |
1185 "Unable to parse proxy's response: %s\n", | 1221 close(source); |
1222 msg = g_strdup_printf("Unable to parse response from HTTP proxy: %s\n", | |
1186 phb->read_buffer); | 1223 phb->read_buffer); |
1187 close(source); | 1224 gaim_proxy_phb_error(phb, msg); |
1188 source = -1; | 1225 g_free(msg); |
1189 g_free(phb->read_buffer); | 1226 return; |
1190 phb->read_buffer = NULL; | 1227 } |
1191 gaim_input_remove(phb->inpa); | 1228 else if (status != 200) |
1192 phb->inpa = 0; | 1229 { |
1193 http_complete(phb, source); | |
1194 return; | |
1195 } else if(status != 200) { | |
1196 gaim_debug_error("proxy", | 1230 gaim_debug_error("proxy", |
1197 "Proxy server replied with:\n%s\n", | 1231 "Proxy server replied with:\n%s\n", |
1198 phb->read_buffer); | 1232 phb->read_buffer); |
1199 | 1233 |
1200 | 1234 |
1201 /* XXX: why in the hell are we calling gaim_connection_error() here? */ | |
1202 if(status == 407 /* Proxy Auth */) { | 1235 if(status == 407 /* Proxy Auth */) { |
1203 gchar *ntlm; | 1236 gchar *ntlm; |
1204 if((ntlm = g_strrstr((const gchar *)phb->read_buffer, "Proxy-Authenticate: NTLM "))) { /* Check for Type-2 */ | 1237 if((ntlm = g_strrstr((const gchar *)phb->read_buffer, "Proxy-Authenticate: NTLM "))) { /* Check for Type-2 */ |
1205 gchar *tmp = ntlm; | 1238 gchar *tmp = ntlm; |
1206 guint8 *nonce; | 1239 guint8 *nonce; |
1207 gchar *domain = (gchar*)gaim_proxy_info_get_username(phb->gpi); | 1240 gchar *domain = (gchar*)gaim_proxy_info_get_username(phb->gpi); |
1208 gchar *username; | 1241 gchar *username; |
1209 gchar *request; | 1242 gchar *request; |
1210 gchar *response; | 1243 gchar *response; |
1211 if(!(username = strchr(domain, '\\'))) { | 1244 username = strchr(domain, '\\'); |
1212 char *msg = g_strdup_printf(_("Proxy connection error %d"), status); | 1245 if (username == NULL) |
1246 { | |
1213 close(source); | 1247 close(source); |
1214 source = -1; | 1248 msg = g_strdup_printf(_("HTTP proxy connection error %d"), status); |
1215 if(phb->account) | 1249 gaim_proxy_phb_error(phb, msg); |
1216 gaim_connection_error(phb->account->gc, msg); | |
1217 else | |
1218 gaim_debug_error("http proxy", "%s\n", msg); | |
1219 g_free(msg); | 1250 g_free(msg); |
1220 gaim_input_remove(phb->inpa); | |
1221 g_free(phb->read_buffer); | |
1222 g_free(phb->host); | |
1223 g_free(phb); | |
1224 return; | 1251 return; |
1225 } | 1252 } |
1226 *username = '\0'; | 1253 *username = '\0'; |
1227 username++; | 1254 username++; |
1228 ntlm += strlen("Proxy-Authenticate: NTLM "); | 1255 ntlm += strlen("Proxy-Authenticate: NTLM "); |
1262 } else if((ntlm = g_strrstr((const char *)phb->read_buffer, "Proxy-Authenticate: NTLM"))) { /* Empty message */ | 1289 } else if((ntlm = g_strrstr((const char *)phb->read_buffer, "Proxy-Authenticate: NTLM"))) { /* Empty message */ |
1263 gchar request[2048]; | 1290 gchar request[2048]; |
1264 gchar *domain = (gchar*) gaim_proxy_info_get_username(phb->gpi); | 1291 gchar *domain = (gchar*) gaim_proxy_info_get_username(phb->gpi); |
1265 gchar *username; | 1292 gchar *username; |
1266 int request_len; | 1293 int request_len; |
1267 if(!(username = strchr(domain, '\\'))) { | 1294 username = strchr(domain, '\\'); |
1268 char *msg = g_strdup_printf(_("Proxy connection error %d"), status); | 1295 if (username == NULL) |
1296 { | |
1269 close(source); | 1297 close(source); |
1270 source = -1; | 1298 msg = g_strdup_printf(_("HTTP proxy connection error %d"), status); |
1271 if(phb->account) | 1299 gaim_proxy_phb_error(phb, msg); |
1272 gaim_connection_error(phb->account->gc, msg); | |
1273 else | |
1274 gaim_debug_error("http proxy", "%s\n", msg); | |
1275 g_free(msg); | 1300 g_free(msg); |
1276 gaim_input_remove(phb->inpa); | |
1277 g_free(phb->read_buffer); | |
1278 g_free(phb->host); | |
1279 g_free(phb); | |
1280 return; | 1301 return; |
1281 } | 1302 } |
1282 *username = '\0'; | 1303 *username = '\0'; |
1283 | 1304 |
1284 request_len = g_snprintf(request, sizeof(request), | 1305 request_len = g_snprintf(request, sizeof(request), |
1311 GAIM_INPUT_WRITE, proxy_do_write, phb); | 1332 GAIM_INPUT_WRITE, proxy_do_write, phb); |
1312 | 1333 |
1313 proxy_do_write(phb, source, cond); | 1334 proxy_do_write(phb, source, cond); |
1314 return; | 1335 return; |
1315 } else { | 1336 } else { |
1316 char *msg = g_strdup_printf(_("Proxy connection error %d"), status); | |
1317 close(source); | 1337 close(source); |
1318 source = -1; | 1338 msg = g_strdup_printf(_("HTTP proxy connection error %d"), status); |
1319 if(phb->account) | 1339 gaim_proxy_phb_error(phb, msg); |
1320 gaim_connection_error(phb->account->gc, msg); | |
1321 else | |
1322 gaim_debug_error("http proxy", "%s\n", msg); | |
1323 g_free(msg); | 1340 g_free(msg); |
1324 gaim_input_remove(phb->inpa); | |
1325 g_free(phb->read_buffer); | |
1326 g_free(phb->host); | |
1327 g_free(phb); | |
1328 return; | 1341 return; |
1329 } | 1342 } |
1330 } | 1343 } |
1331 if(status == 403 /* Forbidden */ ) { | 1344 if(status == 403 /* Forbidden */ ) { |
1332 gchar *msg = g_strdup_printf(_("Access denied: proxy server forbids port %d tunnelling."), phb->port); | 1345 msg = g_strdup_printf(_("Access denied: HTTP proxy server forbids port %d tunnelling."), phb->port); |
1333 if(phb->account) | 1346 gaim_proxy_phb_error(phb, msg); |
1334 gaim_connection_error(phb->account->gc, msg); | |
1335 else | |
1336 gaim_debug_error("http proxy", "%s\n", msg); | |
1337 g_free(msg); | 1347 g_free(msg); |
1338 gaim_input_remove(phb->inpa); | |
1339 g_free(phb->read_buffer); | |
1340 g_free(phb->host); | |
1341 g_free(phb); | |
1342 } else { | 1348 } else { |
1343 char *msg = g_strdup_printf(_("Proxy connection error %d"), status); | 1349 msg = g_strdup_printf(_("HTTP proxy connection error %d"), status); |
1344 if(phb->account) | 1350 gaim_proxy_phb_error(phb, msg); |
1345 gaim_connection_error(phb->account->gc, msg); | |
1346 else | |
1347 gaim_debug_error("http proxy", "%s\n", msg); | |
1348 g_free(msg); | 1351 g_free(msg); |
1349 gaim_input_remove(phb->inpa); | |
1350 g_free(phb->read_buffer); | |
1351 g_free(phb->host); | |
1352 g_free(phb); | |
1353 } | 1352 } |
1354 } else { | 1353 } else { |
1355 gaim_input_remove(phb->inpa); | 1354 gaim_input_remove(phb->inpa); |
1355 phb->inpa = 0; | |
1356 g_free(phb->read_buffer); | 1356 g_free(phb->read_buffer); |
1357 phb->read_buffer = NULL; | 1357 phb->read_buffer = NULL; |
1358 http_complete(phb, source); | 1358 gaim_debug_info("proxy", "HTTP proxy connection established\n"); |
1359 gaim_proxy_phb_connected(phb, source); | |
1359 return; | 1360 return; |
1360 } | 1361 } |
1361 } | 1362 } |
1362 | 1363 |
1363 | 1364 |
1372 int error = ETIMEDOUT; | 1373 int error = ETIMEDOUT; |
1373 | 1374 |
1374 gaim_debug_info("http proxy", "Connected.\n"); | 1375 gaim_debug_info("http proxy", "Connected.\n"); |
1375 | 1376 |
1376 if (phb->inpa > 0) | 1377 if (phb->inpa > 0) |
1378 { | |
1377 gaim_input_remove(phb->inpa); | 1379 gaim_input_remove(phb->inpa); |
1380 phb->inpa = 0; | |
1381 } | |
1378 | 1382 |
1379 len = sizeof(error); | 1383 len = sizeof(error); |
1380 | 1384 |
1381 if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { | 1385 if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { |
1382 close(source); | 1386 close(source); |
1454 if (phb->port != 80) { | 1458 if (phb->port != 80) { |
1455 /* we need to do CONNECT first */ | 1459 /* we need to do CONNECT first */ |
1456 phb->inpa = gaim_input_add(fd, GAIM_INPUT_WRITE, | 1460 phb->inpa = gaim_input_add(fd, GAIM_INPUT_WRITE, |
1457 http_canwrite, phb); | 1461 http_canwrite, phb); |
1458 } else { | 1462 } else { |
1459 http_complete(phb, fd); | 1463 gaim_debug_info("proxy", "HTTP proxy connection established\n"); |
1464 gaim_proxy_phb_connected(phb, fd); | |
1460 } | 1465 } |
1461 } else { | 1466 } else { |
1462 close(fd); | 1467 close(fd); |
1463 return -1; | 1468 return -1; |
1464 } | 1469 } |
1505 | 1510 |
1506 if ((len < 0 && errno == EAGAIN) || (len > 0 && len + phb->read_len < 4)) | 1511 if ((len < 0 && errno == EAGAIN) || (len > 0 && len + phb->read_len < 4)) |
1507 return; | 1512 return; |
1508 else if (len + phb->read_len >= 4) { | 1513 else if (len + phb->read_len >= 4) { |
1509 if (phb->read_buffer[1] == 90) { | 1514 if (phb->read_buffer[1] == 90) { |
1510 if (phb->account == NULL || | 1515 gaim_proxy_phb_connected(phb, source); |
1511 gaim_account_get_connection(phb->account) != NULL) { | |
1512 | |
1513 phb->func(phb->data, source, GAIM_INPUT_READ); | |
1514 } | |
1515 | |
1516 gaim_input_remove(phb->inpa); | |
1517 g_free(phb->read_buffer); | |
1518 g_free(phb->host); | |
1519 g_free(phb); | |
1520 return; | 1516 return; |
1521 } | 1517 } |
1522 } | 1518 } |
1523 | 1519 |
1524 gaim_input_remove(phb->inpa); | 1520 gaim_input_remove(phb->inpa); |
1521 phb->inpa = 0; | |
1525 g_free(phb->read_buffer); | 1522 g_free(phb->read_buffer); |
1526 phb->read_buffer = NULL; | 1523 phb->read_buffer = NULL; |
1527 | 1524 |
1528 close(source); | 1525 close(source); |
1529 | 1526 |
1540 int error = ETIMEDOUT; | 1537 int error = ETIMEDOUT; |
1541 | 1538 |
1542 gaim_debug_info("socks4 proxy", "Connected.\n"); | 1539 gaim_debug_info("socks4 proxy", "Connected.\n"); |
1543 | 1540 |
1544 if (phb->inpa > 0) | 1541 if (phb->inpa > 0) |
1542 { | |
1545 gaim_input_remove(phb->inpa); | 1543 gaim_input_remove(phb->inpa); |
1544 phb->inpa = 0; | |
1545 } | |
1546 | 1546 |
1547 len = sizeof(error); | 1547 len = sizeof(error); |
1548 | 1548 |
1549 if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { | 1549 if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { |
1550 close(source); | 1550 close(source); |
1660 return; | 1660 return; |
1661 else if(len <= 0) { | 1661 else if(len <= 0) { |
1662 gaim_debug_warning("socks5 proxy", "or not...\n"); | 1662 gaim_debug_warning("socks5 proxy", "or not...\n"); |
1663 close(source); | 1663 close(source); |
1664 gaim_input_remove(phb->inpa); | 1664 gaim_input_remove(phb->inpa); |
1665 phb->inpa = 0; | |
1665 g_free(phb->read_buffer); | 1666 g_free(phb->read_buffer); |
1666 phb->read_buffer = NULL; | 1667 phb->read_buffer = NULL; |
1667 try_connect(phb); | 1668 try_connect(phb); |
1668 return; | 1669 return; |
1669 } | 1670 } |
1677 gaim_debug_error("socks5 proxy", socks5errors[buf[1]]); | 1678 gaim_debug_error("socks5 proxy", socks5errors[buf[1]]); |
1678 else | 1679 else |
1679 gaim_debug_error("socks5 proxy", "Bad data.\n"); | 1680 gaim_debug_error("socks5 proxy", "Bad data.\n"); |
1680 close(source); | 1681 close(source); |
1681 gaim_input_remove(phb->inpa); | 1682 gaim_input_remove(phb->inpa); |
1683 phb->inpa = 0; | |
1682 g_free(phb->read_buffer); | 1684 g_free(phb->read_buffer); |
1683 phb->read_buffer = NULL; | 1685 phb->read_buffer = NULL; |
1684 try_connect(phb); | 1686 try_connect(phb); |
1685 return; | 1687 return; |
1686 } | 1688 } |
1713 return; | 1715 return; |
1714 | 1716 |
1715 /* Skip past BND.PORT */ | 1717 /* Skip past BND.PORT */ |
1716 buf += 2; | 1718 buf += 2; |
1717 | 1719 |
1718 if (phb->account == NULL || | 1720 gaim_proxy_phb_connected(phb, source); |
1719 gaim_account_get_connection(phb->account) != NULL) { | |
1720 | |
1721 phb->func(phb->data, source, GAIM_INPUT_READ); | |
1722 } | |
1723 | |
1724 gaim_input_remove(phb->inpa); | |
1725 g_free(phb->read_buffer); | |
1726 g_free(phb->host); | |
1727 g_free(phb); | |
1728 } | 1721 } |
1729 | 1722 |
1730 static void | 1723 static void |
1731 s5_sendconnect(gpointer data, gint source) | 1724 s5_sendconnect(gpointer data, int source) |
1732 { | 1725 { |
1733 struct PHB *phb = data; | 1726 struct PHB *phb = data; |
1734 int hlen = strlen(phb->host); | 1727 int hlen = strlen(phb->host); |
1735 phb->write_buf_len = 5 + hlen + 2; | 1728 phb->write_buf_len = 5 + hlen + 2; |
1736 phb->write_buffer = g_malloc(phb->write_buf_len); | 1729 phb->write_buffer = g_malloc(phb->write_buf_len); |
1747 | 1740 |
1748 phb->read_cb = s5_canread_again; | 1741 phb->read_cb = s5_canread_again; |
1749 | 1742 |
1750 phb->inpa = gaim_input_add(source, GAIM_INPUT_WRITE, proxy_do_write, phb); | 1743 phb->inpa = gaim_input_add(source, GAIM_INPUT_WRITE, proxy_do_write, phb); |
1751 proxy_do_write(phb, source, GAIM_INPUT_WRITE); | 1744 proxy_do_write(phb, source, GAIM_INPUT_WRITE); |
1752 | |
1753 } | 1745 } |
1754 | 1746 |
1755 static void | 1747 static void |
1756 s5_readauth(gpointer data, gint source, GaimInputCondition cond) | 1748 s5_readauth(gpointer data, gint source, GaimInputCondition cond) |
1757 { | 1749 { |
1771 if(len < 0 && errno == EAGAIN) | 1763 if(len < 0 && errno == EAGAIN) |
1772 return; | 1764 return; |
1773 else if(len <= 0) { | 1765 else if(len <= 0) { |
1774 close(source); | 1766 close(source); |
1775 gaim_input_remove(phb->inpa); | 1767 gaim_input_remove(phb->inpa); |
1768 phb->inpa = 0; | |
1776 g_free(phb->read_buffer); | 1769 g_free(phb->read_buffer); |
1777 phb->read_buffer = NULL; | 1770 phb->read_buffer = NULL; |
1778 try_connect(phb); | 1771 try_connect(phb); |
1779 return; | 1772 return; |
1780 } | 1773 } |
1782 | 1775 |
1783 if (phb->read_len < 2) | 1776 if (phb->read_len < 2) |
1784 return; | 1777 return; |
1785 | 1778 |
1786 gaim_input_remove(phb->inpa); | 1779 gaim_input_remove(phb->inpa); |
1780 phb->inpa = 0; | |
1787 | 1781 |
1788 if ((phb->read_buffer[0] != 0x01) || (phb->read_buffer[1] != 0x00)) { | 1782 if ((phb->read_buffer[0] != 0x01) || (phb->read_buffer[1] != 0x00)) { |
1789 close(source); | 1783 close(source); |
1790 g_free(phb->read_buffer); | 1784 g_free(phb->read_buffer); |
1791 phb->read_buffer = NULL; | 1785 phb->read_buffer = NULL; |
1863 if(len < 0 && errno == EAGAIN) | 1857 if(len < 0 && errno == EAGAIN) |
1864 return; | 1858 return; |
1865 else if(len <= 0) { | 1859 else if(len <= 0) { |
1866 close(source); | 1860 close(source); |
1867 gaim_input_remove(phb->inpa); | 1861 gaim_input_remove(phb->inpa); |
1862 phb->inpa = 0; | |
1868 g_free(phb->read_buffer); | 1863 g_free(phb->read_buffer); |
1869 phb->read_buffer = NULL; | 1864 phb->read_buffer = NULL; |
1870 try_connect(phb); | 1865 try_connect(phb); |
1871 return; | 1866 return; |
1872 } | 1867 } |
1878 cmdbuf = phb->read_buffer; | 1873 cmdbuf = phb->read_buffer; |
1879 | 1874 |
1880 if (*cmdbuf != 0x01) { | 1875 if (*cmdbuf != 0x01) { |
1881 close(source); | 1876 close(source); |
1882 gaim_input_remove(phb->inpa); | 1877 gaim_input_remove(phb->inpa); |
1878 phb->inpa = 0; | |
1883 g_free(phb->read_buffer); | 1879 g_free(phb->read_buffer); |
1884 phb->read_buffer = NULL; | 1880 phb->read_buffer = NULL; |
1885 try_connect(phb); | 1881 try_connect(phb); |
1886 return; | 1882 return; |
1887 } | 1883 } |
1899 switch (cmdbuf[0]) { | 1895 switch (cmdbuf[0]) { |
1900 case 0x00: | 1896 case 0x00: |
1901 /* Did auth work? */ | 1897 /* Did auth work? */ |
1902 if (buf[0] == 0x00) { | 1898 if (buf[0] == 0x00) { |
1903 gaim_input_remove(phb->inpa); | 1899 gaim_input_remove(phb->inpa); |
1900 phb->inpa = 0; | |
1904 g_free(phb->read_buffer); | 1901 g_free(phb->read_buffer); |
1905 phb->read_buffer = NULL; | 1902 phb->read_buffer = NULL; |
1906 /* Success */ | 1903 /* Success */ |
1907 s5_sendconnect(phb, source); | 1904 s5_sendconnect(phb, source); |
1908 return; | 1905 return; |
1911 gaim_debug_warning("proxy", | 1908 gaim_debug_warning("proxy", |
1912 "socks5 CHAP authentication " | 1909 "socks5 CHAP authentication " |
1913 "failed. Disconnecting..."); | 1910 "failed. Disconnecting..."); |
1914 close(source); | 1911 close(source); |
1915 gaim_input_remove(phb->inpa); | 1912 gaim_input_remove(phb->inpa); |
1913 phb->inpa = 0; | |
1916 g_free(phb->read_buffer); | 1914 g_free(phb->read_buffer); |
1917 phb->read_buffer = NULL; | 1915 phb->read_buffer = NULL; |
1918 try_connect(phb); | 1916 try_connect(phb); |
1919 return; | 1917 return; |
1920 } | 1918 } |
1955 "as supporting. This is a violation " | 1953 "as supporting. This is a violation " |
1956 "of the socks5 CHAP specification. " | 1954 "of the socks5 CHAP specification. " |
1957 "Disconnecting..."); | 1955 "Disconnecting..."); |
1958 close(source); | 1956 close(source); |
1959 gaim_input_remove(phb->inpa); | 1957 gaim_input_remove(phb->inpa); |
1958 phb->inpa = 0; | |
1960 g_free(phb->read_buffer); | 1959 g_free(phb->read_buffer); |
1961 phb->read_buffer = NULL; | 1960 phb->read_buffer = NULL; |
1962 try_connect(phb); | 1961 try_connect(phb); |
1963 return; | 1962 return; |
1964 } | 1963 } |
1990 if(len < 0 && errno == EAGAIN) | 1989 if(len < 0 && errno == EAGAIN) |
1991 return; | 1990 return; |
1992 else if(len <= 0) { | 1991 else if(len <= 0) { |
1993 close(source); | 1992 close(source); |
1994 gaim_input_remove(phb->inpa); | 1993 gaim_input_remove(phb->inpa); |
1994 phb->inpa = 0; | |
1995 g_free(phb->read_buffer); | 1995 g_free(phb->read_buffer); |
1996 phb->read_buffer = NULL; | 1996 phb->read_buffer = NULL; |
1997 try_connect(phb); | 1997 try_connect(phb); |
1998 return; | 1998 return; |
1999 } | 1999 } |
2001 | 2001 |
2002 if (phb->read_len < 2) | 2002 if (phb->read_len < 2) |
2003 return; | 2003 return; |
2004 | 2004 |
2005 gaim_input_remove(phb->inpa); | 2005 gaim_input_remove(phb->inpa); |
2006 phb->inpa = 0; | |
2006 | 2007 |
2007 if ((phb->read_buffer[0] != 0x05) || (phb->read_buffer[1] == 0xff)) { | 2008 if ((phb->read_buffer[0] != 0x05) || (phb->read_buffer[1] == 0xff)) { |
2008 close(source); | 2009 close(source); |
2009 g_free(phb->read_buffer); | 2010 g_free(phb->read_buffer); |
2010 phb->read_buffer = NULL; | 2011 phb->read_buffer = NULL; |
2092 int error = ETIMEDOUT; | 2093 int error = ETIMEDOUT; |
2093 | 2094 |
2094 gaim_debug_info("socks5 proxy", "Connected.\n"); | 2095 gaim_debug_info("socks5 proxy", "Connected.\n"); |
2095 | 2096 |
2096 if (phb->inpa > 0) | 2097 if (phb->inpa > 0) |
2098 { | |
2097 gaim_input_remove(phb->inpa); | 2099 gaim_input_remove(phb->inpa); |
2100 phb->inpa = 0; | |
2101 } | |
2098 | 2102 |
2099 len = sizeof(error); | 2103 len = sizeof(error); |
2100 if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { | 2104 if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { |
2101 close(source); | 2105 close(source); |
2102 | 2106 |
2223 if (ret > 0) | 2227 if (ret > 0) |
2224 break; | 2228 break; |
2225 } | 2229 } |
2226 | 2230 |
2227 if (ret < 0) { | 2231 if (ret < 0) { |
2228 if (phb->account == NULL || | 2232 gaim_proxy_phb_error(phb, _("TODO")); |
2229 gaim_account_get_connection(phb->account) != NULL) { | |
2230 | |
2231 phb->func(phb->data, -1, GAIM_INPUT_READ); | |
2232 } | |
2233 | |
2234 g_free(phb->host); | |
2235 g_free(phb); | |
2236 } | 2233 } |
2237 } | 2234 } |
2238 | 2235 |
2239 static void | 2236 static void |
2240 connection_host_resolved(GSList *hosts, gpointer data, | 2237 connection_host_resolved(GSList *hosts, gpointer data, |
2311 } | 2308 } |
2312 | 2309 |
2313 return gpi; | 2310 return gpi; |
2314 } | 2311 } |
2315 | 2312 |
2316 /* | 2313 GaimProxyConnectInfo * |
2317 * TODO: It would be really good if this returned some sort of handle | |
2318 * that we could use to cancel the connection. As it is now, | |
2319 * each callback has to check to make sure gc is still valid. | |
2320 * And that is ugly. | |
2321 */ | |
2322 int | |
2323 gaim_proxy_connect(GaimAccount *account, const char *host, int port, | 2314 gaim_proxy_connect(GaimAccount *account, const char *host, int port, |
2324 GaimInputFunction func, gpointer data) | 2315 GaimProxyConnectFunction connect_cb, |
2316 GaimProxyErrorFunction error_cb, gpointer data) | |
2325 { | 2317 { |
2326 const char *connecthost = host; | 2318 const char *connecthost = host; |
2327 int connectport = port; | 2319 int connectport = port; |
2328 struct PHB *phb; | 2320 struct PHB *phb; |
2329 | 2321 |
2330 g_return_val_if_fail(host != NULL, -1); | 2322 g_return_val_if_fail(host != NULL, NULL); |
2331 g_return_val_if_fail(port != 0 && port != -1, -1); | 2323 g_return_val_if_fail(port > 0, NULL); |
2332 g_return_val_if_fail(func != NULL, -1); | 2324 g_return_val_if_fail(connect_cb != NULL, NULL); |
2325 /* g_return_val_if_fail(error_cb != NULL, NULL); *//* TODO: Soon! */ | |
2333 | 2326 |
2334 phb = g_new0(struct PHB, 1); | 2327 phb = g_new0(struct PHB, 1); |
2335 | 2328 phb->connect_cb = connect_cb; |
2336 phb->func = func; | 2329 phb->error_cb = error_cb; |
2337 phb->data = data; | 2330 phb->data = data; |
2338 phb->host = g_strdup(host); | 2331 phb->host = g_strdup(host); |
2339 phb->port = port; | 2332 phb->port = port; |
2340 phb->account = account; | |
2341 phb->gpi = gaim_proxy_get_setup(account); | 2333 phb->gpi = gaim_proxy_get_setup(account); |
2342 | 2334 |
2343 if ((gaim_proxy_info_get_type(phb->gpi) != GAIM_PROXY_NONE) && | 2335 if ((gaim_proxy_info_get_type(phb->gpi) != GAIM_PROXY_NONE) && |
2344 (gaim_proxy_info_get_host(phb->gpi) == NULL || | 2336 (gaim_proxy_info_get_host(phb->gpi) == NULL || |
2345 gaim_proxy_info_get_port(phb->gpi) <= 0)) { | 2337 gaim_proxy_info_get_port(phb->gpi) <= 0)) { |
2346 | 2338 |
2347 gaim_notify_error(NULL, NULL, _("Invalid proxy settings"), _("Either the host name or port number specified for your given proxy type is invalid.")); | 2339 gaim_notify_error(NULL, NULL, _("Invalid proxy settings"), _("Either the host name or port number specified for your given proxy type is invalid.")); |
2348 g_free(phb->host); | 2340 gaim_proxy_phb_destroy(phb); |
2349 g_free(phb); | 2341 return NULL; |
2350 return -1; | |
2351 } | 2342 } |
2352 | 2343 |
2353 switch (gaim_proxy_info_get_type(phb->gpi)) | 2344 switch (gaim_proxy_info_get_type(phb->gpi)) |
2354 { | 2345 { |
2355 case GAIM_PROXY_NONE: | 2346 case GAIM_PROXY_NONE: |
2362 connecthost = gaim_proxy_info_get_host(phb->gpi); | 2353 connecthost = gaim_proxy_info_get_host(phb->gpi); |
2363 connectport = gaim_proxy_info_get_port(phb->gpi); | 2354 connectport = gaim_proxy_info_get_port(phb->gpi); |
2364 break; | 2355 break; |
2365 | 2356 |
2366 default: | 2357 default: |
2367 g_free(phb->host); | 2358 gaim_proxy_phb_destroy(phb); |
2368 g_free(phb); | 2359 return NULL; |
2369 return -1; | 2360 } |
2370 } | 2361 |
2371 | 2362 if (gaim_gethostbyname_async(connecthost, |
2372 return gaim_gethostbyname_async(connecthost, connectport, | 2363 connectport, connection_host_resolved, phb) != 0) |
2373 connection_host_resolved, phb); | 2364 { |
2374 } | 2365 gaim_proxy_phb_destroy(phb); |
2375 | 2366 return NULL; |
2376 int | 2367 } |
2368 | |
2369 phbs = g_slist_prepend(phbs, phb); | |
2370 | |
2371 return phb; | |
2372 } | |
2373 | |
2374 /* | |
2375 * Combine some of this code with gaim_proxy_connect() | |
2376 */ | |
2377 GaimProxyConnectInfo * | |
2377 gaim_proxy_connect_socks5(GaimProxyInfo *gpi, const char *host, int port, | 2378 gaim_proxy_connect_socks5(GaimProxyInfo *gpi, const char *host, int port, |
2378 GaimInputFunction func, gpointer data) | 2379 GaimProxyConnectFunction connect_cb, |
2380 GaimProxyErrorFunction error_cb, gpointer data) | |
2379 { | 2381 { |
2380 struct PHB *phb; | 2382 struct PHB *phb; |
2381 | 2383 |
2384 g_return_val_if_fail(host != NULL, NULL); | |
2385 g_return_val_if_fail(port > 0, NULL); | |
2386 g_return_val_if_fail(connect_cb != NULL, NULL); | |
2387 /* g_return_val_if_fail(error_cb != NULL, NULL); *//* TODO: Soon! */ | |
2388 | |
2382 phb = g_new0(struct PHB, 1); | 2389 phb = g_new0(struct PHB, 1); |
2383 phb->gpi = gpi; | 2390 phb->connect_cb = connect_cb; |
2384 phb->func = func; | 2391 phb->error_cb = error_cb; |
2385 phb->data = data; | 2392 phb->data = data; |
2386 phb->host = g_strdup(host); | 2393 phb->host = g_strdup(host); |
2387 phb->port = port; | 2394 phb->port = port; |
2388 | 2395 phb->gpi = gpi; |
2389 return gaim_gethostbyname_async(gaim_proxy_info_get_host(gpi), | 2396 |
2390 gaim_proxy_info_get_port(gpi), connection_host_resolved, phb); | 2397 if (gaim_gethostbyname_async(gaim_proxy_info_get_host(gpi), |
2398 gaim_proxy_info_get_port(gpi), connection_host_resolved, phb) != 0) | |
2399 { | |
2400 gaim_proxy_phb_destroy(phb); | |
2401 return NULL; | |
2402 } | |
2403 | |
2404 phbs = g_slist_prepend(phbs, phb); | |
2405 | |
2406 return phb; | |
2391 } | 2407 } |
2392 | 2408 |
2393 | 2409 |
2394 static void | 2410 static void |
2395 proxy_pref_cb(const char *name, GaimPrefType type, | 2411 proxy_pref_cb(const char *name, GaimPrefType type, |
2421 gaim_proxy_info_set_port(info, GPOINTER_TO_INT(value)); | 2437 gaim_proxy_info_set_port(info, GPOINTER_TO_INT(value)); |
2422 else if (!strcmp(name, "/core/proxy/username")) | 2438 else if (!strcmp(name, "/core/proxy/username")) |
2423 gaim_proxy_info_set_username(info, value); | 2439 gaim_proxy_info_set_username(info, value); |
2424 else if (!strcmp(name, "/core/proxy/password")) | 2440 else if (!strcmp(name, "/core/proxy/password")) |
2425 gaim_proxy_info_set_password(info, value); | 2441 gaim_proxy_info_set_password(info, value); |
2442 } | |
2443 | |
2444 void * | |
2445 gaim_proxy_get_handle() | |
2446 { | |
2447 static int handle; | |
2448 | |
2449 return &handle; | |
2426 } | 2450 } |
2427 | 2451 |
2428 void | 2452 void |
2429 gaim_proxy_init(void) | 2453 gaim_proxy_init(void) |
2430 { | 2454 { |
2457 if(!g_thread_supported()) | 2481 if(!g_thread_supported()) |
2458 g_thread_init(NULL); | 2482 g_thread_init(NULL); |
2459 #endif | 2483 #endif |
2460 } | 2484 } |
2461 | 2485 |
2462 void * | 2486 void |
2463 gaim_proxy_get_handle() | 2487 gaim_proxy_uninit(void) |
2464 { | 2488 { |
2465 static int handle; | 2489 while (phbs != NULL) |
2466 | 2490 gaim_proxy_phb_destroy(phbs->data); |
2467 return &handle; | 2491 } |
2468 } |