def _socket_handler(self, conn, addr): conn.settimeout(1.0) buffer = b'' feeder = Feeder(conn) while not self.do_stop: try: command = None while command is None and not self.do_stop: command, buffer = feeder.feed(buffer) if command: logging.info("Command = %s", command) self._send_data_to_socket(conn, command.reply()) if type(command) in [Quit, QuitD]: conn.close() break elif type(command) == Finish: conn.close() self.do_stop = True break except socket.timeout: continue except OSError as msg: logging.error("OSError: %s", msg) self.stop_server() else: self._send_data_to_socket(conn, AckFinish().pack()) conn.close() self.threads.remove(threading.currentThread()) logging.info("Thread off conn=%s", conn)
def run_client(self, conn): feeder = Feeder(self.commands) tail = bytes() while True: try: chunk = tail + conn.recv(self.CHUNK_SIZE) packet, tail = feeder.feed(chunk) if not packet: continue process = getattr(self, packet.__class__.__name__.lower()) kwargs = {} kw_only = get_keyword_args(process) if 'conn' in kw_only: kwargs['conn'] = conn process(packet, **kwargs) except (socket.timeout, OSError): conn.close() self.clients.pop(conn, None) return
def run(self): self.feeder = Feeder(self.commands) while True: command = input().split() kwargs = {} cmd_input = getattr(cmd, command[0].upper()) if cmd_input == cmd.PINGD: kwargs['data'] = command[1] packet = eval('{}(**kwargs).pack()'.format(command[0])) self.socket.sendall(packet) self.recv_response()
class FeederTestCase(TestCase): def setUp(self): self.connection = Mock() self.feeder = Feeder(connection=self.connection) def test_empty_feed(self): self.connection.recv.return_value = b'' buffer = b'' self.assertEqual( (None, b''), self.feeder.feed(buffer) ) def test_packet(self): self.connection.recv.return_value = b'\x00\x00\x00\x011' buffer = b'' command, buffer = self.feeder.feed(buffer) self.assertEqual(b'', buffer) self.assertEqual(Ping, type(command)) self.assertEqual(PING, command.command) def test_packet_partly(self): self.connection.recv.return_value = b'\x00' buffer = b'' command, buffer = self.feeder.feed(buffer) self.assertEqual(b'\x00', buffer) self.assertEqual(None, command) self.connection.recv.return_value = b'\x00\x00\x01' command, buffer = self.feeder.feed(buffer) self.assertEqual(b'', buffer) self.assertEqual(None, command) self.connection.recv.return_value = b'1' command, buffer = self.feeder.feed(buffer) self.assertEqual(b'', buffer) self.assertEqual(Ping, type(command)) self.assertEqual(PING, command.command) def test_two_packets(self): self.connection.recv.return_value = b'\x00\x00\x00\x011\x00' buffer = b'' command, buffer = self.feeder.feed(buffer) self.assertEqual(b'\x00', buffer) self.assertEqual(Ping, type(command)) self.assertEqual(PING, command.command) self.connection.recv.return_value = b'\x00\x00\x012' command, buffer = self.feeder.feed(buffer) self.assertEqual(b'', buffer) self.assertEqual(PingD, type(command)) self.assertEqual(PINGD, command.command) def test_packet_with_data(self): self.connection.recv.return_value = b'\x00\x00\x00\x0C2hello world' buffer = b'' command, buffer = self.feeder.feed(buffer) self.assertEqual(b'', buffer) self.assertEqual(PingD, type(command)) self.assertEqual(PINGD, command.command) self.assertEqual('hello world', command.data)
def setUp(self): self.connection = Mock() self.feeder = Feeder(connection=self.connection)
class CommandClient: session_id = None TIMEOUT = 1.0 CHUNK_SIZE = 1024 commands = [cmd.CONNECTED, cmd.PONG, cmd.PONGD, cmd.ACKQUIT, cmd.ACKFINISH] def __init__(self, host, port): self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.socket.settimeout(self.TIMEOUT) self.socket.connect((host, port)) @classmethod def run_client(cls, host, port): client = cls(host, port) try: handler = signal.signal(signal.SIGINT, shutdown_handler) client.run() except (OSError, socket.timeout, ClientFinishException): client.shutdown() finally: signal.signal(signal.SIGINT, handler) def run(self): self.feeder = Feeder(self.commands) while True: command = input().split() kwargs = {} cmd_input = getattr(cmd, command[0].upper()) if cmd_input == cmd.PINGD: kwargs['data'] = command[1] packet = eval('{}(**kwargs).pack()'.format(command[0])) self.socket.sendall(packet) self.recv_response() def recv_response(self): tail = bytes() while True: chunk = tail + self.socket.recv(self.CHUNK_SIZE) packet, tail = self.feeder.feed(chunk) if not packet: continue else: getattr(self, packet.__class__.__name__.lower())(packet) break def connected(self, packet): self.session = packet.session print('{} {}'.format(packet.cmd, packet.session)) def pong(self, packet): print(packet.cmd) def pongd(self, packet): print('{} {}'.format(packet.cmd, packet.data)) def ackquit(self, packet): print('{} {}'.format(packet.cmd, packet.session)) self.shutdown() def ackfinish(self, packet): print(packet.cmd) self.shutdown() def shutdown(self): self.socket.close() logging.info('socket closed') raise SystemExit()