Exemple #1
0
    def test_correct_upgrade_request_76(self):
        connect = [
            "GET /echo HTTP/1.1",
            "Upgrade: WebSocket",
            "Connection: Upgrade",
            "Host: localhost:%s" % self.port,
            "Origin: http://localhost:%s" % self.port,
            "Sec-WebSocket-Protocol: ws",
            "Sec-WebSocket-Key1: 4 @1  46546xW%0l 1 5",
            "Sec-WebSocket-Key2: 12998 5 Y3 1  .P00",
        ]
        sock = eventlet.connect(("localhost", self.port))

        sock.sendall(six.b("\r\n".join(connect) + "\r\n\r\n^n:ds[4U"))
        result = sock.recv(1024)
        # The server responds the correct Websocket handshake
        self.assertEqual(
            result,
            six.b(
                "\r\n".join(
                    [
                        "HTTP/1.1 101 WebSocket Protocol Handshake",
                        "Upgrade: WebSocket",
                        "Connection: Upgrade",
                        "Sec-WebSocket-Origin: http://localhost:%s" % self.port,
                        "Sec-WebSocket-Protocol: ws",
                        "Sec-WebSocket-Location: ws://localhost:%s/echo\r\n\r\n8jKS'y:G*Co,Wxa-" % self.port,
                    ]
                )
            ),
        )
Exemple #2
0
    def test_correct_upgrade_request_75(self):
        connect = [
            "GET /echo HTTP/1.1",
            "Upgrade: WebSocket",
            "Connection: Upgrade",
            "Host: localhost:%s" % self.port,
            "Origin: http://localhost:%s" % self.port,
            "WebSocket-Protocol: ws",
        ]
        sock = eventlet.connect(("localhost", self.port))

        sock.sendall(six.b("\r\n".join(connect) + "\r\n\r\n"))
        result = sock.recv(1024)
        # The server responds the correct Websocket handshake
        self.assertEqual(
            result,
            six.b(
                "\r\n".join(
                    [
                        "HTTP/1.1 101 Web Socket Protocol Handshake",
                        "Upgrade: WebSocket",
                        "Connection: Upgrade",
                        "WebSocket-Origin: http://localhost:%s" % self.port,
                        "WebSocket-Location: ws://localhost:%s/echo\r\n\r\n" % self.port,
                    ]
                )
            ),
        )
Exemple #3
0
    def test_correct_upgrade_request_13(self):
        for http_connection in ['Upgrade', 'UpGrAdE', 'keep-alive, Upgrade']:
            connect = [
                "GET /echo HTTP/1.1",
                "Upgrade: websocket",
                "Connection: %s" % http_connection,
                "Host: %s:%s" % self.server_addr,
                "Origin: http://%s:%s" % self.server_addr,
                "Sec-WebSocket-Version: 13",
                "Sec-WebSocket-Key: d9MXuOzlVQ0h+qRllvSCIg==",
            ]
            sock = eventlet.connect(self.server_addr)

            sock.sendall(six.b('\r\n'.join(connect) + '\r\n\r\n'))
            result = sock.recv(1024)
            # The server responds the correct Websocket handshake
            print('Connection string: %r' % http_connection)
            self.assertEqual(
                result,
                six.b('\r\n'.join([
                    'HTTP/1.1 101 Switching Protocols',
                    'Upgrade: websocket',
                    'Connection: Upgrade',
                    'Sec-WebSocket-Accept: ywSyWXCPNsDxLrQdQrn5RFNRfBU=\r\n\r\n',
                ])))
    def test_correct_upgrade_request_76(self):
        connect = [
            "GET /echo HTTP/1.1",
            "Upgrade: WebSocket",
            "Connection: Upgrade",
            "Host: %s:%s" % self.server_addr,
            "Origin: http://%s:%s" % self.server_addr,
            "Sec-WebSocket-Protocol: ws",
            "Sec-WebSocket-Key1: 4 @1  46546xW%0l 1 5",
            "Sec-WebSocket-Key2: 12998 5 Y3 1  .P00",
        ]
        sock = eventlet.connect(self.server_addr)

        sock.sendall(six.b('\r\n'.join(connect) + '\r\n\r\n^n:ds[4U'))
        result = sock.recv(1024)
        # The server responds the correct Websocket handshake
        self.assertEqual(
            result,
            six.b('\r\n'.join([
                'HTTP/1.1 101 WebSocket Protocol Handshake',
                'Upgrade: WebSocket',
                'Connection: Upgrade',
                'Sec-WebSocket-Origin: http://%s:%s' % self.server_addr,
                'Sec-WebSocket-Protocol: ws',
                'Sec-WebSocket-Location: ws://%s:%s/echo\r\n\r\n8jKS\'y:G*Co,Wxa-'
                % self.server_addr,
            ])))
Exemple #5
0
    def _handle_legacy_request(self, environ):
        if 'eventlet.input' in environ:
            sock = environ['eventlet.input'].get_socket()
        elif 'gunicorn.socket' in environ:
            sock = environ['gunicorn.socket']
        else:
            raise Exception(
                'No eventlet.input or gunicorn.socket present in environ.')

        if 'HTTP_SEC_WEBSOCKET_KEY1' in environ:
            self.protocol_version = 76
            if 'HTTP_SEC_WEBSOCKET_KEY2' not in environ:
                raise BadRequest()
        else:
            self.protocol_version = 75

        if self.protocol_version == 76:
            key1 = self._extract_number(environ['HTTP_SEC_WEBSOCKET_KEY1'])
            key2 = self._extract_number(environ['HTTP_SEC_WEBSOCKET_KEY2'])
            # There's no content-length header in the request, but it has 8
            # bytes of data.
            environ['wsgi.input'].content_length = 8
            key3 = environ['wsgi.input'].read(8)
            key = struct.pack(">II", key1, key2) + key3
            response = md5(key).digest()

        # Start building the response
        scheme = 'ws'
        if environ.get('wsgi.url_scheme') == 'https':
            scheme = 'wss'
        location = '%s://%s%s%s' % (scheme, environ.get('HTTP_HOST'),
                                    environ.get('SCRIPT_NAME'),
                                    environ.get('PATH_INFO'))
        qs = environ.get('QUERY_STRING')
        if qs is not None:
            location += '?' + qs
        if self.protocol_version == 75:
            handshake_reply = (
                b"HTTP/1.1 101 Web Socket Protocol Handshake\r\n"
                b"Upgrade: WebSocket\r\n"
                b"Connection: Upgrade\r\n"
                b"WebSocket-Origin: " + six.b(environ.get('HTTP_ORIGIN')) +
                b"\r\n"
                b"WebSocket-Location: " + six.b(location) + b"\r\n\r\n")
        elif self.protocol_version == 76:
            handshake_reply = (
                b"HTTP/1.1 101 WebSocket Protocol Handshake\r\n"
                b"Upgrade: WebSocket\r\n"
                b"Connection: Upgrade\r\n"
                b"Sec-WebSocket-Origin: " + six.b(environ.get('HTTP_ORIGIN')) +
                b"\r\n"
                b"Sec-WebSocket-Protocol: " +
                six.b(environ.get('HTTP_SEC_WEBSOCKET_PROTOCOL', 'default')) +
                b"\r\n"
                b"Sec-WebSocket-Location: " + six.b(location) + b"\r\n"
                b"\r\n" + response)
        else:  # pragma NO COVER
            raise ValueError("Unknown WebSocket protocol version.")
        sock.sendall(handshake_reply)
        return WebSocket(sock, environ, self.protocol_version)
Exemple #6
0
    def test_empty_query_string(self):
        # verify that a single trailing ? doesn't get nuked
        connect = [
            "GET /echo? HTTP/1.1",
            "Upgrade: WebSocket",
            "Connection: Upgrade",
            "Host: localhost:%s" % self.port,
            "Origin: http://localhost:%s" % self.port,
            "Sec-WebSocket-Protocol: ws",
            "Sec-WebSocket-Key1: 4 @1  46546xW%0l 1 5",
            "Sec-WebSocket-Key2: 12998 5 Y3 1  .P00",
        ]
        sock = eventlet.connect(("localhost", self.port))

        sock.sendall(six.b("\r\n".join(connect) + "\r\n\r\n^n:ds[4U"))
        result = sock.recv(1024)
        self.assertEqual(
            result,
            six.b(
                "\r\n".join(
                    [
                        "HTTP/1.1 101 WebSocket Protocol Handshake",
                        "Upgrade: WebSocket",
                        "Connection: Upgrade",
                        "Sec-WebSocket-Origin: http://localhost:%s" % self.port,
                        "Sec-WebSocket-Protocol: ws",
                        "Sec-WebSocket-Location: ws://localhost:%s/echo?\r\n\r\n8jKS'y:G*Co,Wxa-" % self.port,
                    ]
                )
            ),
        )
    def test_empty_query_string(self):
        # verify that a single trailing ? doesn't get nuked
        connect = [
            "GET /echo? HTTP/1.1",
            "Upgrade: WebSocket",
            "Connection: Upgrade",
            "Host: %s:%s" % self.server_addr,
            "Origin: http://%s:%s" % self.server_addr,
            "Sec-WebSocket-Protocol: ws",
            "Sec-WebSocket-Key1: 4 @1  46546xW%0l 1 5",
            "Sec-WebSocket-Key2: 12998 5 Y3 1  .P00",
        ]
        sock = eventlet.connect(self.server_addr)

        sock.sendall(six.b('\r\n'.join(connect) + '\r\n\r\n^n:ds[4U'))
        result = sock.recv(1024)
        self.assertEqual(
            result,
            six.b('\r\n'.join([
                'HTTP/1.1 101 WebSocket Protocol Handshake',
                'Upgrade: WebSocket',
                'Connection: Upgrade',
                'Sec-WebSocket-Origin: http://%s:%s' % self.server_addr,
                'Sec-WebSocket-Protocol: ws',
                'Sec-WebSocket-Location: ws://%s:%s/echo?\r\n\r\n8jKS\'y:G*Co,Wxa-'
                % self.server_addr,
            ])))
