def write_to_fd(self, data):
return self.socket.send(data)
- def connect(self, address, callback=None, server_hostname=None,
- source_ip=None):
+ def connect(self, address, callback=None, server_hostname=None):
"""Connects the socket to a remote address without blocking.
May only be called if the socket passed to the constructor was
``ssl_options``) and SNI (if supported; requires Python
2.7.9+).
- If ``source_ip`` is specified, will try to use a certain source
- IP address to establish the connection.
-
Note that it is safe to call `IOStream.write
<BaseIOStream.write>` while the connection is pending, in
which case the data will be written as soon as the connection
future = None
else:
future = self._connect_future = TracebackFuture()
- if source_ip:
- try:
- self.socket.bind((source_ip, 0))
- # port = 0, will not bind to a specific port
- except socket.error as e:
- gen_log.error("Unable to use the source IP %s",
- source_ip)
- gen_log.error("%s: %s", self.socket.fileno(), e)
- # log the error and move on
- # will try to connect using the loopback
- gen_log.warning("Using the loopback IP address as source.")
try:
self.socket.connect(address)
except socket.error as e:
return
super(SSLIOStream, self)._handle_write()
- def connect(self, address, callback=None, server_hostname=None,
- source_ip=None):
- # source_ip not used here
+ def connect(self, address, callback=None, server_hostname=None):
self._server_hostname = server_hostname
# Pass a dummy callback to super.connect(), which is slightly
# more efficient than letting it return a Future we ignore.
Asynchronously returns an `.IOStream` (or `.SSLIOStream` if
``ssl_options`` is not None).
- source_ip
- Specify the source IP address to use when establishing
- the connection. In case the user needs to resolve and
- use a specific interface, it has to be handled outside
- of Tornado as this depneds very much on the platform.
+ Using the `source_ip` kwarg, one can specify the source
+ IP address to use when establishing the connection.
+ In case the user needs to resolve and
+ use a specific interface, it has to be handled outside
+ of Tornado as this depends very much on the platform.
"""
addrinfo = yield self.resolver.resolve(host, port, af)
connector = _Connector(
addrinfo, self.io_loop,
- functools.partial(self._create_stream, max_buffer_size),
- source_ip=source_ip)
+ functools.partial(self._create_stream, max_buffer_size,
+ source_ip=source_ip)
+ )
af, addr, stream = yield connector.start()
# TODO: For better performance we could cache the (af, addr)
# information here and re-use it on subsequent connections to
def _create_stream(self, max_buffer_size, af, addr, source_ip=None):
# Always connect in plaintext; we'll convert to ssl if necessary
# after one connection has completed.
+ if source_ip:
+ # If source_ip is needed, will try binding.
+ # If it fails, will exit loudly.
+ self.socket.bind((source_ip, 0))
+ # Does not bind try binding to a specific port,
+ # so the port argument is set to 0.
try:
stream = IOStream(socket.socket(af),
io_loop=self.io_loop,