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 }