Exemple #8
0
    def test_query_string(self):
        # verify that the query string comes out the other side unscathed
        connect = [
            "GET /echo?query_string HTTP/1.1",
            "Upgrade: WebSocket",
            "Connection: Upgrade",
            "Host: localhost:%s" % self.port,
            "Origin: http://localhost:%s" % self.port,
            "Sec-WebSocket-Protocol: ws",
            "Sec-WebSocket-Key1: 4 @1  46546xW%0l 1 5",
            "Sec-WebSocket-Key2: 12998 5 Y3 1  .P00",
        ]
        sock = eventlet.connect(('localhost', self.port))

        sock.sendall(six.b('\r\n'.join(connect) + '\r\n\r\n^n:ds[4U'))
        result = sock.recv(1024)
        self.assertEqual(
            result,
            six.b('\r\n'.join([
                'HTTP/1.1 101 WebSocket Protocol Handshake',
                'Upgrade: WebSocket',
                'Connection: Upgrade',
                'Sec-WebSocket-Origin: http://localhost:%s' % self.port,
                'Sec-WebSocket-Protocol: ws',
                'Sec-WebSocket-Location: '
                'ws://localhost:%s/echo?query_string\r\n\r\n8jKS\'y:G*Co,Wxa-'
                % self.port,
            ])))
Exemple #9
0
    def test_query_string(self):
        # verify that the query string comes out the other side unscathed
        connect = [
            "GET /echo?query_string HTTP/1.1",
            "Upgrade: WebSocket",
            "Connection: Upgrade",
            "Host: %s:%s" % self.server_addr,
            "Origin: http://%s:%s" % self.server_addr,
            "Sec-WebSocket-Protocol: ws",
            "Sec-WebSocket-Key1: 4 @1  46546xW%0l 1 5",
            "Sec-WebSocket-Key2: 12998 5 Y3 1  .P00",
        ]
        sock = eventlet.connect(self.server_addr)

        sock.sendall(six.b("\r\n".join(connect) + "\r\n\r\n^n:ds[4U"))
        result = sock.recv(1024)
        self.assertEqual(
            result,
            six.b(
                "\r\n".join(
                    [
                        "HTTP/1.1 101 WebSocket Protocol Handshake",
                        "Upgrade: WebSocket",
                        "Connection: Upgrade",
                        "Sec-WebSocket-Origin: http://%s:%s" % self.server_addr,
                        "Sec-WebSocket-Protocol: ws",
                        "Sec-WebSocket-Location: "
                        "ws://%s:%s/echo?query_string\r\n\r\n8jKS'y:G*Co,Wxa-" % self.server_addr,
                    ]
                )
            ),
        )
Exemple #10
0
        def write(data):
            towrite = []
            if not headers_set:
                raise AssertionError("write() before start_response()")
            elif not headers_sent:
                status, response_headers = headers_set
                headers_sent.append(1)
                header_list = [
                    header[0].lower() for header in response_headers
                ]
                towrite.append(
                    six.b('%s %s\r\n' % (self.protocol_version, status)))
                for header in response_headers:
                    towrite.append(six.b('%s: %s\r\n' % header))

                # send Date header?
                if 'date' not in header_list:
                    towrite.append(
                        six.b('Date: %s\r\n' %
                              (format_date_time(time.time()), )))

                client_conn = self.headers.get('Connection', '').lower()
                send_keep_alive = False
                if self.close_connection == 0 and \
                   self.server.keepalive and (client_conn == 'keep-alive' or
                                              (self.request_version == 'HTTP/1.1' and
                                               not client_conn == 'close')):
                    # only send keep-alives back to clients that sent them,
                    # it's redundant for 1.1 connections
                    send_keep_alive = (client_conn == 'keep-alive')
                    self.close_connection = 0
                else:
                    self.close_connection = 1

                if 'content-length' not in header_list:
                    if self.request_version == 'HTTP/1.1':
                        use_chunked[0] = True
                        towrite.append(b'Transfer-Encoding: chunked\r\n')
                    elif 'content-length' not in header_list:
                        # client is 1.0 and therefore must read to EOF
                        self.close_connection = 1

                if self.close_connection:
                    towrite.append(b'Connection: close\r\n')
                elif send_keep_alive:
                    towrite.append(b'Connection: keep-alive\r\n')
                towrite.append(b'\r\n')
                # end of header writing

            if use_chunked[0]:
                # Write the chunked encoding
                towrite.append(
                    six.b("%x" % (len(data), )) + b"\r\n" + data + b"\r\n")
            else:
                towrite.append(data)
            wfile.writelines(towrite)
            wfile.flush()
            length[0] = length[0] + sum(map(len, towrite))
Exemple #11
0
    def _handle_legacy_request(self, environ):
        sock = environ['eventlet.input'].get_socket()

        if 'HTTP_SEC_WEBSOCKET_KEY1' in environ:
            self.protocol_version = 76
            if 'HTTP_SEC_WEBSOCKET_KEY2' not in environ:
                raise BadRequest()
        else:
            self.protocol_version = 75

        if self.protocol_version == 76:
            key1 = self._extract_number(environ['HTTP_SEC_WEBSOCKET_KEY1'])
            key2 = self._extract_number(environ['HTTP_SEC_WEBSOCKET_KEY2'])
            # There's no content-length header in the request, but it has 8
            # bytes of data.
            environ['wsgi.input'].content_length = 8
            key3 = environ['wsgi.input'].read(8)
            key = struct.pack(">II", key1, key2) + key3
            response = md5(key).digest()

        # Start building the response
        scheme = 'ws'
        if environ.get('wsgi.url_scheme') == 'https':
            scheme = 'wss'
        location = '%s://%s%s%s' % (
            scheme,
            environ.get('HTTP_HOST'),
            environ.get('SCRIPT_NAME'),
            environ.get('PATH_INFO')
        )
        qs = environ.get('QUERY_STRING')
        if qs is not None:
            location += '?' + qs
        if self.protocol_version == 75:
            handshake_reply = (
                b"HTTP/1.1 101 Web Socket Protocol Handshake\r\n"
                b"Upgrade: WebSocket\r\n"
                b"Connection: Upgrade\r\n"
                b"WebSocket-Origin: " + six.b(environ.get('HTTP_ORIGIN')) + b"\r\n"
                b"WebSocket-Location: " + six.b(location) + b"\r\n\r\n"
            )
        elif self.protocol_version == 76:
            handshake_reply = (
                b"HTTP/1.1 101 WebSocket Protocol Handshake\r\n"
                b"Upgrade: WebSocket\r\n"
                b"Connection: Upgrade\r\n"
                b"Sec-WebSocket-Origin: " + six.b(environ.get('HTTP_ORIGIN')) + b"\r\n"
                b"Sec-WebSocket-Protocol: " +
                six.b(environ.get('HTTP_SEC_WEBSOCKET_PROTOCOL', 'default')) + b"\r\n"
                b"Sec-WebSocket-Location: " + six.b(location) + b"\r\n"
                b"\r\n" + response
            )
        else:  # pragma NO COVER
            raise ValueError("Unknown WebSocket protocol version.")
        sock.sendall(handshake_reply)
        return WebSocket(sock, environ, self.protocol_version)
Exemple #12
0
    def _handle_hybi_request(self, environ):
        if 'eventlet.input' in environ:
            sock = environ['eventlet.input'].get_socket()
        elif 'gunicorn.socket' in environ:
            sock = environ['gunicorn.socket']
        else:
            raise Exception('No eventlet.input or gunicorn.socket present in environ.')

        hybi_version = environ['HTTP_SEC_WEBSOCKET_VERSION']
        if hybi_version not in ('8', '13', ):
            raise BadRequest(status='426 Upgrade Required',
                             headers=[('Sec-WebSocket-Version', '8, 13')])
        self.protocol_version = int(hybi_version)
        if 'HTTP_SEC_WEBSOCKET_KEY' not in environ:
            # That's bad.
            raise BadRequest()
        origin = environ.get(
            'HTTP_ORIGIN',
            (environ.get('HTTP_SEC_WEBSOCKET_ORIGIN', '')
             if self.protocol_version <= 8 else ''))
        if self.origin_checker is not None:
            if not self.origin_checker(environ.get('HTTP_HOST'), origin):
                raise BadRequest(status='403 Forbidden')
        protocols = environ.get('HTTP_SEC_WEBSOCKET_PROTOCOL', None)
        negotiated_protocol = None
        if protocols:
            for p in (i.strip() for i in protocols.split(',')):
                if p in self.supported_protocols:
                    negotiated_protocol = p
                    break

        key = environ['HTTP_SEC_WEBSOCKET_KEY']
        response = base64.b64encode(sha1(six.b(key) + PROTOCOL_GUID).digest())
        handshake_reply = [b"HTTP/1.1 101 Switching Protocols",
                           b"Upgrade: websocket",
                           b"Connection: Upgrade",
                           b"Sec-WebSocket-Accept: " + response]
        if negotiated_protocol:
            handshake_reply.append(b"Sec-WebSocket-Protocol: " + six.b(negotiated_protocol))

        parsed_extensions = {}
        extensions = self._parse_extension_header(environ.get("HTTP_SEC_WEBSOCKET_EXTENSIONS"))

        deflate = self._negotiate_permessage_deflate(extensions)
        if deflate is not None:
            parsed_extensions["permessage-deflate"] = deflate

        formatted_ext = self._format_extension_header(parsed_extensions)
        if formatted_ext is not None:
            handshake_reply.append(b"Sec-WebSocket-Extensions: " + formatted_ext)

        sock.sendall(b'\r\n'.join(handshake_reply) + b'\r\n\r\n')
        return RFC6455WebSocket(sock, environ, self.protocol_version,
                                protocol=negotiated_protocol,
                                extensions=parsed_extensions)
