def make_message() -> bytes: pub_header = PublicHeader() pub_header.protocol_version = bytes(VERSION, 'ascii') pub_header.packet_number = 1 pub_header.connection_id = random.randint(0, 0xffffffffffffffff) chlo_msg = handshake.Message() chlo_msg.tag = b'CHLO' chlo_msg.tags = tags.Container({ 'VER': VERSION, 'PDMD': 'X509', 'PAD': b'\x00' * 1000 }) chlo_msg_buff = chlo_msg.to_bytes() stream_header = StreamFrameHeader() stream_header.id = 1 stream_header.has_data_length = True stream_header.data_length = len(chlo_msg_buff) # TODO: infer id length from id field. stream_header.id_length = 1 pub_header_buff = pub_header.to_bytes() stream_header_buff = stream_header.to_bytes() padding = b'\x00' * (1300 - (len(pub_header_buff) + 12 \ + len(stream_header_buff) + len(chlo_msg_buff))) packet_hash = fnv.hash(pub_header_buff + stream_header_buff + chlo_msg_buff + padding) return pub_header_buff + packet_hash.to_bytes(16, byteorder='little')[:12] \ + stream_header_buff + chlo_msg_buff + padding
def it_returns_bytes_array_with_tag_values_placed_after_tag_metainfo(): msg = handshake.Message() msg.tag = b'CHLO' msg.tags = tags.Container({'SNI': 'www.example.com'}) buff = msg.to_bytes() assert_that(buff[16:31], is_(b'www.example.com'))
def it_returns_bytes_array_which_includes_tag_count_with_padding(): msg = handshake.Message() msg.tag = b'CHLO' msg.tags = tags.Container({'tag1': 'val1'}) buff = msg.to_bytes() assert_that(buff[4:8], is_(b'\x01\x00\x00\x00'))
def it_returns_values_in_ascending_order_by_tag_name(): msg_tags = tags.Container() msg_tags['V'] = 'value1' msg_tags['P'] = 'value3' msg_tags['A'] = 'value2' stored_tag_values = [t for t in msg_tags.values()] assert_that(stored_tag_values, is_(['value2', 'value3', 'value1']))
def it_returns_keys_in_the_ascending_order_by_tag_name_int_value(): msg_tags = tags.Container() msg_tags['V'] = 'value1' msg_tags['P'] = 'value2' msg_tags['A'] = 'value3' stored_tags = [t for t in msg_tags.keys()] assert_that(stored_tags, is_([0x41, 0x50, 0x56]))
def it_returns_bytes_array_with_tag_names_and_data_offsets_placed_after_tag_count( ): msg = handshake.Message() msg.tag = b'CHLO' msg.tags = tags.Container({'SNI': 'www.example.com'}) buff = msg.to_bytes() assert_that(buff[8:12], is_(b'SNI\x00')) assert_that(buff[12:16], is_(b'\x0f\x00\x00\x00'))
def it_is_able_to_parse_message_serialized_with_to_bytes(): msg = handshake.Message() msg.tag = b'CHLO' msg.tags = tags.Container({'SNI': 'www.example.com', 'VER': 'Q034'}) deserialized_msg = decode_handshake_message(msg.to_bytes()) assert_that(deserialized_msg.tag, is_(b'CHLO')) assert_that(deserialized_msg.tags, has_entries({ 'SNI': b'www.example.com', 'VER': b'Q034' }))
def it_sets_tag_value_than_can_be_retrieved_later(): msg_tags = tags.Container() msg_tags['TAG1'] = 'value1' assert_that(msg_tags['TAG1'], is_('value1'))
def it_converts_dictionary_keys_into_ints_and_stores_the_values(): msg_tags = tags.Container({'1': 'value1', '2': 'value2'}) assert_that(msg_tags.items(), is_([(0x31, 'value1'), (0x32, 'value2')]))
def it_converts_string_keys_to_ints_in_little_endian_before_storing(): msg_tags = tags.Container() msg_tags['1234'] = 'value1' assert_that(msg_tags[0x34333231], is_('value1'))
def it_accepts_32_bit_ints_as_tag_values(): msg_tags = tags.Container() msg_tags[0x01020304] = 'value1' assert_that(msg_tags[0x01020304], is_('value1'))