18 #ifndef ZMQ_HAVE_WINDOWS
20 #include <sys/types.h>
21 #include <sys/socket.h>
22 #if defined ZMQ_HAVE_VXWORKS
27 zmq::socks_connecter_t::socks_connecter_t (
class io_thread_t *io_thread_,
28 class session_base_t *session_,
31 address_t *proxy_addr_,
32 bool delayed_start_) :
33 stream_connecter_base_t (
34 io_thread_, session_,
options_, addr_, delayed_start_),
35 _proxy_addr (proxy_addr_),
36 _auth_method (socks_no_auth_required),
40 _proxy_addr->to_string (_endpoint);
43 zmq::socks_connecter_t::~socks_connecter_t ()
48 void zmq::socks_connecter_t::set_auth_method_none ()
50 _auth_method = socks_no_auth_required;
51 _auth_username.clear ();
52 _auth_password.clear ();
55 void zmq::socks_connecter_t::set_auth_method_basic (
58 _auth_method = socks_basic_auth;
59 _auth_username = username_;
60 _auth_password = password_;
63 void zmq::socks_connecter_t::in_event ()
65 int expected_status = -1;
68 if (_status == waiting_for_choice) {
69 int rc = _choice_decoder.input (_s);
70 if (rc == 0 || rc == -1)
72 else if (_choice_decoder.message_ready ()) {
73 const socks_choice_t choice = _choice_decoder.decode ();
74 rc = process_server_response (choice);
78 if (choice.method == socks_basic_auth)
79 expected_status = sending_basic_auth_request;
81 expected_status = sending_request;
84 }
else if (_status == waiting_for_auth_response) {
85 int rc = _auth_response_decoder.input (_s);
86 if (rc == 0 || rc == -1)
88 else if (_auth_response_decoder.message_ready ()) {
89 const socks_auth_response_t auth_response =
90 _auth_response_decoder.decode ();
91 rc = process_server_response (auth_response);
95 expected_status = sending_request;
98 }
else if (_status == waiting_for_response) {
99 int rc = _response_decoder.input (_s);
100 if (rc == 0 || rc == -1)
102 else if (_response_decoder.message_ready ()) {
103 const socks_response_t
response = _response_decoder.decode ();
104 rc = process_server_response (response);
118 if (expected_status == sending_basic_auth_request) {
119 _basic_auth_request_encoder.encode (
120 socks_basic_auth_request_t (_auth_username, _auth_password));
121 reset_pollin (_handle);
122 set_pollout (_handle);
123 _status = sending_basic_auth_request;
124 }
else if (expected_status == sending_request) {
127 if (parse_address (_addr->address, hostname, port) == -1)
130 _request_encoder.encode (socks_request_t (1, hostname, port));
131 reset_pollin (_handle);
132 set_pollout (_handle);
133 _status = sending_request;
138 void zmq::socks_connecter_t::out_event ()
141 _status == waiting_for_proxy_connection || _status == sending_greeting
142 || _status == sending_basic_auth_request || _status == sending_request);
144 if (_status == waiting_for_proxy_connection) {
145 const int rc =
static_cast<int> (check_proxy_connection ());
149 _greeting_encoder.encode (socks_greeting_t (_auth_method));
150 _status = sending_greeting;
152 }
else if (_status == sending_greeting) {
153 zmq_assert (_greeting_encoder.has_pending_data ());
154 const int rc = _greeting_encoder.output (_s);
155 if (rc == -1 || rc == 0)
157 else if (!_greeting_encoder.has_pending_data ()) {
158 reset_pollout (_handle);
159 set_pollin (_handle);
160 _status = waiting_for_choice;
162 }
else if (_status == sending_basic_auth_request) {
163 zmq_assert (_basic_auth_request_encoder.has_pending_data ());
164 const int rc = _basic_auth_request_encoder.output (_s);
165 if (rc == -1 || rc == 0)
167 else if (!_basic_auth_request_encoder.has_pending_data ()) {
168 reset_pollout (_handle);
169 set_pollin (_handle);
170 _status = waiting_for_auth_response;
173 zmq_assert (_request_encoder.has_pending_data ());
174 const int rc = _request_encoder.output (_s);
175 if (rc == -1 || rc == 0)
177 else if (!_request_encoder.has_pending_data ()) {
178 reset_pollout (_handle);
179 set_pollin (_handle);
180 _status = waiting_for_response;
185 void zmq::socks_connecter_t::start_connecting ()
190 const int rc = connect_to_proxy ();
194 _handle = add_fd (_s);
195 set_pollout (_handle);
196 _status = sending_greeting;
200 _handle = add_fd (_s);
201 set_pollout (_handle);
202 _status = waiting_for_proxy_connection;
203 _socket->event_connect_delayed (
210 add_reconnect_timer ();
214 int zmq::socks_connecter_t::process_server_response (
215 const socks_choice_t &response_)
217 return response_.method == socks_no_auth_required
218 || response_.method == socks_basic_auth
223 int zmq::socks_connecter_t::process_server_response (
224 const socks_response_t &response_)
226 return response_.response_code == 0 ? 0 : -1;
229 int zmq::socks_connecter_t::process_server_response (
230 const socks_auth_response_t &response_)
232 return response_.response_code == 0 ? 0 : -1;
235 void zmq::socks_connecter_t::error ()
239 _greeting_encoder.reset ();
240 _choice_decoder.reset ();
241 _basic_auth_request_encoder.reset ();
242 _auth_response_decoder.reset ();
243 _request_encoder.reset ();
244 _response_decoder.reset ();
246 add_reconnect_timer ();
249 int zmq::socks_connecter_t::connect_to_proxy ()
254 if (_proxy_addr->resolved.tcp_addr !=
NULL) {
258 _proxy_addr->resolved.tcp_addr =
new (std::nothrow) tcp_address_t ();
264 _proxy_addr->resolved.tcp_addr);
275 const tcp_address_t *
const tcp_addr = _proxy_addr->resolved.tcp_addr;
280 if (tcp_addr->has_src_addr ()) {
281 #if defined ZMQ_HAVE_VXWORKS
282 rc = ::bind (_s, (sockaddr *) tcp_addr->src_addr (),
283 tcp_addr->src_addrlen ());
285 rc = ::bind (_s, tcp_addr->src_addr (), tcp_addr->src_addrlen ());
294 #if defined ZMQ_HAVE_VXWORKS
295 rc = ::connect (_s, (sockaddr *) tcp_addr->addr (), tcp_addr->addrlen ());
297 rc = ::connect (_s, tcp_addr->addr (), tcp_addr->addrlen ());
305 #ifdef ZMQ_HAVE_WINDOWS
306 const int last_error = WSAGetLastError ();
307 if (last_error == WSAEINPROGRESS || last_error == WSAEWOULDBLOCK)
310 errno = wsa_error_to_errno (last_error);
320 zmq::fd_t zmq::socks_connecter_t::check_proxy_connection ()
const
324 #if defined ZMQ_HAVE_HPUX || defined ZMQ_HAVE_VXWORKS
327 socklen_t
len =
sizeof err;
330 int rc = getsockopt (_s, SOL_SOCKET, SO_ERROR,
331 reinterpret_cast<char *
> (&
err), &
len);
335 #ifdef ZMQ_HAVE_WINDOWS
338 wsa_assert (
err == WSAECONNREFUSED ||
err == WSAETIMEDOUT
339 ||
err == WSAECONNABORTED ||
err == WSAEHOSTUNREACH
340 ||
err == WSAENETUNREACH ||
err == WSAENETDOWN
341 ||
err == WSAEACCES ||
err == WSAEINVAL
342 ||
err == WSAEADDRINUSE);
371 int zmq::socks_connecter_t::parse_address (
const std::string &address_,
376 const size_t idx = address_.rfind (
':');
377 if (
idx == std::string::npos) {
383 if (
idx < 2 || address_[0] !=
'[' || address_[
idx - 1] !=
']')
384 hostname_ = address_.substr (0,
idx);
386 hostname_ = address_.substr (1,
idx - 2);
391 port_ =
static_cast<uint16_t
> (atoi (port_str.c_str ()));