Exemple #13
0
        def write(data):
            towrite = []
            if not headers_set:
                raise AssertionError("write() before start_response()")
            elif not headers_sent:
                status, response_headers = headers_set
                headers_sent.append(1)
                header_list = [header[0].lower() for header in response_headers]
                towrite.append(six.b('%s %s\r\n' % (self.protocol_version, status)))
                for header in response_headers:
                    towrite.append(six.b('%s: %s\r\n' % header))

                # send Date header?
                if 'date' not in header_list:
                    towrite.append(six.b('Date: %s\r\n' % (format_date_time(time.time()),)))

                client_conn = self.headers.get('Connection', '').lower()
                send_keep_alive = False
                if self.close_connection == 0 and \
                   self.server.keepalive and (client_conn == 'keep-alive' or
                                              (self.request_version == 'HTTP/1.1' and
                                               not client_conn == 'close')):
                        # only send keep-alives back to clients that sent them,
                        # it's redundant for 1.1 connections
                    send_keep_alive = (client_conn == 'keep-alive')
                    self.close_connection = 0
                else:
                    self.close_connection = 1

                if 'content-length' not in header_list:
                    if self.request_version == 'HTTP/1.1':
                        use_chunked[0] = True
                        towrite.append(b'Transfer-Encoding: chunked\r\n')
                    elif 'content-length' not in header_list:
                        # client is 1.0 and therefore must read to EOF
                        self.close_connection = 1

                if self.close_connection:
                    towrite.append(b'Connection: close\r\n')
                elif send_keep_alive:
                    towrite.append(b'Connection: keep-alive\r\n')
                towrite.append(b'\r\n')
                # end of header writing

            if use_chunked[0]:
                # Write the chunked encoding
                towrite.append(six.b("%x" % (len(data),)) + b"\r\n" + data + b"\r\n")
            else:
                towrite.append(data)
            wfile.writelines(towrite)
            wfile.flush()
            length[0] = length[0] + sum(map(len, towrite))
Exemple #14
0
 def _format_extension_header(self, parsed_extensions):
     if not parsed_extensions:
         return None
     parts = []
     for name, config in parsed_extensions.items():
         ext_parts = [six.b(name)]
         for key, value in config.items():
             if value is False:
                 pass
             elif value is True:
                 ext_parts.append(six.b(key))
             else:
                 ext_parts.append(six.b("%s=%s" % (key, str(value))))
         parts.append(b"; ".join(ext_parts))
     return b", ".join(parts)
Exemple #15
0
    def test_sending_messages_to_websocket_76(self):
        connect = [
            "GET /echo HTTP/1.1",
            "Upgrade: WebSocket",
            "Connection: Upgrade",
            "Host: %s:%s" % self.server_addr,
            "Origin: http://%s:%s" % self.server_addr,
            "Sec-WebSocket-Protocol: ws",
            "Sec-WebSocket-Key1: 4 @1  46546xW%0l 1 5",
            "Sec-WebSocket-Key2: 12998 5 Y3 1  .P00",
        ]
        sock = eventlet.connect(self.server_addr)

        sock.sendall(six.b('\r\n'.join(connect) + '\r\n\r\n^n:ds[4U'))
        sock.recv(1024)
        sock.sendall(b'\x00hello\xFF')
        result = sock.recv(1024)
        self.assertEqual(result, b'\x00hello\xff')
        sock.sendall(b'\x00start')
        eventlet.sleep(0.001)
        sock.sendall(b' end\xff')
        result = sock.recv(1024)
        self.assertEqual(result, b'\x00start end\xff')
        sock.shutdown(socket.SHUT_RDWR)
        sock.close()
        eventlet.sleep(0.01)
Exemple #16
0
    def test_app_socket_errors_75(self):
        error_detected = [False]
        done_with_request = event.Event()
        site = self.site

        def error_detector(environ, start_response):
            try:
                try:
                    return site(environ, start_response)
                except:
                    error_detected[0] = True
                    raise
            finally:
                done_with_request.send(True)

        self.site = error_detector
        self.spawn_server()
        connect = [
            "GET /error HTTP/1.1",
            "Upgrade: WebSocket",
            "Connection: Upgrade",
            "Host: localhost:%s" % self.port,
            "Origin: http://localhost:%s" % self.port,
            "WebSocket-Protocol: ws",
        ]
        sock = eventlet.connect(('localhost', self.port))
        sock.sendall(six.b('\r\n'.join(connect) + '\r\n\r\n'))
        sock.recv(1024)
        done_with_request.wait()
        assert error_detected[0]
Exemple #17
0
    def test_client_invalid_packet_76(self):
        error_detected = [False]
        done_with_request = event.Event()
        site = self.site

        def error_detector(environ, start_response):
            try:
                try:
                    return site(environ, start_response)
                except:
                    error_detected[0] = True
                    raise
            finally:
                done_with_request.send(True)

        self.site = error_detector
        self.spawn_server()
        connect = [
            "GET /echo HTTP/1.1",
            "Upgrade: WebSocket",
            "Connection: Upgrade",
            "Host: localhost:%s" % self.port,
            "Origin: http://localhost:%s" % self.port,
            "Sec-WebSocket-Protocol: ws",
            "Sec-WebSocket-Key1: 4 @1  46546xW%0l 1 5",
            "Sec-WebSocket-Key2: 12998 5 Y3 1  .P00",
        ]
        sock = eventlet.connect(('localhost', self.port))
        sock.sendall(six.b('\r\n'.join(connect) + '\r\n\r\n^n:ds[4U'))
        sock.recv(1024)  # get the headers
        sock.sendall(b'\xef\x00')  # Weird packet.
        done_with_request.wait()
        assert error_detected[0]
Exemple #18
0
    def test_accept_deflate_ext_window_max_bits_13(self):
        for extension_string, vals in [
            ('permessage-deflate; client_max_window_bits', [15]),
            ('permessage-deflate;   Server_Max_Window_Bits  =  11', [11]),
            ('permessage-deflate; server_max_window_bits; '
             'client_max_window_bits=9', [15, 9])
        ]:
            sock = eventlet.connect(self.server_addr)

            sock.sendall(six.b(self.connect % extension_string))
            result = sock.recv(1024)

            # The server responds the correct Websocket handshake
            # print('Extension offer: %r' % extension_string)
            match = re.match(self.handshake_re, result)
            assert match is not None
            assert len(match.groups()) == 1

            offered_parts = [
                part.strip().lower() for part in extension_string.split(';')
            ]
            offered_parts_names = [
                part.split('=')[0].strip() for part in offered_parts
            ]
            offered_parts_dict = dict(zip(offered_parts_names[1:], vals))

            accepted_ext_parts = match.groups()[0].decode().split('; ')
            assert accepted_ext_parts[0] == 'permessage-deflate'
            for param, val in (part.split('=')
                               for part in accepted_ext_parts[1:]):
                assert int(val) == offered_parts_dict[param]
Exemple #19
0
    def test_server_compress_with_context_takeover_13(self):
        extensions_string = 'permessage-deflate; client_no_context_takeover;'
        extensions = {
            'permessage-deflate': {
                'client_no_context_takeover': True,
                'server_no_context_takeover': False
            }
        }

        sock = eventlet.connect(self.server_addr)
        sock.sendall(six.b(self.connect % extensions_string))
        sock.recv(1024)
        ws = websocket.RFC6455WebSocket(sock, {},
                                        client=True,
                                        extensions=extensions)

        # Deflated values taken from Section 7.2.3 of RFC 7692
        # https://tools.ietf.org/html/rfc7692#section-7.2.3
        ws.send(b'Hello')
        msg1 = self.get_deflated_reply(ws)
        assert msg1 == b'\xf2\x48\xcd\xc9\xc9\x07\x00'

        ws.send(b'Hello')
        msg2 = self.get_deflated_reply(ws)
        assert msg2 == b'\xf2\x00\x11\x00\x00'

        ws.close()
        eventlet.sleep(0.01)
