Пример #1
0
 def connect(self):
     self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
     self.stream = SSLIOStream(self.s,
                               ssl_options=dict(certfile=self.certfile))
     self.stream.connect(self.host, self._on_connect)
     self.stream.read_until_close(self._on_close,
                                  streaming_callback=self._on_read)
Пример #2
0
 def _handle_connection(self, connection, address):
     if self.ssl_options is not None:
         assert ssl, "Python 2.6+ and OpenSSL required for SSL"
         try:
             connection = ssl_wrap_socket(connection,
                                          self.ssl_options,
                                          server_side=True,
                                          do_handshake_on_connect=False)
         except ssl.SSLError as err:
             if err.args[0] == ssl.SSL_ERROR_EOF:
                 return connection.close()
             else:
                 raise
         except socket.error as err:
             if errno_from_exception(err) in (errno.ECONNABORTED, errno.EINVAL):
                 return connection.close()
             else:
                 raise
     try:
         if self.ssl_options is not None:
             stream = SSLIOStream(connection, io_loop=self.io_loop,
                                  max_buffer_size=self.max_buffer_size,
                                  read_chunk_size=self.read_chunk_size)
         else:
             stream = IOStream(connection, io_loop=self.io_loop,
                               max_buffer_size=self.max_buffer_size,
                               read_chunk_size=self.read_chunk_size)
         self.handle_stream(stream, address)
     except Exception:
         self.handle_exception(sys.exc_info())
Пример #3
0
    def on_client_read(self, data):
        self.flush()

        request_info = self.on_request(data)

        logger.debug(
            "[%s] Got request for %s://%s:%s",
            self._client_address,
            request_info.scheme,
            request_info.target_host,
            request_info.target_port,
        )

        if self._server_stream is None:
            s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
            stream = (
                SSLIOStream(s, ssl_options={})
                if request_info.scheme == "https"
                else IOStream(s)
            )
            stream.connect(
                (request_info.target_host, request_info.target_port),
                self.on_server_connect,
                server_hostname=request_info.target_host,
            )
            self._server_stream = StreamWrapper(stream, self.on_server_close, True)

        self._server_stream.write(request_info.data)
Пример #4
0
    def connect_to_server(self, server_cls):
        server = client = None
        try:
            sock, port = bind_unused_port()
            server = server_cls(ssl_options=_server_ssl_options())
            server.add_socket(sock)

            ssl_ctx = ssl.create_default_context(ssl.Purpose.SERVER_AUTH)
            ssl_ctx.check_hostname = False
            ssl_ctx.verify_mode = ssl.CERT_NONE
            # These tests fail with ConnectionAbortedErrors with TLS
            # 1.3 on windows python 3.7.4 (which includes an upgrade
            # to openssl 1.1.c. Other platforms might be affected with
            # newer openssl too). Disable it until we figure out
            # what's up.
            # Update 2021-12-28: Still happening with Python 3.10 on
            # Windows. OP_NO_TLSv1_3 now raises a DeprecationWarning.
            with ignore_deprecation():
                ssl_ctx.options |= getattr(ssl, "OP_NO_TLSv1_3", 0)
                client = SSLIOStream(socket.socket(), ssl_options=ssl_ctx)
            yield client.connect(("127.0.0.1", port))
            self.assertIsNotNone(client.socket.cipher())
        finally:
            if server is not None:
                server.stop()
            if client is not None:
                client.close()
Пример #5
0
    def __init__(self, io_loop, request, callback):
        self.start_time = time.time()
        self.io_loop = io_loop
        self.request = request
        self.callback = callback
        self.code = None
        self.headers = None
        self.chunks = None
        self._decompressor = None
        # Timeout handle returned by IOLoop.add_timeout
        self._timeout = None
        with stack_context.StackContext(self.cleanup):
            parsed = urlparse.urlsplit(self.request.url)
            if ":" in parsed.netloc:
                host, _, port = parsed.netloc.partition(":")
                port = int(port)
            else:
                host = parsed.netloc
                port = 443 if parsed.scheme == "https" else 80

            if parsed.scheme == "https":
                # TODO: cert verification, etc
                self.stream = SSLIOStream(socket.socket(),
                                          io_loop=self.io_loop)
            else:
                self.stream = IOStream(socket.socket(), io_loop=self.io_loop)
            timeout = min(request.connect_timeout, request.request_timeout)
            if timeout:
                self._connect_timeout = self.io_loop.add_timeout(
                    self.start_time + timeout, self._on_timeout)
            self.stream.connect((host, port),
                                functools.partial(self._on_connect, parsed))
