Beispiel #1
0
 def setUp(self):
     self.channel = DummyChannel()
     request = Request(self.channel, False)
     transport = WebSocketTransport(request)
     handler = TestHandler(transport)
     transport._attachHandler(handler)
     self.decoder = WebSocketFrameDecoder(request, handler)
     self.decoder.MAX_LENGTH = 100
 def setUp(self):
     self.channel = DummyChannel()
     request = Request(self.channel, False)
     transport = WebSocketTransport(request)
     handler = TestHandler(transport)
     transport._attachHandler(handler)
     self.decoder = WebSocketFrameDecoder(request, handler)
     self.decoder.MAX_LENGTH = 100
Beispiel #3
0
        def finishHandshake(nonce):
            """ Receive nonce value from request body, and calculate repsonse. """
            protocolHeaders = self.requestHeaders.getRawHeaders(
                "WebSocket-Protocol", [])
            if len(protocolHeaders) not in (0, 1):
                return finish()
            if protocolHeaders:
                if protocolHeaders[0] not in self.site.supportedProtocols:
                    return finish()
                protocolHeader = protocolHeaders[0]
            else:
                protocolHeader = None

            originHeader = originHeaders[0]
            hostHeader = hostHeaders[0]
            self.startedWriting = True
            handshake = [
                "HTTP/1.1 101 Web Socket Protocol Handshake",
                "Upgrade: WebSocket", "Connection: Upgrade"
            ]
            handshake.append("Sec-WebSocket-Origin: %s" % (originHeader))
            if self.isSecure():
                scheme = "wss"
            else:
                scheme = "ws"
            handshake.append("Sec-WebSocket-Location: %s://%s%s" %
                             (scheme, hostHeader, self.uri))

            if protocolHeader is not None:
                handshake.append("Sec-WebSocket-Protocol: %s" % protocolHeader)

            for header in handshake:
                self.write("%s\r\n" % header)

            self.write("\r\n")

            # concatenate num1 (32 bit in), num2 (32 bit int), nonce, and take md5 of result
            res = struct.pack('>II8s', num1, num2, nonce)
            server_response = md5(res).digest()
            self.write(server_response)

            # XXX we probably don't want to set _transferDecoder
            self.channel._transferDecoder = WebSocketFrameDecoder(
                self, handler)

            transport._connectionMade()
Beispiel #4
0
    def renderWebSocket(self):
        """
        Render a WebSocket request.

        If the request is not identified with a proper WebSocket handshake, the
        connection will be closed. Otherwise, the response to the handshake is
        sent and a C{WebSocketHandler} is created to handle the request.
        """
        # check for post-75 handshake requests
        isSecHandshake = self.requestHeaders.getRawHeaders(
            "Sec-WebSocket-Key1", [])
        if isSecHandshake:
            self._clientHandshake76()
        else:
            check = self._checkClientHandshake()
            if check is None:
                return
            originHeader, hostHeader, protocolHeader, handler = check
            self.startedWriting = True
            handshake = [
                "HTTP/1.1 101 Web Socket Protocol Handshake",
                "Upgrade: WebSocket", "Connection: Upgrade"
            ]
            handshake.append("WebSocket-Origin: %s" % (originHeader))
            if self.isSecure():
                scheme = "wss"
            else:
                scheme = "ws"
            handshake.append("WebSocket-Location: %s://%s%s" %
                             (scheme, hostHeader, self.uri))

            if protocolHeader is not None:
                handshake.append("WebSocket-Protocol: %s" % protocolHeader)

            for header in handshake:
                self.write("%s\r\n" % header)

            self.write("\r\n")
            self.channel.setRawMode()
            # XXX we probably don't want to set _transferDecoder
            self.channel._transferDecoder = WebSocketFrameDecoder(
                self, handler)
            handler.transport._connectionMade()
            return