Exemple #20
0
    def test_server_compress_no_context_takeover_13(self):
        extensions_string = 'permessage-deflate; server_no_context_takeover;'
        extensions = {
            'permessage-deflate': {
                'client_no_context_takeover': False,
                'server_no_context_takeover': True
            }
        }

        sock = eventlet.connect(self.server_addr)
        sock.sendall(six.b(self.connect % extensions_string))
        sock.recv(1024)
        ws = websocket.RFC6455WebSocket(sock, {},
                                        client=True,
                                        extensions=extensions)

        masked_msg1 = ws._pack_message(b'Hello', masked=True)
        ws._send(masked_msg1)
        masked_msg2 = ws._pack_message(b'Hello', masked=True)
        ws._send(masked_msg2)
        # Verify that client uses context takeover by checking
        # that the second message
        assert len(masked_msg2) < len(masked_msg1)

        # Verify that server drops context between messages
        # Deflated values taken from Section 7.2.3 of RFC 7692
        # https://tools.ietf.org/html/rfc7692#section-7.2.3
        reply_msg1 = self.get_deflated_reply(ws)
        assert reply_msg1 == b'\xf2\x48\xcd\xc9\xc9\x07\x00'
        reply_msg2 = self.get_deflated_reply(ws)
        assert reply_msg2 == b'\xf2\x48\xcd\xc9\xc9\x07\x00'
Exemple #21
0
    def test_breaking_the_connection_76(self):
        error_detected = [False]
        done_with_request = event.Event()
        site = self.site

        def error_detector(environ, start_response):
            try:
                try:
                    return site(environ, start_response)
                except:
                    error_detected[0] = True
                    raise
            finally:
                done_with_request.send(True)

        self.site = error_detector
        self.spawn_server()
        connect = [
            "GET /range HTTP/1.1",
            "Upgrade: WebSocket",
            "Connection: Upgrade",
            "Host: %s:%s" % self.server_addr,
            "Origin: http://%s:%s" % self.server_addr,
            "Sec-WebSocket-Protocol: ws",
            "Sec-WebSocket-Key1: 4 @1  46546xW%0l 1 5",
            "Sec-WebSocket-Key2: 12998 5 Y3 1  .P00",
        ]
        sock = eventlet.connect(self.server_addr)
        sock.sendall(six.b("\r\n".join(connect) + "\r\n\r\n^n:ds[4U"))
        sock.recv(1024)  # get the headers
        sock.close()  # close while the app is running
        done_with_request.wait()
        assert not error_detected[0]
Exemple #22
0
    def test_compressed_send_recv_both_no_context_13(self):
        extensions_string = (
            'permessage-deflate;'
            ' server_no_context_takeover; client_no_context_takeover')
        extensions = {
            'permessage-deflate': {
                'client_no_context_takeover': True,
                'server_no_context_takeover': True
            }
        }

        sock = eventlet.connect(self.server_addr)
        sock.sendall(six.b(self.connect % extensions_string))
        sock.recv(1024)
        ws = websocket.RFC6455WebSocket(sock, {},
                                        client=True,
                                        extensions=extensions)

        ws.send(b'hello')
        assert ws.wait() == b'hello'
        ws.send(b'hello world!')
        ws.send(u'hello world again!')
        assert ws.wait() == b'hello world!'
        assert ws.wait() == u'hello world again!'

        ws.close()
        eventlet.sleep(0.01)
Exemple #23
0
    def test_breaking_the_connection_75(self):
        error_detected = [False]
        done_with_request = event.Event()
        site = self.site

        def error_detector(environ, start_response):
            try:
                try:
                    return site(environ, start_response)
                except:
                    error_detected[0] = True
                    raise
            finally:
                done_with_request.send(True)

        self.site = error_detector
        self.spawn_server()
        connect = [
            "GET /range HTTP/1.1",
            "Upgrade: WebSocket",
            "Connection: Upgrade",
            "Host: %s:%s" % self.server_addr,
            "Origin: http://%s:%s" % self.server_addr,
            "WebSocket-Protocol: ws",
        ]
        sock = eventlet.connect(self.server_addr)
        sock.sendall(six.b('\r\n'.join(connect) + '\r\n\r\n'))
        sock.recv(1024)  # get the headers
        sock.close()  # close while the app is running
        done_with_request.wait()
        assert not error_detected[0]
Exemple #24
0
    def test_sending_messages_to_websocket_76(self):
        connect = [
            "GET /echo HTTP/1.1",
            "Upgrade: WebSocket",
            "Connection: Upgrade",
            "Host: %s:%s" % self.server_addr,
            "Origin: http://%s:%s" % self.server_addr,
            "Sec-WebSocket-Protocol: ws",
            "Sec-WebSocket-Key1: 4 @1  46546xW%0l 1 5",
            "Sec-WebSocket-Key2: 12998 5 Y3 1  .P00",
        ]
        sock = eventlet.connect(self.server_addr)

        sock.sendall(six.b("\r\n".join(connect) + "\r\n\r\n^n:ds[4U"))
        sock.recv(1024)
        sock.sendall(b"\x00hello\xFF")
        result = sock.recv(1024)
        self.assertEqual(result, b"\x00hello\xff")
        sock.sendall(b"\x00start")
        eventlet.sleep(0.001)
        sock.sendall(b" end\xff")
        result = sock.recv(1024)
        self.assertEqual(result, b"\x00start end\xff")
        sock.shutdown(socket.SHUT_RDWR)
        sock.close()
        eventlet.sleep(0.01)
Exemple #25
0
    def test_app_socket_errors_76(self):
        error_detected = [False]
        done_with_request = event.Event()
        site = self.site

        def error_detector(environ, start_response):
            try:
                try:
                    return site(environ, start_response)
                except:
                    error_detected[0] = True
                    raise
            finally:
                done_with_request.send(True)

        self.site = error_detector
        self.spawn_server()
        connect = [
            "GET /error HTTP/1.1",
            "Upgrade: WebSocket",
            "Connection: Upgrade",
            "Host: %s:%s" % self.server_addr,
            "Origin: http://%s:%s" % self.server_addr,
            "Sec-WebSocket-Protocol: ws",
            "Sec-WebSocket-Key1: 4 @1  46546xW%0l 1 5",
            "Sec-WebSocket-Key2: 12998 5 Y3 1  .P00",
        ]
        sock = eventlet.connect(self.server_addr)
        sock.sendall(six.b('\r\n'.join(connect) + '\r\n\r\n^n:ds[4U'))
        sock.recv(1024)
        done_with_request.wait()
        assert error_detected[0]
    def test_client_closing_connection_13(self):
        error_detected = [False]
        done_with_request = event.Event()
        site = self.site

        def error_detector(environ, start_response):
            try:
                try:
                    return site(environ, start_response)
                except:
                    error_detected[0] = True
                    raise
            finally:
                done_with_request.send(True)
        self.site = error_detector
        self.spawn_server()
        connect = [
            "GET /echo HTTP/1.1",
            "Upgrade: websocket",
            "Connection: Upgrade",
            "Host: %s:%s" % self.server_addr,
            "Origin: http://%s:%s" % self.server_addr,
            "Sec-WebSocket-Version: 13",
            "Sec-WebSocket-Key: d9MXuOzlVQ0h+qRllvSCIg==",
        ]
        sock = eventlet.connect(self.server_addr)
        sock.sendall(six.b('\r\n'.join(connect) + '\r\n\r\n'))
        sock.recv(1024)  # get the headers
        closeframe = struct.pack('!BBIH', 1 << 7 | 8, 1 << 7 | 2, 0, 1000)
        sock.sendall(closeframe)  # "Close the connection" packet.
        done_with_request.wait()
        assert not error_detected[0]
    def test_client_closing_connection_13(self):
        error_detected = [False]
        done_with_request = event.Event()
        site = self.site

        def error_detector(environ, start_response):
            try:
                try:
                    return site(environ, start_response)
                except:
                    error_detected[0] = True
                    raise
            finally:
                done_with_request.send(True)

        self.site = error_detector
        self.spawn_server()
        connect = [
            "GET /echo HTTP/1.1",
            "Upgrade: websocket",
            "Connection: Upgrade",
            "Host: localhost:%s" % self.port,
            "Origin: http://localhost:%s" % self.port,
            "Sec-WebSocket-Version: 13",
            "Sec-WebSocket-Key: d9MXuOzlVQ0h+qRllvSCIg==",
        ]
        sock = eventlet.connect(('localhost', self.port))
        sock.sendall(six.b('\r\n'.join(connect) + '\r\n\r\n'))
        sock.recv(1024)  # get the headers
        closeframe = struct.pack('!BBIH', 1 << 7 | 8, 1 << 7 | 2, 0, 1000)
        sock.sendall(closeframe)  # "Close the connection" packet.
        done_with_request.wait()
        assert not error_detected[0]
Exemple #28
0
    def test_breaking_the_connection_75(self):
        error_detected = [False]
        done_with_request = event.Event()
        site = self.site

        def error_detector(environ, start_response):
            try:
                try:
                    return site(environ, start_response)
                except:
                    error_detected[0] = True
                    raise
            finally:
                done_with_request.send(True)
        self.site = error_detector
        self.spawn_server()
        connect = [
            "GET /range HTTP/1.1",
            "Upgrade: WebSocket",
            "Connection: Upgrade",
            "Host: localhost:%s" % self.port,
            "Origin: http://localhost:%s" % self.port,
            "WebSocket-Protocol: ws",
        ]
        sock = eventlet.connect(
            ('localhost', self.port))
        sock.sendall(six.b('\r\n'.join(connect) + '\r\n\r\n'))
        sock.recv(1024)  # get the headers
        sock.close()  # close while the app is running
        done_with_request.wait()
        assert not error_detected[0]