Пример #6
0
 def _handle_connection(self, connection, address):
     if self.ssl_options is not None:
         assert ssl, "Python 2.6+ and OpenSSL required for SSL"
         try:
             connection = ssl.wrap_socket(connection,
                                          server_side=True,
                                          do_handshake_on_connect=False,
                                          **self.ssl_options)
         except ssl.SSLError as err:
             if err.args[0] == ssl.SSL_ERROR_EOF:
                 return connection.close()
             else:
                 raise
         except socket.error as err:
             if err.args[0] == errno.ECONNABORTED:
                 return connection.close()
             else:
                 raise
     try:
         if self.ssl_options is not None:
             stream = SSLIOStream(connection, io_loop=self.io_loop)
         else:
             stream = IOStream(connection, io_loop=self.io_loop)
         self.handle_stream(stream, address)
     except Exception:
         logging.error("Error in connection callback", exc_info=True)
Пример #7
0
 def _make_server_iostream(self, connection, **kwargs):
     connection = ssl.wrap_socket(
         connection,
         server_side=True,
         do_handshake_on_connect=False,
         **_server_ssl_options()
     )
     return SSLIOStream(connection, **kwargs)
Пример #8
0
 def _make_server_iostream(self, connection, **kwargs):
     ssl_ctx = ssl_options_to_context(_server_ssl_options(),
                                      server_side=True)
     connection = ssl_ctx.wrap_socket(
         connection,
         server_side=True,
         do_handshake_on_connect=False,
     )
     return SSLIOStream(connection, **kwargs)
Пример #9
0
 def _make_server_iostream(self, connection, **kwargs):
     context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
     context.load_cert_chain(
         os.path.join(os.path.dirname(__file__), 'test.crt'),
         os.path.join(os.path.dirname(__file__), 'test.key'))
     connection = ssl_wrap_socket(connection, context,
                                  server_side=True,
                                  do_handshake_on_connect=False)
     return SSLIOStream(connection, io_loop=self.io_loop, **kwargs)
Пример #10
0
 def _make_server_iostream(self, connection, **kwargs):
     ssl_options = dict(
         certfile=os.path.join(os.path.dirname(__file__), 'test.crt'),
         keyfile=os.path.join(os.path.dirname(__file__), 'test.key'),
     )
     connection = ssl.wrap_socket(connection,
                                  server_side=True,
                                  do_handshake_on_connect=False,
                                  **ssl_options)
     return SSLIOStream(connection, io_loop=self.io_loop, **kwargs)
    def _on_resolve(self, addrinfo):
        af, sockaddr = addrinfo[0]

        if self.parsed.scheme == "https":
            ssl_options = {}
            if self.request.validate_cert:
                ssl_options["cert_reqs"] = ssl.CERT_REQUIRED
            if self.request.ca_certs is not None:
                ssl_options["ca_certs"] = self.request.ca_certs
            else:
                ssl_options["ca_certs"] = _DEFAULT_CA_CERTS
            if self.request.client_key is not None:
                ssl_options["keyfile"] = self.request.client_key
            if self.request.client_cert is not None:
                ssl_options["certfile"] = self.request.client_cert

            # SSL interoperability is tricky.  We want to disable
            # SSLv2 for security reasons; it wasn't disabled by default
            # until openssl 1.0.  The best way to do this is to use
            # the SSL_OP_NO_SSLv2, but that wasn't exposed to python
            # until 3.2.  Python 2.7 adds the ciphers argument, which
            # can also be used to disable SSLv2.  As a last resort
            # on python 2.6, we set ssl_version to SSLv3.  This is
            # more narrow than we'd like since it also breaks
            # compatibility with servers configured for TLSv1 only,
            # but nearly all servers support SSLv3:
            # http://blog.ivanristic.com/2011/09/ssl-survey-protocol-support.html
            if sys.version_info >= (2, 7):
                ssl_options["ciphers"] = "DEFAULT:!SSLv2"
            else:
                # This is really only necessary for pre-1.0 versions
                # of openssl, but python 2.6 doesn't expose version
                # information.
                ssl_options["ssl_version"] = ssl.PROTOCOL_SSLv3

            self.stream = SSLIOStream(socket.socket(af),
                                      io_loop=self.io_loop,
                                      ssl_options=ssl_options,
                                      max_buffer_size=self.max_buffer_size)
        else:
            self.stream = IOStream(socket.socket(af),
                                   io_loop=self.io_loop,
                                   max_buffer_size=self.max_buffer_size)
        timeout = min(self.request.connect_timeout,
                      self.request.request_timeout)
        if timeout:
            self._timeout = self.io_loop.add_timeout(
                self.start_time + timeout,
                stack_context.wrap(self._on_timeout))
        self.stream.set_close_callback(self._on_close)
        # ipv6 addresses are broken (in self.parsed.hostname) until
        # 2.7, here is correctly parsed value calculated in __init__
        self.stream.connect(sockaddr,
                            self._on_connect,
                            server_hostname=self.parsed_hostname)
