def test_frame_data(): frame = Frame() try: frame.data = bytearray(Frame.FRAME_MAX_SIZE) + 1 # test over-byte except Exception: pass else: assert 0 # passed over byte frame.data = b'\xFF\xFF' + bytearray(Frame.FRAME_MIN_SIZE) frame.id = 0x0 frame_bin = frame.get_frame_bin() assert frame_bin[0] << 16 | frame_bin[1] << 8 | frame_bin[2] << 0 == len(frame.data) # type is 0 assert frame_bin[3] == 0 # flag is 0 assert frame_bin[4] == 0 assert frame_bin[5] << 24 | frame_bin[6] << 16 | frame_bin[7] << 8 | frame_bin[8] << 0 == 0x0 # check payload assert frame_bin[9:] == b'\xFF\xFF' + bytearray(Frame.FRAME_MIN_SIZE)
def get_frame_bin(self): # Encode header encoder = Encoder() headers_frame_field = bytearray() if self._data is None: # if user didn't touch data self._data = encoder.encode(self._header_list) # encode header list self._flag = self.flag # get flag by method if self._is_padded: headers_frame_field.append(self._pad_len) # append pad length self._data += bytearray(self._pad_len) # append pad byte in pad length headers_frame_field += int_to_bytes(self.promised_stream_id, 4) # append promised stream id self._data = headers_frame_field + self._data # append HEADERS field print('push promise data', Frame.get_frame_bin(self)) return Frame.get_frame_bin(self)
def test_malform_frame_data(): try: Frame.load(b'\x00\x00\x02\x04\x00\x00\x00\x00\x00') # frame length is 2 but real size is 0 except: pass else: assert 0 # Exception was not raised
def __init__(self, id, end_stream=False): self.is_end_stream = end_stream self._is_padded = False Frame.__init__(self, type=FrameType.DATA, flag=0x0, id=id)
def test_malform_setting_frame_data(): try: # setting value is not 4 byte Frame.load(b'\x00\x00\x04\x04\x00\x00\x00\x00\x00\x00\x01\x00\x00\x01') except: pass else: assert 0 # Exception was not raised
def __init__(self, id, header_list=[], end_header=True, end_stream=False): self.is_end_stream = end_stream self.is_end_header = end_header self._is_priority = False self._is_padded = False self._header_list = header_list # http header list self._encoded_data = None Frame.__init__(self, type=FrameType.HEADERS, flag=0x0, id=id, data=None)
def __init__(self, id, header_list=[], end_header=True): self.is_end_header = end_header self._is_priority = False self._is_padded = False self._header_list = header_list # http header list self._encoded_data = None self.promised_stream_id = 0x0 # default Frame.__init__(self, type=FrameType.PUSH_PROMISE, flag=0x0, id=id, data=None)
def get_frame_bin(self): # Encode header encoder = Encoder() headers_frame_field = bytearray() if self._data is None: # if user didn't touch data self._data = encoder.encode(self._header_list) # encode header list self._flag = self.flag # get flag by method if self._is_padded: headers_frame_field.append(self._pad_len) # append pad length self._data += bytearray(self._pad_len) # append pad byte in pad length if self._is_priority: headers_frame_field += int_to_bytes(self._dependency_id, 4) # append dependency stream id headers_frame_field.append(self._weight) self._data = headers_frame_field + self._data # append HEADERS field return Frame.get_frame_bin(self)
def test_chrom_refresh_frame_data(): frame_data = b'\x00\x00\x1e\x01%\x00\x00\x00\x07\x00\x00\x00\x00\xb6\xc7\x82\x00\x84\xb9X\xd3?\x89bQ\xf71\x0fR\xe6!\xff\x87\xbf\xc5\xc4\xc2\xbe\xc0' frame = Frame.load(frame_data) print(frame)
def test_header_frame_data(): frame = HeaderFrame(id=0x0201) frame.method = "GET" frame.scheme = 'https' frame.path = '/' frame.add('host', 'localhost') frame.add('accept', 'text/html') assert frame.type == FrameType.HEADERS read_frame = Frame.load(frame.get_frame_bin()) assert read_frame.method == "GET" assert read_frame.scheme == "https" assert read_frame.path == "/" assert read_frame.get('host') == "localhost" assert read_frame.get('accept') == "text/html"
def parse_http2_request(self): self.raw_requestdata = self.connection.read(9) frame_header = Frame.parse_header(self.raw_requestdata) frm_len, frm_type, frm_flag, frm_id = frame_header while frm_len + 9 > len(self.raw_requestdata): self.raw_requestdata += self.connection.read(frm_len - len(self.raw_requestdata) + 9) # read left data stream = self.http2_connection.get_stream(frm_id) stream.receive_frame(frame_header, self.raw_requestdata) if stream.is_wait_for_res: print('end stream id : ', stream.id, ' frm_id ', frm_id) self.headers = stream._client_headers # self.request_version = 'HTTP/2.0' always self.requestline = stream.method + ' ' + stream.path + ' HTTP/2.0' # virtual request line self.path = stream.path self.command = stream.method self.response_stream = stream self.stream = stream return True # handle one request return False
def get_frame_bin(self): if self._data is None and not self.is_ack: # If user didn't set data self._data = bytearray() for setting in self._setting_list: # set identifier 16 bit self._data.append((setting[0] & 0x0000FF00) >> 8) self._data.append((setting[0] & 0x000000FF) >> 0) # set value 32 bit self._data.append((setting[1] & 0xFF000000) >> 24) self._data.append((setting[1] & 0x00FF0000) >> 16) self._data.append((setting[1] & 0x0000FF00) >> 8) self._data.append((setting[1] & 0x000000FF) >> 0) elif self.is_ack: # if ACK SETTINGS frame clear payload self._data = bytearray() self._flag = SettingFrame.ACK_FLAG # call super get_frame_bin return Frame.get_frame_bin(self)
def get_frame_bin(self): if self._data is None: # if user didn't touch data self._data = bytearray() self._data += int_to_bytes(self._dependency_id) # append dependency stream id self._data.append(self._weight) return Frame.get_frame_bin(self)
def test_multiple_header_frame_data(): encoded_frames = [] frame = HeaderFrame(id=0x0201, end_header=False) frame.method = "GET" frame.scheme = 'https' frame.path = '/' assert frame.type == FrameType.HEADERS encoded_frames.append(Frame.load(frame.get_frame_bin())) assert encoded_frames[0].is_encoded second_frame = HeaderFrame(id=0x0201, end_header=False) second_frame.add('host', 'localhost') second_frame.add('accept', 'text/html') encoded_frames.append(Frame.load(second_frame.get_frame_bin())) last_frame = HeaderFrame(id=0x0201, end_header=True) last_frame.add('accept-language', 'ko') read_frame = Frame.load(last_frame.get_frame_bin(), None, encoded_frames) assert read_frame.method == "GET" assert read_frame.scheme == "https" assert read_frame.path == "/" assert read_frame.get('host') == "localhost" assert read_frame.get('accept') == "text/html" assert read_frame.get('accept-language') == "ko"
def test_data_frame_data(): frame = DataFrame(id=0x0201) # set data as default html format frame.set_text(u'<html><heade></heade><body></body></html>', 'utf-8') assert frame.type == FrameType.DATA read_frame = Frame.load(frame.get_frame_bin()) assert read_frame.data == frame.data # check is same data
def test_padded_data_frame_data(): frame = DataFrame(id=0x0201) # set data as default html format data = u'<html><heade></heade><body></body></html>' frame.set_text(data, 'utf-8') frame.padding(10) assert frame.type == FrameType.DATA read_frame = Frame.load(frame.get_frame_bin()) assert read_frame.data == data.encode('utf-8') # check is same data
def receive_frame(self, frame_header, frame_raw): try: frame = Frame.load(frame_raw, frame_header, decoder=self.connection.decoder) if isinstance(frame, HeaderFrame): self._last_header_raw = frame.data # get payload of frame raw self._client_headers = frame.get_all() self.state = StreamState.OPEN # if header recv, open stream if frame.is_end_header: self.is_end_header = frame.is_end_header print('is_end_stream ', frame.is_end_stream) elif isinstance(frame, DataFrame): # TODO : need test self.req_stream_io.write(frame.data) print('is_end_stream ', frame.is_end_stream) else: # ignore unknow frame return False if not isinstance(frame, PriorityFrame): # priority frame always be able to recieved if self.state == StreamState.HALF_CLOSED_REMOTE: if not(isinstance(frame.RSTFrame)): # or TODO: WINDOW_UPDATE raise ProtocolError() elif self.state == StreamState.CLOSED: if not(isinstance(frame.RSTFrame)): # or TODO: WINDOW_UPDATE raise ProtocolError() elif time() - self._closed_time > 1: # if these streams are recv after 1 sec raise ProtocolError() if hasattr(frame, 'is_end_stream') and frame.is_end_stream: # stream that can change state if self.state == StreamState.HALF_CLOSED_LOCAL: self.close() elif self.state == StreamState.OPEN: self.state = StreamState.HALF_CLOSED_REMOTE else: # it would not be occured raise ProtocolError() if isinstance(frame, RSTFrame): self.close() except: raise ProtocolError() # unknow exception occur protocol error return False return True
def test_ack_setting_frame(): frame = SettingFrame(is_ack=True) try: frame.set(SettingFrame.SETTINGS_HEADER_TABLE_SIZE, 100) except: pass else: assert 0 # Exception was not raised read_frame = Frame.load(frame.get_frame_bin()) assert read_frame.is_ack
def test_setting_frame_data(): frame = SettingFrame() frame.set(SettingFrame.SETTINGS_HEADER_TABLE_SIZE, 100) frame.set(SettingFrame.SETTINGS_ENABLE_PUSH, 1) assert frame.type == FrameType.SETTINGS read_frame = Frame.load(frame.get_frame_bin()) assert read_frame.get(SettingFrame.SETTINGS_HEADER_TABLE_SIZE) == 100 assert read_frame.get(SettingFrame.SETTINGS_ENABLE_PUSH) == 1
def get_frame_bin(self): headers_frame_field = bytearray() if self._data is None: self._data = bytearray() # check for safe self._flag = self.flag # get flag by method if self._is_padded: headers_frame_field.append(self._pad_len) # append pad length self._data += bytearray(self._pad_len) # append pad byte in pad length self._data = headers_frame_field + self._data # append HEADERS field return Frame.get_frame_bin(self)
def __init__(self, is_ack=False): self._setting_list = [] self.is_ack = is_ack # is frame ACK SETTINGS frame Frame.__init__(self, type=FrameType.SETTINGS, flag=0x0, id=0x0, data=None)
def __init__(self, id, dep_stream_id, weight): self._dependency_id = dep_stream_id self._weight = weight Frame.__init__(self, type=FrameType.PRIORITY, flag=0x0, id=id, data=None)