class WebSocketFrameDecoderTestCase(TestCase):
    """
    Test for C{WebSocketFrameDecoder}.
    """

    def setUp(self):
        self.channel = DummyChannel()
        request = Request(self.channel, False)
        transport = WebSocketTransport(request)
        handler = TestHandler(transport)
        transport._attachHandler(handler)
        self.decoder = WebSocketFrameDecoder(request, handler)
        self.decoder.MAX_LENGTH = 100


    def test_oneFrame(self):
        """
        We can send one frame handled with one C{dataReceived} call.
        """
        self.decoder.dataReceived("\x00frame\xff")
        self.assertEquals(self.decoder.handler.frames, ["frame"])


    def test_oneFrameSplitted(self):
        """
        A frame can be split into several C{dataReceived} calls, and will be
        combined again when sent to the C{WebSocketHandler}.
        """
        self.decoder.dataReceived("\x00fra")
        self.decoder.dataReceived("me\xff")
        self.assertEquals(self.decoder.handler.frames, ["frame"])


    def test_multipleFrames(self):
        """
        Several frames can be received in a single C{dataReceived} call.
        """
        self.decoder.dataReceived("\x00frame1\xff\x00frame2\xff")
        self.assertEquals(self.decoder.handler.frames, ["frame1", "frame2"])


    def test_missingNull(self):
        """
        If a frame not starting with C{\\x00} is received, the connection is
        dropped.
        """
        self.decoder.dataReceived("frame\xff")
        self.assertTrue(self.channel.transport.disconnected)


    def test_missingNullAfterGoodFrame(self):
        """
        If a frame not starting with C{\\x00} is received after a correct
        frame, the connection is dropped.
        """
        self.decoder.dataReceived("\x00frame\xfffoo")
        self.assertTrue(self.channel.transport.disconnected)
        self.assertEquals(self.decoder.handler.frames, ["frame"])


    def test_emptyReceive(self):
        """
        Received an empty string doesn't do anything.
        """
        self.decoder.dataReceived("")
        self.assertFalse(self.channel.transport.disconnected)


    def test_maxLength(self):
        """
        If a frame is received which is bigger than C{MAX_LENGTH}, the
        connection is dropped.
        """
        self.decoder.dataReceived("\x00" + "x" * 101)
        self.assertTrue(self.channel.transport.disconnected)


    def test_maxLengthFrameCompleted(self):
        """
        If a too big frame is received in several fragments, the connection is
        dropped.
        """
        self.decoder.dataReceived("\x00" + "x" * 90)
        self.decoder.dataReceived("x" * 11 + "\xff")
        self.assertTrue(self.channel.transport.disconnected)


    def test_frameLengthReset(self):
        """
        The length of frames is reset between frame, thus not creating an error
        when the accumulated length exceeds the maximum frame length.
        """
        for i in range(15):
            self.decoder.dataReceived("\x00" + "x" * 10 + "\xff")
        self.assertFalse(self.channel.transport.disconnected)
