class PTCServerProtocol(object): def __init__(self, address, port): self.state = CLOSED self.control_block = ServerControlBlock(address, port) self.socket = Soquete(address, port) self.packet_builder = PacketBuilder(self) self.connection_closed_event = threading.Event() def is_connected(self): return self.state == ESTABLISHED def is_closed(self): return self.state == CLOSED def build_packet(self, flags=None): ack = self.control_block.get_receive_seq() packet = self.packet_builder.build(flags=flags, ack=ack) return packet def send_packet(self, packet): self.socket.send(packet) def receive(self, size): if self.is_closed() and self.incoming_buffer.empty(): raise Exception('cannot receive: connection ended and no more pending data buffered') elif self.incoming_buffer.empty() and not self.is_connected(): raise Exception('cannot receive: connection not established') if size < MIN_PACKET_SIZE: size = MIN_PACKET_SIZE data = self.incoming_buffer.sync_get(MIN_PACKET_SIZE, size) return data def accept(self): self.incoming_buffer = DataBuffer() self.state = CLOSED self.worker = ServerProtocolWorker.spawn_for(self) self.worker.start() # No hay mucho por hacer... simplemente esperar a que caiga el SYN del cliente self.connected_event = threading.Event() self.connected_event.wait() def handle_incoming(self, packet): seq_number = packet.get_seq_number() if DEBUG: print 'recibi el paquete numero', seq_number if SYNFlag in packet: self.control_block.set_destination_address(packet.get_source_ip()) self.control_block.set_destination_port(packet.get_source_port()) self.control_block.set_receive_seq(seq_number) ack_packet = self.build_packet(flags=[ACKFlag]) self.send_packet(ack_packet) self.control_block.set_receive_seq(seq_number) self.control_block.increment_receive_seq() self.state = ESTABLISHED self.connected_event.set() if DEBUG: print 'server established' if FINFlag in packet: if self.control_block.accepts(seq_number): if DEBUG: print 'server ended' self.state = FIN_RECEIVED self.send_ack() self.close() else: data = packet.get_payload() if DEBUG: print 'recibí un paquete con esta data:', data if self.control_block.accepts(seq_number) and data: self.incoming_buffer.put(data) if self.state != FIN_RECEIVED: self.send_ack() self.control_block.increment_receive_seq() def send_ack(self): ack_packet = self.build_packet(flags=[ACKFlag]) self.send_packet(ack_packet) def shutdown(self): self.worker.stop() # Esto es por si falló el establecimiento de conexión (para destrabar al thread principal) self.connected_event.set() def close(self): self.state = CLOSED self.connection_closed_event.set() def wait_for_close(self): self.connection_closed_event.wait()
class PTCServerProtocol(object): def __init__(self, address, port): self.state = CLOSED self.control_block = ServerControlBlock(address, port) self.socket = Soquete(address, port) self.packet_builder = PacketBuilder(self) self.connection_closed_event = threading.Event() def is_connected(self): return self.state == ESTABLISHED def is_closed(self): return self.state == CLOSED def build_packet(self, flags=None): ack = self.control_block.get_receive_seq() packet = self.packet_builder.build(flags=flags, ack=ack) return packet def send_packet(self, packet): self.socket.send(packet) def receive(self, size): if self.is_closed() and self.incoming_buffer.empty(): raise Exception('cannot receive: connection ended and no more pending data buffered') elif self.incoming_buffer.empty() and not self.is_connected(): raise Exception('cannot receive: connection not established') if size < MIN_PACKET_SIZE: size = MIN_PACKET_SIZE data = self.incoming_buffer.sync_get(MIN_PACKET_SIZE, size) return data def accept(self): self.incoming_buffer = DataBuffer() self.state = CLOSED self.worker = ServerProtocolWorker.spawn_for(self) self.worker.start() # No hay mucho por hacer... simplemente esperar a que caiga el SYN del cliente self.connected_event = threading.Event() self.connected_event.wait() def handle_incoming(self, packet): seq_number = packet.get_seq_number() if(debug): print ("Recibi el paquete numero: "), print (seq_number) if SYNFlag in packet: self.control_block.set_destination_address(packet.get_source_ip()) self.control_block.set_destination_port(packet.get_source_port()) self.control_block.set_receive_seq(seq_number) ack_packet = self.build_packet(flags=[ACKFlag]) self.send_packet(ack_packet) self.control_block.set_receive_seq(seq_number) self.control_block.increment_receive_seq() self.state = ESTABLISHED self.connected_event.set() if FINFlag in packet: if self.control_block.accepts(seq_number): self.state = FIN_RECEIVED self.send_ack() self.close() else: data = packet.get_payload() if self.control_block.accepts(seq_number) and data: self.incoming_buffer.put(data) if self.state != FIN_RECEIVED: self.send_ack() self.control_block.increment_receive_seq() def send_ack(self): ack_packet = self.build_packet(flags=[ACKFlag]) self.send_packet(ack_packet) def shutdown(self): self.worker.stop() # Esto es por si falló el establecimiento de conexión (para destrabar al thread principal) self.connected_event.set() def close(self): self.state = CLOSED self.connection_closed_event.set() def wait_for_close(self): self.connection_closed_event.wait()