示例#1
0
def create_length_header(length, mask):
    """Creates a length header.

    Args:
        length: Frame length. Must be less than 2^63.
        mask: Mask bit. Must be boolean.

    Raises:
        ValueError: when bad data is given.
    """

    if mask:
        mask_bit = 1 << 7
    else:
        mask_bit = 0

    if length < 0:
        raise ValueError('length must be non negative integer')
    elif length <= 125:
        return util.pack_byte(mask_bit | length)
    elif length < (1 << 16):
        return util.pack_byte(mask_bit | 126) + struct.pack('!H', length)
    elif length < (1 << 63):
        return util.pack_byte(mask_bit | 127) + struct.pack('!Q', length)
    else:
        raise ValueError('Payload is too big for one frame')
def web_socket_transfer_data(request):
    match = re.search(r'\?case=(\d+_\d+)$', request.ws_resource)
    if match is None:
        msgutil.send_message(request,
                             'FAIL: Query value is incorrect or missing')
        return

    payload_length, extended_length = (match.group(1)).split('_', 1)
    payload_length = int(payload_length)
    extended_length = int(extended_length)

    # pywebsocket refuses to create a frame with error encode length.
    # Thus, we need to build a frame manually.
    header = util.pack_byte(0x80
                            | common.OPCODE_TEXT)  # 0x80 is for "fin" bit.
    # No Mask and two bytes extended payload length.
    header += util.pack_byte(payload_length)
    if payload_length == 126:
        header += struct.pack('!H', extended_length)
    elif payload_length == 127:
        header += struct.pack('!Q', extended_length)
    else:
        msgutil.send_message(request,
                             'FAIL: Query value is incorrect or missing')
        return
    request.connection.write(header)
    request.connection.write(b'X' * extended_length)
    def _build_close_frame(self, code, reason, mask):
        frame = util.pack_byte(1 << 7 | OPCODE_CLOSE)

        if code is not None:
            body = struct.pack('!H', code) + reason.encode('utf-8')
        else:
            body = b''
        if mask:
            frame += util.pack_byte(1 << 7 | len(body)) + self._mask_hybi(body)
        else:
            frame += util.pack_byte(len(body)) + body
        return frame
示例#4
0
def create_header(opcode, payload_length, fin, rsv1, rsv2, rsv3, mask):
    """Creates a frame header.

    Raises:
        Exception: when bad data is given.
    """

    if opcode < 0 or 0xf < opcode:
        raise ValueError('Opcode out of range')

    if payload_length < 0 or (1 << 63) <= payload_length:
        raise ValueError('payload_length out of range')

    if (fin | rsv1 | rsv2 | rsv3) & ~1:
        raise ValueError('FIN bit and Reserved bit parameter must be 0 or 1')

    header = b''

    first_byte = ((fin << 7)
                  | (rsv1 << 6) | (rsv2 << 5) | (rsv3 << 4)
                  | opcode)
    header += util.pack_byte(first_byte)
    header += create_length_header(payload_length, mask)

    return header
示例#5
0
def web_socket_transfer_data(request):
    length = 0x8000000000000000

    # pywebsocket refuses to send a frame with too long payload.
    # Thus, we need to build a frame manually.
    header = util.pack_byte(0x80
                            | common.OPCODE_TEXT)  # 0x80 is for "fin" bit.
    header += util.pack_byte(127)
    header += struct.pack('!Q', length)
    request.connection.write(header)

    # Send data indefinitely to simulate a real (broken) server sending a big
    # frame. A client should ignore these bytes and abort the connection.
    while True:
        request.connection.write(b'X' * 4096)
        time.sleep(1)
    def send_data(self,
                  payload,
                  frame_type,
                  end=True,
                  mask=True,
                  rsv1=0,
                  rsv2=0,
                  rsv3=0):
        if self._outgoing_frame_filter is not None:
            payload = self._outgoing_frame_filter.filter(payload)

        if self._fragmented:
            opcode = OPCODE_CONTINUATION
        else:
            opcode = frame_type

        if end:
            self._fragmented = False
            fin = 1
        else:
            self._fragmented = True
            fin = 0

        if mask:
            mask_bit = 1 << 7
        else:
            mask_bit = 0

        header = util.pack_byte(fin << 7 | rsv1 << 6 | rsv2 << 5 | rsv3 << 4
                                | opcode)
        payload_length = len(payload)
        if payload_length <= 125:
            header += util.pack_byte(mask_bit | payload_length)
        elif payload_length < 1 << 16:
            header += util.pack_byte(mask_bit | 126) + struct.pack(
                '!H', payload_length)
        elif payload_length < 1 << 63:
            header += util.pack_byte(mask_bit | 127) + struct.pack(
                '!Q', payload_length)
        else:
            raise Exception('Too long payload (%d byte)' % payload_length)
        if mask:
            payload = self._mask_hybi(payload)
        self._socket.sendall(header + payload)
 def _mask_hybi(self, s):
     # TODO(tyoshino): os.urandom does open/read/close for every call. If
     # performance matters, change this to some library call that generates
     # cryptographically secure pseudo random number sequence.
     masking_nonce = os.urandom(4)
     result = [masking_nonce]
     count = 0
     for c in iterbytes(s):
         result.append(util.pack_byte(c ^ indexbytes(masking_nonce, count)))
         count = (count + 1) % len(masking_nonce)
     return b''.join(result)
示例#8
0
    def test_mask_large_data(self):
        masker = util.RepeatedXorMasker(b'mASk')
        original = b''.join([util.pack_byte(i % 256) for i in range(1000)])
        result = masker.mask(original)
        expected = b''.join([
            util.pack_byte((i % 256) ^ ord('mASk'[i % 4])) for i in range(1000)
        ])
        self.assertEqual(expected, result)

        masker = util.RepeatedXorMasker(b'MaSk')
        first_part = b'The WebSocket Protocol enables two-way communication.'
        result = masker.mask(first_part)
        self.assertEqual(
            b'\x19\t6K\x1a\x0418"\x028\x0e9A\x03\x19"\x15<\x08"\rs\x0e#'
            b'\x001\x07(\x12s\x1f:\x0e~\x1c,\x18s\x08"\x0c>\x1e#\x080\n9'
            b'\x08<\x05c', result)
        second_part = b'It has two parts: a handshake and the data transfer.'
        result = masker.mask(second_part)
        self.assertEqual(
            b"('K%\x00 K9\x16<K=\x00!\x1f>[s\nm\t2\x05)\x12;\n&\x04s\n#"
            b"\x05s\x1f%\x04s\x0f,\x152K9\x132\x05>\x076\x19c", result)
def web_socket_transfer_data(request):
    # pyformat: disable
    messages_to_send = [[b'Hello, ', b'world!'],
                        [b'', b'Hello, ', b'', b'world!',
                         b''], [b'', b'', b''],
                        [util.pack_byte(i) for i in range(256)]]
    # pyformat: enable
    for message_list in messages_to_send:
        for index, message in enumerate(message_list):
            # FIXME: Should use better API to send binary messages when
            # pywebsocket supports it.
            if index == 0:
                opcode = common.OPCODE_BINARY
            else:
                opcode = common.OPCODE_CONTINUATION
            if index < len(message_list) - 1:
                final = 0
            else:
                final = 1
            header = stream.create_header(opcode, len(message), final, 0, 0, 0,
                                          0)
            request.connection.write(header + message)
def all_distinct_bytes():
    return b''.join([util.pack_byte(i) for i in range(256)])