Mercurial > pidgin
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 } |
