Mercurial > pidgin
comparison src/proxy.c @ 14096:a70c6011dc81
[gaim-migrate @ 16725]
Rename "phb" to "connect_info" everywhere
committer: Tailor Script <tailor@pidgin.im>
| author | Mark Doliner <mark@kingant.net> |
|---|---|
| date | Sat, 12 Aug 2006 20:40:07 +0000 |
| parents | 3b871b67556d |
| children | 7ded3834168f |
comparison
equal
deleted
inserted
replaced
| 14095:3b871b67556d | 14096:a70c6011dc81 |
|---|---|
| 67 "Command not supported\n", | 67 "Command not supported\n", |
| 68 "Address type not supported\n" | 68 "Address type not supported\n" |
| 69 }; | 69 }; |
| 70 | 70 |
| 71 static GaimProxyInfo *global_proxy_info = NULL; | 71 static GaimProxyInfo *global_proxy_info = NULL; |
| 72 static GSList *phbs = NULL; | 72 static GSList *connect_infos = NULL; |
| 73 | 73 |
| 74 static void try_connect(struct _GaimProxyConnectInfo *); | 74 static void try_connect(struct _GaimProxyConnectInfo *); |
| 75 | 75 |
| 76 /************************************************************************** | 76 /************************************************************************** |
| 77 * Proxy structure API | 77 * Proxy structure API |
| 255 /************************************************************************** | 255 /************************************************************************** |
| 256 * Proxy API | 256 * Proxy API |
| 257 **************************************************************************/ | 257 **************************************************************************/ |
| 258 | 258 |
| 259 static void | 259 static void |
| 260 gaim_proxy_phb_destroy(struct _GaimProxyConnectInfo *phb) | 260 gaim_proxy_connect_info_destroy(struct _GaimProxyConnectInfo *connect_info) |
| 261 { | 261 { |
| 262 phbs = g_slist_remove(phbs, phb); | 262 connect_infos = g_slist_remove(connect_infos, connect_info); |
| 263 | 263 |
| 264 if (phb->inpa > 0) | 264 if (connect_info->inpa > 0) |
| 265 gaim_input_remove(phb->inpa); | 265 gaim_input_remove(connect_info->inpa); |
| 266 | 266 |
| 267 while (phb->hosts != NULL) | 267 while (connect_info->hosts != NULL) |
| 268 { | 268 { |
| 269 /* Discard the length... */ | 269 /* Discard the length... */ |
| 270 phb->hosts = g_slist_remove(phb->hosts, phb->hosts->data); | 270 connect_info->hosts = g_slist_remove(connect_info->hosts, connect_info->hosts->data); |
| 271 /* Free the address... */ | 271 /* Free the address... */ |
| 272 g_free(phb->hosts->data); | 272 g_free(connect_info->hosts->data); |
| 273 phb->hosts = g_slist_remove(phb->hosts, phb->hosts->data); | 273 connect_info->hosts = g_slist_remove(connect_info->hosts, connect_info->hosts->data); |
| 274 } | 274 } |
| 275 | 275 |
| 276 g_free(phb->host); | 276 g_free(connect_info->host); |
| 277 g_free(phb->write_buffer); | 277 g_free(connect_info->write_buffer); |
| 278 g_free(phb->read_buffer); | 278 g_free(connect_info->read_buffer); |
| 279 g_free(phb); | 279 g_free(connect_info); |
| 280 } | 280 } |
| 281 | 281 |
| 282 static void | 282 static void |
| 283 gaim_proxy_phb_connected(struct _GaimProxyConnectInfo *phb, int fd) | 283 gaim_proxy_connect_info_connected(struct _GaimProxyConnectInfo *connect_info, int fd) |
| 284 { | 284 { |
| 285 phb->connect_cb(phb->data, fd); | 285 connect_info->connect_cb(connect_info->data, fd); |
| 286 gaim_proxy_phb_destroy(phb); | 286 gaim_proxy_connect_info_destroy(connect_info); |
| 287 } | 287 } |
| 288 | 288 |
| 289 /** | 289 /** |
| 290 * @param error An error message explaining why the connection | 290 * @param error An error message explaining why the connection |
| 291 * failed. This will be passed to the callback function | 291 * failed. This will be passed to the callback function |
| 292 * specified in the call to gaim_proxy_connect(). | 292 * specified in the call to gaim_proxy_connect(). |
| 293 */ | 293 */ |
| 294 static void | 294 static void |
| 295 gaim_proxy_phb_error(struct _GaimProxyConnectInfo *phb, const gchar *error_message) | 295 gaim_proxy_connect_info_error(struct _GaimProxyConnectInfo *connect_info, const gchar *error_message) |
| 296 { | 296 { |
| 297 if (phb->error_cb == NULL) | 297 if (connect_info->error_cb == NULL) |
| 298 { | 298 { |
| 299 /* | 299 /* |
| 300 * TODO | 300 * TODO |
| 301 * While we're transitioning to the new gaim_proxy_connect() | 301 * While we're transitioning to the new gaim_proxy_connect() |
| 302 * code, not all callers supply an error_cb. If this is the | 302 * code, not all callers supply an error_cb. If this is the |
| 303 * case then they're expecting connect_cb to be called with | 303 * case then they're expecting connect_cb to be called with |
| 304 * an fd of -1 in the case of an error. Once all callers have | 304 * an fd of -1 in the case of an error. Once all callers have |
| 305 * been changed this whole if statement should be removed. | 305 * been changed this whole if statement should be removed. |
| 306 */ | 306 */ |
| 307 phb->connect_cb(phb->data, -1); | 307 connect_info->connect_cb(connect_info->data, -1); |
| 308 gaim_proxy_phb_destroy(phb); | 308 gaim_proxy_connect_info_destroy(connect_info); |
| 309 return; | 309 return; |
| 310 } | 310 } |
| 311 | 311 |
| 312 phb->error_cb(phb->data, error_message); | 312 connect_info->error_cb(connect_info->data, error_message); |
| 313 gaim_proxy_phb_destroy(phb); | 313 gaim_proxy_connect_info_destroy(connect_info); |
| 314 } | 314 } |
| 315 | 315 |
| 316 #if defined(__unix__) || defined(__APPLE__) | 316 #if defined(__unix__) || defined(__APPLE__) |
| 317 | 317 |
| 318 /* | 318 /* |
| 988 #endif /* not __unix__ or __APPLE__ or _WIN32 */ | 988 #endif /* not __unix__ or __APPLE__ or _WIN32 */ |
| 989 | 989 |
| 990 static void | 990 static void |
| 991 no_one_calls(gpointer data, gint source, GaimInputCondition cond) | 991 no_one_calls(gpointer data, gint source, GaimInputCondition cond) |
| 992 { | 992 { |
| 993 struct _GaimProxyConnectInfo *phb = data; | 993 struct _GaimProxyConnectInfo *connect_info = data; |
| 994 socklen_t len; | 994 socklen_t len; |
| 995 int error=0, ret; | 995 int error=0, ret; |
| 996 | 996 |
| 997 gaim_debug_info("proxy", "Connected.\n"); | 997 gaim_debug_info("proxy", "Connected.\n"); |
| 998 | 998 |
| 1014 return; /* we'll be called again later */ | 1014 return; /* we'll be called again later */ |
| 1015 if (ret < 0 || error != 0) { | 1015 if (ret < 0 || error != 0) { |
| 1016 if (ret!=0) | 1016 if (ret!=0) |
| 1017 error = errno; | 1017 error = errno; |
| 1018 close(source); | 1018 close(source); |
| 1019 gaim_input_remove(phb->inpa); | 1019 gaim_input_remove(connect_info->inpa); |
| 1020 phb->inpa = 0; | 1020 connect_info->inpa = 0; |
| 1021 | 1021 |
| 1022 gaim_debug_error("proxy", | 1022 gaim_debug_error("proxy", |
| 1023 "getsockopt SO_ERROR check: %s\n", strerror(error)); | 1023 "getsockopt SO_ERROR check: %s\n", strerror(error)); |
| 1024 | 1024 |
| 1025 try_connect(phb); | 1025 try_connect(connect_info); |
| 1026 return; | 1026 return; |
| 1027 } | 1027 } |
| 1028 | 1028 |
| 1029 gaim_input_remove(phb->inpa); | 1029 gaim_input_remove(connect_info->inpa); |
| 1030 phb->inpa = 0; | 1030 connect_info->inpa = 0; |
| 1031 | 1031 |
| 1032 gaim_proxy_phb_connected(phb, source); | 1032 gaim_proxy_connect_info_connected(connect_info, source); |
| 1033 } | 1033 } |
| 1034 | 1034 |
| 1035 static gboolean clean_connect(gpointer data) | 1035 static gboolean clean_connect(gpointer data) |
| 1036 { | 1036 { |
| 1037 struct _GaimProxyConnectInfo *phb = data; | 1037 struct _GaimProxyConnectInfo *connect_info = data; |
| 1038 | 1038 |
| 1039 gaim_proxy_phb_connected(phb, phb->port); | 1039 gaim_proxy_connect_info_connected(connect_info, connect_info->port); |
| 1040 | 1040 |
| 1041 return FALSE; | 1041 return FALSE; |
| 1042 } | 1042 } |
| 1043 | 1043 |
| 1044 | 1044 |
| 1045 static int | 1045 static int |
| 1046 proxy_connect_none(struct _GaimProxyConnectInfo *phb, struct sockaddr *addr, socklen_t addrlen) | 1046 proxy_connect_none(struct _GaimProxyConnectInfo *connect_info, struct sockaddr *addr, socklen_t addrlen) |
| 1047 { | 1047 { |
| 1048 int fd = -1; | 1048 int fd = -1; |
| 1049 | 1049 |
| 1050 gaim_debug_info("proxy", | 1050 gaim_debug_info("proxy", |
| 1051 "Connecting to %s:%d with no proxy\n", phb->host, phb->port); | 1051 "Connecting to %s:%d with no proxy\n", connect_info->host, connect_info->port); |
| 1052 | 1052 |
| 1053 if ((fd = socket(addr->sa_family, SOCK_STREAM, 0)) < 0) { | 1053 if ((fd = socket(addr->sa_family, SOCK_STREAM, 0)) < 0) { |
| 1054 gaim_debug_error("proxy", | 1054 gaim_debug_error("proxy", |
| 1055 "Unable to create socket: %s\n", strerror(errno)); | 1055 "Unable to create socket: %s\n", strerror(errno)); |
| 1056 return -1; | 1056 return -1; |
| 1063 if (connect(fd, (struct sockaddr *)addr, addrlen) < 0) { | 1063 if (connect(fd, (struct sockaddr *)addr, addrlen) < 0) { |
| 1064 if ((errno == EINPROGRESS) || (errno == EINTR)) { | 1064 if ((errno == EINPROGRESS) || (errno == EINTR)) { |
| 1065 /* This just confuses people. */ | 1065 /* This just confuses people. */ |
| 1066 /* gaim_debug_warning("proxy", | 1066 /* gaim_debug_warning("proxy", |
| 1067 "Connect would have blocked.\n"); */ | 1067 "Connect would have blocked.\n"); */ |
| 1068 phb->inpa = gaim_input_add(fd, GAIM_INPUT_WRITE, no_one_calls, phb); | 1068 connect_info->inpa = gaim_input_add(fd, GAIM_INPUT_WRITE, no_one_calls, connect_info); |
| 1069 } | 1069 } |
| 1070 else { | 1070 else { |
| 1071 gaim_debug_error("proxy", | 1071 gaim_debug_error("proxy", |
| 1072 "Connect failed: %s\n", strerror(errno)); | 1072 "Connect failed: %s\n", strerror(errno)); |
| 1073 close(fd); | 1073 close(fd); |
| 1083 gaim_debug_error("proxy", "getsockopt failed.\n"); | 1083 gaim_debug_error("proxy", "getsockopt failed.\n"); |
| 1084 close(fd); | 1084 close(fd); |
| 1085 return -1; | 1085 return -1; |
| 1086 } | 1086 } |
| 1087 /* TODO: Why is the following line so strange? */ | 1087 /* TODO: Why is the following line so strange? */ |
| 1088 phb->port = fd; /* bleh */ | 1088 connect_info->port = fd; /* bleh */ |
| 1089 gaim_timeout_add(10, clean_connect, phb); /* we do this because we never | 1089 gaim_timeout_add(10, clean_connect, connect_info); /* we do this because we never |
| 1090 want to call our callback | 1090 want to call our callback |
| 1091 before we return. */ | 1091 before we return. */ |
| 1092 } | 1092 } |
| 1093 | 1093 |
| 1094 return fd; | 1094 return fd; |
| 1095 } | 1095 } |
| 1096 | 1096 |
| 1097 static void | 1097 static void |
| 1098 proxy_do_write(gpointer data, gint source, GaimInputCondition cond) | 1098 proxy_do_write(gpointer data, gint source, GaimInputCondition cond) |
| 1099 { | 1099 { |
| 1100 struct _GaimProxyConnectInfo *phb = data; | 1100 struct _GaimProxyConnectInfo *connect_info = data; |
| 1101 const guchar *request = phb->write_buffer + phb->written_len; | 1101 const guchar *request = connect_info->write_buffer + connect_info->written_len; |
| 1102 gsize request_len = phb->write_buf_len - phb->written_len; | 1102 gsize request_len = connect_info->write_buf_len - connect_info->written_len; |
| 1103 | 1103 |
| 1104 int ret = write(source, request, request_len); | 1104 int ret = write(source, request, request_len); |
| 1105 | 1105 |
| 1106 if(ret < 0 && errno == EAGAIN) | 1106 if(ret < 0 && errno == EAGAIN) |
| 1107 return; | 1107 return; |
| 1108 else if(ret < 0) { | 1108 else if(ret < 0) { |
| 1109 gaim_input_remove(phb->inpa); | 1109 gaim_input_remove(connect_info->inpa); |
| 1110 phb->inpa = 0; | 1110 connect_info->inpa = 0; |
| 1111 close(source); | 1111 close(source); |
| 1112 g_free(phb->write_buffer); | 1112 g_free(connect_info->write_buffer); |
| 1113 phb->write_buffer = NULL; | 1113 connect_info->write_buffer = NULL; |
| 1114 try_connect(phb); | 1114 try_connect(connect_info); |
| 1115 return; | 1115 return; |
| 1116 } else if (ret < request_len) { | 1116 } else if (ret < request_len) { |
| 1117 phb->written_len += ret; | 1117 connect_info->written_len += ret; |
| 1118 return; | 1118 return; |
| 1119 } | 1119 } |
| 1120 | 1120 |
| 1121 gaim_input_remove(phb->inpa); | 1121 gaim_input_remove(connect_info->inpa); |
| 1122 g_free(phb->write_buffer); | 1122 g_free(connect_info->write_buffer); |
| 1123 phb->write_buffer = NULL; | 1123 connect_info->write_buffer = NULL; |
| 1124 | 1124 |
| 1125 /* register the response handler for the response */ | 1125 /* register the response handler for the response */ |
| 1126 phb->inpa = gaim_input_add(source, GAIM_INPUT_READ, phb->read_cb, phb); | 1126 connect_info->inpa = gaim_input_add(source, GAIM_INPUT_READ, connect_info->read_cb, connect_info); |
| 1127 } | 1127 } |
| 1128 | 1128 |
| 1129 #define HTTP_GOODSTRING "HTTP/1.0 200" | 1129 #define HTTP_GOODSTRING "HTTP/1.0 200" |
| 1130 #define HTTP_GOODSTRING2 "HTTP/1.1 200" | 1130 #define HTTP_GOODSTRING2 "HTTP/1.1 200" |
| 1131 | 1131 |
| 1133 static void | 1133 static void |
| 1134 http_canread(gpointer data, gint source, GaimInputCondition cond) | 1134 http_canread(gpointer data, gint source, GaimInputCondition cond) |
| 1135 { | 1135 { |
| 1136 int len, headers_len, status = 0; | 1136 int len, headers_len, status = 0; |
| 1137 gboolean error; | 1137 gboolean error; |
| 1138 struct _GaimProxyConnectInfo *phb = data; | 1138 struct _GaimProxyConnectInfo *connect_info = data; |
| 1139 guchar *p; | 1139 guchar *p; |
| 1140 gsize max_read; | 1140 gsize max_read; |
| 1141 gchar *msg; | 1141 gchar *msg; |
| 1142 | 1142 |
| 1143 if(phb->read_buffer == NULL) { | 1143 if(connect_info->read_buffer == NULL) { |
| 1144 phb->read_buf_len = 8192; | 1144 connect_info->read_buf_len = 8192; |
| 1145 phb->read_buffer = g_malloc(phb->read_buf_len); | 1145 connect_info->read_buffer = g_malloc(connect_info->read_buf_len); |
| 1146 phb->read_len = 0; | 1146 connect_info->read_len = 0; |
| 1147 } | 1147 } |
| 1148 | 1148 |
| 1149 p = phb->read_buffer + phb->read_len; | 1149 p = connect_info->read_buffer + connect_info->read_len; |
| 1150 max_read = phb->read_buf_len - phb->read_len - 1; | 1150 max_read = connect_info->read_buf_len - connect_info->read_len - 1; |
| 1151 | 1151 |
| 1152 len = read(source, p, max_read); | 1152 len = read(source, p, max_read); |
| 1153 if(len < 0 && errno == EAGAIN) | 1153 if(len < 0 && errno == EAGAIN) |
| 1154 return; | 1154 return; |
| 1155 else if(len <= 0) { | 1155 else if(len <= 0) { |
| 1156 close(source); | 1156 close(source); |
| 1157 gaim_proxy_phb_error(phb, _("Lost connection with server for an unknown reason.")); | 1157 gaim_proxy_connect_info_error(connect_info, _("Lost connection with server for an unknown reason.")); |
| 1158 return; | 1158 return; |
| 1159 } else { | 1159 } else { |
| 1160 phb->read_len += len; | 1160 connect_info->read_len += len; |
| 1161 } | 1161 } |
| 1162 p[len] = '\0'; | 1162 p[len] = '\0'; |
| 1163 | 1163 |
| 1164 if((p = (guchar *)g_strstr_len((const gchar *)phb->read_buffer, phb->read_len, "\r\n\r\n"))) { | 1164 if((p = (guchar *)g_strstr_len((const gchar *)connect_info->read_buffer, connect_info->read_len, "\r\n\r\n"))) { |
| 1165 *p = '\0'; | 1165 *p = '\0'; |
| 1166 headers_len = (p - phb->read_buffer) + 4; | 1166 headers_len = (p - connect_info->read_buffer) + 4; |
| 1167 } else if(len == max_read) | 1167 } else if(len == max_read) |
| 1168 headers_len = len; | 1168 headers_len = len; |
| 1169 else | 1169 else |
| 1170 return; | 1170 return; |
| 1171 | 1171 |
| 1172 error = strncmp((const char *)phb->read_buffer, "HTTP/", 5) != 0; | 1172 error = strncmp((const char *)connect_info->read_buffer, "HTTP/", 5) != 0; |
| 1173 if (!error) | 1173 if (!error) |
| 1174 { | 1174 { |
| 1175 int major; | 1175 int major; |
| 1176 p = phb->read_buffer + 5; | 1176 p = connect_info->read_buffer + 5; |
| 1177 major = strtol((const char *)p, (char **)&p, 10); | 1177 major = strtol((const char *)p, (char **)&p, 10); |
| 1178 error = (major == 0) || (*p != '.'); | 1178 error = (major == 0) || (*p != '.'); |
| 1179 if(!error) { | 1179 if(!error) { |
| 1180 int minor; | 1180 int minor; |
| 1181 p++; | 1181 p++; |
| 1188 } | 1188 } |
| 1189 } | 1189 } |
| 1190 } | 1190 } |
| 1191 | 1191 |
| 1192 /* Read the contents */ | 1192 /* Read the contents */ |
| 1193 p = (guchar *)g_strrstr((const gchar *)phb->read_buffer, "Content-Length: "); | 1193 p = (guchar *)g_strrstr((const gchar *)connect_info->read_buffer, "Content-Length: "); |
| 1194 if (p != NULL) | 1194 if (p != NULL) |
| 1195 { | 1195 { |
| 1196 gchar *tmp; | 1196 gchar *tmp; |
| 1197 int len = 0; | 1197 int len = 0; |
| 1198 char tmpc; | 1198 char tmpc; |
| 1203 len = atoi((const char *)p); | 1203 len = atoi((const char *)p); |
| 1204 if(tmp) | 1204 if(tmp) |
| 1205 *tmp = '\r'; | 1205 *tmp = '\r'; |
| 1206 | 1206 |
| 1207 /* Compensate for what has already been read */ | 1207 /* Compensate for what has already been read */ |
| 1208 len -= phb->read_len - headers_len; | 1208 len -= connect_info->read_len - headers_len; |
| 1209 /* I'm assuming that we're doing this to prevent the server from | 1209 /* I'm assuming that we're doing this to prevent the server from |
| 1210 complaining / breaking since we don't read the whole page */ | 1210 complaining / breaking since we don't read the whole page */ |
| 1211 while(len--) { | 1211 while(len--) { |
| 1212 /* TODO: deal with EAGAIN (and other errors) better */ | 1212 /* TODO: deal with EAGAIN (and other errors) better */ |
| 1213 if (read(source, &tmpc, 1) < 0 && errno != EAGAIN) | 1213 if (read(source, &tmpc, 1) < 0 && errno != EAGAIN) |
| 1217 | 1217 |
| 1218 if (error) | 1218 if (error) |
| 1219 { | 1219 { |
| 1220 close(source); | 1220 close(source); |
| 1221 msg = g_strdup_printf("Unable to parse response from HTTP proxy: %s\n", | 1221 msg = g_strdup_printf("Unable to parse response from HTTP proxy: %s\n", |
| 1222 phb->read_buffer); | 1222 connect_info->read_buffer); |
| 1223 gaim_proxy_phb_error(phb, msg); | 1223 gaim_proxy_connect_info_error(connect_info, msg); |
| 1224 g_free(msg); | 1224 g_free(msg); |
| 1225 return; | 1225 return; |
| 1226 } | 1226 } |
| 1227 else if (status != 200) | 1227 else if (status != 200) |
| 1228 { | 1228 { |
| 1229 gaim_debug_error("proxy", | 1229 gaim_debug_error("proxy", |
| 1230 "Proxy server replied with:\n%s\n", | 1230 "Proxy server replied with:\n%s\n", |
| 1231 phb->read_buffer); | 1231 connect_info->read_buffer); |
| 1232 | 1232 |
| 1233 | 1233 |
| 1234 if(status == 407 /* Proxy Auth */) { | 1234 if(status == 407 /* Proxy Auth */) { |
| 1235 gchar *ntlm; | 1235 gchar *ntlm; |
| 1236 if((ntlm = g_strrstr((const gchar *)phb->read_buffer, "Proxy-Authenticate: NTLM "))) { /* Check for Type-2 */ | 1236 if((ntlm = g_strrstr((const gchar *)connect_info->read_buffer, "Proxy-Authenticate: NTLM "))) { /* Check for Type-2 */ |
| 1237 gchar *tmp = ntlm; | 1237 gchar *tmp = ntlm; |
| 1238 guint8 *nonce; | 1238 guint8 *nonce; |
| 1239 gchar *domain = (gchar*)gaim_proxy_info_get_username(phb->gpi); | 1239 gchar *domain = (gchar*)gaim_proxy_info_get_username(connect_info->gpi); |
| 1240 gchar *username; | 1240 gchar *username; |
| 1241 gchar *request; | 1241 gchar *request; |
| 1242 gchar *response; | 1242 gchar *response; |
| 1243 username = strchr(domain, '\\'); | 1243 username = strchr(domain, '\\'); |
| 1244 if (username == NULL) | 1244 if (username == NULL) |
| 1245 { | 1245 { |
| 1246 close(source); | 1246 close(source); |
| 1247 msg = g_strdup_printf(_("HTTP proxy connection error %d"), status); | 1247 msg = g_strdup_printf(_("HTTP proxy connection error %d"), status); |
| 1248 gaim_proxy_phb_error(phb, msg); | 1248 gaim_proxy_connect_info_error(connect_info, msg); |
| 1249 g_free(msg); | 1249 g_free(msg); |
| 1250 return; | 1250 return; |
| 1251 } | 1251 } |
| 1252 *username = '\0'; | 1252 *username = '\0'; |
| 1253 username++; | 1253 username++; |
| 1254 ntlm += strlen("Proxy-Authenticate: NTLM "); | 1254 ntlm += strlen("Proxy-Authenticate: NTLM "); |
| 1255 while(*tmp != '\r' && *tmp != '\0') tmp++; | 1255 while(*tmp != '\r' && *tmp != '\0') tmp++; |
| 1256 *tmp = '\0'; | 1256 *tmp = '\0'; |
| 1257 nonce = gaim_ntlm_parse_type2(ntlm, NULL); | 1257 nonce = gaim_ntlm_parse_type2(ntlm, NULL); |
| 1258 response = gaim_ntlm_gen_type3(username, | 1258 response = gaim_ntlm_gen_type3(username, |
| 1259 (gchar*) gaim_proxy_info_get_password(phb->gpi), | 1259 (gchar*) gaim_proxy_info_get_password(connect_info->gpi), |
| 1260 (gchar*) gaim_proxy_info_get_host(phb->gpi), | 1260 (gchar*) gaim_proxy_info_get_host(connect_info->gpi), |
| 1261 domain, nonce, NULL); | 1261 domain, nonce, NULL); |
| 1262 username--; | 1262 username--; |
| 1263 *username = '\\'; | 1263 *username = '\\'; |
| 1264 request = g_strdup_printf( | 1264 request = g_strdup_printf( |
| 1265 "CONNECT %s:%d HTTP/1.1\r\n" | 1265 "CONNECT %s:%d HTTP/1.1\r\n" |
| 1266 "Host: %s:%d\r\n" | 1266 "Host: %s:%d\r\n" |
| 1267 "Proxy-Authorization: NTLM %s\r\n" | 1267 "Proxy-Authorization: NTLM %s\r\n" |
| 1268 "Proxy-Connection: Keep-Alive\r\n\r\n", | 1268 "Proxy-Connection: Keep-Alive\r\n\r\n", |
| 1269 phb->host, phb->port, phb->host, | 1269 connect_info->host, connect_info->port, connect_info->host, |
| 1270 phb->port, response); | 1270 connect_info->port, response); |
| 1271 g_free(response); | 1271 g_free(response); |
| 1272 | 1272 |
| 1273 gaim_input_remove(phb->inpa); | 1273 gaim_input_remove(connect_info->inpa); |
| 1274 g_free(phb->read_buffer); | 1274 g_free(connect_info->read_buffer); |
| 1275 phb->read_buffer = NULL; | 1275 connect_info->read_buffer = NULL; |
| 1276 | 1276 |
| 1277 phb->write_buffer = (guchar *)request; | 1277 connect_info->write_buffer = (guchar *)request; |
| 1278 phb->write_buf_len = strlen(request); | 1278 connect_info->write_buf_len = strlen(request); |
| 1279 phb->written_len = 0; | 1279 connect_info->written_len = 0; |
| 1280 | 1280 |
| 1281 phb->read_cb = http_canread; | 1281 connect_info->read_cb = http_canread; |
| 1282 | 1282 |
| 1283 phb->inpa = gaim_input_add(source, | 1283 connect_info->inpa = gaim_input_add(source, |
| 1284 GAIM_INPUT_WRITE, proxy_do_write, phb); | 1284 GAIM_INPUT_WRITE, proxy_do_write, connect_info); |
| 1285 | 1285 |
| 1286 proxy_do_write(phb, source, cond); | 1286 proxy_do_write(connect_info, source, cond); |
| 1287 return; | 1287 return; |
| 1288 } else if((ntlm = g_strrstr((const char *)phb->read_buffer, "Proxy-Authenticate: NTLM"))) { /* Empty message */ | 1288 } else if((ntlm = g_strrstr((const char *)connect_info->read_buffer, "Proxy-Authenticate: NTLM"))) { /* Empty message */ |
| 1289 gchar request[2048]; | 1289 gchar request[2048]; |
| 1290 gchar *domain = (gchar*) gaim_proxy_info_get_username(phb->gpi); | 1290 gchar *domain = (gchar*) gaim_proxy_info_get_username(connect_info->gpi); |
| 1291 gchar *username; | 1291 gchar *username; |
| 1292 int request_len; | 1292 int request_len; |
| 1293 username = strchr(domain, '\\'); | 1293 username = strchr(domain, '\\'); |
| 1294 if (username == NULL) | 1294 if (username == NULL) |
| 1295 { | 1295 { |
| 1296 close(source); | 1296 close(source); |
| 1297 msg = g_strdup_printf(_("HTTP proxy connection error %d"), status); | 1297 msg = g_strdup_printf(_("HTTP proxy connection error %d"), status); |
| 1298 gaim_proxy_phb_error(phb, msg); | 1298 gaim_proxy_connect_info_error(connect_info, msg); |
| 1299 g_free(msg); | 1299 g_free(msg); |
| 1300 return; | 1300 return; |
| 1301 } | 1301 } |
| 1302 *username = '\0'; | 1302 *username = '\0'; |
| 1303 | 1303 |
| 1304 request_len = g_snprintf(request, sizeof(request), | 1304 request_len = g_snprintf(request, sizeof(request), |
| 1305 "CONNECT %s:%d HTTP/1.1\r\n" | 1305 "CONNECT %s:%d HTTP/1.1\r\n" |
| 1306 "Host: %s:%d\r\n", | 1306 "Host: %s:%d\r\n", |
| 1307 phb->host, phb->port, | 1307 connect_info->host, connect_info->port, |
| 1308 phb->host, phb->port); | 1308 connect_info->host, connect_info->port); |
| 1309 | 1309 |
| 1310 g_return_if_fail(request_len < sizeof(request)); | 1310 g_return_if_fail(request_len < sizeof(request)); |
| 1311 request_len += g_snprintf(request + request_len, | 1311 request_len += g_snprintf(request + request_len, |
| 1312 sizeof(request) - request_len, | 1312 sizeof(request) - request_len, |
| 1313 "Proxy-Authorization: NTLM %s\r\n" | 1313 "Proxy-Authorization: NTLM %s\r\n" |
| 1314 "Proxy-Connection: Keep-Alive\r\n\r\n", | 1314 "Proxy-Connection: Keep-Alive\r\n\r\n", |
| 1315 gaim_ntlm_gen_type1( | 1315 gaim_ntlm_gen_type1( |
| 1316 (gchar*) gaim_proxy_info_get_host(phb->gpi), | 1316 (gchar*) gaim_proxy_info_get_host(connect_info->gpi), |
| 1317 domain)); | 1317 domain)); |
| 1318 *username = '\\'; | 1318 *username = '\\'; |
| 1319 | 1319 |
| 1320 gaim_input_remove(phb->inpa); | 1320 gaim_input_remove(connect_info->inpa); |
| 1321 g_free(phb->read_buffer); | 1321 g_free(connect_info->read_buffer); |
| 1322 phb->read_buffer = NULL; | 1322 connect_info->read_buffer = NULL; |
| 1323 | 1323 |
| 1324 phb->write_buffer = g_memdup(request, request_len); | 1324 connect_info->write_buffer = g_memdup(request, request_len); |
| 1325 phb->write_buf_len = request_len; | 1325 connect_info->write_buf_len = request_len; |
| 1326 phb->written_len = 0; | 1326 connect_info->written_len = 0; |
| 1327 | 1327 |
| 1328 phb->read_cb = http_canread; | 1328 connect_info->read_cb = http_canread; |
| 1329 | 1329 |
| 1330 phb->inpa = gaim_input_add(source, | 1330 connect_info->inpa = gaim_input_add(source, |
| 1331 GAIM_INPUT_WRITE, proxy_do_write, phb); | 1331 GAIM_INPUT_WRITE, proxy_do_write, connect_info); |
| 1332 | 1332 |
| 1333 proxy_do_write(phb, source, cond); | 1333 proxy_do_write(connect_info, source, cond); |
| 1334 return; | 1334 return; |
| 1335 } else { | 1335 } else { |
| 1336 close(source); | 1336 close(source); |
| 1337 msg = g_strdup_printf(_("HTTP proxy connection error %d"), status); | 1337 msg = g_strdup_printf(_("HTTP proxy connection error %d"), status); |
| 1338 gaim_proxy_phb_error(phb, msg); | 1338 gaim_proxy_connect_info_error(connect_info, msg); |
| 1339 g_free(msg); | 1339 g_free(msg); |
| 1340 return; | 1340 return; |
| 1341 } | 1341 } |
| 1342 } | 1342 } |
| 1343 if(status == 403 /* Forbidden */ ) { | 1343 if(status == 403 /* Forbidden */ ) { |
| 1344 msg = g_strdup_printf(_("Access denied: HTTP proxy server forbids port %d tunnelling."), phb->port); | 1344 msg = g_strdup_printf(_("Access denied: HTTP proxy server forbids port %d tunnelling."), connect_info->port); |
| 1345 gaim_proxy_phb_error(phb, msg); | 1345 gaim_proxy_connect_info_error(connect_info, msg); |
| 1346 g_free(msg); | 1346 g_free(msg); |
| 1347 } else { | 1347 } else { |
| 1348 msg = g_strdup_printf(_("HTTP proxy connection error %d"), status); | 1348 msg = g_strdup_printf(_("HTTP proxy connection error %d"), status); |
| 1349 gaim_proxy_phb_error(phb, msg); | 1349 gaim_proxy_connect_info_error(connect_info, msg); |
| 1350 g_free(msg); | 1350 g_free(msg); |
| 1351 } | 1351 } |
| 1352 } else { | 1352 } else { |
| 1353 gaim_input_remove(phb->inpa); | 1353 gaim_input_remove(connect_info->inpa); |
| 1354 phb->inpa = 0; | 1354 connect_info->inpa = 0; |
| 1355 g_free(phb->read_buffer); | 1355 g_free(connect_info->read_buffer); |
| 1356 phb->read_buffer = NULL; | 1356 connect_info->read_buffer = NULL; |
| 1357 gaim_debug_info("proxy", "HTTP proxy connection established\n"); | 1357 gaim_debug_info("proxy", "HTTP proxy connection established\n"); |
| 1358 gaim_proxy_phb_connected(phb, source); | 1358 gaim_proxy_connect_info_connected(connect_info, source); |
| 1359 return; | 1359 return; |
| 1360 } | 1360 } |
| 1361 } | 1361 } |
| 1362 | 1362 |
| 1363 | 1363 |
| 1365 static void | 1365 static void |
| 1366 http_canwrite(gpointer data, gint source, GaimInputCondition cond) | 1366 http_canwrite(gpointer data, gint source, GaimInputCondition cond) |
| 1367 { | 1367 { |
| 1368 char request[8192]; | 1368 char request[8192]; |
| 1369 int request_len = 0; | 1369 int request_len = 0; |
| 1370 struct _GaimProxyConnectInfo *phb = data; | 1370 struct _GaimProxyConnectInfo *connect_info = data; |
| 1371 socklen_t len; | 1371 socklen_t len; |
| 1372 int error = ETIMEDOUT; | 1372 int error = ETIMEDOUT; |
| 1373 | 1373 |
| 1374 gaim_debug_info("http proxy", "Connected.\n"); | 1374 gaim_debug_info("http proxy", "Connected.\n"); |
| 1375 | 1375 |
| 1376 if (phb->inpa > 0) | 1376 if (connect_info->inpa > 0) |
| 1377 { | 1377 { |
| 1378 gaim_input_remove(phb->inpa); | 1378 gaim_input_remove(connect_info->inpa); |
| 1379 phb->inpa = 0; | 1379 connect_info->inpa = 0; |
| 1380 } | 1380 } |
| 1381 | 1381 |
| 1382 len = sizeof(error); | 1382 len = sizeof(error); |
| 1383 | 1383 |
| 1384 if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { | 1384 if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { |
| 1385 close(source); | 1385 close(source); |
| 1386 | 1386 |
| 1387 try_connect(phb); | 1387 try_connect(connect_info); |
| 1388 return; | 1388 return; |
| 1389 } | 1389 } |
| 1390 | 1390 |
| 1391 gaim_debug_info("proxy", "using CONNECT tunnelling for %s:%d\n", | 1391 gaim_debug_info("proxy", "using CONNECT tunnelling for %s:%d\n", |
| 1392 phb->host, phb->port); | 1392 connect_info->host, connect_info->port); |
| 1393 request_len = g_snprintf(request, sizeof(request), | 1393 request_len = g_snprintf(request, sizeof(request), |
| 1394 "CONNECT %s:%d HTTP/1.1\r\nHost: %s:%d\r\n", | 1394 "CONNECT %s:%d HTTP/1.1\r\nHost: %s:%d\r\n", |
| 1395 phb->host, phb->port, phb->host, phb->port); | 1395 connect_info->host, connect_info->port, connect_info->host, connect_info->port); |
| 1396 | 1396 |
| 1397 if (gaim_proxy_info_get_username(phb->gpi) != NULL) { | 1397 if (gaim_proxy_info_get_username(connect_info->gpi) != NULL) { |
| 1398 char *t1, *t2; | 1398 char *t1, *t2; |
| 1399 t1 = g_strdup_printf("%s:%s", | 1399 t1 = g_strdup_printf("%s:%s", |
| 1400 gaim_proxy_info_get_username(phb->gpi), | 1400 gaim_proxy_info_get_username(connect_info->gpi), |
| 1401 gaim_proxy_info_get_password(phb->gpi) ? | 1401 gaim_proxy_info_get_password(connect_info->gpi) ? |
| 1402 gaim_proxy_info_get_password(phb->gpi) : ""); | 1402 gaim_proxy_info_get_password(connect_info->gpi) : ""); |
| 1403 t2 = gaim_base64_encode((const guchar *)t1, strlen(t1)); | 1403 t2 = gaim_base64_encode((const guchar *)t1, strlen(t1)); |
| 1404 g_free(t1); | 1404 g_free(t1); |
| 1405 g_return_if_fail(request_len < sizeof(request)); | 1405 g_return_if_fail(request_len < sizeof(request)); |
| 1406 | 1406 |
| 1407 request_len += g_snprintf(request + request_len, | 1407 request_len += g_snprintf(request + request_len, |
| 1408 sizeof(request) - request_len, | 1408 sizeof(request) - request_len, |
| 1409 "Proxy-Authorization: Basic %s\r\n" | 1409 "Proxy-Authorization: Basic %s\r\n" |
| 1410 "Proxy-Authorization: NTLM %s\r\n" | 1410 "Proxy-Authorization: NTLM %s\r\n" |
| 1411 "Proxy-Connection: Keep-Alive\r\n", t2, | 1411 "Proxy-Connection: Keep-Alive\r\n", t2, |
| 1412 gaim_ntlm_gen_type1( | 1412 gaim_ntlm_gen_type1( |
| 1413 (gchar*)gaim_proxy_info_get_host(phb->gpi),"")); | 1413 (gchar*)gaim_proxy_info_get_host(connect_info->gpi),"")); |
| 1414 g_free(t2); | 1414 g_free(t2); |
| 1415 } | 1415 } |
| 1416 | 1416 |
| 1417 g_return_if_fail(request_len < sizeof(request)); | 1417 g_return_if_fail(request_len < sizeof(request)); |
| 1418 strcpy(request + request_len, "\r\n"); | 1418 strcpy(request + request_len, "\r\n"); |
| 1419 request_len += 2; | 1419 request_len += 2; |
| 1420 phb->write_buffer = g_memdup(request, request_len); | 1420 connect_info->write_buffer = g_memdup(request, request_len); |
| 1421 phb->write_buf_len = request_len; | 1421 connect_info->write_buf_len = request_len; |
| 1422 phb->written_len = 0; | 1422 connect_info->written_len = 0; |
| 1423 | 1423 |
| 1424 phb->read_cb = http_canread; | 1424 connect_info->read_cb = http_canread; |
| 1425 | 1425 |
| 1426 phb->inpa = gaim_input_add(source, GAIM_INPUT_WRITE, proxy_do_write, | 1426 connect_info->inpa = gaim_input_add(source, GAIM_INPUT_WRITE, proxy_do_write, |
| 1427 phb); | 1427 connect_info); |
| 1428 | 1428 |
| 1429 proxy_do_write(phb, source, cond); | 1429 proxy_do_write(connect_info, source, cond); |
| 1430 } | 1430 } |
| 1431 | 1431 |
| 1432 static int | 1432 static int |
| 1433 proxy_connect_http(struct _GaimProxyConnectInfo *phb, struct sockaddr *addr, socklen_t addrlen) | 1433 proxy_connect_http(struct _GaimProxyConnectInfo *connect_info, struct sockaddr *addr, socklen_t addrlen) |
| 1434 { | 1434 { |
| 1435 int fd = -1; | 1435 int fd = -1; |
| 1436 | 1436 |
| 1437 gaim_debug_info("http proxy", | 1437 gaim_debug_info("http proxy", |
| 1438 "Connecting to %s:%d via %s:%d using HTTP\n", | 1438 "Connecting to %s:%d via %s:%d using HTTP\n", |
| 1439 (phb->host ? phb->host : "(null)"), phb->port, | 1439 (connect_info->host ? connect_info->host : "(null)"), connect_info->port, |
| 1440 (gaim_proxy_info_get_host(phb->gpi) ? gaim_proxy_info_get_host(phb->gpi) : "(null)"), | 1440 (gaim_proxy_info_get_host(connect_info->gpi) ? gaim_proxy_info_get_host(connect_info->gpi) : "(null)"), |
| 1441 gaim_proxy_info_get_port(phb->gpi)); | 1441 gaim_proxy_info_get_port(connect_info->gpi)); |
| 1442 | 1442 |
| 1443 if ((fd = socket(addr->sa_family, SOCK_STREAM, 0)) < 0) { | 1443 if ((fd = socket(addr->sa_family, SOCK_STREAM, 0)) < 0) { |
| 1444 return -1; | 1444 return -1; |
| 1445 } | 1445 } |
| 1446 | 1446 |
| 1452 if (connect(fd, addr, addrlen) < 0) { | 1452 if (connect(fd, addr, addrlen) < 0) { |
| 1453 if ((errno == EINPROGRESS) || (errno == EINTR)) { | 1453 if ((errno == EINPROGRESS) || (errno == EINTR)) { |
| 1454 gaim_debug_warning("http proxy", | 1454 gaim_debug_warning("http proxy", |
| 1455 "Connect would have blocked.\n"); | 1455 "Connect would have blocked.\n"); |
| 1456 | 1456 |
| 1457 if (phb->port != 80) { | 1457 if (connect_info->port != 80) { |
| 1458 /* we need to do CONNECT first */ | 1458 /* we need to do CONNECT first */ |
| 1459 phb->inpa = gaim_input_add(fd, GAIM_INPUT_WRITE, | 1459 connect_info->inpa = gaim_input_add(fd, GAIM_INPUT_WRITE, |
| 1460 http_canwrite, phb); | 1460 http_canwrite, connect_info); |
| 1461 } else { | 1461 } else { |
| 1462 gaim_debug_info("proxy", "HTTP proxy connection established\n"); | 1462 gaim_debug_info("proxy", "HTTP proxy connection established\n"); |
| 1463 gaim_proxy_phb_connected(phb, fd); | 1463 gaim_proxy_connect_info_connected(connect_info, fd); |
| 1464 } | 1464 } |
| 1465 } else { | 1465 } else { |
| 1466 close(fd); | 1466 close(fd); |
| 1467 return -1; | 1467 return -1; |
| 1468 } | 1468 } |
| 1477 len = sizeof(error); | 1477 len = sizeof(error); |
| 1478 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { | 1478 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { |
| 1479 close(fd); | 1479 close(fd); |
| 1480 return -1; | 1480 return -1; |
| 1481 } | 1481 } |
| 1482 http_canwrite(phb, fd, GAIM_INPUT_WRITE); | 1482 http_canwrite(connect_info, fd, GAIM_INPUT_WRITE); |
| 1483 } | 1483 } |
| 1484 | 1484 |
| 1485 return fd; | 1485 return fd; |
| 1486 } | 1486 } |
| 1487 | 1487 |
| 1488 | 1488 |
| 1489 static void | 1489 static void |
| 1490 s4_canread(gpointer data, gint source, GaimInputCondition cond) | 1490 s4_canread(gpointer data, gint source, GaimInputCondition cond) |
| 1491 { | 1491 { |
| 1492 struct _GaimProxyConnectInfo *phb = data; | 1492 struct _GaimProxyConnectInfo *connect_info = data; |
| 1493 guchar *buf; | 1493 guchar *buf; |
| 1494 int len, max_read; | 1494 int len, max_read; |
| 1495 | 1495 |
| 1496 /* This is really not going to block under normal circumstances, but to | 1496 /* This is really not going to block under normal circumstances, but to |
| 1497 * be correct, we deal with the unlikely scenario */ | 1497 * be correct, we deal with the unlikely scenario */ |
| 1498 | 1498 |
| 1499 if (phb->read_buffer == NULL) { | 1499 if (connect_info->read_buffer == NULL) { |
| 1500 phb->read_buf_len = 12; | 1500 connect_info->read_buf_len = 12; |
| 1501 phb->read_buffer = g_malloc(phb->read_buf_len); | 1501 connect_info->read_buffer = g_malloc(connect_info->read_buf_len); |
| 1502 phb->read_len = 0; | 1502 connect_info->read_len = 0; |
| 1503 } | 1503 } |
| 1504 | 1504 |
| 1505 buf = phb->read_buffer + phb->read_len; | 1505 buf = connect_info->read_buffer + connect_info->read_len; |
| 1506 max_read = phb->read_buf_len - phb->read_len; | 1506 max_read = connect_info->read_buf_len - connect_info->read_len; |
| 1507 | 1507 |
| 1508 len = read(source, buf, max_read); | 1508 len = read(source, buf, max_read); |
| 1509 | 1509 |
| 1510 if ((len < 0 && errno == EAGAIN) || (len > 0 && len + phb->read_len < 4)) | 1510 if ((len < 0 && errno == EAGAIN) || (len > 0 && len + connect_info->read_len < 4)) |
| 1511 return; | 1511 return; |
| 1512 else if (len + phb->read_len >= 4) { | 1512 else if (len + connect_info->read_len >= 4) { |
| 1513 if (phb->read_buffer[1] == 90) { | 1513 if (connect_info->read_buffer[1] == 90) { |
| 1514 gaim_proxy_phb_connected(phb, source); | 1514 gaim_proxy_connect_info_connected(connect_info, source); |
| 1515 return; | 1515 return; |
| 1516 } | 1516 } |
| 1517 } | 1517 } |
| 1518 | 1518 |
| 1519 gaim_input_remove(phb->inpa); | 1519 gaim_input_remove(connect_info->inpa); |
| 1520 phb->inpa = 0; | 1520 connect_info->inpa = 0; |
| 1521 g_free(phb->read_buffer); | 1521 g_free(connect_info->read_buffer); |
| 1522 phb->read_buffer = NULL; | 1522 connect_info->read_buffer = NULL; |
| 1523 | 1523 |
| 1524 close(source); | 1524 close(source); |
| 1525 | 1525 |
| 1526 try_connect(phb); | 1526 try_connect(connect_info); |
| 1527 } | 1527 } |
| 1528 | 1528 |
| 1529 static void | 1529 static void |
| 1530 s4_canwrite(gpointer data, gint source, GaimInputCondition cond) | 1530 s4_canwrite(gpointer data, gint source, GaimInputCondition cond) |
| 1531 { | 1531 { |
| 1532 unsigned char packet[9]; | 1532 unsigned char packet[9]; |
| 1533 struct hostent *hp; | 1533 struct hostent *hp; |
| 1534 struct _GaimProxyConnectInfo *phb = data; | 1534 struct _GaimProxyConnectInfo *connect_info = data; |
| 1535 socklen_t len; | 1535 socklen_t len; |
| 1536 int error = ETIMEDOUT; | 1536 int error = ETIMEDOUT; |
| 1537 | 1537 |
| 1538 gaim_debug_info("socks4 proxy", "Connected.\n"); | 1538 gaim_debug_info("socks4 proxy", "Connected.\n"); |
| 1539 | 1539 |
| 1540 if (phb->inpa > 0) | 1540 if (connect_info->inpa > 0) |
| 1541 { | 1541 { |
| 1542 gaim_input_remove(phb->inpa); | 1542 gaim_input_remove(connect_info->inpa); |
| 1543 phb->inpa = 0; | 1543 connect_info->inpa = 0; |
| 1544 } | 1544 } |
| 1545 | 1545 |
| 1546 len = sizeof(error); | 1546 len = sizeof(error); |
| 1547 | 1547 |
| 1548 if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { | 1548 if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { |
| 1549 close(source); | 1549 close(source); |
| 1550 | 1550 |
| 1551 try_connect(phb); | 1551 try_connect(connect_info); |
| 1552 return; | 1552 return; |
| 1553 } | 1553 } |
| 1554 | 1554 |
| 1555 /* | 1555 /* |
| 1556 * The socks4 spec doesn't include support for doing host name | 1556 * The socks4 spec doesn't include support for doing host name |
| 1558 * extensions to the protocol. Since we don't know if a | 1558 * extensions to the protocol. Since we don't know if a |
| 1559 * server supports this, it would need to be implemented | 1559 * server supports this, it would need to be implemented |
| 1560 * with an option, or some detection mechanism - in the | 1560 * with an option, or some detection mechanism - in the |
| 1561 * meantime, stick with plain old SOCKS4. | 1561 * meantime, stick with plain old SOCKS4. |
| 1562 */ | 1562 */ |
| 1563 if (!(hp = gethostbyname(phb->host))) { | 1563 if (!(hp = gethostbyname(connect_info->host))) { |
| 1564 close(source); | 1564 close(source); |
| 1565 | 1565 |
| 1566 try_connect(phb); | 1566 try_connect(connect_info); |
| 1567 return; | 1567 return; |
| 1568 } | 1568 } |
| 1569 | 1569 |
| 1570 packet[0] = 4; | 1570 packet[0] = 4; |
| 1571 packet[1] = 1; | 1571 packet[1] = 1; |
| 1572 packet[2] = phb->port >> 8; | 1572 packet[2] = connect_info->port >> 8; |
| 1573 packet[3] = phb->port & 0xff; | 1573 packet[3] = connect_info->port & 0xff; |
| 1574 packet[4] = (unsigned char)(hp->h_addr_list[0])[0]; | 1574 packet[4] = (unsigned char)(hp->h_addr_list[0])[0]; |
| 1575 packet[5] = (unsigned char)(hp->h_addr_list[0])[1]; | 1575 packet[5] = (unsigned char)(hp->h_addr_list[0])[1]; |
| 1576 packet[6] = (unsigned char)(hp->h_addr_list[0])[2]; | 1576 packet[6] = (unsigned char)(hp->h_addr_list[0])[2]; |
| 1577 packet[7] = (unsigned char)(hp->h_addr_list[0])[3]; | 1577 packet[7] = (unsigned char)(hp->h_addr_list[0])[3]; |
| 1578 packet[8] = 0; | 1578 packet[8] = 0; |
| 1579 | 1579 |
| 1580 phb->write_buffer = g_memdup(packet, sizeof(packet)); | 1580 connect_info->write_buffer = g_memdup(packet, sizeof(packet)); |
| 1581 phb->write_buf_len = sizeof(packet); | 1581 connect_info->write_buf_len = sizeof(packet); |
| 1582 phb->written_len = 0; | 1582 connect_info->written_len = 0; |
| 1583 phb->read_cb = s4_canread; | 1583 connect_info->read_cb = s4_canread; |
| 1584 | 1584 |
| 1585 phb->inpa = gaim_input_add(source, GAIM_INPUT_WRITE, proxy_do_write, phb); | 1585 connect_info->inpa = gaim_input_add(source, GAIM_INPUT_WRITE, proxy_do_write, connect_info); |
| 1586 | 1586 |
| 1587 proxy_do_write(phb, source, cond); | 1587 proxy_do_write(connect_info, source, cond); |
| 1588 } | 1588 } |
| 1589 | 1589 |
| 1590 static int | 1590 static int |
| 1591 proxy_connect_socks4(struct _GaimProxyConnectInfo *phb, struct sockaddr *addr, socklen_t addrlen) | 1591 proxy_connect_socks4(struct _GaimProxyConnectInfo *connect_info, struct sockaddr *addr, socklen_t addrlen) |
| 1592 { | 1592 { |
| 1593 int fd = -1; | 1593 int fd = -1; |
| 1594 | 1594 |
| 1595 gaim_debug_info("socks4 proxy", | 1595 gaim_debug_info("socks4 proxy", |
| 1596 "Connecting to %s:%d via %s:%d using SOCKS4\n", | 1596 "Connecting to %s:%d via %s:%d using SOCKS4\n", |
| 1597 phb->host, phb->port, | 1597 connect_info->host, connect_info->port, |
| 1598 gaim_proxy_info_get_host(phb->gpi), | 1598 gaim_proxy_info_get_host(connect_info->gpi), |
| 1599 gaim_proxy_info_get_port(phb->gpi)); | 1599 gaim_proxy_info_get_port(connect_info->gpi)); |
| 1600 | 1600 |
| 1601 if ((fd = socket(addr->sa_family, SOCK_STREAM, 0)) < 0) | 1601 if ((fd = socket(addr->sa_family, SOCK_STREAM, 0)) < 0) |
| 1602 return -1; | 1602 return -1; |
| 1603 | 1603 |
| 1604 fcntl(fd, F_SETFL, O_NONBLOCK); | 1604 fcntl(fd, F_SETFL, O_NONBLOCK); |
| 1608 | 1608 |
| 1609 if (connect(fd, addr, addrlen) < 0) { | 1609 if (connect(fd, addr, addrlen) < 0) { |
| 1610 if ((errno == EINPROGRESS) || (errno == EINTR)) { | 1610 if ((errno == EINPROGRESS) || (errno == EINTR)) { |
| 1611 gaim_debug_warning("socks4 proxy", | 1611 gaim_debug_warning("socks4 proxy", |
| 1612 "Connect would have blocked.\n"); | 1612 "Connect would have blocked.\n"); |
| 1613 phb->inpa = gaim_input_add(fd, GAIM_INPUT_WRITE, s4_canwrite, phb); | 1613 connect_info->inpa = gaim_input_add(fd, GAIM_INPUT_WRITE, s4_canwrite, connect_info); |
| 1614 } | 1614 } |
| 1615 else { | 1615 else { |
| 1616 close(fd); | 1616 close(fd); |
| 1617 return -1; | 1617 return -1; |
| 1618 } | 1618 } |
| 1628 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { | 1628 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { |
| 1629 close(fd); | 1629 close(fd); |
| 1630 return -1; | 1630 return -1; |
| 1631 } | 1631 } |
| 1632 | 1632 |
| 1633 s4_canwrite(phb, fd, GAIM_INPUT_WRITE); | 1633 s4_canwrite(connect_info, fd, GAIM_INPUT_WRITE); |
| 1634 } | 1634 } |
| 1635 | 1635 |
| 1636 return fd; | 1636 return fd; |
| 1637 } | 1637 } |
| 1638 | 1638 |
| 1639 static void | 1639 static void |
| 1640 s5_canread_again(gpointer data, gint source, GaimInputCondition cond) | 1640 s5_canread_again(gpointer data, gint source, GaimInputCondition cond) |
| 1641 { | 1641 { |
| 1642 guchar *dest, *buf; | 1642 guchar *dest, *buf; |
| 1643 struct _GaimProxyConnectInfo *phb = data; | 1643 struct _GaimProxyConnectInfo *connect_info = data; |
| 1644 int len; | 1644 int len; |
| 1645 | 1645 |
| 1646 if (phb->read_buffer == NULL) { | 1646 if (connect_info->read_buffer == NULL) { |
| 1647 phb->read_buf_len = 512; | 1647 connect_info->read_buf_len = 512; |
| 1648 phb->read_buffer = g_malloc(phb->read_buf_len); | 1648 connect_info->read_buffer = g_malloc(connect_info->read_buf_len); |
| 1649 phb->read_len = 0; | 1649 connect_info->read_len = 0; |
| 1650 } | 1650 } |
| 1651 | 1651 |
| 1652 dest = phb->read_buffer + phb->read_len; | 1652 dest = connect_info->read_buffer + connect_info->read_len; |
| 1653 buf = phb->read_buffer; | 1653 buf = connect_info->read_buffer; |
| 1654 | 1654 |
| 1655 gaim_debug_info("socks5 proxy", "Able to read again.\n"); | 1655 gaim_debug_info("socks5 proxy", "Able to read again.\n"); |
| 1656 | 1656 |
| 1657 len = read(source, dest, (phb->read_buf_len - phb->read_len)); | 1657 len = read(source, dest, (connect_info->read_buf_len - connect_info->read_len)); |
| 1658 if(len < 0 && errno == EAGAIN) | 1658 if(len < 0 && errno == EAGAIN) |
| 1659 return; | 1659 return; |
| 1660 else if(len <= 0) { | 1660 else if(len <= 0) { |
| 1661 gaim_debug_warning("socks5 proxy", "or not...\n"); | 1661 gaim_debug_warning("socks5 proxy", "or not...\n"); |
| 1662 close(source); | 1662 close(source); |
| 1663 gaim_input_remove(phb->inpa); | 1663 gaim_input_remove(connect_info->inpa); |
| 1664 phb->inpa = 0; | 1664 connect_info->inpa = 0; |
| 1665 g_free(phb->read_buffer); | 1665 g_free(connect_info->read_buffer); |
| 1666 phb->read_buffer = NULL; | 1666 connect_info->read_buffer = NULL; |
| 1667 try_connect(phb); | 1667 try_connect(connect_info); |
| 1668 return; | 1668 return; |
| 1669 } | 1669 } |
| 1670 phb->read_len += len; | 1670 connect_info->read_len += len; |
| 1671 | 1671 |
| 1672 if(phb->read_len < 4) | 1672 if(connect_info->read_len < 4) |
| 1673 return; | 1673 return; |
| 1674 | 1674 |
| 1675 if ((buf[0] != 0x05) || (buf[1] != 0x00)) { | 1675 if ((buf[0] != 0x05) || (buf[1] != 0x00)) { |
| 1676 if ((buf[0] == 0x05) && (buf[1] < 0x09)) | 1676 if ((buf[0] == 0x05) && (buf[1] < 0x09)) |
| 1677 gaim_debug_error("socks5 proxy", socks5errors[buf[1]]); | 1677 gaim_debug_error("socks5 proxy", socks5errors[buf[1]]); |
| 1678 else | 1678 else |
| 1679 gaim_debug_error("socks5 proxy", "Bad data.\n"); | 1679 gaim_debug_error("socks5 proxy", "Bad data.\n"); |
| 1680 close(source); | 1680 close(source); |
| 1681 gaim_input_remove(phb->inpa); | 1681 gaim_input_remove(connect_info->inpa); |
| 1682 phb->inpa = 0; | 1682 connect_info->inpa = 0; |
| 1683 g_free(phb->read_buffer); | 1683 g_free(connect_info->read_buffer); |
| 1684 phb->read_buffer = NULL; | 1684 connect_info->read_buffer = NULL; |
| 1685 try_connect(phb); | 1685 try_connect(connect_info); |
| 1686 return; | 1686 return; |
| 1687 } | 1687 } |
| 1688 | 1688 |
| 1689 /* Skip past BND.ADDR */ | 1689 /* Skip past BND.ADDR */ |
| 1690 switch(buf[3]) { | 1690 switch(buf[3]) { |
| 1691 case 0x01: /* the address is a version-4 IP address, with a length of 4 octets */ | 1691 case 0x01: /* the address is a version-4 IP address, with a length of 4 octets */ |
| 1692 if(phb->read_len < 4 + 4) | 1692 if(connect_info->read_len < 4 + 4) |
| 1693 return; | 1693 return; |
| 1694 buf += 4 + 4; | 1694 buf += 4 + 4; |
| 1695 break; | 1695 break; |
| 1696 case 0x03: /* the address field contains a fully-qualified domain name. The first | 1696 case 0x03: /* the address field contains a fully-qualified domain name. The first |
| 1697 octet of the address field contains the number of octets of name that | 1697 octet of the address field contains the number of octets of name that |
| 1698 follow, there is no terminating NUL octet. */ | 1698 follow, there is no terminating NUL octet. */ |
| 1699 if(phb->read_len < 4 + 1) | 1699 if(connect_info->read_len < 4 + 1) |
| 1700 return; | 1700 return; |
| 1701 buf += 4 + 1; | 1701 buf += 4 + 1; |
| 1702 if(phb->read_len < 4 + 1 + buf[0]) | 1702 if(connect_info->read_len < 4 + 1 + buf[0]) |
| 1703 return; | 1703 return; |
| 1704 buf += buf[0]; | 1704 buf += buf[0]; |
| 1705 break; | 1705 break; |
| 1706 case 0x04: /* the address is a version-6 IP address, with a length of 16 octets */ | 1706 case 0x04: /* the address is a version-6 IP address, with a length of 16 octets */ |
| 1707 if(phb->read_len < 4 + 16) | 1707 if(connect_info->read_len < 4 + 16) |
| 1708 return; | 1708 return; |
| 1709 buf += 4 + 16; | 1709 buf += 4 + 16; |
| 1710 break; | 1710 break; |
| 1711 } | 1711 } |
| 1712 | 1712 |
| 1713 if(phb->read_len < (buf - phb->read_buffer) + 2) | 1713 if(connect_info->read_len < (buf - connect_info->read_buffer) + 2) |
| 1714 return; | 1714 return; |
| 1715 | 1715 |
| 1716 /* Skip past BND.PORT */ | 1716 /* Skip past BND.PORT */ |
| 1717 buf += 2; | 1717 buf += 2; |
| 1718 | 1718 |
| 1719 gaim_proxy_phb_connected(phb, source); | 1719 gaim_proxy_connect_info_connected(connect_info, source); |
| 1720 } | 1720 } |
| 1721 | 1721 |
| 1722 static void | 1722 static void |
| 1723 s5_sendconnect(gpointer data, int source) | 1723 s5_sendconnect(gpointer data, int source) |
| 1724 { | 1724 { |
| 1725 struct _GaimProxyConnectInfo *phb = data; | 1725 struct _GaimProxyConnectInfo *connect_info = data; |
| 1726 int hlen = strlen(phb->host); | 1726 int hlen = strlen(connect_info->host); |
| 1727 phb->write_buf_len = 5 + hlen + 2; | 1727 connect_info->write_buf_len = 5 + hlen + 2; |
| 1728 phb->write_buffer = g_malloc(phb->write_buf_len); | 1728 connect_info->write_buffer = g_malloc(connect_info->write_buf_len); |
| 1729 phb->written_len = 0; | 1729 connect_info->written_len = 0; |
| 1730 | 1730 |
| 1731 phb->write_buffer[0] = 0x05; | 1731 connect_info->write_buffer[0] = 0x05; |
| 1732 phb->write_buffer[1] = 0x01; /* CONNECT */ | 1732 connect_info->write_buffer[1] = 0x01; /* CONNECT */ |
| 1733 phb->write_buffer[2] = 0x00; /* reserved */ | 1733 connect_info->write_buffer[2] = 0x00; /* reserved */ |
| 1734 phb->write_buffer[3] = 0x03; /* address type -- host name */ | 1734 connect_info->write_buffer[3] = 0x03; /* address type -- host name */ |
| 1735 phb->write_buffer[4] = hlen; | 1735 connect_info->write_buffer[4] = hlen; |
| 1736 memcpy(phb->write_buffer + 5, phb->host, hlen); | 1736 memcpy(connect_info->write_buffer + 5, connect_info->host, hlen); |
| 1737 phb->write_buffer[5 + hlen] = phb->port >> 8; | 1737 connect_info->write_buffer[5 + hlen] = connect_info->port >> 8; |
| 1738 phb->write_buffer[5 + hlen + 1] = phb->port & 0xff; | 1738 connect_info->write_buffer[5 + hlen + 1] = connect_info->port & 0xff; |
| 1739 | 1739 |
| 1740 phb->read_cb = s5_canread_again; | 1740 connect_info->read_cb = s5_canread_again; |
| 1741 | 1741 |
| 1742 phb->inpa = gaim_input_add(source, GAIM_INPUT_WRITE, proxy_do_write, phb); | 1742 connect_info->inpa = gaim_input_add(source, GAIM_INPUT_WRITE, proxy_do_write, connect_info); |
| 1743 proxy_do_write(phb, source, GAIM_INPUT_WRITE); | 1743 proxy_do_write(connect_info, source, GAIM_INPUT_WRITE); |
| 1744 } | 1744 } |
| 1745 | 1745 |
| 1746 static void | 1746 static void |
| 1747 s5_readauth(gpointer data, gint source, GaimInputCondition cond) | 1747 s5_readauth(gpointer data, gint source, GaimInputCondition cond) |
| 1748 { | 1748 { |
| 1749 struct _GaimProxyConnectInfo *phb = data; | 1749 struct _GaimProxyConnectInfo *connect_info = data; |
| 1750 int len; | 1750 int len; |
| 1751 | 1751 |
| 1752 if (phb->read_buffer == NULL) { | 1752 if (connect_info->read_buffer == NULL) { |
| 1753 phb->read_buf_len = 2; | 1753 connect_info->read_buf_len = 2; |
| 1754 phb->read_buffer = g_malloc(phb->read_buf_len); | 1754 connect_info->read_buffer = g_malloc(connect_info->read_buf_len); |
| 1755 phb->read_len = 0; | 1755 connect_info->read_len = 0; |
| 1756 } | 1756 } |
| 1757 | 1757 |
| 1758 gaim_debug_info("socks5 proxy", "Got auth response.\n"); | 1758 gaim_debug_info("socks5 proxy", "Got auth response.\n"); |
| 1759 | 1759 |
| 1760 len = read(source, phb->read_buffer + phb->read_len, | 1760 len = read(source, connect_info->read_buffer + connect_info->read_len, |
| 1761 phb->read_buf_len - phb->read_len); | 1761 connect_info->read_buf_len - connect_info->read_len); |
| 1762 if(len < 0 && errno == EAGAIN) | 1762 if(len < 0 && errno == EAGAIN) |
| 1763 return; | 1763 return; |
| 1764 else if(len <= 0) { | 1764 else if(len <= 0) { |
| 1765 close(source); | 1765 close(source); |
| 1766 gaim_input_remove(phb->inpa); | 1766 gaim_input_remove(connect_info->inpa); |
| 1767 phb->inpa = 0; | 1767 connect_info->inpa = 0; |
| 1768 g_free(phb->read_buffer); | 1768 g_free(connect_info->read_buffer); |
| 1769 phb->read_buffer = NULL; | 1769 connect_info->read_buffer = NULL; |
| 1770 try_connect(phb); | 1770 try_connect(connect_info); |
| 1771 return; | 1771 return; |
| 1772 } | 1772 } |
| 1773 phb->read_len += len; | 1773 connect_info->read_len += len; |
| 1774 | 1774 |
| 1775 if (phb->read_len < 2) | 1775 if (connect_info->read_len < 2) |
| 1776 return; | 1776 return; |
| 1777 | 1777 |
| 1778 gaim_input_remove(phb->inpa); | 1778 gaim_input_remove(connect_info->inpa); |
| 1779 phb->inpa = 0; | 1779 connect_info->inpa = 0; |
| 1780 | 1780 |
| 1781 if ((phb->read_buffer[0] != 0x01) || (phb->read_buffer[1] != 0x00)) { | 1781 if ((connect_info->read_buffer[0] != 0x01) || (connect_info->read_buffer[1] != 0x00)) { |
| 1782 close(source); | 1782 close(source); |
| 1783 g_free(phb->read_buffer); | 1783 g_free(connect_info->read_buffer); |
| 1784 phb->read_buffer = NULL; | 1784 connect_info->read_buffer = NULL; |
| 1785 try_connect(phb); | 1785 try_connect(connect_info); |
| 1786 return; | 1786 return; |
| 1787 } | 1787 } |
| 1788 | 1788 |
| 1789 g_free(phb->read_buffer); | 1789 g_free(connect_info->read_buffer); |
| 1790 phb->read_buffer = NULL; | 1790 connect_info->read_buffer = NULL; |
| 1791 | 1791 |
| 1792 s5_sendconnect(phb, source); | 1792 s5_sendconnect(connect_info, source); |
| 1793 } | 1793 } |
| 1794 | 1794 |
| 1795 static void hmacmd5_chap(const unsigned char * challenge, int challen, const char * passwd, unsigned char * response) | 1795 static void hmacmd5_chap(const unsigned char * challenge, int challen, const char * passwd, unsigned char * response) |
| 1796 { | 1796 { |
| 1797 GaimCipher *cipher; | 1797 GaimCipher *cipher; |
| 1837 | 1837 |
| 1838 static void | 1838 static void |
| 1839 s5_readchap(gpointer data, gint source, GaimInputCondition cond) | 1839 s5_readchap(gpointer data, gint source, GaimInputCondition cond) |
| 1840 { | 1840 { |
| 1841 guchar *cmdbuf, *buf; | 1841 guchar *cmdbuf, *buf; |
| 1842 struct _GaimProxyConnectInfo *phb = data; | 1842 struct _GaimProxyConnectInfo *connect_info = data; |
| 1843 int len, navas, currentav; | 1843 int len, navas, currentav; |
| 1844 | 1844 |
| 1845 gaim_debug(GAIM_DEBUG_INFO, "socks5 proxy", "Got CHAP response.\n"); | 1845 gaim_debug(GAIM_DEBUG_INFO, "socks5 proxy", "Got CHAP response.\n"); |
| 1846 | 1846 |
| 1847 if (phb->read_buffer == NULL) { | 1847 if (connect_info->read_buffer == NULL) { |
| 1848 phb->read_buf_len = 20; | 1848 connect_info->read_buf_len = 20; |
| 1849 phb->read_buffer = g_malloc(phb->read_buf_len); | 1849 connect_info->read_buffer = g_malloc(connect_info->read_buf_len); |
| 1850 phb->read_len = 0; | 1850 connect_info->read_len = 0; |
| 1851 } | 1851 } |
| 1852 | 1852 |
| 1853 len = read(source, phb->read_buffer + phb->read_len, | 1853 len = read(source, connect_info->read_buffer + connect_info->read_len, |
| 1854 phb->read_buf_len - phb->read_len); | 1854 connect_info->read_buf_len - connect_info->read_len); |
| 1855 | 1855 |
| 1856 if(len < 0 && errno == EAGAIN) | 1856 if(len < 0 && errno == EAGAIN) |
| 1857 return; | 1857 return; |
| 1858 else if(len <= 0) { | 1858 else if(len <= 0) { |
| 1859 close(source); | 1859 close(source); |
| 1860 gaim_input_remove(phb->inpa); | 1860 gaim_input_remove(connect_info->inpa); |
| 1861 phb->inpa = 0; | 1861 connect_info->inpa = 0; |
| 1862 g_free(phb->read_buffer); | 1862 g_free(connect_info->read_buffer); |
| 1863 phb->read_buffer = NULL; | 1863 connect_info->read_buffer = NULL; |
| 1864 try_connect(phb); | 1864 try_connect(connect_info); |
| 1865 return; | 1865 return; |
| 1866 } | 1866 } |
| 1867 phb->read_len += len; | 1867 connect_info->read_len += len; |
| 1868 | 1868 |
| 1869 if (phb->read_len < 2) | 1869 if (connect_info->read_len < 2) |
| 1870 return; | 1870 return; |
| 1871 | 1871 |
| 1872 cmdbuf = phb->read_buffer; | 1872 cmdbuf = connect_info->read_buffer; |
| 1873 | 1873 |
| 1874 if (*cmdbuf != 0x01) { | 1874 if (*cmdbuf != 0x01) { |
| 1875 close(source); | 1875 close(source); |
| 1876 gaim_input_remove(phb->inpa); | 1876 gaim_input_remove(connect_info->inpa); |
| 1877 phb->inpa = 0; | 1877 connect_info->inpa = 0; |
| 1878 g_free(phb->read_buffer); | 1878 g_free(connect_info->read_buffer); |
| 1879 phb->read_buffer = NULL; | 1879 connect_info->read_buffer = NULL; |
| 1880 try_connect(phb); | 1880 try_connect(connect_info); |
| 1881 return; | 1881 return; |
| 1882 } | 1882 } |
| 1883 cmdbuf++; | 1883 cmdbuf++; |
| 1884 | 1884 |
| 1885 navas = *cmdbuf; | 1885 navas = *cmdbuf; |
| 1886 cmdbuf++; | 1886 cmdbuf++; |
| 1887 | 1887 |
| 1888 for (currentav = 0; currentav < navas; currentav++) { | 1888 for (currentav = 0; currentav < navas; currentav++) { |
| 1889 if (phb->read_len - (cmdbuf - phb->read_buffer) < 2) | 1889 if (connect_info->read_len - (cmdbuf - connect_info->read_buffer) < 2) |
| 1890 return; | 1890 return; |
| 1891 if (phb->read_len - (cmdbuf - phb->read_buffer) < cmdbuf[1]) | 1891 if (connect_info->read_len - (cmdbuf - connect_info->read_buffer) < cmdbuf[1]) |
| 1892 return; | 1892 return; |
| 1893 buf = cmdbuf + 2; | 1893 buf = cmdbuf + 2; |
| 1894 switch (cmdbuf[0]) { | 1894 switch (cmdbuf[0]) { |
| 1895 case 0x00: | 1895 case 0x00: |
| 1896 /* Did auth work? */ | 1896 /* Did auth work? */ |
| 1897 if (buf[0] == 0x00) { | 1897 if (buf[0] == 0x00) { |
| 1898 gaim_input_remove(phb->inpa); | 1898 gaim_input_remove(connect_info->inpa); |
| 1899 phb->inpa = 0; | 1899 connect_info->inpa = 0; |
| 1900 g_free(phb->read_buffer); | 1900 g_free(connect_info->read_buffer); |
| 1901 phb->read_buffer = NULL; | 1901 connect_info->read_buffer = NULL; |
| 1902 /* Success */ | 1902 /* Success */ |
| 1903 s5_sendconnect(phb, source); | 1903 s5_sendconnect(connect_info, source); |
| 1904 return; | 1904 return; |
| 1905 } else { | 1905 } else { |
| 1906 /* Failure */ | 1906 /* Failure */ |
| 1907 gaim_debug_warning("proxy", | 1907 gaim_debug_warning("proxy", |
| 1908 "socks5 CHAP authentication " | 1908 "socks5 CHAP authentication " |
| 1909 "failed. Disconnecting..."); | 1909 "failed. Disconnecting..."); |
| 1910 close(source); | 1910 close(source); |
| 1911 gaim_input_remove(phb->inpa); | 1911 gaim_input_remove(connect_info->inpa); |
| 1912 phb->inpa = 0; | 1912 connect_info->inpa = 0; |
| 1913 g_free(phb->read_buffer); | 1913 g_free(connect_info->read_buffer); |
| 1914 phb->read_buffer = NULL; | 1914 connect_info->read_buffer = NULL; |
| 1915 try_connect(phb); | 1915 try_connect(connect_info); |
| 1916 return; | 1916 return; |
| 1917 } | 1917 } |
| 1918 break; | 1918 break; |
| 1919 case 0x03: | 1919 case 0x03: |
| 1920 /* Server wants our credentials */ | 1920 /* Server wants our credentials */ |
| 1921 | 1921 |
| 1922 phb->write_buf_len = 16 + 4; | 1922 connect_info->write_buf_len = 16 + 4; |
| 1923 phb->write_buffer = g_malloc(phb->write_buf_len); | 1923 connect_info->write_buffer = g_malloc(connect_info->write_buf_len); |
| 1924 phb->written_len = 0; | 1924 connect_info->written_len = 0; |
| 1925 | 1925 |
| 1926 hmacmd5_chap(buf, cmdbuf[1], | 1926 hmacmd5_chap(buf, cmdbuf[1], |
| 1927 gaim_proxy_info_get_password(phb->gpi), | 1927 gaim_proxy_info_get_password(connect_info->gpi), |
| 1928 phb->write_buffer + 4); | 1928 connect_info->write_buffer + 4); |
| 1929 phb->write_buffer[0] = 0x01; | 1929 connect_info->write_buffer[0] = 0x01; |
| 1930 phb->write_buffer[1] = 0x01; | 1930 connect_info->write_buffer[1] = 0x01; |
| 1931 phb->write_buffer[2] = 0x04; | 1931 connect_info->write_buffer[2] = 0x04; |
| 1932 phb->write_buffer[3] = 0x10; | 1932 connect_info->write_buffer[3] = 0x10; |
| 1933 | 1933 |
| 1934 gaim_input_remove(phb->inpa); | 1934 gaim_input_remove(connect_info->inpa); |
| 1935 g_free(phb->read_buffer); | 1935 g_free(connect_info->read_buffer); |
| 1936 phb->read_buffer = NULL; | 1936 connect_info->read_buffer = NULL; |
| 1937 | 1937 |
| 1938 phb->read_cb = s5_readchap; | 1938 connect_info->read_cb = s5_readchap; |
| 1939 | 1939 |
| 1940 phb->inpa = gaim_input_add(source, | 1940 connect_info->inpa = gaim_input_add(source, |
| 1941 GAIM_INPUT_WRITE, proxy_do_write, phb); | 1941 GAIM_INPUT_WRITE, proxy_do_write, connect_info); |
| 1942 | 1942 |
| 1943 proxy_do_write(phb, source, GAIM_INPUT_WRITE); | 1943 proxy_do_write(connect_info, source, GAIM_INPUT_WRITE); |
| 1944 break; | 1944 break; |
| 1945 case 0x11: | 1945 case 0x11: |
| 1946 /* Server wants to select an algorithm */ | 1946 /* Server wants to select an algorithm */ |
| 1947 if (buf[0] != 0x85) { | 1947 if (buf[0] != 0x85) { |
| 1948 /* Only currently support HMAC-MD5 */ | 1948 /* Only currently support HMAC-MD5 */ |
| 1951 "algorithm that we did not advertise " | 1951 "algorithm that we did not advertise " |
| 1952 "as supporting. This is a violation " | 1952 "as supporting. This is a violation " |
| 1953 "of the socks5 CHAP specification. " | 1953 "of the socks5 CHAP specification. " |
| 1954 "Disconnecting..."); | 1954 "Disconnecting..."); |
| 1955 close(source); | 1955 close(source); |
| 1956 gaim_input_remove(phb->inpa); | 1956 gaim_input_remove(connect_info->inpa); |
| 1957 phb->inpa = 0; | 1957 connect_info->inpa = 0; |
| 1958 g_free(phb->read_buffer); | 1958 g_free(connect_info->read_buffer); |
| 1959 phb->read_buffer = NULL; | 1959 connect_info->read_buffer = NULL; |
| 1960 try_connect(phb); | 1960 try_connect(connect_info); |
| 1961 return; | 1961 return; |
| 1962 } | 1962 } |
| 1963 break; | 1963 break; |
| 1964 } | 1964 } |
| 1965 cmdbuf = buf + cmdbuf[1]; | 1965 cmdbuf = buf + cmdbuf[1]; |
| 1970 } | 1970 } |
| 1971 | 1971 |
| 1972 static void | 1972 static void |
| 1973 s5_canread(gpointer data, gint source, GaimInputCondition cond) | 1973 s5_canread(gpointer data, gint source, GaimInputCondition cond) |
| 1974 { | 1974 { |
| 1975 struct _GaimProxyConnectInfo *phb = data; | 1975 struct _GaimProxyConnectInfo *connect_info = data; |
| 1976 int len; | 1976 int len; |
| 1977 | 1977 |
| 1978 if (phb->read_buffer == NULL) { | 1978 if (connect_info->read_buffer == NULL) { |
| 1979 phb->read_buf_len = 2; | 1979 connect_info->read_buf_len = 2; |
| 1980 phb->read_buffer = g_malloc(phb->read_buf_len); | 1980 connect_info->read_buffer = g_malloc(connect_info->read_buf_len); |
| 1981 phb->read_len = 0; | 1981 connect_info->read_len = 0; |
| 1982 } | 1982 } |
| 1983 | 1983 |
| 1984 gaim_debug_info("socks5 proxy", "Able to read.\n"); | 1984 gaim_debug_info("socks5 proxy", "Able to read.\n"); |
| 1985 | 1985 |
| 1986 len = read(source, phb->read_buffer + phb->read_len, | 1986 len = read(source, connect_info->read_buffer + connect_info->read_len, |
| 1987 phb->read_buf_len - phb->read_len); | 1987 connect_info->read_buf_len - connect_info->read_len); |
| 1988 if(len < 0 && errno == EAGAIN) | 1988 if(len < 0 && errno == EAGAIN) |
| 1989 return; | 1989 return; |
| 1990 else if(len <= 0) { | 1990 else if(len <= 0) { |
| 1991 close(source); | 1991 close(source); |
| 1992 gaim_input_remove(phb->inpa); | 1992 gaim_input_remove(connect_info->inpa); |
| 1993 phb->inpa = 0; | 1993 connect_info->inpa = 0; |
| 1994 g_free(phb->read_buffer); | 1994 g_free(connect_info->read_buffer); |
| 1995 phb->read_buffer = NULL; | 1995 connect_info->read_buffer = NULL; |
| 1996 try_connect(phb); | 1996 try_connect(connect_info); |
| 1997 return; | 1997 return; |
| 1998 } | 1998 } |
| 1999 phb->read_len += len; | 1999 connect_info->read_len += len; |
| 2000 | 2000 |
| 2001 if (phb->read_len < 2) | 2001 if (connect_info->read_len < 2) |
| 2002 return; | 2002 return; |
| 2003 | 2003 |
| 2004 gaim_input_remove(phb->inpa); | 2004 gaim_input_remove(connect_info->inpa); |
| 2005 phb->inpa = 0; | 2005 connect_info->inpa = 0; |
| 2006 | 2006 |
| 2007 if ((phb->read_buffer[0] != 0x05) || (phb->read_buffer[1] == 0xff)) { | 2007 if ((connect_info->read_buffer[0] != 0x05) || (connect_info->read_buffer[1] == 0xff)) { |
| 2008 close(source); | 2008 close(source); |
| 2009 g_free(phb->read_buffer); | 2009 g_free(connect_info->read_buffer); |
| 2010 phb->read_buffer = NULL; | 2010 connect_info->read_buffer = NULL; |
| 2011 try_connect(phb); | 2011 try_connect(connect_info); |
| 2012 return; | 2012 return; |
| 2013 } | 2013 } |
| 2014 | 2014 |
| 2015 if (phb->read_buffer[1] == 0x02) { | 2015 if (connect_info->read_buffer[1] == 0x02) { |
| 2016 gsize i, j; | 2016 gsize i, j; |
| 2017 const char *u, *p; | 2017 const char *u, *p; |
| 2018 | 2018 |
| 2019 u = gaim_proxy_info_get_username(phb->gpi); | 2019 u = gaim_proxy_info_get_username(connect_info->gpi); |
| 2020 p = gaim_proxy_info_get_password(phb->gpi); | 2020 p = gaim_proxy_info_get_password(connect_info->gpi); |
| 2021 | 2021 |
| 2022 i = (u == NULL) ? 0 : strlen(u); | 2022 i = (u == NULL) ? 0 : strlen(u); |
| 2023 j = (p == NULL) ? 0 : strlen(p); | 2023 j = (p == NULL) ? 0 : strlen(p); |
| 2024 | 2024 |
| 2025 phb->write_buf_len = 1 + 1 + i + 1 + j; | 2025 connect_info->write_buf_len = 1 + 1 + i + 1 + j; |
| 2026 phb->write_buffer = g_malloc(phb->write_buf_len); | 2026 connect_info->write_buffer = g_malloc(connect_info->write_buf_len); |
| 2027 phb->written_len = 0; | 2027 connect_info->written_len = 0; |
| 2028 | 2028 |
| 2029 phb->write_buffer[0] = 0x01; /* version 1 */ | 2029 connect_info->write_buffer[0] = 0x01; /* version 1 */ |
| 2030 phb->write_buffer[1] = i; | 2030 connect_info->write_buffer[1] = i; |
| 2031 if (u != NULL) | 2031 if (u != NULL) |
| 2032 memcpy(phb->write_buffer + 2, u, i); | 2032 memcpy(connect_info->write_buffer + 2, u, i); |
| 2033 phb->write_buffer[2 + i] = j; | 2033 connect_info->write_buffer[2 + i] = j; |
| 2034 if (p != NULL) | 2034 if (p != NULL) |
| 2035 memcpy(phb->write_buffer + 2 + i + 1, p, j); | 2035 memcpy(connect_info->write_buffer + 2 + i + 1, p, j); |
| 2036 | 2036 |
| 2037 g_free(phb->read_buffer); | 2037 g_free(connect_info->read_buffer); |
| 2038 phb->read_buffer = NULL; | 2038 connect_info->read_buffer = NULL; |
| 2039 | 2039 |
| 2040 phb->read_cb = s5_readauth; | 2040 connect_info->read_cb = s5_readauth; |
| 2041 | 2041 |
| 2042 phb->inpa = gaim_input_add(source, GAIM_INPUT_WRITE, | 2042 connect_info->inpa = gaim_input_add(source, GAIM_INPUT_WRITE, |
| 2043 proxy_do_write, phb); | 2043 proxy_do_write, connect_info); |
| 2044 | 2044 |
| 2045 proxy_do_write(phb, source, GAIM_INPUT_WRITE); | 2045 proxy_do_write(connect_info, source, GAIM_INPUT_WRITE); |
| 2046 | 2046 |
| 2047 return; | 2047 return; |
| 2048 } else if (phb->read_buffer[1] == 0x03) { | 2048 } else if (connect_info->read_buffer[1] == 0x03) { |
| 2049 gsize userlen; | 2049 gsize userlen; |
| 2050 userlen = strlen(gaim_proxy_info_get_username(phb->gpi)); | 2050 userlen = strlen(gaim_proxy_info_get_username(connect_info->gpi)); |
| 2051 | 2051 |
| 2052 phb->write_buf_len = 7 + userlen; | 2052 connect_info->write_buf_len = 7 + userlen; |
| 2053 phb->write_buffer = g_malloc(phb->write_buf_len); | 2053 connect_info->write_buffer = g_malloc(connect_info->write_buf_len); |
| 2054 phb->written_len = 0; | 2054 connect_info->written_len = 0; |
| 2055 | 2055 |
| 2056 phb->write_buffer[0] = 0x01; | 2056 connect_info->write_buffer[0] = 0x01; |
| 2057 phb->write_buffer[1] = 0x02; | 2057 connect_info->write_buffer[1] = 0x02; |
| 2058 phb->write_buffer[2] = 0x11; | 2058 connect_info->write_buffer[2] = 0x11; |
| 2059 phb->write_buffer[3] = 0x01; | 2059 connect_info->write_buffer[3] = 0x01; |
| 2060 phb->write_buffer[4] = 0x85; | 2060 connect_info->write_buffer[4] = 0x85; |
| 2061 phb->write_buffer[5] = 0x02; | 2061 connect_info->write_buffer[5] = 0x02; |
| 2062 phb->write_buffer[6] = userlen; | 2062 connect_info->write_buffer[6] = userlen; |
| 2063 memcpy(phb->write_buffer + 7, | 2063 memcpy(connect_info->write_buffer + 7, |
| 2064 gaim_proxy_info_get_username(phb->gpi), userlen); | 2064 gaim_proxy_info_get_username(connect_info->gpi), userlen); |
| 2065 | 2065 |
| 2066 g_free(phb->read_buffer); | 2066 g_free(connect_info->read_buffer); |
| 2067 phb->read_buffer = NULL; | 2067 connect_info->read_buffer = NULL; |
| 2068 | 2068 |
| 2069 phb->read_cb = s5_readchap; | 2069 connect_info->read_cb = s5_readchap; |
| 2070 | 2070 |
| 2071 phb->inpa = gaim_input_add(source, GAIM_INPUT_WRITE, | 2071 connect_info->inpa = gaim_input_add(source, GAIM_INPUT_WRITE, |
| 2072 proxy_do_write, phb); | 2072 proxy_do_write, connect_info); |
| 2073 | 2073 |
| 2074 proxy_do_write(phb, source, GAIM_INPUT_WRITE); | 2074 proxy_do_write(connect_info, source, GAIM_INPUT_WRITE); |
| 2075 | 2075 |
| 2076 return; | 2076 return; |
| 2077 } else { | 2077 } else { |
| 2078 g_free(phb->read_buffer); | 2078 g_free(connect_info->read_buffer); |
| 2079 phb->read_buffer = NULL; | 2079 connect_info->read_buffer = NULL; |
| 2080 | 2080 |
| 2081 s5_sendconnect(phb, source); | 2081 s5_sendconnect(connect_info, source); |
| 2082 } | 2082 } |
| 2083 } | 2083 } |
| 2084 | 2084 |
| 2085 static void | 2085 static void |
| 2086 s5_canwrite(gpointer data, gint source, GaimInputCondition cond) | 2086 s5_canwrite(gpointer data, gint source, GaimInputCondition cond) |
| 2087 { | 2087 { |
| 2088 unsigned char buf[5]; | 2088 unsigned char buf[5]; |
| 2089 int i; | 2089 int i; |
| 2090 struct _GaimProxyConnectInfo *phb = data; | 2090 struct _GaimProxyConnectInfo *connect_info = data; |
| 2091 socklen_t len; | 2091 socklen_t len; |
| 2092 int error = ETIMEDOUT; | 2092 int error = ETIMEDOUT; |
| 2093 | 2093 |
| 2094 gaim_debug_info("socks5 proxy", "Connected.\n"); | 2094 gaim_debug_info("socks5 proxy", "Connected.\n"); |
| 2095 | 2095 |
| 2096 if (phb->inpa > 0) | 2096 if (connect_info->inpa > 0) |
| 2097 { | 2097 { |
| 2098 gaim_input_remove(phb->inpa); | 2098 gaim_input_remove(connect_info->inpa); |
| 2099 phb->inpa = 0; | 2099 connect_info->inpa = 0; |
| 2100 } | 2100 } |
| 2101 | 2101 |
| 2102 len = sizeof(error); | 2102 len = sizeof(error); |
| 2103 if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { | 2103 if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { |
| 2104 close(source); | 2104 close(source); |
| 2105 | 2105 |
| 2106 try_connect(phb); | 2106 try_connect(connect_info); |
| 2107 return; | 2107 return; |
| 2108 } | 2108 } |
| 2109 | 2109 |
| 2110 i = 0; | 2110 i = 0; |
| 2111 buf[0] = 0x05; /* SOCKS version 5 */ | 2111 buf[0] = 0x05; /* SOCKS version 5 */ |
| 2112 | 2112 |
| 2113 if (gaim_proxy_info_get_username(phb->gpi) != NULL) { | 2113 if (gaim_proxy_info_get_username(connect_info->gpi) != NULL) { |
| 2114 buf[1] = 0x03; /* three methods */ | 2114 buf[1] = 0x03; /* three methods */ |
| 2115 buf[2] = 0x00; /* no authentication */ | 2115 buf[2] = 0x00; /* no authentication */ |
| 2116 buf[3] = 0x03; /* CHAP authentication */ | 2116 buf[3] = 0x03; /* CHAP authentication */ |
| 2117 buf[4] = 0x02; /* username/password authentication */ | 2117 buf[4] = 0x02; /* username/password authentication */ |
| 2118 i = 5; | 2118 i = 5; |
| 2121 buf[1] = 0x01; | 2121 buf[1] = 0x01; |
| 2122 buf[2] = 0x00; | 2122 buf[2] = 0x00; |
| 2123 i = 3; | 2123 i = 3; |
| 2124 } | 2124 } |
| 2125 | 2125 |
| 2126 phb->write_buf_len = i; | 2126 connect_info->write_buf_len = i; |
| 2127 phb->write_buffer = g_malloc(phb->write_buf_len); | 2127 connect_info->write_buffer = g_malloc(connect_info->write_buf_len); |
| 2128 memcpy(phb->write_buffer, buf, i); | 2128 memcpy(connect_info->write_buffer, buf, i); |
| 2129 | 2129 |
| 2130 phb->read_cb = s5_canread; | 2130 connect_info->read_cb = s5_canread; |
| 2131 | 2131 |
| 2132 phb->inpa = gaim_input_add(source, GAIM_INPUT_WRITE, proxy_do_write, phb); | 2132 connect_info->inpa = gaim_input_add(source, GAIM_INPUT_WRITE, proxy_do_write, connect_info); |
| 2133 proxy_do_write(phb, source, GAIM_INPUT_WRITE); | 2133 proxy_do_write(connect_info, source, GAIM_INPUT_WRITE); |
| 2134 } | 2134 } |
| 2135 | 2135 |
| 2136 static int | 2136 static int |
| 2137 proxy_connect_socks5(struct _GaimProxyConnectInfo *phb, struct sockaddr *addr, socklen_t addrlen) | 2137 proxy_connect_socks5(struct _GaimProxyConnectInfo *connect_info, struct sockaddr *addr, socklen_t addrlen) |
| 2138 { | 2138 { |
| 2139 int fd = -1; | 2139 int fd = -1; |
| 2140 | 2140 |
| 2141 gaim_debug_info("socks5 proxy", | 2141 gaim_debug_info("socks5 proxy", |
| 2142 "Connecting to %s:%d via %s:%d using SOCKS5\n", | 2142 "Connecting to %s:%d via %s:%d using SOCKS5\n", |
| 2143 phb->host, phb->port, | 2143 connect_info->host, connect_info->port, |
| 2144 gaim_proxy_info_get_host(phb->gpi), | 2144 gaim_proxy_info_get_host(connect_info->gpi), |
| 2145 gaim_proxy_info_get_port(phb->gpi)); | 2145 gaim_proxy_info_get_port(connect_info->gpi)); |
| 2146 | 2146 |
| 2147 if ((fd = socket(addr->sa_family, SOCK_STREAM, 0)) < 0) | 2147 if ((fd = socket(addr->sa_family, SOCK_STREAM, 0)) < 0) |
| 2148 return -1; | 2148 return -1; |
| 2149 | 2149 |
| 2150 fcntl(fd, F_SETFL, O_NONBLOCK); | 2150 fcntl(fd, F_SETFL, O_NONBLOCK); |
| 2155 if (connect(fd, addr, addrlen) < 0) { | 2155 if (connect(fd, addr, addrlen) < 0) { |
| 2156 if ((errno == EINPROGRESS) || (errno == EINTR)) { | 2156 if ((errno == EINPROGRESS) || (errno == EINTR)) { |
| 2157 gaim_debug_warning("socks5 proxy", | 2157 gaim_debug_warning("socks5 proxy", |
| 2158 "Connect would have blocked.\n"); | 2158 "Connect would have blocked.\n"); |
| 2159 | 2159 |
| 2160 phb->inpa = gaim_input_add(fd, GAIM_INPUT_WRITE, s5_canwrite, phb); | 2160 connect_info->inpa = gaim_input_add(fd, GAIM_INPUT_WRITE, s5_canwrite, connect_info); |
| 2161 } | 2161 } |
| 2162 else { | 2162 else { |
| 2163 close(fd); | 2163 close(fd); |
| 2164 return -1; | 2164 return -1; |
| 2165 } | 2165 } |
| 2176 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { | 2176 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { |
| 2177 close(fd); | 2177 close(fd); |
| 2178 return -1; | 2178 return -1; |
| 2179 } | 2179 } |
| 2180 | 2180 |
| 2181 s5_canwrite(phb, fd, GAIM_INPUT_WRITE); | 2181 s5_canwrite(connect_info, fd, GAIM_INPUT_WRITE); |
| 2182 } | 2182 } |
| 2183 | 2183 |
| 2184 return fd; | 2184 return fd; |
| 2185 } | 2185 } |
| 2186 | 2186 |
| 2187 static void try_connect(struct _GaimProxyConnectInfo *phb) | 2187 static void try_connect(struct _GaimProxyConnectInfo *connect_info) |
| 2188 { | 2188 { |
| 2189 size_t addrlen; | 2189 size_t addrlen; |
| 2190 struct sockaddr *addr; | 2190 struct sockaddr *addr; |
| 2191 int ret = -1; | 2191 int ret = -1; |
| 2192 | 2192 |
| 2193 while (phb->hosts) { | 2193 while (connect_info->hosts) { |
| 2194 addrlen = GPOINTER_TO_INT(phb->hosts->data); | 2194 addrlen = GPOINTER_TO_INT(connect_info->hosts->data); |
| 2195 phb->hosts = g_slist_remove(phb->hosts, phb->hosts->data); | 2195 connect_info->hosts = g_slist_remove(connect_info->hosts, connect_info->hosts->data); |
| 2196 addr = phb->hosts->data; | 2196 addr = connect_info->hosts->data; |
| 2197 phb->hosts = g_slist_remove(phb->hosts, phb->hosts->data); | 2197 connect_info->hosts = g_slist_remove(connect_info->hosts, connect_info->hosts->data); |
| 2198 | 2198 |
| 2199 switch (gaim_proxy_info_get_type(phb->gpi)) { | 2199 switch (gaim_proxy_info_get_type(connect_info->gpi)) { |
| 2200 case GAIM_PROXY_NONE: | 2200 case GAIM_PROXY_NONE: |
| 2201 ret = proxy_connect_none(phb, addr, addrlen); | 2201 ret = proxy_connect_none(connect_info, addr, addrlen); |
| 2202 break; | 2202 break; |
| 2203 | 2203 |
| 2204 case GAIM_PROXY_HTTP: | 2204 case GAIM_PROXY_HTTP: |
| 2205 ret = proxy_connect_http(phb, addr, addrlen); | 2205 ret = proxy_connect_http(connect_info, addr, addrlen); |
| 2206 break; | 2206 break; |
| 2207 | 2207 |
| 2208 case GAIM_PROXY_SOCKS4: | 2208 case GAIM_PROXY_SOCKS4: |
| 2209 ret = proxy_connect_socks4(phb, addr, addrlen); | 2209 ret = proxy_connect_socks4(connect_info, addr, addrlen); |
| 2210 break; | 2210 break; |
| 2211 | 2211 |
| 2212 case GAIM_PROXY_SOCKS5: | 2212 case GAIM_PROXY_SOCKS5: |
| 2213 ret = proxy_connect_socks5(phb, addr, addrlen); | 2213 ret = proxy_connect_socks5(connect_info, addr, addrlen); |
| 2214 break; | 2214 break; |
| 2215 | 2215 |
| 2216 case GAIM_PROXY_USE_ENVVAR: | 2216 case GAIM_PROXY_USE_ENVVAR: |
| 2217 ret = proxy_connect_http(phb, addr, addrlen); | 2217 ret = proxy_connect_http(connect_info, addr, addrlen); |
| 2218 break; | 2218 break; |
| 2219 | 2219 |
| 2220 default: | 2220 default: |
| 2221 break; | 2221 break; |
| 2222 } | 2222 } |
| 2226 if (ret > 0) | 2226 if (ret > 0) |
| 2227 break; | 2227 break; |
| 2228 } | 2228 } |
| 2229 | 2229 |
| 2230 if (ret < 0) { | 2230 if (ret < 0) { |
| 2231 gaim_proxy_phb_error(phb, _("TODO")); | 2231 gaim_proxy_connect_info_error(connect_info, _("TODO")); |
| 2232 } | 2232 } |
| 2233 } | 2233 } |
| 2234 | 2234 |
| 2235 static void | 2235 static void |
| 2236 connection_host_resolved(GSList *hosts, gpointer data, | 2236 connection_host_resolved(GSList *hosts, gpointer data, |
| 2237 const char *error_message) | 2237 const char *error_message) |
| 2238 { | 2238 { |
| 2239 struct _GaimProxyConnectInfo *phb = (struct _GaimProxyConnectInfo*)data; | 2239 struct _GaimProxyConnectInfo *connect_info = (struct _GaimProxyConnectInfo*)data; |
| 2240 | 2240 |
| 2241 phb->hosts = hosts; | 2241 connect_info->hosts = hosts; |
| 2242 | 2242 |
| 2243 try_connect(phb); | 2243 try_connect(connect_info); |
| 2244 } | 2244 } |
| 2245 | 2245 |
| 2246 GaimProxyInfo * | 2246 GaimProxyInfo * |
| 2247 gaim_proxy_get_setup(GaimAccount *account) | 2247 gaim_proxy_get_setup(GaimAccount *account) |
| 2248 { | 2248 { |
| 2314 GaimProxyConnectFunction connect_cb, | 2314 GaimProxyConnectFunction connect_cb, |
| 2315 GaimProxyErrorFunction error_cb, gpointer data) | 2315 GaimProxyErrorFunction error_cb, gpointer data) |
| 2316 { | 2316 { |
| 2317 const char *connecthost = host; | 2317 const char *connecthost = host; |
| 2318 int connectport = port; | 2318 int connectport = port; |
| 2319 struct _GaimProxyConnectInfo *phb; | 2319 struct _GaimProxyConnectInfo *connect_info; |
| 2320 | 2320 |
| 2321 g_return_val_if_fail(host != NULL, NULL); | 2321 g_return_val_if_fail(host != NULL, NULL); |
| 2322 g_return_val_if_fail(port > 0, NULL); | 2322 g_return_val_if_fail(port > 0, NULL); |
| 2323 g_return_val_if_fail(connect_cb != NULL, NULL); | 2323 g_return_val_if_fail(connect_cb != NULL, NULL); |
| 2324 /* g_return_val_if_fail(error_cb != NULL, NULL); *//* TODO: Soon! */ | 2324 /* g_return_val_if_fail(error_cb != NULL, NULL); *//* TODO: Soon! */ |
| 2325 | 2325 |
| 2326 phb = g_new0(struct _GaimProxyConnectInfo, 1); | 2326 connect_info = g_new0(struct _GaimProxyConnectInfo, 1); |
| 2327 phb->connect_cb = connect_cb; | 2327 connect_info->connect_cb = connect_cb; |
| 2328 phb->error_cb = error_cb; | 2328 connect_info->error_cb = error_cb; |
| 2329 phb->data = data; | 2329 connect_info->data = data; |
| 2330 phb->host = g_strdup(host); | 2330 connect_info->host = g_strdup(host); |
| 2331 phb->port = port; | 2331 connect_info->port = port; |
| 2332 phb->gpi = gaim_proxy_get_setup(account); | 2332 connect_info->gpi = gaim_proxy_get_setup(account); |
| 2333 | 2333 |
| 2334 if ((gaim_proxy_info_get_type(phb->gpi) != GAIM_PROXY_NONE) && | 2334 if ((gaim_proxy_info_get_type(connect_info->gpi) != GAIM_PROXY_NONE) && |
| 2335 (gaim_proxy_info_get_host(phb->gpi) == NULL || | 2335 (gaim_proxy_info_get_host(connect_info->gpi) == NULL || |
| 2336 gaim_proxy_info_get_port(phb->gpi) <= 0)) { | 2336 gaim_proxy_info_get_port(connect_info->gpi) <= 0)) { |
| 2337 | 2337 |
| 2338 gaim_notify_error(NULL, NULL, _("Invalid proxy settings"), _("Either the host name or port number specified for your given proxy type is invalid.")); | 2338 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_proxy_phb_destroy(phb); | 2339 gaim_proxy_connect_info_destroy(connect_info); |
| 2340 return NULL; | 2340 return NULL; |
| 2341 } | 2341 } |
| 2342 | 2342 |
| 2343 switch (gaim_proxy_info_get_type(phb->gpi)) | 2343 switch (gaim_proxy_info_get_type(connect_info->gpi)) |
| 2344 { | 2344 { |
| 2345 case GAIM_PROXY_NONE: | 2345 case GAIM_PROXY_NONE: |
| 2346 break; | 2346 break; |
| 2347 | 2347 |
| 2348 case GAIM_PROXY_HTTP: | 2348 case GAIM_PROXY_HTTP: |
| 2349 case GAIM_PROXY_SOCKS4: | 2349 case GAIM_PROXY_SOCKS4: |
| 2350 case GAIM_PROXY_SOCKS5: | 2350 case GAIM_PROXY_SOCKS5: |
| 2351 case GAIM_PROXY_USE_ENVVAR: | 2351 case GAIM_PROXY_USE_ENVVAR: |
| 2352 connecthost = gaim_proxy_info_get_host(phb->gpi); | 2352 connecthost = gaim_proxy_info_get_host(connect_info->gpi); |
| 2353 connectport = gaim_proxy_info_get_port(phb->gpi); | 2353 connectport = gaim_proxy_info_get_port(connect_info->gpi); |
| 2354 break; | 2354 break; |
| 2355 | 2355 |
| 2356 default: | 2356 default: |
| 2357 gaim_proxy_phb_destroy(phb); | 2357 gaim_proxy_connect_info_destroy(connect_info); |
| 2358 return NULL; | 2358 return NULL; |
| 2359 } | 2359 } |
| 2360 | 2360 |
| 2361 if (gaim_gethostbyname_async(connecthost, | 2361 if (gaim_gethostbyname_async(connecthost, |
| 2362 connectport, connection_host_resolved, phb) != 0) | 2362 connectport, connection_host_resolved, connect_info) != 0) |
| 2363 { | 2363 { |
| 2364 gaim_proxy_phb_destroy(phb); | 2364 gaim_proxy_connect_info_destroy(connect_info); |
| 2365 return NULL; | 2365 return NULL; |
| 2366 } | 2366 } |
| 2367 | 2367 |
| 2368 phbs = g_slist_prepend(phbs, phb); | 2368 connect_infos = g_slist_prepend(connect_infos, connect_info); |
| 2369 | 2369 |
| 2370 return phb; | 2370 return connect_info; |
| 2371 } | 2371 } |
| 2372 | 2372 |
| 2373 /* | 2373 /* |
| 2374 * Combine some of this code with gaim_proxy_connect() | 2374 * Combine some of this code with gaim_proxy_connect() |
| 2375 */ | 2375 */ |
| 2376 GaimProxyConnectInfo * | 2376 GaimProxyConnectInfo * |
| 2377 gaim_proxy_connect_socks5(GaimProxyInfo *gpi, const char *host, int port, | 2377 gaim_proxy_connect_socks5(GaimProxyInfo *gpi, const char *host, int port, |
| 2378 GaimProxyConnectFunction connect_cb, | 2378 GaimProxyConnectFunction connect_cb, |
| 2379 GaimProxyErrorFunction error_cb, gpointer data) | 2379 GaimProxyErrorFunction error_cb, gpointer data) |
| 2380 { | 2380 { |
| 2381 struct _GaimProxyConnectInfo *phb; | 2381 struct _GaimProxyConnectInfo *connect_info; |
| 2382 | 2382 |
| 2383 g_return_val_if_fail(host != NULL, NULL); | 2383 g_return_val_if_fail(host != NULL, NULL); |
| 2384 g_return_val_if_fail(port > 0, NULL); | 2384 g_return_val_if_fail(port > 0, NULL); |
| 2385 g_return_val_if_fail(connect_cb != NULL, NULL); | 2385 g_return_val_if_fail(connect_cb != NULL, NULL); |
| 2386 /* g_return_val_if_fail(error_cb != NULL, NULL); *//* TODO: Soon! */ | 2386 /* g_return_val_if_fail(error_cb != NULL, NULL); *//* TODO: Soon! */ |
| 2387 | 2387 |
| 2388 phb = g_new0(struct _GaimProxyConnectInfo, 1); | 2388 connect_info = g_new0(struct _GaimProxyConnectInfo, 1); |
| 2389 phb->connect_cb = connect_cb; | 2389 connect_info->connect_cb = connect_cb; |
| 2390 phb->error_cb = error_cb; | 2390 connect_info->error_cb = error_cb; |
| 2391 phb->data = data; | 2391 connect_info->data = data; |
| 2392 phb->host = g_strdup(host); | 2392 connect_info->host = g_strdup(host); |
| 2393 phb->port = port; | 2393 connect_info->port = port; |
| 2394 phb->gpi = gpi; | 2394 connect_info->gpi = gpi; |
| 2395 | 2395 |
| 2396 if (gaim_gethostbyname_async(gaim_proxy_info_get_host(gpi), | 2396 if (gaim_gethostbyname_async(gaim_proxy_info_get_host(gpi), |
| 2397 gaim_proxy_info_get_port(gpi), connection_host_resolved, phb) != 0) | 2397 gaim_proxy_info_get_port(gpi), connection_host_resolved, connect_info) != 0) |
| 2398 { | 2398 { |
| 2399 gaim_proxy_phb_destroy(phb); | 2399 gaim_proxy_connect_info_destroy(connect_info); |
| 2400 return NULL; | 2400 return NULL; |
| 2401 } | 2401 } |
| 2402 | 2402 |
| 2403 phbs = g_slist_prepend(phbs, phb); | 2403 connect_infos = g_slist_prepend(connect_infos, connect_info); |
| 2404 | 2404 |
| 2405 return phb; | 2405 return connect_info; |
| 2406 } | 2406 } |
| 2407 | 2407 |
| 2408 | 2408 |
| 2409 static void | 2409 static void |
| 2410 proxy_pref_cb(const char *name, GaimPrefType type, | 2410 proxy_pref_cb(const char *name, GaimPrefType type, |
| 2483 } | 2483 } |
| 2484 | 2484 |
| 2485 void | 2485 void |
| 2486 gaim_proxy_uninit(void) | 2486 gaim_proxy_uninit(void) |
| 2487 { | 2487 { |
| 2488 while (phbs != NULL) | 2488 while (connect_infos != NULL) |
| 2489 gaim_proxy_phb_destroy(phbs->data); | 2489 gaim_proxy_connect_info_destroy(connect_infos->data); |
| 2490 } | 2490 } |