Beispiel #6
0
class WebSocketFrameDecoderTestCase(TestCase):
    """
    Test for C{WebSocketFrameDecoder}.
    """

    def setUp(self):
        self.channel = DummyChannel()
        request = Request(self.channel, False)
        transport = WebSocketTransport(request)
        handler = TestHandler(transport)
        transport._attachHandler(handler)
        self.decoder = WebSocketFrameDecoder(request, handler)
        self.decoder.MAX_LENGTH = 100
        self.decoder.MAX_BINARY_LENGTH = 1000


    def assertOneDecodingError(self):
        """
        Assert that exactly one L{DecodingError} has been logged and return
        that error.
        """
        errors = self.flushLoggedErrors(DecodingError)
        self.assertEquals(len(errors), 1)
        return errors[0]


    def test_oneFrame(self):
        """
        We can send one frame handled with one C{dataReceived} call.
        """
        self.decoder.dataReceived("\x00frame\xff")
        self.assertEquals(self.decoder.handler.frames, ["frame"])


    def test_oneFrameSplitted(self):
        """
        A frame can be split into several C{dataReceived} calls, and will be
        combined again when sent to the C{WebSocketHandler}.
        """
        self.decoder.dataReceived("\x00fra")
        self.decoder.dataReceived("me\xff")
        self.assertEquals(self.decoder.handler.frames, ["frame"])


    def test_multipleFrames(self):
        """
        Several frames can be received in a single C{dataReceived} call.
        """
        self.decoder.dataReceived("\x00frame1\xff\x00frame2\xff")
        self.assertEquals(self.decoder.handler.frames, ["frame1", "frame2"])


    def test_missingNull(self):
        """
        If a frame not starting with C{\\x00} is received, the connection is
        dropped.
        """
        self.decoder.dataReceived("frame\xff")
        self.assertOneDecodingError()
        self.assertTrue(self.channel.transport.disconnected)


    def test_missingNullAfterGoodFrame(self):
        """
        If a frame not starting with C{\\x00} is received after a correct
        frame, the connection is dropped.
        """
        self.decoder.dataReceived("\x00frame\xfffoo")
        self.assertOneDecodingError()
        self.assertTrue(self.channel.transport.disconnected)
        self.assertEquals(self.decoder.handler.frames, ["frame"])


    def test_emptyReceive(self):
        """
        Received an empty string doesn't do anything.
        """
        self.decoder.dataReceived("")
        self.assertFalse(self.channel.transport.disconnected)


    def test_maxLength(self):
        """
        If a frame is received which is bigger than C{MAX_LENGTH}, the
        connection is dropped.
        """
        self.decoder.dataReceived("\x00" + "x" * 101)
        self.assertTrue(self.channel.transport.disconnected)


    def test_maxLengthFrameCompleted(self):
        """
        If a too big frame is received in several fragments, the connection is
        dropped.
        """
        self.decoder.dataReceived("\x00" + "x" * 90)
        self.decoder.dataReceived("x" * 11 + "\xff")
        self.assertTrue(self.channel.transport.disconnected)


    def test_frameLengthReset(self):
        """
        The length of frames is reset between frame, thus not creating an error
        when the accumulated length exceeds the maximum frame length.
        """
        for i in range(15):
            self.decoder.dataReceived("\x00" + "x" * 10 + "\xff")
        self.assertFalse(self.channel.transport.disconnected)


    def test_oneBinaryFrame(self):
        """
        A binary frame is parsed and ignored, the following text frame is
        delivered.
        """
        self.decoder.dataReceived("\xff\x0abinarydata\x00text frame\xff")
        self.assertEquals(self.decoder.handler.frames, ["text frame"])


    def test_multipleBinaryFrames(self):
        """
        Text frames intermingled with binary frames are parsed correctly.
        """
        tf1, tf2, tf3 = "\x00frame1\xff", "\x00frame2\xff", "\x00frame3\xff"
        bf1, bf2, bf3 = "\xff\x01X", "\xff\x1a" + "X" * 0x1a, "\xff\x02AB"

        self.decoder.dataReceived(tf1 + bf1 + bf2 + tf2 + tf3 + bf3)
        self.assertEquals(self.decoder.handler.frames,
                          ["frame1", "frame2", "frame3"])


    def test_binaryFrameMultipleLengthBytes(self):
        """
        A binary frame can have its length field spread across multiple bytes.
        """
        bf = "\xff\x81\x48" + "X" * 200
        tf = "\x00frame\xff"
        self.decoder.dataReceived(bf + tf + bf)
        self.assertEquals(self.decoder.handler.frames, ["frame"])


    def test_binaryAndTextSplitted(self):
        """
        Intermingled binary and text frames can be split across several
        C{dataReceived} calls.
        """
        tf1, tf2 = "\x00text\xff", "\x00other text\xff"
        bf1, bf2, bf3 = ("\xff\x01X", "\xff\x81\x48" + "X" * 200,
                         "\xff\x20" + "X" * 32)

        chunks = [bf1[0], bf1[1:], tf1[:2], tf1[2:] + bf2[:2], bf2[2:-2],
                  bf2[-2:-1], bf2[1] + tf2[:-1], tf2[-1], bf3]
        for c in chunks:
            self.decoder.dataReceived(c)

        self.assertEquals(self.decoder.handler.frames, ["text", "other text"])
        self.assertFalse(self.channel.transport.disconnected)


    def text_maxBinaryLength(self):
        """
        If a binary frame's declared length exceeds MAX_BINARY_LENGTH, the
        connection is dropped.
        """
        self.decoder.dataReceived("\xff\xff\xff\xff\xff\xff")
        self.assertTrue(self.channel.transport.disconnected)


    def test_closingHandshake(self):
        """
        After receiving the closing handshake, the server sends its own closing
        handshake and ignores all future data.
        """
        self.decoder.dataReceived("\x00frame\xff\xff\x00random crap")
        self.decoder.dataReceived("more random crap, that's discarded")
        self.assertEquals(self.decoder.handler.frames, ["frame"])
        self.assertTrue(self.decoder.closing)


    def test_invalidFrameType(self):
        """
        Frame types other than 0x00 and 0xff cause the connection to be
        dropped.
        """
        ok = "\x00ok\xff"
        wrong = "\x05foo\xff"

        self.decoder.dataReceived(ok + wrong + ok)
        self.assertEquals(self.decoder.handler.frames, ["ok"])
        error = self.assertOneDecodingError()
        self.assertTrue(self.channel.transport.disconnected)


    def test_emptyFrame(self):
        """
        An empty text frame is correctly parsed.
        """
        self.decoder.dataReceived("\x00\xff")
        self.assertEquals(self.decoder.handler.frames, [""])
        self.assertFalse(self.channel.transport.disconnected)
