def main(): game_network, result = game(hacker, zardus) if result == WIN: chat_network = chat(zardus, adamd) stop([game_network, chat_network]) else: stop([game_network])
def handle_closed(ops): try: connection: Connection = Connection.connection_list[ops.connection_id] shim_print(f"HANDLE CLOSED - connection {ops.connection_id}") if connection.HANDLE_STATE_CLOSED: connection.HANDLE_STATE_CLOSED(connection) # If a Connection becomes finished before a requested Receive action can be satisfied, # the implementation should deliver any partial Message content outstanding..." if connection.receive_request_queue: if connection.buffered_message_data_object: handler, min_length, max_length = connection.receive_request_queue.pop(0) shim_print("Dispatching received partial as connection is closing and there is buffered data") message_context = MessageContext() handler(connection, connection.buffered_message_data_object, message_context, True, None) # "...or if none is available, an indication that there will be no more received Messages." else: shim_print("Connection closed, there will be no more received messages") # TODO: Should this be thrown as an error (error event?) #if connection.connection_type == 'active': # should check if there is any cloned connections etc... # backend.stop(ops.ctx) except: shim_print("An error occurred in the Python callback: {} - {}".format(sys.exc_info()[0], inspect.currentframe().f_code.co_name), level='error') backend.stop(ops.ctx) return NEAT_OK
def handle_all_written(ops): try: close = False connection = Connection.connection_list[ops.connection_id] shim_print(f"ALL WRITTEN - connection {ops.connection_id}") if not connection.messages_passed_to_back_end: return NEAT_OK message, message_context, handler = connection.messages_passed_to_back_end.pop(0) if handler: handler(connection, None) if connection.close_called and len(connection.messages_passed_to_back_end) == 0: shim_print("All messages passed down to the network layer - calling close") close = True elif message_context.props[MessageProperties.FINAL] is True: shim_print("Message marked final has been completely sent, closing connection / sending FIN") close = True if close: neat_close(connection.__ops.ctx, connection.__ops.flow) except: shim_print("An error occurred: {}".format(sys.exc_info()[0])) backend.stop(ops.ctx) return NEAT_OK
def received_called(ops): try: ops.on_readable = handle_readable neat_set_operations(ops.ctx, ops.flow, ops) except: shim_print("An error occurred in the Python callback: {} - {}".format(sys.exc_info()[0], inspect.currentframe().f_code.co_name), level='error') backend.stop(ops.ctx) return NEAT_OK
def handle_writable(ops): try: connection: Connection = Connection.connection_list[ops.connection_id] shim_print(f"ON WRITABLE CALLBACK - connection {connection.connection_id}") # Socket is writable, write if any messages passed to the transport system if not connection.msg_list.empty(): # Todo: Should we do coalescing of batch sends here? message_to_be_sent, context, handler, expired_epoch = connection.msg_list.get().item # If lifetime was set, check if send action has expired if expired_epoch and expired_epoch < int(time.time()): shim_print("""Send action expired: Expired: {} - Now: {}""".format(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(expired_epoch)), time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(int(time.time())))), level='error') handler(connection, SendErrorReason.MESSAGE_TIMEOUT) return NEAT_OK neat_result = backend.write(ops, message_to_be_sent) if neat_result: if neat_result == NEAT_ERROR_MESSAGE_TOO_BIG: reason = SendErrorReason.MESSAGE_TOO_LARGE elif neat_result == NEAT_ERROR_IO: reason = SendErrorReason.FAILURE_UNDERLYING_STACK shim_print(f"SendError - {reason.value}") handler(connection, reason) return # Keep message until NEAT confirms sending with all_written connection.messages_passed_to_back_end.append((message_to_be_sent, context, handler)) else: pass shim_print("WHAT") ops.on_writable = None neat_set_operations(ops.ctx, ops.flow, ops) return NEAT_OK except: shim_print("An error occurred in the Python callback: {} - {}".format(sys.exc_info()[0], inspect.currentframe().f_code.co_name), level='error') backend.stop(ops.ctx) return NEAT_OK
def clone(self, clone_error_handler: Callable[['Connection'], None]) -> None: """Calling Clone on a Connection yields a group of two Connections: the parent Connection on which Clone was called, and the resulting cloned Connection. These connections are "entangled" with each other, and become part of a Connection Group. Calling Clone on any of these two Connections adds a third Connection to the Connection Group, and so on. Connections in a Connection Group generally share :py:class:`connection_properties`. However, there are exceptions, such as the priority property, which obviously will not trigger a change for all connections in the connection group. As with all other properties, priority is copied to the new Connection when calling Clone(). :param clone_error_handler: A function to handle the event which fires when the cloning operation fails. The connection which clone was called on is sent with the handler. """ try: shim_print("CLONE") # NEAT boilerplate flow = neat_new_flow(self.context) ops = neat_flow_operations() # Create new connection and register eventual error_handler new_connection = Connection(self.preconnection, 'active', parent=self) new_connection.clone_error_handler = clone_error_handler # Set connection id for the new clone in the operations struct ops.connection_id = new_connection.connection_id # Set callbacks to properly handle clone establishment / error ops.on_error = on_clone_error ops.on_connected = handle_clone_ready neat_set_operations(self.context, flow, ops) backend.pass_candidates_to_back_end([self.transport_stack], self.context, flow) # Asynchronously call NEAT to create a new connection neat_open(self.context, flow, self.preconnection.remote_endpoint.address, self.preconnection.remote_endpoint.port, None, 0) return new_connection except: shim_print("An error occurred in the Python callback: {} - {}".format(sys.exc_info()[0], inspect.currentframe().f_code.co_name),level='error') backend.stop(self.context)
def on_initiate_timeout(ops): shim_print("Timeout - aborting Active open", level="error") backend.stop(ops.ctx) return NEAT_OK
def on_initiate_error(ops): shim_print("Initiate error - Unable to connect to remote endpoint", level="error") backend.stop(ops.ctx) return NEAT_OK
def handle_readable(ops): try: shim_print(ops) connection: Connection = Connection.connection_list[ops.connection_id] shim_print(f"HANDLE READABLE - connection {connection.connection_id}") if connection.receive_request_queue: msg = backend.read(ops, connection.receive_buffer_size) shim_print(f'Data received from stream: {ops.stream_id}') shim_print(msg) if connection.message_framer: if connection.framer_placeholder.earmarked_bytes_missing > 0: connection.framer_placeholder.fill_earmarked_bytes(msg) # Case if more data than unfulfilled message is received? else: connection.framer_placeholder.inbound_data = msg connection.message_framer.dispatch_handle_received_data(connection) else: handler, min_length, max_length = connection.receive_request_queue.pop(0) message_data_object = MessageDataObject(msg, len(msg)) # Create a message context to pass to the receive handler message_context = MessageContext() message_context.remote_endpoint = connection.remote_endpoint message_context.local_endpoint = connection.local_endpoint if connection.stack_supports_message_boundary_preservation: # "If an incoming Message is larger than the minimum of this size and # the maximum Message size on receive for the Connection's Protocol Stack, # it will be delivered via ReceivedPartial events" if len(msg) > min(max_length, connection.transport_properties.connection_properties[ConnectionProperties.MAXIMUM_MESSAGE_SIZE_ON_RECEIVE]): partition_size = min(max_length, connection.transport_properties.connection_properties[ConnectionProperties.MAXIMUM_MESSAGE_SIZE_ON_RECEIVE]) partitioned_message_data_object = MessageDataObject(partition_size) connection.partitioned_message_data_object = partitioned_message_data_object handler(connection, message_data_object, message_context, False, None) else: handler(connection, message_data_object, message_context, None, None) # Min length does not need to be checked with stacks that deliver complete messages # TODO: Check if there possibly could be scenarios with SCTP where partial messages is delivered else: # No message boundary preservation and no framer yields a receive partial event # TODO: Now, a handler must be sent, but should it be possible to pass None, i.e no handler and just discard bytes/message? if connection.buffered_message_data_object: message_data_object.combine_message_data_objects(connection.buffered_message_data_object) if min_length and min_length > message_data_object.length: connection.buffered_message_data_object = message_data_object connection.receive(handler, min_length, max_length) elif max_length < message_data_object.length: # ReceivePartial event - not end of message connection.buffered_message_data_object = None partitioned_message_data_object = message_data_object.partition(max_length) connection.partitioned_message_data_object = partitioned_message_data_object handler(connection, message_data_object, message_context, False, None) else: handler(connection, message_data_object, message_context, True, None) else: shim_print("READABLE SET TO NONE - receive queue empty", level='error') ops.on_readable = None neat_set_operations(ops.ctx, ops.flow, ops) except SystemError: return NEAT_OK except Exception as es: shim_print("An error occurred in the Python callback: {} {} - {}".format(sys.exc_info()[0], es.args, inspect.currentframe().f_code.co_name), level='error') backend.stop(ops.ctx) return NEAT_OK
def stop(self) -> None: backend.stop(self.context)
def stop(self): shim_print("LISTENER STOP") if self.HANDLE_STATE_STOPPED: self.HANDLE_STATE_STOPPED() backend.stop(self.__context)