| 295 /** |
295 /** |
| 296 * @param error An error message explaining why the connection |
296 * @param error An error message explaining why the connection |
| 297 * failed. This will be passed to the callback function |
297 * failed. This will be passed to the callback function |
| 298 * specified in the call to gaim_proxy_connect(). |
298 * specified in the call to gaim_proxy_connect(). |
| 299 */ |
299 */ |
| |
300 /* |
| |
301 * TODO: Make sure all callers of this function pass a really really |
| |
302 * good error_message. |
| |
303 */ |
| 300 static void |
304 static void |
| 301 gaim_proxy_connect_info_error(GaimProxyConnectInfo *connect_info, const gchar *error_message) |
305 gaim_proxy_connect_info_error(GaimProxyConnectInfo *connect_info, const gchar *error_message) |
| 302 { |
306 { |
| 303 if (connect_info->error_cb == NULL) |
307 if (connect_info->error_cb == NULL) |
| 304 { |
308 { |
| 1064 fcntl(fd, F_SETFL, O_NONBLOCK); |
1068 fcntl(fd, F_SETFL, O_NONBLOCK); |
| 1065 #ifndef _WIN32 |
1069 #ifndef _WIN32 |
| 1066 fcntl(fd, F_SETFD, FD_CLOEXEC); |
1070 fcntl(fd, F_SETFD, FD_CLOEXEC); |
| 1067 #endif |
1071 #endif |
| 1068 |
1072 |
| 1069 if (connect(fd, (struct sockaddr *)addr, addrlen) < 0) { |
1073 if (connect(fd, (struct sockaddr *)addr, addrlen) != 0) |
| |
1074 { |
| 1070 if ((errno == EINPROGRESS) || (errno == EINTR)) { |
1075 if ((errno == EINPROGRESS) || (errno == EINTR)) { |
| 1071 /* This just confuses people. */ |
1076 /* This just confuses people. */ |
| 1072 /* gaim_debug_warning("proxy", |
1077 /* gaim_debug_warning("proxy", |
| 1073 "Connect would have blocked.\n"); */ |
1078 "Connect would have blocked.\n"); */ |
| 1074 connect_info->inpa = gaim_input_add(fd, GAIM_INPUT_WRITE, no_one_calls, connect_info); |
1079 connect_info->inpa = gaim_input_add(fd, GAIM_INPUT_WRITE, no_one_calls, connect_info); |
| 1083 else { |
1088 else { |
| 1084 socklen_t len; |
1089 socklen_t len; |
| 1085 int error = ETIMEDOUT; |
1090 int error = ETIMEDOUT; |
| 1086 gaim_debug_misc("proxy", "Connect didn't block.\n"); |
1091 gaim_debug_misc("proxy", "Connect didn't block.\n"); |
| 1087 len = sizeof(error); |
1092 len = sizeof(error); |
| 1088 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { |
1093 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) != 0) |
| |
1094 { |
| 1089 gaim_debug_error("proxy", "getsockopt failed.\n"); |
1095 gaim_debug_error("proxy", "getsockopt failed.\n"); |
| 1090 close(fd); |
1096 close(fd); |
| 1091 return -1; |
1097 return -1; |
| 1092 } |
1098 } |
| 1093 /* TODO: Why is the following line so strange? */ |
1099 /* TODO: Why is the following line so strange? */ |
| 1453 fcntl(fd, F_SETFL, O_NONBLOCK); |
1459 fcntl(fd, F_SETFL, O_NONBLOCK); |
| 1454 #ifndef _WIN32 |
1460 #ifndef _WIN32 |
| 1455 fcntl(fd, F_SETFD, FD_CLOEXEC); |
1461 fcntl(fd, F_SETFD, FD_CLOEXEC); |
| 1456 #endif |
1462 #endif |
| 1457 |
1463 |
| 1458 if (connect(fd, addr, addrlen) < 0) { |
1464 if (connect(fd, addr, addrlen) != 0) |
| |
1465 { |
| 1459 if ((errno == EINPROGRESS) || (errno == EINTR)) { |
1466 if ((errno == EINPROGRESS) || (errno == EINTR)) { |
| 1460 gaim_debug_warning("http proxy", |
1467 gaim_debug_warning("http proxy", |
| 1461 "Connect would have blocked.\n"); |
1468 "Connect would have blocked.\n"); |
| 1462 |
1469 |
| 1463 if (connect_info->port != 80) { |
1470 if (connect_info->port != 80) { |
| 1479 |
1486 |
| 1480 gaim_debug_misc("http proxy", |
1487 gaim_debug_misc("http proxy", |
| 1481 "Connect didn't block.\n"); |
1488 "Connect didn't block.\n"); |
| 1482 |
1489 |
| 1483 len = sizeof(error); |
1490 len = sizeof(error); |
| 1484 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { |
1491 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) != 0) |
| |
1492 { |
| 1485 close(fd); |
1493 close(fd); |
| 1486 return -1; |
1494 return -1; |
| 1487 } |
1495 } |
| 1488 http_canwrite(connect_info, fd, GAIM_INPUT_WRITE); |
1496 http_canwrite(connect_info, fd, GAIM_INPUT_WRITE); |
| 1489 } |
1497 } |
| 1610 fcntl(fd, F_SETFL, O_NONBLOCK); |
1618 fcntl(fd, F_SETFL, O_NONBLOCK); |
| 1611 #ifndef _WIN32 |
1619 #ifndef _WIN32 |
| 1612 fcntl(fd, F_SETFD, FD_CLOEXEC); |
1620 fcntl(fd, F_SETFD, FD_CLOEXEC); |
| 1613 #endif |
1621 #endif |
| 1614 |
1622 |
| 1615 if (connect(fd, addr, addrlen) < 0) { |
1623 if (connect(fd, addr, addrlen) != 0) |
| |
1624 { |
| 1616 if ((errno == EINPROGRESS) || (errno == EINTR)) { |
1625 if ((errno == EINPROGRESS) || (errno == EINTR)) { |
| 1617 gaim_debug_warning("socks4 proxy", |
1626 gaim_debug_warning("socks4 proxy", |
| 1618 "Connect would have blocked.\n"); |
1627 "Connect would have blocked.\n"); |
| 1619 connect_info->inpa = gaim_input_add(fd, GAIM_INPUT_WRITE, s4_canwrite, connect_info); |
1628 connect_info->inpa = gaim_input_add(fd, GAIM_INPUT_WRITE, s4_canwrite, connect_info); |
| 1620 } |
1629 } |
| 1629 gaim_debug_misc("socks4 proxy", |
1638 gaim_debug_misc("socks4 proxy", |
| 1630 "Connect didn't block.\n"); |
1639 "Connect didn't block.\n"); |
| 1631 |
1640 |
| 1632 len = sizeof(error); |
1641 len = sizeof(error); |
| 1633 |
1642 |
| 1634 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { |
1643 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) != 0) |
| |
1644 { |
| 1635 close(fd); |
1645 close(fd); |
| 1636 return -1; |
1646 return -1; |
| 1637 } |
1647 } |
| 1638 |
1648 |
| 1639 s4_canwrite(connect_info, fd, GAIM_INPUT_WRITE); |
1649 s4_canwrite(connect_info, fd, GAIM_INPUT_WRITE); |
| 2157 fcntl(fd, F_SETFL, O_NONBLOCK); |
2167 fcntl(fd, F_SETFL, O_NONBLOCK); |
| 2158 #ifndef _WIN32 |
2168 #ifndef _WIN32 |
| 2159 fcntl(fd, F_SETFD, FD_CLOEXEC); |
2169 fcntl(fd, F_SETFD, FD_CLOEXEC); |
| 2160 #endif |
2170 #endif |
| 2161 |
2171 |
| 2162 if (connect(fd, addr, addrlen) < 0) { |
2172 if (connect(fd, addr, addrlen) != 0) |
| |
2173 { |
| 2163 if ((errno == EINPROGRESS) || (errno == EINTR)) { |
2174 if ((errno == EINPROGRESS) || (errno == EINTR)) { |
| 2164 gaim_debug_warning("socks5 proxy", |
2175 gaim_debug_warning("socks5 proxy", |
| 2165 "Connect would have blocked.\n"); |
2176 "Connect would have blocked.\n"); |
| 2166 |
2177 |
| 2167 connect_info->inpa = gaim_input_add(fd, GAIM_INPUT_WRITE, s5_canwrite, connect_info); |
2178 connect_info->inpa = gaim_input_add(fd, GAIM_INPUT_WRITE, s5_canwrite, connect_info); |
| 2177 |
2188 |
| 2178 gaim_debug_misc("socks5 proxy", "Connect didn't block.\n"); |
2189 gaim_debug_misc("socks5 proxy", "Connect didn't block.\n"); |
| 2179 |
2190 |
| 2180 len = sizeof(error); |
2191 len = sizeof(error); |
| 2181 |
2192 |
| 2182 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { |
2193 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) != 0) |
| |
2194 { |
| 2183 close(fd); |
2195 close(fd); |
| 2184 return -1; |
2196 return -1; |
| 2185 } |
2197 } |
| 2186 |
2198 |
| 2187 s5_canwrite(connect_info, fd, GAIM_INPUT_WRITE); |
2199 s5_canwrite(connect_info, fd, GAIM_INPUT_WRITE); |
| 2194 { |
2206 { |
| 2195 size_t addrlen; |
2207 size_t addrlen; |
| 2196 struct sockaddr *addr; |
2208 struct sockaddr *addr; |
| 2197 int ret = -1; |
2209 int ret = -1; |
| 2198 |
2210 |
| 2199 while (connect_info->hosts) { |
2211 if (connect_info->hosts == NULL) |
| |
2212 { |
| |
2213 gaim_proxy_connect_info_error(connect_info, _("Could not resolve host name")); |
| |
2214 return; |
| |
2215 } |
| |
2216 |
| |
2217 while (connect_info->hosts) |
| |
2218 { |
| 2200 addrlen = GPOINTER_TO_INT(connect_info->hosts->data); |
2219 addrlen = GPOINTER_TO_INT(connect_info->hosts->data); |
| 2201 connect_info->hosts = g_slist_remove(connect_info->hosts, connect_info->hosts->data); |
2220 connect_info->hosts = g_slist_remove(connect_info->hosts, connect_info->hosts->data); |
| 2202 addr = connect_info->hosts->data; |
2221 addr = connect_info->hosts->data; |
| 2203 connect_info->hosts = g_slist_remove(connect_info->hosts, connect_info->hosts->data); |
2222 connect_info->hosts = g_slist_remove(connect_info->hosts, connect_info->hosts->data); |
| 2204 |
2223 |
| 2227 break; |
2246 break; |
| 2228 } |
2247 } |
| 2229 |
2248 |
| 2230 g_free(addr); |
2249 g_free(addr); |
| 2231 |
2250 |
| 2232 if (ret > 0) |
2251 if (ret >= 0) |
| 2233 break; |
2252 break; |
| 2234 } |
2253 } |
| 2235 |
2254 |
| 2236 if (ret < 0) { |
2255 if (ret < 0) { |
| 2237 gaim_proxy_connect_info_error(connect_info, _("TODO")); |
2256 gaim_proxy_connect_info_error(connect_info, _("Unable to establish a connection")); |
| 2238 } |
2257 } |
| 2239 } |
2258 } |
| 2240 |
2259 |
| 2241 static void |
2260 static void |
| 2242 connection_host_resolved(GSList *hosts, gpointer data, |
2261 connection_host_resolved(GSList *hosts, gpointer data, |
| 2243 const char *error_message) |
2262 const char *error_message) |
| 2244 { |
2263 { |
| 2245 GaimProxyConnectInfo *connect_info; |
2264 GaimProxyConnectInfo *connect_info; |
| |
2265 |
| |
2266 if (error_message != NULL) |
| |
2267 { |
| |
2268 gaim_debug_info("proxy", "Error while resolving hostname: %s\n", error_message); |
| |
2269 /* TODO: Destroy connect_info and return? */ |
| |
2270 } |
| 2246 |
2271 |
| 2247 connect_info = data; |
2272 connect_info = data; |
| 2248 connect_info->hosts = hosts; |
2273 connect_info->hosts = hosts; |
| 2249 |
2274 |
| 2250 try_connect(connect_info); |
2275 try_connect(connect_info); |