Beispiel #7
0
class WebSocketFrameDecoderTestCase(TestCase):
    """
    Test for C{WebSocketFrameDecoder}.
    """
    def setUp(self):
        self.channel = DummyChannel()
        request = Request(self.channel, False)
        transport = WebSocketTransport(request)
        handler = TestHandler(transport)
        transport._attachHandler(handler)
        self.decoder = WebSocketFrameDecoder(request, handler)
        self.decoder.MAX_LENGTH = 100

    def test_oneFrame(self):
        """
        We can send one frame handled with one C{dataReceived} call.
        """
        self.decoder.dataReceived("\x00frame\xff")
        self.assertEquals(self.decoder.handler.frames, ["frame"])

    def test_oneFrameSplitted(self):
        """
        A frame can be split into several C{dataReceived} calls, and will be
        combined again when sent to the C{WebSocketHandler}.
        """
        self.decoder.dataReceived("\x00fra")
        self.decoder.dataReceived("me\xff")
        self.assertEquals(self.decoder.handler.frames, ["frame"])

    def test_multipleFrames(self):
        """
        Several frames can be received in a single C{dataReceived} call.
        """
        self.decoder.dataReceived("\x00frame1\xff\x00frame2\xff")
        self.assertEquals(self.decoder.handler.frames, ["frame1", "frame2"])

    def test_missingNull(self):
        """
        If a frame not starting with C{\\x00} is received, the connection is
        dropped.
        """
        self.decoder.dataReceived("frame\xff")
        self.assertTrue(self.channel.transport.disconnected)

    def test_missingNullAfterGoodFrame(self):
        """
        If a frame not starting with C{\\x00} is received after a correct
        frame, the connection is dropped.
        """
        self.decoder.dataReceived("\x00frame\xfffoo")
        self.assertTrue(self.channel.transport.disconnected)
        self.assertEquals(self.decoder.handler.frames, ["frame"])

    def test_emptyReceive(self):
        """
        Received an empty string doesn't do anything.
        """
        self.decoder.dataReceived("")
        self.assertFalse(self.channel.transport.disconnected)

    def test_maxLength(self):
        """
        If a frame is received which is bigger than C{MAX_LENGTH}, the
        connection is dropped.
        """
        self.decoder.dataReceived("\x00" + "x" * 101)
        self.assertTrue(self.channel.transport.disconnected)

    def test_maxLengthFrameCompleted(self):
        """
        If a too big frame is received in several fragments, the connection is
        dropped.
        """
        self.decoder.dataReceived("\x00" + "x" * 90)
        self.decoder.dataReceived("x" * 11 + "\xff")
        self.assertTrue(self.channel.transport.disconnected)

    def test_frameLengthReset(self):
        """
        The length of frames is reset between frame, thus not creating an error
        when the accumulated length exceeds the maximum frame length.
        """
        for i in range(15):
            self.decoder.dataReceived("\x00" + "x" * 10 + "\xff")
        self.assertFalse(self.channel.transport.disconnected)