Exemple #29
0
    def test_client_invalid_packet_76(self):
        error_detected = [False]
        done_with_request = event.Event()
        site = self.site

        def error_detector(environ, start_response):
            try:
                try:
                    return site(environ, start_response)
                except:
                    error_detected[0] = True
                    raise
            finally:
                done_with_request.send(True)

        self.site = error_detector
        self.spawn_server()
        connect = [
            "GET /echo HTTP/1.1",
            "Upgrade: WebSocket",
            "Connection: Upgrade",
            "Host: localhost:%s" % self.port,
            "Origin: http://localhost:%s" % self.port,
            "Sec-WebSocket-Protocol: ws",
            "Sec-WebSocket-Key1: 4 @1  46546xW%0l 1 5",
            "Sec-WebSocket-Key2: 12998 5 Y3 1  .P00",
        ]
        sock = eventlet.connect(("localhost", self.port))
        sock.sendall(six.b("\r\n".join(connect) + "\r\n\r\n^n:ds[4U"))
        sock.recv(1024)  # get the headers
        sock.sendall(b"\xef\x00")  # Weird packet.
        done_with_request.wait()
        assert error_detected[0]
Exemple #30
0
    def test_query_string(self):
        # verify that the query string comes out the other side unscathed
        connect = [
            "GET /echo?query_string HTTP/1.1",
            "Upgrade: WebSocket",
            "Connection: Upgrade",
            "Host: localhost:%s" % self.port,
            "Origin: http://localhost:%s" % self.port,
            "Sec-WebSocket-Protocol: ws",
            "Sec-WebSocket-Key1: 4 @1  46546xW%0l 1 5",
            "Sec-WebSocket-Key2: 12998 5 Y3 1  .P00",
        ]
        sock = eventlet.connect(
            ('localhost', self.port))

        sock.sendall(six.b('\r\n'.join(connect) + '\r\n\r\n^n:ds[4U'))
        result = sock.recv(1024)
        self.assertEqual(result, '\r\n'.join([
            'HTTP/1.1 101 WebSocket Protocol Handshake',
            'Upgrade: WebSocket',
            'Connection: Upgrade',
            'Sec-WebSocket-Origin: http://localhost:%s' % self.port,
            'Sec-WebSocket-Protocol: ws',
            'Sec-WebSocket-Location: '
            'ws://localhost:%s/echo?query_string\r\n\r\n8jKS\'y:G*Co,Wxa-' % self.port,
        ]))
Exemple #31
0
    def test_client_invalid_packet_13(self):
        error_detected = [False]
        done_with_request = event.Event()
        site = self.site

        def error_detector(environ, start_response):
            try:
                try:
                    return site(environ, start_response)
                except:
                    error_detected[0] = True
                    raise
            finally:
                done_with_request.send(True)
        self.site = error_detector
        self.spawn_server()
        connect = [
            "GET /echo HTTP/1.1",
            "Upgrade: websocket",
            "Connection: Upgrade",
            "Host: localhost:%s" % self.port,
            "Origin: http://localhost:%s" % self.port,
            "Sec-WebSocket-Version: 13",
            "Sec-WebSocket-Key: d9MXuOzlVQ0h+qRllvSCIg==",
        ]
        sock = eventlet.connect(
            ('localhost', self.port))
        sock.sendall(six.b('\r\n'.join(connect) + '\r\n\r\n'))
        sock.recv(1024)  # get the headers
        sock.sendall(b'\x07\xff')  # Weird packet.
        done_with_request.wait()
        assert not error_detected[0]
Exemple #32
0
    def test_app_socket_errors_76(self):
        error_detected = [False]
        done_with_request = event.Event()
        site = self.site

        def error_detector(environ, start_response):
            try:
                try:
                    return site(environ, start_response)
                except:
                    error_detected[0] = True
                    raise
            finally:
                done_with_request.send(True)
        self.site = error_detector
        self.spawn_server()
        connect = [
            "GET /error HTTP/1.1",
            "Upgrade: WebSocket",
            "Connection: Upgrade",
            "Host: localhost:%s" % self.port,
            "Origin: http://localhost:%s" % self.port,
            "Sec-WebSocket-Protocol: ws",
            "Sec-WebSocket-Key1: 4 @1  46546xW%0l 1 5",
            "Sec-WebSocket-Key2: 12998 5 Y3 1  .P00",
        ]
        sock = eventlet.connect(
            ('localhost', self.port))
        sock.sendall(six.b('\r\n'.join(connect) + '\r\n\r\n^n:ds[4U'))
        sock.recv(1024)
        done_with_request.wait()
        assert error_detected[0]
    def test_breaking_the_connection_13(self):
        error_detected = [False]
        done_with_request = event.Event()
        site = self.site

        def error_detector(environ, start_response):
            try:
                try:
                    return site(environ, start_response)
                except:
                    error_detected[0] = True
                    raise
            finally:
                done_with_request.send(True)
        self.site = error_detector
        self.spawn_server()
        connect = [
            "GET /echo HTTP/1.1",
            "Upgrade: websocket",
            "Connection: Upgrade",
            "Host: %s:%s" % self.server_addr,
            "Origin: http://%s:%s" % self.server_addr,
            "Sec-WebSocket-Version: 13",
            "Sec-WebSocket-Key: d9MXuOzlVQ0h+qRllvSCIg==",
        ]
        sock = eventlet.connect(self.server_addr)
        sock.sendall(six.b('\r\n'.join(connect) + '\r\n\r\n'))
        sock.recv(1024)  # get the headers
        sock.close()  # close while the app is running
        done_with_request.wait()
        assert not error_detected[0]
Exemple #34
0
    def test_client_invalid_packet_13(self):
        error_detected = [False]
        done_with_request = event.Event()
        site = self.site

        def error_detector(environ, start_response):
            try:
                try:
                    return site(environ, start_response)
                except:
                    error_detected[0] = True
                    raise
            finally:
                done_with_request.send(True)

        self.site = error_detector
        self.spawn_server()
        connect = [
            "GET /echo HTTP/1.1",
            "Upgrade: websocket",
            "Connection: Upgrade",
            "Host: %s:%s" % self.server_addr,
            "Origin: http://%s:%s" % self.server_addr,
            "Sec-WebSocket-Version: 13",
            "Sec-WebSocket-Key: d9MXuOzlVQ0h+qRllvSCIg==",
        ]
        sock = eventlet.connect(self.server_addr)
        sock.sendall(six.b('\r\n'.join(connect) + '\r\n\r\n'))
        sock.recv(1024)  # get the headers
        sock.sendall(b'\x07\xff')  # Weird packet.
        done_with_request.wait()
        assert not error_detected[0]
Exemple #35
0
    def test_app_socket_errors_75(self):
        error_detected = [False]
        done_with_request = event.Event()
        site = self.site

        def error_detector(environ, start_response):
            try:
                try:
                    return site(environ, start_response)
                except:
                    error_detected[0] = True
                    raise
            finally:
                done_with_request.send(True)

        self.site = error_detector
        self.spawn_server()
        connect = [
            "GET /error HTTP/1.1",
            "Upgrade: WebSocket",
            "Connection: Upgrade",
            "Host: localhost:%s" % self.port,
            "Origin: http://localhost:%s" % self.port,
            "WebSocket-Protocol: ws",
        ]
        sock = eventlet.connect(("localhost", self.port))
        sock.sendall(six.b("\r\n".join(connect) + "\r\n\r\n"))
        sock.recv(1024)
        done_with_request.wait()
        assert error_detected[0]
Exemple #36
0
    def test_sending_messages_to_websocket_76(self):
        connect = [
            "GET /echo HTTP/1.1",
            "Upgrade: WebSocket",
            "Connection: Upgrade",
            "Host: localhost:%s" % self.port,
            "Origin: http://localhost:%s" % self.port,
            "Sec-WebSocket-Protocol: ws",
            "Sec-WebSocket-Key1: 4 @1  46546xW%0l 1 5",
            "Sec-WebSocket-Key2: 12998 5 Y3 1  .P00",
        ]
        sock = eventlet.connect(
            ('localhost', self.port))

        sock.sendall(six.b('\r\n'.join(connect) + '\r\n\r\n^n:ds[4U'))
        sock.recv(1024)
        sock.sendall(b'\x00hello\xFF')
        result = sock.recv(1024)
        self.assertEqual(result, b'\x00hello\xff')
        sock.sendall(b'\x00start')
        eventlet.sleep(0.001)
        sock.sendall(b' end\xff')
        result = sock.recv(1024)
        self.assertEqual(result, b'\x00start end\xff')
        sock.shutdown(socket.SHUT_RDWR)
        sock.close()
        eventlet.sleep(0.01)