Пример #12
0
 def _make_server_iostream(self, connection, **kwargs):
     context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
     context.load_cert_chain(
         os.path.join(os.path.dirname(__file__), "test.crt"),
         os.path.join(os.path.dirname(__file__), "test.key"),
     )
     connection = ssl_wrap_socket(connection,
                                  context,
                                  server_side=True,
                                  do_handshake_on_connect=False)
     return SSLIOStream(connection, **kwargs)
Пример #13
0
 def connect(self):
     self.__stream = SSLIOStream(
         socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0),
         io_loop=self.__io_loop,
         ssl_options={
             'ssl_version': ssl.PROTOCOL_TLSv1,
             # 'ca_certs': path.join(CERT_ROOT, 'entrust_root_ca.pem'),
             'certfile': self.__cert,
             # 'cert_reqs': ssl.CERT_REQUIRED
         })
     self.__stream.set_close_callback(self._on_close)
     self.__stream.connect(self.__svr_addr, self.__on_connect)
Пример #14
0
    def _handle_connection(self, connection: socket.socket, address: Any) -> None:
        # 此处获取到的是sock.accept() 返回的两个数据, 也就是request和address嘛
        # 每当有用户建立连接, 都会进入此处
        if self.ssl_options is not None:
            assert ssl, "Python 2.6+ and OpenSSL required for SSL"
            try:
                connection = ssl_wrap_socket(
                    connection,
                    self.ssl_options,
                    server_side=True,
                    do_handshake_on_connect=False,
                )
            except ssl.SSLError as err:
                if err.args[0] == ssl.SSL_ERROR_EOF:
                    return connection.close()
                else:
                    raise
            except socket.error as err:
                # If the connection is closed immediately after it is created
                # (as in a port scan), we can get one of several errors.
                # wrap_socket makes an internal call to getpeername,
                # which may return either EINVAL (Mac OS X) or ENOTCONN
                # (Linux).  If it returns ENOTCONN, this error is
                # silently swallowed by the ssl module, so we need to
                # catch another error later on (AttributeError in
                # SSLIOStream._do_ssl_handshake).
                # To test this behavior, try nmap with the -sT flag.
                # https://github.com/tornadoweb/tornado/pull/750
                if errno_from_exception(err) in (errno.ECONNABORTED, errno.EINVAL):
                    return connection.close()
                else:
                    raise
        try:
            if self.ssl_options is not None:
                stream = SSLIOStream(
                    connection,
                    max_buffer_size=self.max_buffer_size,
                    read_chunk_size=self.read_chunk_size,
                )  # type: IOStream
            else:
                stream = IOStream(
                    connection,
                    max_buffer_size=self.max_buffer_size,
                    read_chunk_size=self.read_chunk_size,
                )

            future = self.handle_stream(stream, address)  # 会注册一个未来对象到loop里面
            if future is not None:  # 也就是说一个http连接到了这之后接结束了, 剩下的事都在loop中
                IOLoop.current().add_future(
                    gen.convert_yielded(future), lambda f: f.result()
                )
        except Exception:
            app_log.error("Error in connection callback", exc_info=True)