Beispiel #8
0
class WebSocketFrameDecoderTestCase(TestCase):
    """
    Test for C{WebSocketFrameDecoder}.
    """
    def setUp(self):
        self.channel = DummyChannel()
        request = Request(self.channel, False)
        transport = WebSocketTransport(request)
        handler = TestHandler(transport)
        transport._attachHandler(handler)
        self.decoder = WebSocketFrameDecoder(request, handler)
        self.decoder.MAX_LENGTH = 100
        self.decoder.MAX_BINARY_LENGTH = 1000

    def assertOneDecodingError(self):
        """
        Assert that exactly one L{DecodingError} has been logged and return
        that error.
        """
        errors = self.flushLoggedErrors(DecodingError)
        self.assertEquals(len(errors), 1)
        return errors[0]

    def test_oneFrame(self):
        """
        We can send one frame handled with one C{dataReceived} call.
        """
        self.decoder.dataReceived("\x00frame\xff")
        self.assertEquals(self.decoder.handler.frames, ["frame"])

    def test_oneFrameSplitted(self):
        """
        A frame can be split into several C{dataReceived} calls, and will be
        combined again when sent to the C{WebSocketHandler}.
        """
        self.decoder.dataReceived("\x00fra")
        self.decoder.dataReceived("me\xff")
        self.assertEquals(self.decoder.handler.frames, ["frame"])

    def test_multipleFrames(self):
        """
        Several frames can be received in a single C{dataReceived} call.
        """
        self.decoder.dataReceived("\x00frame1\xff\x00frame2\xff")
        self.assertEquals(self.decoder.handler.frames, ["frame1", "frame2"])

    def test_missingNull(self):
        """
        If a frame not starting with C{\\x00} is received, the connection is
        dropped.
        """
        self.decoder.dataReceived("frame\xff")
        self.assertOneDecodingError()
        self.assertTrue(self.channel.transport.disconnected)

    def test_missingNullAfterGoodFrame(self):
        """
        If a frame not starting with C{\\x00} is received after a correct
        frame, the connection is dropped.
        """
        self.decoder.dataReceived("\x00frame\xfffoo")
        self.assertOneDecodingError()
        self.assertTrue(self.channel.transport.disconnected)
        self.assertEquals(self.decoder.handler.frames, ["frame"])

    def test_emptyReceive(self):
        """
        Received an empty string doesn't do anything.
        """
        self.decoder.dataReceived("")
        self.assertFalse(self.channel.transport.disconnected)

    def test_maxLength(self):
        """
        If a frame is received which is bigger than C{MAX_LENGTH}, the
        connection is dropped.
        """
        self.decoder.dataReceived("\x00" + "x" * 101)
        self.assertTrue(self.channel.transport.disconnected)

    def test_maxLengthFrameCompleted(self):
        """
        If a too big frame is received in several fragments, the connection is
        dropped.
        """
        self.decoder.dataReceived("\x00" + "x" * 90)
        self.decoder.dataReceived("x" * 11 + "\xff")
        self.assertTrue(self.channel.transport.disconnected)

    def test_frameLengthReset(self):
        """
        The length of frames is reset between frame, thus not creating an error
        when the accumulated length exceeds the maximum frame length.
        """
        for i in range(15):
            self.decoder.dataReceived("\x00" + "x" * 10 + "\xff")
        self.assertFalse(self.channel.transport.disconnected)

    def test_oneBinaryFrame(self):
        """
        A binary frame is parsed and ignored, the following text frame is
        delivered.
        """
        self.decoder.dataReceived("\xff\x0abinarydata\x00text frame\xff")
        self.assertEquals(self.decoder.handler.frames, ["text frame"])

    def test_multipleBinaryFrames(self):
        """
        Text frames intermingled with binary frames are parsed correctly.
        """
        tf1, tf2, tf3 = "\x00frame1\xff", "\x00frame2\xff", "\x00frame3\xff"
        bf1, bf2, bf3 = "\xff\x01X", "\xff\x1a" + "X" * 0x1a, "\xff\x02AB"

        self.decoder.dataReceived(tf1 + bf1 + bf2 + tf2 + tf3 + bf3)
        self.assertEquals(self.decoder.handler.frames,
                          ["frame1", "frame2", "frame3"])

    def test_binaryFrameMultipleLengthBytes(self):
        """
        A binary frame can have its length field spread across multiple bytes.
        """
        bf = "\xff\x81\x48" + "X" * 200
        tf = "\x00frame\xff"
        self.decoder.dataReceived(bf + tf + bf)
        self.assertEquals(self.decoder.handler.frames, ["frame"])

    def test_binaryAndTextSplitted(self):
        """
        Intermingled binary and text frames can be split across several
        C{dataReceived} calls.
        """
        tf1, tf2 = "\x00text\xff", "\x00other text\xff"
        bf1, bf2, bf3 = ("\xff\x01X", "\xff\x81\x48" + "X" * 200,
                         "\xff\x20" + "X" * 32)

        chunks = [
            bf1[0], bf1[1:], tf1[:2], tf1[2:] + bf2[:2], bf2[2:-2], bf2[-2:-1],
            bf2[1] + tf2[:-1], tf2[-1], bf3
        ]
        for c in chunks:
            self.decoder.dataReceived(c)

        self.assertEquals(self.decoder.handler.frames, ["text", "other text"])
        self.assertFalse(self.channel.transport.disconnected)

    def text_maxBinaryLength(self):
        """
        If a binary frame's declared length exceeds MAX_BINARY_LENGTH, the
        connection is dropped.
        """
        self.decoder.dataReceived("\xff\xff\xff\xff\xff\xff")
        self.assertTrue(self.channel.transport.disconnected)

    def test_closingHandshake(self):
        """
        After receiving the closing handshake, the server sends its own closing
        handshake and ignores all future data.
        """
        self.decoder.dataReceived("\x00frame\xff\xff\x00random crap")
        self.decoder.dataReceived("more random crap, that's discarded")
        self.assertEquals(self.decoder.handler.frames, ["frame"])
        self.assertTrue(self.decoder.closing)

    def test_invalidFrameType(self):
        """
        Frame types other than 0x00 and 0xff cause the connection to be
        dropped.
        """
        ok = "\x00ok\xff"
        wrong = "\x05foo\xff"

        self.decoder.dataReceived(ok + wrong + ok)
        self.assertEquals(self.decoder.handler.frames, ["ok"])
        error = self.assertOneDecodingError()
        self.assertTrue(self.channel.transport.disconnected)

    def test_emptyFrame(self):
        """
        An empty text frame is correctly parsed.
        """
        self.decoder.dataReceived("\x00\xff")
        self.assertEquals(self.decoder.handler.frames, [""])
        self.assertFalse(self.channel.transport.disconnected)