Exemple #37
0
    def _handle_hybi_request(self, environ):
        if 'eventlet.input' in environ:
            sock = environ['eventlet.input'].get_socket()
        elif 'gunicorn.socket' in environ:
            sock = environ["gunicorn.socket"]
        else:
            raise Exception("No eventlet.input or gunicorn.socket present in environ. No where from to take socket.")

        hybi_version = environ['HTTP_SEC_WEBSOCKET_VERSION']
        if hybi_version not in ('8', '13', ):
            raise BadRequest(status='426 Upgrade Required',
                             headers=[('Sec-WebSocket-Version', '8, 13')])
        self.protocol_version = int(hybi_version)
        if 'HTTP_SEC_WEBSOCKET_KEY' not in environ:
            # That's bad.
            raise BadRequest()
        origin = environ.get(
            'HTTP_ORIGIN',
            (environ.get('HTTP_SEC_WEBSOCKET_ORIGIN', '')
             if self.protocol_version <= 8 else ''))
        if self.origin_checker is not None:
            if not self.origin_checker(environ.get('HTTP_HOST'), origin):
                raise BadRequest(status='403 Forbidden')
        protocols = environ.get('HTTP_SEC_WEBSOCKET_PROTOCOL', None)
        negotiated_protocol = None
        if protocols:
            for p in (i.strip() for i in protocols.split(',')):
                if p in self.supported_protocols:
                    negotiated_protocol = p
                    break
        # extensions = environ.get('HTTP_SEC_WEBSOCKET_EXTENSIONS', None)
        # if extensions:
        #    extensions = [i.strip() for i in extensions.split(',')]

        key = environ['HTTP_SEC_WEBSOCKET_KEY']
        response = base64.b64encode(sha1(six.b(key) + PROTOCOL_GUID).digest())
        handshake_reply = [b"HTTP/1.1 101 Switching Protocols",
                           b"Upgrade: websocket",
                           b"Connection: Upgrade",
                           b"Sec-WebSocket-Accept: " + response]
        if negotiated_protocol:
            handshake_reply.append(b"Sec-WebSocket-Protocol: " + six.b(negotiated_protocol))
        sock.sendall(b'\r\n'.join(handshake_reply) + b'\r\n\r\n')
        return RFC6455WebSocket(sock, environ, self.protocol_version,
                                protocol=negotiated_protocol)
Exemple #38
0
    def _handle_hybi_request(self, environ):
        sock = environ['eventlet.input'].get_socket()
        hybi_version = environ['HTTP_SEC_WEBSOCKET_VERSION']
        if hybi_version not in (
                '8',
                '13',
        ):
            raise BadRequest(status='426 Upgrade Required',
                             headers=[('Sec-WebSocket-Version', '8, 13')])
        self.protocol_version = int(hybi_version)
        if 'HTTP_SEC_WEBSOCKET_KEY' not in environ:
            # That's bad.
            raise BadRequest()
        origin = environ.get('HTTP_ORIGIN',
                             (environ.get('HTTP_SEC_WEBSOCKET_ORIGIN', '')
                              if self.protocol_version <= 8 else ''))
        if self.origin_checker is not None:
            if not self.origin_checker(environ.get('HTTP_HOST'), origin):
                raise BadRequest(status='403 Forbidden')
        protocols = environ.get('HTTP_SEC_WEBSOCKET_PROTOCOL', None)
        negotiated_protocol = None
        if protocols:
            for p in (i.strip() for i in protocols.split(',')):
                if p in self.supported_protocols:
                    negotiated_protocol = p
                    break
        # extensions = environ.get('HTTP_SEC_WEBSOCKET_EXTENSIONS', None)
        # if extensions:
        #    extensions = [i.strip() for i in extensions.split(',')]

        key = environ['HTTP_SEC_WEBSOCKET_KEY']
        response = base64.b64encode(sha1(six.b(key) + PROTOCOL_GUID).digest())
        handshake_reply = [
            b"HTTP/1.1 101 Switching Protocols", b"Upgrade: websocket",
            b"Connection: Upgrade", b"Sec-WebSocket-Accept: " + response
        ]
        if negotiated_protocol:
            handshake_reply.append(b"Sec-WebSocket-Protocol: " +
                                   six.b(negotiated_protocol))
        sock.sendall(b'\r\n'.join(handshake_reply) + b'\r\n\r\n')
        return RFC6455WebSocket(sock,
                                environ,
                                self.protocol_version,
                                protocol=negotiated_protocol)
    def _pack_message(message):
        """Pack the message inside ``00`` and ``FF``

        As per the dataframing section (5.3) for the websocket spec
        """
        if isinstance(message, six.text_type):
            message = message.encode('utf-8')
        elif not isinstance(message, six.binary_type):
            message = six.b(str(message))
        packed = b"\x00" + message + b"\xFF"
        return packed
Exemple #40
0
    def test_getting_messages_from_websocket_75(self):
        connect = [
            "GET /range HTTP/1.1",
            "Upgrade: WebSocket",
            "Connection: Upgrade",
            "Host: %s:%s" % self.server_addr,
            "Origin: http://%s:%s" % self.server_addr,
            "WebSocket-Protocol: ws",
        ]
        sock = eventlet.connect(self.server_addr)

        sock.sendall(six.b('\r\n'.join(connect) + '\r\n\r\n'))
        resp = sock.recv(1024)
        headers, result = resp.split(b'\r\n\r\n')
        msgs = [result.strip(b'\x00\xff')]
        cnt = 10
        while cnt:
            msgs.append(sock.recv(20).strip(b'\x00\xff'))
            cnt -= 1
        # Last item in msgs is an empty string
        self.assertEqual(msgs[:-1], [six.b('msg %d' % i) for i in range(10)])
Exemple #41
0
    def test_getting_messages_from_websocket_75(self):
        connect = [
            "GET /range HTTP/1.1",
            "Upgrade: WebSocket",
            "Connection: Upgrade",
            "Host: localhost:%s" % self.port,
            "Origin: http://localhost:%s" % self.port,
            "WebSocket-Protocol: ws",
        ]
        sock = eventlet.connect(("localhost", self.port))

        sock.sendall(six.b("\r\n".join(connect) + "\r\n\r\n"))
        resp = sock.recv(1024)
        headers, result = resp.split(b"\r\n\r\n")
        msgs = [result.strip(b"\x00\xff")]
        cnt = 10
        while cnt:
            msgs.append(sock.recv(20).strip(b"\x00\xff"))
            cnt -= 1
        # Last item in msgs is an empty string
        self.assertEqual(msgs[:-1], [six.b("msg %d" % i) for i in range(10)])
Exemple #42
0
    def test_getting_messages_from_websocket_76(self):
        connect = [
            "GET /range HTTP/1.1",
            "Upgrade: WebSocket",
            "Connection: Upgrade",
            "Host: %s:%s" % self.server_addr,
            "Origin: http://%s:%s" % self.server_addr,
            "Sec-WebSocket-Protocol: ws",
            "Sec-WebSocket-Key1: 4 @1  46546xW%0l 1 5",
            "Sec-WebSocket-Key2: 12998 5 Y3 1  .P00",
        ]
        sock = eventlet.connect(self.server_addr)

        sock.sendall(six.b("\r\n".join(connect) + "\r\n\r\n^n:ds[4U"))
        resp = sock.recv(1024)
        headers, result = resp.split(b"\r\n\r\n")
        msgs = [result[16:].strip(b"\x00\xff")]
        cnt = 10
        while cnt:
            msgs.append(sock.recv(20).strip(b"\x00\xff"))
            cnt -= 1
        # Last item in msgs is an empty string
        self.assertEqual(msgs[:-1], [six.b("msg %d" % i) for i in range(10)])
Exemple #43
0
    def test_correct_upgrade_request_13(self):
        for http_connection in ['Upgrade', 'UpGrAdE', 'keep-alive, Upgrade']:
            connect = [
                "GET /echo HTTP/1.1",
                "Upgrade: websocket",
                "Connection: %s" % http_connection,
                "Host: localhost:%s" % self.port,
                "Origin: http://localhost:%s" % self.port,
                "Sec-WebSocket-Version: 13",
                "Sec-WebSocket-Key: d9MXuOzlVQ0h+qRllvSCIg==",
            ]
            sock = eventlet.connect(('localhost', self.port))

            sock.sendall(six.b('\r\n'.join(connect) + '\r\n\r\n'))
            result = sock.recv(1024)
            # The server responds the correct Websocket handshake
            print('Connection string: %r' % http_connection)
            self.assertEqual(result, six.b('\r\n'.join([
                'HTTP/1.1 101 Switching Protocols',
                'Upgrade: websocket',
                'Connection: Upgrade',
                'Sec-WebSocket-Accept: ywSyWXCPNsDxLrQdQrn5RFNRfBU=\r\n\r\n',
            ])))
Exemple #44
0
    def test_getting_messages_from_websocket_76(self):
        connect = [
            "GET /range HTTP/1.1",
            "Upgrade: WebSocket",
            "Connection: Upgrade",
            "Host: localhost:%s" % self.port,
            "Origin: http://localhost:%s" % self.port,
            "Sec-WebSocket-Protocol: ws",
            "Sec-WebSocket-Key1: 4 @1  46546xW%0l 1 5",
            "Sec-WebSocket-Key2: 12998 5 Y3 1  .P00",
        ]
        sock = eventlet.connect(('localhost', self.port))

        sock.sendall(six.b('\r\n'.join(connect) + '\r\n\r\n^n:ds[4U'))
        resp = sock.recv(1024)
        headers, result = resp.split(b'\r\n\r\n')
        msgs = [result[16:].strip(b'\x00\xff')]
        cnt = 10
        while cnt:
            msgs.append(sock.recv(20).strip(b'\x00\xff'))
            cnt -= 1
        # Last item in msgs is an empty string
        self.assertEqual(msgs[:-1], [six.b('msg %d' % i) for i in range(10)])