Пример #15
0
 def _create_stream(self, host, ssl_options, max_buffer_size, af, addr):
     # TODO: we should connect in plaintext mode and start the
     # ssl handshake only after stopping the _Connector.
     if ssl_options is None:
         stream = IOStream(socket.socket(af),
                           io_loop=self.io_loop,
                           max_buffer_size=max_buffer_size)
     else:
         stream = SSLIOStream(socket.socket(af),
                              io_loop=self.io_loop,
                              ssl_options=ssl_options,
                              max_buffer_size=max_buffer_size)
     return stream.connect(addr, server_hostname=host)
Пример #16
0
    def __init__(self, uid, port):
        super(Client, self).__init__('client')

        self.uid = uid
        self.port = port

        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.conn = SSLIOStream(self.sock,
                                ssl_options={
                                    'ca_certs': SERVER_CRT_PATH,
                                    'cert_reqs': ssl.CERT_REQUIRED
                                })
        self.conn.connect(('127.0.0.1', self.port), self.on_connect)
Пример #17
0
 def _handle_connection(self, connection, address):
     # 如果可以的话,启用ssl
     # address = ('127.0.0.1', 63959)
     # connection : socket object
     if self.ssl_options is not None:
         assert ssl, "Python 2.6+ and OpenSSL required for SSL"
         try:
             connection = ssl_wrap_socket(connection,
                                          self.ssl_options,
                                          server_side=True,
                                          do_handshake_on_connect=False)
         except ssl.SSLError as err:
             if err.args[0] == ssl.SSL_ERROR_EOF:
                 return connection.close()
             else:
                 raise
         except socket.error as err:
             # If the connection is closed immediately after it is created
             # (as in a port scan), we can get one of several errors.
             # wrap_socket makes an internal call to getpeername,
             # which may return either EINVAL (Mac OS X) or ENOTCONN
             # (Linux).  If it returns ENOTCONN, this error is
             # silently swallowed by the ssl module, so we need to
             # catch another error later on (AttributeError in
             # SSLIOStream._do_ssl_handshake).
             # To test this behavior, try nmap with the -sT flag.
             # https://github.com/tornadoweb/tornado/pull/750
             if errno_from_exception(err) in (errno.ECONNABORTED,
                                              errno.EINVAL):
                 return connection.close()
             else:
                 raise
     try:
         if self.ssl_options is not None:
             stream = SSLIOStream(connection,
                                  io_loop=self.io_loop,
                                  max_buffer_size=self.max_buffer_size,
                                  read_chunk_size=self.read_chunk_size)
         else:
             # 根据connection获得一个IOStream的对象,便于数据的读取
             stream = IOStream(connection,
                               io_loop=self.io_loop,
                               max_buffer_size=self.max_buffer_size,
                               read_chunk_size=self.read_chunk_size)
         # 开始处理进来的数据连接
         self.handle_stream(stream, address)
     except Exception:
         app_log.error("Error in connection callback", exc_info=True)
