def socket_handler(listener): sock = listener.accept()[0] # Dispose of the first two packets. sock.recv(65535) sock.recv(65535) # Send a Settings frame that reduces the flow-control window to # 64 bytes. f = SettingsFrame(0) f.settings[SettingsFrame.INITIAL_WINDOW_SIZE] = 64 sock.send(f.serialize()) # Grab three frames, the settings ACK, the initial headers frame, # and the first data frame. for x in range(0, 3): data.append(sock.recv(65535)) # Send a WindowUpdate giving more window room to the stream. f = WindowUpdateFrame(1) f.window_increment = 64 sock.send(f.serialize()) # Send one that gives more room to the connection. f = WindowUpdateFrame(0) f.window_increment = 64 sock.send(f.serialize()) # Reeive the remaining frame. data.append(sock.recv(65535)) send_event.set() # We're done. sock.close()
def _send_preamble(self): self._sock.send(b'PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n') f = SettingsFrame(0) f.settings[SettingsFrame.ENABLE_PUSH] = 0 f.settings[SettingsFrame.INITIAL_WINDOW_SIZE] = self.local_settings[SettingsFrame.INITIAL_WINDOW_SIZE] f.settings[SettingsFrame.SETTINGS_MAX_FRAME_SIZE] = self.local_settings[SettingsFrame.SETTINGS_MAX_FRAME_SIZE] self._send_cb(f) # update local connection windows size f = WindowUpdateFrame(0) f.window_increment = self.local_connection_initial_windows - DEFAULT_WINDOW_SIZE self._send_cb(f)
def receive_frame(self, frame): if frame.type == WindowUpdateFrame.type: # self.logger.debug("WindowUpdateFrame %d", frame.window_increment) self.increase_remote_window_size(frame.window_increment) elif frame.type == PingFrame.type: if 'ACK' in frame.flags: ping_time = struct.unpack("!d", frame.opaque_data)[0] time_now = time.time() rtt = (time_now - ping_time) * 1000 if rtt < 0: self.logger.error("rtt:%f ping_time:%f now:%f", rtt, ping_time, time_now) self.rtt = rtt self.ping_on_way -= 1 #self.logger.debug("RTT:%d, on_way:%d", self.rtt, self.ping_on_way) if self.keep_running and self.ping_on_way == 0: self.accept_task = True else: # The spec requires us to reply with PING+ACK and identical data. p = PingFrame(0) p.flags.add('ACK') p.opaque_data = frame.opaque_data self._send_cb(p) elif frame.type == SettingsFrame.type: if 'ACK' not in frame.flags: # send ACK as soon as possible f = SettingsFrame(0) f.flags.add('ACK') self._send_cb(f) # this may trigger send DataFrame blocked by remote window self._update_settings(frame) else: self.accept_task = True self.idle_cb() elif frame.type == GoAwayFrame.type: # If we get GoAway with error code zero, we are doing a graceful # shutdown and all is well. Otherwise, throw an exception. # If an error occured, try to read the error description from # code registry otherwise use the frame's additional data. error_string = frame._extra_info() time_cost = time.time() - self.last_recv_time if frame.additional_data != "session_timed_out": self.logger.warn("goaway:%s, t:%d", error_string, time_cost) self.close("GoAway:%s inactive time:%d" % (error_string, time_cost)) elif frame.type == BlockedFrame.type: self.logger.warn("%s get BlockedFrame", self.ip_str) elif frame.type in FRAMES: # This frame isn't valid at this point. #raise ValueError("Unexpected frame %s." % frame) self.logger.error("%s Unexpected frame %s.", self.ip_str, frame) else: # pragma: no cover # Unexpected frames belong to extensions. Just drop it on the # floor, but log so that users know that something happened. self.logger.error("%s Received unknown frame, type %d", self.ip_str, frame.type)
def socket_handler(listener): sock = listener.accept()[0] # We should get two packets: one connection header string, one # SettingsFrame. first = sock.recv(65535) second = sock.recv(65535) data.append(first) data.append(second) # We need to send back a SettingsFrame. f = SettingsFrame(0) sock.send(f.serialize()) send_event.wait() sock.close()
def test_receive_unexpected_frame(self): # SETTINGS frames are never defined on streams, so send one of those. s = Stream(1, None, None, None, None, None, None) f = SettingsFrame(0) with pytest.raises(ValueError): s.receive_frame(f)
def receive_preamble(sock): # Receive the HTTP/2 'preamble'. first = sock.recv(65535) # Work around some bugs: if the first message received was only the PRI # string, aim to receive a settings frame as well. if len(first) <= len(b'PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n'): sock.recv(65535) sock.send(SettingsFrame(0).serialize()) sock.recv(65535) return
def test_send_tolerate_peer_gone(self): class ErrorSocket(DummySocket): def send(self, data): raise socket.error(errno.EPIPE) c = HTTP20Connection('www.google.com') c._sock = ErrorSocket() f = SettingsFrame(0) with pytest.raises(socket.error): c._send_cb(f, False) c._sock = DummySocket() c._send_cb(f, True) # shouldn't raise an error
def test_connections_handle_resizing_header_tables_properly(self): sock = DummySocket() f = SettingsFrame(0) f.settings[SettingsFrame.HEADER_TABLE_SIZE] = 1024 c = HTTP20Connection('www.google.com') c._sock = sock # 'Receive' the SETTINGS frame. c.receive_frame(f) # Confirm that the setting is stored and the header table shrunk. assert c._settings[SettingsFrame.HEADER_TABLE_SIZE] == 1024 # Confirm we got a SETTINGS ACK. f2 = decode_frame(sock.queue[0]) assert isinstance(f2, SettingsFrame) assert f2.stream_id == 0 assert f2.flags == set(['ACK'])