Exemple #45
0
    def test_accept_basic_deflate_ext_13(self):
        for extension in [
                'permessage-deflate',
                'PeRMessAGe-dEFlaTe',
        ]:
            sock = eventlet.connect(self.server_addr)

            sock.sendall(six.b(self.connect % extension))
            result = sock.recv(1024)

            # The server responds the correct Websocket handshake
            # print('Extension offer: %r' % extension)
            match = re.match(self.handshake_re, result)
            assert match is not None
            assert len(match.groups()) == 1
Exemple #46
0
    def test_reject_max_window_bits_out_of_range_13(self):
        extension_string = ('permessage-deflate; client_max_window_bits=7,'
                            'permessage-deflate; server_max_window_bits=16, '
                            'permessage-deflate; client_max_window_bits=16; '
                            'server_max_window_bits=7, '
                            'permessage-deflate')
        sock = eventlet.connect(self.server_addr)

        sock.sendall(six.b(self.connect % extension_string))
        result = sock.recv(1024)

        # The server responds the correct Websocket handshake
        # print('Extension offer: %r' % extension_string)
        match = re.match(self.handshake_re, result)
        assert match.groups()[0] == b'permessage-deflate'
Exemple #47
0
    def test_correct_upgrade_request_75(self):
        connect = [
            "GET /echo HTTP/1.1",
            "Upgrade: WebSocket",
            "Connection: Upgrade",
            "Host: %s:%s" % self.server_addr,
            "Origin: http://%s:%s" % self.server_addr,
            "WebSocket-Protocol: ws",
        ]
        sock = eventlet.connect(self.server_addr)

        sock.sendall(six.b('\r\n'.join(connect) + '\r\n\r\n'))
        result = sock.recv(1024)
        # The server responds the correct Websocket handshake
        self.assertEqual(
            result,
            six.b('\r\n'.join([
                'HTTP/1.1 101 Web Socket Protocol Handshake',
                'Upgrade: WebSocket',
                'Connection: Upgrade',
                'WebSocket-Origin: http://%s:%s' % self.server_addr,
                'WebSocket-Location: ws://%s:%s/echo\r\n\r\n' %
                self.server_addr,
            ])))
Exemple #48
0
 def test_server_closing_connect_76(self):
     connect = [
         "GET / HTTP/1.1",
         "Upgrade: WebSocket",
         "Connection: Upgrade",
         "Host: %s:%s" % self.server_addr,
         "Origin: http://%s:%s" % self.server_addr,
         "Sec-WebSocket-Protocol: ws",
         "Sec-WebSocket-Key1: 4 @1  46546xW%0l 1 5",
         "Sec-WebSocket-Key2: 12998 5 Y3 1  .P00",
     ]
     sock = eventlet.connect(self.server_addr)
     sock.sendall(six.b("\r\n".join(connect) + "\r\n\r\n^n:ds[4U"))
     resp = sock.recv(1024)
     headers, result = resp.split(b"\r\n\r\n")
     # The remote server should have immediately closed the connection.
     self.assertEqual(result[16:], b"\xff\x00")
Exemple #49
0
 def test_server_closing_connect_76(self):
     connect = [
         "GET / HTTP/1.1",
         "Upgrade: WebSocket",
         "Connection: Upgrade",
         "Host: %s:%s" % self.server_addr,
         "Origin: http://%s:%s" % self.server_addr,
         "Sec-WebSocket-Protocol: ws",
         "Sec-WebSocket-Key1: 4 @1  46546xW%0l 1 5",
         "Sec-WebSocket-Key2: 12998 5 Y3 1  .P00",
     ]
     sock = eventlet.connect(self.server_addr)
     sock.sendall(six.b('\r\n'.join(connect) + '\r\n\r\n^n:ds[4U'))
     resp = sock.recv(1024)
     headers, result = resp.split(b'\r\n\r\n')
     # The remote server should have immediately closed the connection.
     self.assertEqual(result[16:], b'\xff\x00')
Exemple #50
0
    def _send_hundred_continue_response(self):
        towrite = []

        # 100 Continue status line
        towrite.append(self.wfile_line)

        # Optional headers
        if self.hundred_continue_headers is not None:
            # 100 Continue headers
            for header in self.hundred_continue_headers:
                towrite.append(six.b('%s: %s\r\n' % header))

        # Blank line
        towrite.append(b'\r\n')

        self.wfile.writelines(towrite)
        self.wfile = None
        self.wfile_line = None
Exemple #51
0
    def _send_hundred_continue_response(self):
        towrite = []

        # 100 Continue status line
        towrite.append(self.wfile_line)

        # Optional headers
        if self.hundred_continue_headers is not None:
            # 100 Continue headers
            for header in self.hundred_continue_headers:
                towrite.append(six.b('%s: %s\r\n' % header))

        # Blank line
        towrite.append(b'\r\n')

        self.wfile.writelines(towrite)
        self.wfile = None
        self.wfile_line = None
Exemple #52
0
    def send_hundred_continue_response(self):
        towrite = []

        # 100 Continue status line
        towrite.append(self.wfile_line)

        # Optional headers
        if self.hundred_continue_headers is not None:
            # 100 Continue headers
            for header in self.hundred_continue_headers:
                towrite.append(six.b('%s: %s\r\n' % header))

        # Blank line
        towrite.append(b'\r\n')

        self.wfile.writelines(towrite)

        # Reinitialize chunk_length (expect more data)
        self.chunk_length = -1
Exemple #53
0
    def test_ssl_sending_messages(self):
        s = eventlet.wrap_ssl(eventlet.listen(('localhost', 0)),
                              certfile=tests.certificate_file,
                              keyfile=tests.private_key_file,
                              server_side=True)
        self.spawn_server(sock=s)
        connect = [
            "GET /echo HTTP/1.1",
            "Upgrade: WebSocket",
            "Connection: Upgrade",
            "Host: %s:%s" % self.server_addr,
            "Origin: http://%s:%s" % self.server_addr,
            "Sec-WebSocket-Protocol: ws",
            "Sec-WebSocket-Key1: 4 @1  46546xW%0l 1 5",
            "Sec-WebSocket-Key2: 12998 5 Y3 1  .P00",
        ]
        sock = eventlet.wrap_ssl(eventlet.connect(self.server_addr))

        sock.sendall(six.b('\r\n'.join(connect) + '\r\n\r\n^n:ds[4U'))
        first_resp = b''
        while b'\r\n\r\n' not in first_resp:
            first_resp += sock.recv()
            print('resp now:')
            print(first_resp)
        # make sure it sets the wss: protocol on the location header
        loc_line = [
            x for x in first_resp.split(b"\r\n")
            if x.lower().startswith(b'sec-websocket-location')
        ][0]
        expect_wss = ('wss://%s:%s' % self.server_addr).encode()
        assert expect_wss in loc_line, "Expecting wss protocol in location: %s" % loc_line

        sock.sendall(b'\x00hello\xFF')
        result = sock.recv(1024)
        self.assertEqual(result, b'\x00hello\xff')
        sock.sendall(b'\x00start')
        eventlet.sleep(0.001)
        sock.sendall(b' end\xff')
        result = sock.recv(1024)
        self.assertEqual(result, b'\x00start end\xff')
        greenio.shutdown_safe(sock)
        sock.close()
        eventlet.sleep(0.01)
Exemple #54
0
    def test_ssl_sending_messages(self):
        s = eventlet.wrap_ssl(
            eventlet.listen(("localhost", 0)),
            certfile=tests.certificate_file,
            keyfile=tests.private_key_file,
            server_side=True,
        )
        self.spawn_server(sock=s)
        connect = [
            "GET /echo HTTP/1.1",
            "Upgrade: WebSocket",
            "Connection: Upgrade",
            "Host: %s:%s" % self.server_addr,
            "Origin: http://%s:%s" % self.server_addr,
            "Sec-WebSocket-Protocol: ws",
            "Sec-WebSocket-Key1: 4 @1  46546xW%0l 1 5",
            "Sec-WebSocket-Key2: 12998 5 Y3 1  .P00",
        ]
        sock = eventlet.wrap_ssl(eventlet.connect(self.server_addr))

        sock.sendall(six.b("\r\n".join(connect) + "\r\n\r\n^n:ds[4U"))
        first_resp = b""
        while b"\r\n\r\n" not in first_resp:
            first_resp += sock.recv()
            print("resp now:")
            print(first_resp)
        # make sure it sets the wss: protocol on the location header
        loc_line = [x for x in first_resp.split(b"\r\n") if x.lower().startswith(b"sec-websocket-location")][0]
        expect_wss = ("wss://%s:%s" % self.server_addr).encode()
        assert expect_wss in loc_line, "Expecting wss protocol in location: %s" % loc_line

        sock.sendall(b"\x00hello\xFF")
        result = sock.recv(1024)
        self.assertEqual(result, b"\x00hello\xff")
        sock.sendall(b"\x00start")
        eventlet.sleep(0.001)
        sock.sendall(b" end\xff")
        result = sock.recv(1024)
        self.assertEqual(result, b"\x00start end\xff")
        greenio.shutdown_safe(sock)
        sock.close()
        eventlet.sleep(0.01)