Пример #18
0
    def connect_to_server(self, server_cls):
        server = client = None
        try:
            sock, port = bind_unused_port()
            server = server_cls(ssl_options=_server_ssl_options())
            server.add_socket(sock)

            client = SSLIOStream(socket.socket(),
                                 ssl_options=dict(cert_reqs=ssl.CERT_NONE))
            yield client.connect(("10.0.0.7", port))
            self.assertIsNotNone(client.socket.cipher())
        finally:
            if server is not None:
                server.stop()
            if client is not None:
                client.close()
    def _create_stream(self, addrinfo):
        af = addrinfo[0][0]
        if self.parsed.scheme == "https":
            ssl_options = {}
            if self.request.validate_cert:
                ssl_options["cert_reqs"] = ssl.CERT_REQUIRED
            if self.request.ca_certs is not None:
                ssl_options["ca_certs"] = self.request.ca_certs
            else:
                ssl_options["ca_certs"] = _DEFAULT_CA_CERTS
            if self.request.client_key is not None:
                ssl_options["keyfile"] = self.request.client_key
            if self.request.client_cert is not None:
                ssl_options["certfile"] = self.request.client_cert

            # SSL interoperability is tricky.  We want to disable
            # SSLv2 for security reasons; it wasn't disabled by default
            # until openssl 1.0.  The best way to do this is to use
            # the SSL_OP_NO_SSLv2, but that wasn't exposed to python
            # until 3.2.  Python 2.7 adds the ciphers argument, which
            # can also be used to disable SSLv2.  As a last resort
            # on python 2.6, we set ssl_version to TLSv1.  This is
            # more narrow than we'd like since it also breaks
            # compatibility with servers configured for SSLv3 only,
            # but nearly all servers support both SSLv3 and TLSv1:
            # http://blog.ivanristic.com/2011/09/ssl-survey-protocol-support.html
            if sys.version_info >= (2, 7):
                # In addition to disabling SSLv2, we also exclude certain
                # classes of insecure ciphers.
                ssl_options["ciphers"] = "DEFAULT:!SSLv2:!EXPORT:!DES"
            else:
                # This is really only necessary for pre-1.0 versions
                # of openssl, but python 2.6 doesn't expose version
                # information.
                ssl_options["ssl_version"] = ssl.PROTOCOL_TLSv1

            return SSLIOStream(socket.socket(af),
                               io_loop=self.io_loop,
                               ssl_options=ssl_options,
                               max_buffer_size=self.max_buffer_size)
        else:
            return IOStream(socket.socket(af),
                            io_loop=self.io_loop,
                            max_buffer_size=self.max_buffer_size)
Пример #20
0
    def __init__(self, io_loop, client, request, callback):
        self.start_time = time.time()
        self.io_loop = io_loop
        self.client = client
        self.request = request
        self.callback = callback
        self.code = None
        self.headers = None
        self.chunks = None
        self._decompressor = None
        # Timeout handle returned by IOLoop.add_timeout
        self._timeout = None
        with stack_context.StackContext(self.cleanup):
            parsed = urlparse.urlsplit(self.request.url)
            if ":" in parsed.netloc:
                host, _, port = parsed.netloc.partition(":")
                port = int(port)
            else:
                host = parsed.netloc
                port = 443 if parsed.scheme == "https" else 80
            if self.client.hostname_mapping is not None:
                host = self.client.hostname_mapping.get(host, host)

            if parsed.scheme == "https":
                ssl_options = {}
                if request.validate_cert:
                    ssl_options["cert_reqs"] = ssl.CERT_REQUIRED
                if request.ca_certs is not None:
                    ssl_options["ca_certs"] = request.ca_certs
                else:
                    ssl_options["ca_certs"] = _DEFAULT_CA_CERTS
                self.stream = SSLIOStream(socket.socket(),
                                          io_loop=self.io_loop,
                                          ssl_options=ssl_options)
            else:
                self.stream = IOStream(socket.socket(), io_loop=self.io_loop)
            timeout = min(request.connect_timeout, request.request_timeout)
            if timeout:
                self._connect_timeout = self.io_loop.add_timeout(
                    self.start_time + timeout, self._on_timeout)
            self.stream.set_close_callback(self._on_close)
            self.stream.connect((host, port),
                                functools.partial(self._on_connect, parsed))
