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])
Exemple #2
0
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
Exemple #3
0
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
Exemple #4
0
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
Exemple #5
0
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
Exemple #6
0
    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
Exemple #9
0
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
Exemple #10
0
 def stop(self) -> None:
     backend.stop(self.context)
Exemple #11
0
 def stop(self):
     shim_print("LISTENER STOP")
     if self.HANDLE_STATE_STOPPED:
         self.HANDLE_STATE_STOPPED()
     backend.stop(self.__context)