| 835 return; |
835 return; |
| 836 } |
836 } |
| 837 } |
837 } |
| 838 |
838 |
| 839 static void |
839 static void |
| 840 http_canwrite(gpointer data, gint source, PurpleInputCondition cond) |
840 http_start_connect_tunneling(PurpleProxyConnectData *connect_data) { |
| 841 { |
|
| 842 GString *request; |
841 GString *request; |
| 843 PurpleProxyConnectData *connect_data; |
|
| 844 int error = ETIMEDOUT; |
|
| 845 int ret; |
842 int ret; |
| 846 |
|
| 847 connect_data = data; |
|
| 848 |
|
| 849 purple_debug_info("proxy", "Connected to %s:%d.\n", |
|
| 850 connect_data->host, connect_data->port); |
|
| 851 |
|
| 852 if (connect_data->inpa > 0) |
|
| 853 { |
|
| 854 purple_input_remove(connect_data->inpa); |
|
| 855 connect_data->inpa = 0; |
|
| 856 } |
|
| 857 |
|
| 858 ret = purple_input_get_error(connect_data->fd, &error); |
|
| 859 if ((ret != 0) || (error != 0)) |
|
| 860 { |
|
| 861 if (ret != 0) |
|
| 862 error = errno; |
|
| 863 purple_proxy_connect_data_disconnect(connect_data, g_strerror(error)); |
|
| 864 return; |
|
| 865 } |
|
| 866 |
843 |
| 867 purple_debug_info("proxy", "Using CONNECT tunneling for %s:%d\n", |
844 purple_debug_info("proxy", "Using CONNECT tunneling for %s:%d\n", |
| 868 connect_data->host, connect_data->port); |
845 connect_data->host, connect_data->port); |
| 869 |
846 |
| 870 request = g_string_sized_new(4096); |
847 request = g_string_sized_new(4096); |
| 910 connect_data->written_len = 0; |
887 connect_data->written_len = 0; |
| 911 connect_data->read_cb = http_canread; |
888 connect_data->read_cb = http_canread; |
| 912 |
889 |
| 913 connect_data->inpa = purple_input_add(connect_data->fd, |
890 connect_data->inpa = purple_input_add(connect_data->fd, |
| 914 PURPLE_INPUT_WRITE, proxy_do_write, connect_data); |
891 PURPLE_INPUT_WRITE, proxy_do_write, connect_data); |
| 915 proxy_do_write(connect_data, connect_data->fd, cond); |
892 proxy_do_write(connect_data, connect_data->fd, PURPLE_INPUT_WRITE); |
| |
893 } |
| |
894 |
| |
895 static void |
| |
896 http_canwrite(gpointer data, gint source, PurpleInputCondition cond) { |
| |
897 PurpleProxyConnectData *connect_data = data; |
| |
898 int ret, error = ETIMEDOUT; |
| |
899 |
| |
900 purple_debug_info("proxy", "Connected to %s:%d.\n", |
| |
901 connect_data->host, connect_data->port); |
| |
902 |
| |
903 if (connect_data->inpa > 0) { |
| |
904 purple_input_remove(connect_data->inpa); |
| |
905 connect_data->inpa = 0; |
| |
906 } |
| |
907 |
| |
908 ret = purple_input_get_error(connect_data->fd, &error); |
| |
909 if (ret != 0 || error != 0) { |
| |
910 if (ret != 0) |
| |
911 error = errno; |
| |
912 purple_proxy_connect_data_disconnect(connect_data, g_strerror(error)); |
| |
913 return; |
| |
914 } |
| |
915 |
| |
916 if (connect_data->port == 80) { |
| |
917 /* |
| |
918 * If we're trying to connect to something running on |
| |
919 * port 80 then we assume the traffic using this |
| |
920 * connection is going to be HTTP traffic. If it's |
| |
921 * not then this will fail (uglily). But it's good |
| |
922 * to avoid using the CONNECT method because it's |
| |
923 * not always allowed. |
| |
924 */ |
| |
925 purple_debug_info("proxy", "HTTP proxy connection established\n"); |
| |
926 purple_proxy_connect_data_connected(connect_data); |
| |
927 } else { |
| |
928 http_start_connect_tunneling(connect_data); |
| |
929 } |
| |
930 |
| 916 } |
931 } |
| 917 |
932 |
| 918 static void |
933 static void |
| 919 proxy_connect_http(PurpleProxyConnectData *connect_data, struct sockaddr *addr, socklen_t addrlen) |
934 proxy_connect_http(PurpleProxyConnectData *connect_data, struct sockaddr *addr, socklen_t addrlen) |
| 920 { |
935 { |
| 938 fcntl(connect_data->fd, F_SETFL, flags | O_NONBLOCK); |
953 fcntl(connect_data->fd, F_SETFL, flags | O_NONBLOCK); |
| 939 #ifndef _WIN32 |
954 #ifndef _WIN32 |
| 940 fcntl(connect_data->fd, F_SETFD, FD_CLOEXEC); |
955 fcntl(connect_data->fd, F_SETFD, FD_CLOEXEC); |
| 941 #endif |
956 #endif |
| 942 |
957 |
| 943 if (connect(connect_data->fd, addr, addrlen) != 0) |
958 if (connect(connect_data->fd, addr, addrlen) != 0) { |
| 944 { |
959 if (errno == EINPROGRESS || errno == EINTR) { |
| 945 if ((errno == EINPROGRESS) || (errno == EINTR)) |
|
| 946 { |
|
| 947 purple_debug_info("proxy", "Connection in progress\n"); |
960 purple_debug_info("proxy", "Connection in progress\n"); |
| 948 |
961 |
| 949 if (connect_data->port != 80) |
962 connect_data->inpa = purple_input_add(connect_data->fd, |
| 950 { |
963 PURPLE_INPUT_WRITE, http_canwrite, connect_data); |
| 951 /* we need to do CONNECT first */ |
964 } else |
| 952 connect_data->inpa = purple_input_add(connect_data->fd, |
|
| 953 PURPLE_INPUT_WRITE, http_canwrite, connect_data); |
|
| 954 } |
|
| 955 else |
|
| 956 { |
|
| 957 /* |
|
| 958 * If we're trying to connect to something running on |
|
| 959 * port 80 then we assume the traffic using this |
|
| 960 * connection is going to be HTTP traffic. If it's |
|
| 961 * not then this will fail (uglily). But it's good |
|
| 962 * to avoid using the CONNECT method because it's |
|
| 963 * not always allowed. |
|
| 964 */ |
|
| 965 purple_debug_info("proxy", "HTTP proxy connection established\n"); |
|
| 966 purple_proxy_connect_data_connected(connect_data); |
|
| 967 } |
|
| 968 } |
|
| 969 else |
|
| 970 { |
|
| 971 purple_proxy_connect_data_disconnect(connect_data, g_strerror(errno)); |
965 purple_proxy_connect_data_disconnect(connect_data, g_strerror(errno)); |
| 972 } |
966 } else { |
| 973 } |
|
| 974 else |
|
| 975 { |
|
| 976 purple_debug_info("proxy", "Connected immediately.\n"); |
967 purple_debug_info("proxy", "Connected immediately.\n"); |
| 977 |
968 |
| 978 http_canwrite(connect_data, connect_data->fd, PURPLE_INPUT_WRITE); |
969 http_canwrite(connect_data, connect_data->fd, PURPLE_INPUT_WRITE); |
| 979 } |
970 } |
| 980 } |
971 } |