Пример #21
0
 def _handle_connection(self, connection, address):
     if self.ssl_options is not None:
         assert ssl, "Python 2.6+ and OpenSSL required for SSL"
         try:
             connection = ssl_wrap_socket(connection,
                                          self.ssl_options,
                                          server_side=True,
                                          do_handshake_on_connect=False)
         except ssl.SSLError as err:
             if err.args[0] == ssl.SSL_ERROR_EOF:
                 return connection.close()
             else:
                 raise
         except socket.error as err:
             # If the connection is closed immediately after it is created
             # (as in a port scan), we can get one of several errors.
             # wrap_socket makes an internal call to getpeername,
             # which may return either EINVAL (Mac OS X) or ENOTCONN
             # (Linux).  If it returns ENOTCONN, this error is
             # silently swallowed by the ssl module, so we need to
             # catch another error later on (AttributeError in
             # SSLIOStream._do_ssl_handshake).
             # To test this behavior, try nmap with the -sT flag.
             # https://github.com/facebook/tornado/pull/750
             if err.args[0] in (errno.ECONNABORTED, errno.EINVAL):
                 return connection.close()
             else:
                 raise
     try:
         if self.ssl_options is not None:
             stream = SSLIOStream(connection,
                                  io_loop=self.io_loop,
                                  max_buffer_size=self.max_buffer_size)
         else:
             stream = IOStream(connection,
                               io_loop=self.io_loop,
                               max_buffer_size=self.max_buffer_size)
         self.handle_stream(stream, address)
         # 这个_handle_conntion基本是用在底层iostream的处理上面,
         # 而路由的分发,我猜测应该是在生成request对象那个时候才开始的
     except Exception:
         app_log.error("Error in connection callback", exc_info=True)
Пример #22
0
 def _Connect(self):
     try:
         ssl_options = {
             'certfile': secrets.GetSecretFile(self._settings['certfile'])
         }
         self._sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
         self._stream = SSLIOStream(self._sock,
                                    io_loop=self._io_loop,
                                    ssl_options=ssl_options)
         self._stream.set_close_callback(self._OnClose)
         self._stream.connect(self._host, self._OnConnect)
     except KeyError:
         logging.warning(
             'failed to initialize connection to APN service at %s:%d '
             'whose certificate is missing from secrets/%s' %
             (self._host[0], self._host[1], self._settings['certfile']))
         return
     except:
         self._stream = None
         raise
Пример #23
0
 def _make_iostream(self, s):
     assert ssl, "Python 2.6+ and OpenSSL required for SSL"
     try:
         s = ssl.wrap_socket(s,
                             server_side=True,
                             do_handshake_on_connect=False,
                             **self.ssl_options)
     except ssl.SSLError as err:
         if err.args[0] == ssl.SSL_ERROR_EOF:
             s.close()
             return
         else:
             raise
     except socket.error as err:
         if err.args[0] == errno.ECONNABORTED:
             s.close()
             return
         else:
             raise
     return SSLIOStream(s)
    def connect(self, host, port):
        self.authority = host
        s = socket.socket()
        self.io_stream = SSLIOStream(s, ssl_options=self.ssl_context)

        yield self.io_stream.connect((host, port), server_hostname=host)
        logger.debug("Connected!")
        self.known_proto = self.io_stream.socket.selected_alpn_protocol()

        assert self.known_proto == self.ALPN_HTTP2_PROTOCOL, "ALPN protocol was not h2, was {} instead".format(
            self.known_proto)

        self.io_stream.set_close_callback(self.connection_lost)

        logger.debug("Talking to a valid HTTP2 server! Sending preamble")
        self.conn.initiate_connection()

        self.io_stream.read_until_close(streaming_callback=self.data_received)
        data = self.conn.data_to_send()
        yield self.io_stream.write(data)
        logger.debug("Preamble Sent! Should be connected now")
Пример #25
0
 def _make_client_iostream(self, connection, **kwargs):
     context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
     return SSLIOStream(connection,
                        io_loop=self.io_loop,
                        ssl_options=context,
                        **kwargs)
Пример #26
0
 def _make_client_iostream(self, connection, **kwargs):
     return SSLIOStream(connection, io_loop=self.io_loop, **kwargs)
Пример #27
0
 def _make_client_iostream(self):
     return SSLIOStream(socket.socket(), io_loop=self.io_loop)