Exemple #55
0
    def test_ssl_sending_messages(self):
        s = eventlet.wrap_ssl(eventlet.listen(('localhost', 0)),
                              certfile=certificate_file,
                              keyfile=private_key_file,
                              server_side=True)
        self.spawn_server(sock=s)
        connect = [
            "GET /echo HTTP/1.1",
            "Upgrade: WebSocket",
            "Connection: Upgrade",
            "Host: localhost:%s" % self.port,
            "Origin: http://localhost:%s" % self.port,
            "Sec-WebSocket-Protocol: ws",
            "Sec-WebSocket-Key1: 4 @1  46546xW%0l 1 5",
            "Sec-WebSocket-Key2: 12998 5 Y3 1  .P00",
        ]
        sock = eventlet.wrap_ssl(eventlet.connect(
            ('localhost', self.port)))

        sock.sendall(six.b('\r\n'.join(connect) + '\r\n\r\n^n:ds[4U'))
        first_resp = b''
        while b'\r\n\r\n' not in first_resp:
            first_resp += sock.recv()
            print('resp now:')
            print(first_resp)
        # make sure it sets the wss: protocol on the location header
        loc_line = [x for x in first_resp.split(b"\r\n")
                    if x.lower().startswith(b'sec-websocket-location')][0]
        self.assert_(b"wss://localhost" in loc_line,
                     "Expecting wss protocol in location: %s" % loc_line)
        sock.sendall(b'\x00hello\xFF')
        result = sock.recv(1024)
        self.assertEqual(result, b'\x00hello\xff')
        sock.sendall(b'\x00start')
        eventlet.sleep(0.001)
        sock.sendall(b' end\xff')
        result = sock.recv(1024)
        self.assertEqual(result, b'\x00start end\xff')
        greenio.shutdown_safe(sock)
        sock.close()
        eventlet.sleep(0.01)
 def test_send_recv_13(self):
     connect = [
         "GET /echo HTTP/1.1",
         "Upgrade: websocket",
         "Connection: Upgrade",
         "Host: %s:%s" % self.server_addr,
         "Origin: http://%s:%s" % self.server_addr,
         "Sec-WebSocket-Version: 13",
         "Sec-WebSocket-Key: d9MXuOzlVQ0h+qRllvSCIg==",
     ]
     sock = eventlet.connect(self.server_addr)
     sock.sendall(six.b('\r\n'.join(connect) + '\r\n\r\n'))
     sock.recv(1024)
     ws = websocket.RFC6455WebSocket(sock, {}, client=True)
     ws.send(b'hello')
     assert ws.wait() == b'hello'
     ws.send(b'hello world!\x01')
     ws.send(u'hello world again!')
     assert ws.wait() == b'hello world!\x01'
     assert ws.wait() == u'hello world again!'
     ws.close()
     eventlet.sleep(0.01)
Exemple #57
0
    def test_sending_messages_to_websocket_75(self):
        connect = [
            "GET /echo HTTP/1.1",
            "Upgrade: WebSocket",
            "Connection: Upgrade",
            "Host: localhost:%s" % self.port,
            "Origin: http://localhost:%s" % self.port,
            "WebSocket-Protocol: ws",
        ]
        sock = eventlet.connect(("localhost", self.port))

        sock.sendall(six.b("\r\n".join(connect) + "\r\n\r\n"))
        sock.recv(1024)
        sock.sendall(b"\x00hello\xFF")
        result = sock.recv(1024)
        self.assertEqual(result, b"\x00hello\xff")
        sock.sendall(b"\x00start")
        eventlet.sleep(0.001)
        sock.sendall(b" end\xff")
        result = sock.recv(1024)
        self.assertEqual(result, b"\x00start end\xff")
        sock.shutdown(socket.SHUT_RDWR)
        sock.close()
        eventlet.sleep(0.01)
Exemple #58
0
    def handle_one_response(self):
        start = time.time()
        headers_set = []
        headers_sent = []

        wfile = self.wfile
        result = None
        use_chunked = [False]
        length = [0]
        status_code = [200]

        def write(data, _writelines=wfile.writelines):
            towrite = []
            if not headers_set:
                raise AssertionError("write() before start_response()")
            elif not headers_sent:
                status, response_headers = headers_set
                headers_sent.append(1)
                header_list = [header[0].lower() for header in response_headers]
                towrite.append(six.b('%s %s\r\n' % (self.protocol_version, status)))
                for header in response_headers:
                    towrite.append(six.b('%s: %s\r\n' % header))

                # send Date header?
                if 'date' not in header_list:
                    towrite.append(six.b('Date: %s\r\n' % (format_date_time(time.time()),)))

                client_conn = self.headers.get('Connection', '').lower()
                send_keep_alive = False
                if self.close_connection == 0 and \
                   self.server.keepalive and (client_conn == 'keep-alive' or
                                              (self.request_version == 'HTTP/1.1' and
                                               not client_conn == 'close')):
                        # only send keep-alives back to clients that sent them,
                        # it's redundant for 1.1 connections
                    send_keep_alive = (client_conn == 'keep-alive')
                    self.close_connection = 0
                else:
                    self.close_connection = 1

                if 'content-length' not in header_list:
                    if self.request_version == 'HTTP/1.1':
                        use_chunked[0] = True
                        towrite.append(b'Transfer-Encoding: chunked\r\n')
                    elif 'content-length' not in header_list:
                        # client is 1.0 and therefore must read to EOF
                        self.close_connection = 1

                if self.close_connection:
                    towrite.append(b'Connection: close\r\n')
                elif send_keep_alive:
                    towrite.append(b'Connection: keep-alive\r\n')
                towrite.append(b'\r\n')
                # end of header writing

            if use_chunked[0]:
                # Write the chunked encoding
                towrite.append(six.b("%x" % (len(data),)) + b"\r\n" + data + b"\r\n")
            else:
                towrite.append(data)
            _writelines(towrite)
            length[0] = length[0] + sum(map(len, towrite))

        def start_response(status, response_headers, exc_info=None):
            status_code[0] = status.split()[0]
            if exc_info:
                try:
                    if headers_sent:
                        # Re-raise original exception if headers sent
                        six.reraise(exc_info[0], exc_info[1], exc_info[2])
                finally:
                    # Avoid dangling circular ref
                    exc_info = None

            # Response headers capitalization
            # CONTent-TYpe: TExt/PlaiN -> Content-Type: TExt/PlaiN
            # Per HTTP RFC standard, header name is case-insensitive.
            # Please, fix your client to ignore header case if possible.
            if self.capitalize_response_headers:
                response_headers = [
                    ('-'.join([x.capitalize() for x in key.split('-')]), value)
                    for key, value in response_headers]

            headers_set[:] = [status, response_headers]
            return write

        try:
            try:
                result = self.application(self.environ, start_response)
                if (isinstance(result, _AlreadyHandled)
                        or isinstance(getattr(result, '_obj', None), _AlreadyHandled)):
                    self.close_connection = 1
                    return

                # Set content-length if possible
                if not headers_sent and hasattr(result, '__len__') and \
                        'Content-Length' not in [h for h, _v in headers_set[1]]:
                    headers_set[1].append(('Content-Length', str(sum(map(len, result)))))

                towrite = []
                towrite_size = 0
                just_written_size = 0
                minimum_write_chunk_size = int(self.environ.get(
                    'eventlet.minimum_write_chunk_size', self.minimum_chunk_size))
                for data in result:
                    if isinstance(data, six.text_type):
                        data = data.encode('ascii')

                    towrite.append(data)
                    towrite_size += len(data)
                    if towrite_size >= minimum_write_chunk_size:
                        write(b''.join(towrite))
                        towrite = []
                        just_written_size = towrite_size
                        towrite_size = 0
                if towrite:
                    just_written_size = towrite_size
                    write(b''.join(towrite))
                if not headers_sent or (use_chunked[0] and just_written_size):
                    write(b'')
            except Exception:
                self.close_connection = 1
                tb = traceback.format_exc()
                self.server.log.info(tb)
                if not headers_sent:
                    err_body = six.b(tb) if self.server.debug else b''
                    start_response("500 Internal Server Error",
                                   [('Content-type', 'text/plain'),
                                    ('Content-length', len(err_body))])
                    write(err_body)
        finally:
            if hasattr(result, 'close'):
                result.close()
            if (self.environ['eventlet.input'].chunked_input or
                    self.environ['eventlet.input'].position
                    < (self.environ['eventlet.input'].content_length or 0)):
                # Read and discard body if there was no pending 100-continue
                if not self.environ['eventlet.input'].wfile:
                    # NOTE: MINIMUM_CHUNK_SIZE is used here for purpose different than chunking.
                    # We use it only cause it's at hand and has reasonable value in terms of
                    # emptying the buffer.
                    while self.environ['eventlet.input'].read(MINIMUM_CHUNK_SIZE):
                        pass
            finish = time.time()

            for hook, args, kwargs in self.environ['eventlet.posthooks']:
                hook(self.environ, *args, **kwargs)

            if self.server.log_output:
                self.server.log.info(self.server.log_format % {
                    'client_ip': self.get_client_ip(),
                    'client_port': self.client_address[1],
                    'date_time': self.log_date_time_string(),
                    'request_line': self.requestline,
                    'status_code': status_code[0],
                    'body_length': length[0],
                    'wall_seconds': finish - start,
                })