Пример #28
0
    def __init__(self, io_loop, client, request, release_callback,
                 final_callback, max_buffer_size):
        self.start_time = time.time()
        self.io_loop = io_loop
        self.client = client
        self.request = request
        self.release_callback = release_callback
        self.final_callback = final_callback
        self.code = None
        self.headers = None
        self.chunks = None
        self._decompressor = None
        # Timeout handle returned by IOLoop.add_timeout
        self._timeout = None
        with stack_context.StackContext(self.cleanup):
            parsed = urlparse.urlsplit(_unicode(self.request.url))
            if ssl is None and parsed.scheme == "https":
                raise ValueError("HTTPS requires either python2.6+ or "
                                 "curl_httpclient")
            if parsed.scheme not in ("http", "https"):
                raise ValueError("Unsupported url scheme: %s" %
                                 self.request.url)
            # urlsplit results have hostname and port results, but they
            # didn't support ipv6 literals until python 2.7.
            netloc = parsed.netloc
            if "@" in netloc:
                userpass, _, netloc = netloc.rpartition("@")
            match = re.match(r'^(.+):(\d+)$', netloc)
            if match:
                host = match.group(1)
                port = int(match.group(2))
            else:
                host = netloc
                port = 443 if parsed.scheme == "https" else 80
            if re.match(r'^\[.*\]$', host):
                # raw ipv6 addresses in urls are enclosed in brackets
                host = host[1:-1]
            if self.client.hostname_mapping is not None:
                host = self.client.hostname_mapping.get(host, host)

            if request.allow_ipv6:
                af = socket.AF_UNSPEC
            else:
                # We only try the first IP we get from getaddrinfo,
                # so restrict to ipv4 by default.
                af = socket.AF_INET

            addrinfo = socket.getaddrinfo(host, port, af, socket.SOCK_STREAM,
                                          0, 0)
            af, socktype, proto, canonname, sockaddr = addrinfo[0]

            if parsed.scheme == "https":
                ssl_options = {}
                if request.validate_cert:
                    ssl_options["cert_reqs"] = ssl.CERT_REQUIRED
                if request.ca_certs is not None:
                    ssl_options["ca_certs"] = request.ca_certs
                else:
                    ssl_options["ca_certs"] = _DEFAULT_CA_CERTS
                if request.client_key is not None:
                    ssl_options["keyfile"] = request.client_key
                if request.client_cert is not None:
                    ssl_options["certfile"] = request.client_cert
                self.stream = SSLIOStream(socket.socket(af, socktype, proto),
                                          io_loop=self.io_loop,
                                          ssl_options=ssl_options,
                                          max_buffer_size=max_buffer_size)
            else:
                self.stream = IOStream(socket.socket(af, socktype, proto),
                                       io_loop=self.io_loop,
                                       max_buffer_size=max_buffer_size)
            timeout = min(request.connect_timeout, request.request_timeout)
            if timeout:
                self._timeout = self.io_loop.add_timeout(
                    self.start_time + timeout,
                    self._on_timeout)
            self.stream.set_close_callback(self._on_close)
            self.stream.connect(sockaddr,
                                functools.partial(self._on_connect, parsed))
Пример #29
0
                                             server_side=True,
                                             do_handshake_on_connect=False,
                                             **self.ssl_options)
            except ssl.SSLError, err:
                if err.args[0] == ssl.SSL_ERROR_EOF:
                    return connection.close()
                else:
                    raise
            except socket.error, err:
                if err.args[0] == errno.ECONNABORTED:
                    return connection.close()
                else:
                    raise
        try:
            if self.ssl_options is not None:
                stream = SSLIOStream(connection, io_loop=self.io_loop)
            else:
                stream = IOStream(connection, io_loop=self.io_loop)
            self.handle_stream(stream, address)
        except Exception:
            app_log.error("Error in connection callback", exc_info=True)


def bind_sockets(port, address=None, family=socket.AF_UNSPEC, backlog=128, flags=None):
    """Creates listening sockets bound to the given port and address.

    Returns a list of socket objects (multiple sockets are returned if
    the given address maps to multiple IP addresses, which is most common
    for mixed IPv4 and IPv6 use).

    Address may be either an IP address or hostname.  If it's a hostname,
Пример #30
0
    def __init__(self, io_loop, client, request, release_callback,
                 final_callback, max_buffer_size):
        self.start_time = time.time()
        self.io_loop = io_loop
        self.client = client
        self.request = request
        self.release_callback = release_callback
        self.final_callback = final_callback
        self.code = None
        self.headers = None
        self.chunks = None
        self._decompressor = None
        # Timeout handle returned by IOLoop.add_timeout
        self._timeout = None
        with stack_context.StackContext(self.cleanup):
            parsed = urlparse.urlsplit(_unicode(self.request.url))
            if ssl is None and parsed.scheme == "https":
                raise ValueError("HTTPS requires either python2.6+ or "
                                 "curl_httpclient")
            if parsed.scheme not in ("http", "https"):
                raise ValueError("Unsupported url scheme: %s" %
                                 self.request.url)
            # urlsplit results have hostname and port results, but they
            # didn't support ipv6 literals until python 2.7.
            netloc = parsed.netloc
            if "@" in netloc:
                userpass, _, netloc = netloc.rpartition("@")
            match = re.match(r'^(.+):(\d+)$', netloc)
            if match:
                host = match.group(1)
                port = int(match.group(2))
            else:
                host = netloc
                port = 443 if parsed.scheme == "https" else 80
            if re.match(r'^\[.*\]$', host):
                # raw ipv6 addresses in urls are enclosed in brackets
                host = host[1:-1]
            if self.client.hostname_mapping is not None:
                host = self.client.hostname_mapping.get(host, host)

            if request.allow_ipv6:
                af = socket.AF_UNSPEC
            else:
                # We only try the first IP we get from getaddrinfo,
                # so restrict to ipv4 by default.
                af = socket.AF_INET

            addrinfo = socket.getaddrinfo(host, port, af, socket.SOCK_STREAM,
                                          0, 0)
            af, socktype, proto, canonname, sockaddr = addrinfo[0]

            if parsed.scheme == "https":
                ssl_options = {}
                if request.validate_cert:
                    ssl_options["cert_reqs"] = ssl.CERT_REQUIRED
                if request.ca_certs is not None:
                    ssl_options["ca_certs"] = request.ca_certs
                else:
                    ssl_options["ca_certs"] = _DEFAULT_CA_CERTS
                if request.client_key is not None:
                    ssl_options["keyfile"] = request.client_key
                if request.client_cert is not None:
                    ssl_options["certfile"] = request.client_cert

                # SSL interoperability is tricky.  We want to disable
                # SSLv2 for security reasons; it wasn't disabled by default
                # until openssl 1.0.  The best way to do this is to use
                # the SSL_OP_NO_SSLv2, but that wasn't exposed to python
                # until 3.2.  Python 2.7 adds the ciphers argument, which
                # can also be used to disable SSLv2.  As a last resort
                # on python 2.6, we set ssl_version to SSLv3.  This is
                # more narrow than we'd like since it also breaks
                # compatibility with servers configured for TLSv1 only,
                # but nearly all servers support SSLv3:
                # http://blog.ivanristic.com/2011/09/ssl-survey-protocol-support.html
                if sys.version_info >= (2, 7):
                    ssl_options["ciphers"] = "DEFAULT:!SSLv2"
                else:
                    # This is really only necessary for pre-1.0 versions
                    # of openssl, but python 2.6 doesn't expose version
                    # information.
                    ssl_options["ssl_version"] = ssl.PROTOCOL_SSLv3

                self.stream = SSLIOStream(socket.socket(af, socktype, proto),
                                          io_loop=self.io_loop,
                                          ssl_options=ssl_options,
                                          max_buffer_size=max_buffer_size)
            else:
                self.stream = IOStream(socket.socket(af, socktype, proto),
                                       io_loop=self.io_loop,
                                       max_buffer_size=max_buffer_size)
            timeout = min(request.connect_timeout, request.request_timeout)
            if timeout:
                self._timeout = self.io_loop.add_timeout(
                    self.start_time + timeout, self._on_timeout)
            self.stream.set_close_callback(self._on_close)
            self.stream.connect(sockaddr,
                                functools.partial(self._on_connect, parsed))