示例#1
0
文件: upnp.py 项目: capuanob/Uchat
def delete_port_mapping(
        protocol: SupportedTransportProtocols = SupportedTransportProtocols.
    TCP,
        external_port: int = LISTENING_PORT):
    """
    Removes any UPnP temporary port forwards, to be executed on the application's closure
    :param protocol: Transport protocol of port to be deleted
    :param external_port: Port as viewable from internet
    """

    port_forward_deleted = False
    upnp = UPnP()
    upnp.discoverdelay = 20  # Gives up after 20 ms

    try:
        discovered_count = upnp.discover()
        if discovered_count > 0:
            upnp.selectigd()
            port_forward_deleted = upnp.deleteportmapping(
                external_port, protocol.value)
        if not port_forward_deleted:
            # Send signal to show failure message and how to set up static port forwarding
            print_err(
                2, "Failed to delete UPnP Port Mapping on {} port {}".format(
                    protocol.value, external_port))
            pass
    except Exception as e:
        print(type(e))
        print(str(e))
        pass
    print("UPnP Port Mapping Deleted")
示例#2
0
    def recv_message(self) -> Optional[Message]:
        """
        Decodes incoming bytes on the communication socket
        :return: A Message application, if possible
        """
        try:
            incoming_bytes = self.__sock.recv(4)
            message_len = struct.Struct('I').unpack(incoming_bytes)[0]
            message_bytes = self.__sock.recv(message_len)
            message_type = MessageType(
                struct.Struct('B').unpack(message_bytes[:1])[0])

            # Parse bytes to rebuild mag
            if message_type is MessageType.GREETING:
                return GreetingMessage.from_bytes(message_bytes)
            elif message_type is MessageType.CHAT:
                return ChatMessage.from_bytes(message_bytes)
            elif message_type is MessageType.FAREWELL:
                return FarewellMessage.from_bytes()
            else:
                return None
        except struct.error as struct_err:
            print_err(
                3, "Unable to decode bytes on listening socket.\n" +
                str(struct_err))
            return None
        except OSError as os_err:
            print_err(
                2,
                "Unable to receive bytes on listening socket.\n" + str(os_err))
            return None
示例#3
0
文件: upnp.py 项目: capuanob/Uchat
def ensure_port_is_forwarded(
        protocol: SupportedTransportProtocols = SupportedTransportProtocols.
    TCP,
        external_port: int = LISTENING_PORT,
        internal_port=LISTENING_PORT):
    """
    Ensures that the given external to internal port mapping has been forwarded to allow inbound connections to this
    host on this port.
    If already done, whether by lack of NAT, firewall, or static port forwarding, no action is taken.
    Otherwise, the port is forwarded dynamically using UPnP (if supported by the router and OS) for the duration of the
    application's runtime.

    :param protocol: Transport protocol of port to be mapped
    :param external_port: Port as viewable from the internet
    :param internal_port: Port as viewable from the LAN
    """
    upnp = UPnP()
    upnp.discoverdelay = 20  # Gives up after 20 ms

    port_forwarded = False
    discovered_count = upnp.discover()

    if discovered_count > 0:
        upnp.selectigd()
        port_forwarded = upnp.addportmapping(external_port, protocol.value,
                                             upnp.lanaddr, internal_port,
                                             'UChat P2P Messaging', '')

    if not port_forwarded:
        # Send signal to show failure message and how to set up static port forwarding
        print_err(
            2, "Unable to open UPnP {} port {}".format(protocol.value,
                                                       external_port))
    print("UPnP Port Mapping added")
示例#4
0
 def free(self):
     """
     Used to unbind a TCP socket and free its port
     """
     try:
         self.__sock.shutdown(socket.SHUT_RDWR)  # Send FIN to peer
         self.__sock.close()  # Decrement the handle count by 1
     except OSError as os_err:
         print_err(2, "Unable to free socket.\n" + str(os_err))
示例#5
0
 def send_farewell(self, peer: Peer):
     if conv := self.conversation(peer):
         if conv.state() is not ConversationState.CLOSED:
             print("Sending farewell")
             farewell_msg = FarewellMessage()
             self.send(peer, farewell_msg)
         else:
             print_err(4,
                       "Will not send farewell on {}".format(conv.state()))
示例#6
0
 def get_local_addr(self) -> Optional[Tuple[str, int]]:
     """
     :return: the socket name, associated with the socket's local address
     """
     try:
         return self.__sock.getsockname()
     except OSError as os_err:
         print_err(2, "Unable to get socket name\n" + str(os_err))
         return None
示例#7
0
    def send_bytes(self, message: bytes):
        """

        :param message: Send provided bytes via an already connected socket
        """
        try:
            self.__sock.sendall(message)
        except OSError as os_err:
            print_err(
                2, "Failure to send {}... to peer\n".format(message[:10]) +
                str(os_err))
示例#8
0
 def send_chat(self, peer: Peer, chat_message: ChatMessage):
     """
     Gets a line of input from stdin and sends it to another client as a wrapped ChatMessage
     """
     if conv := self.conversation(peer):
         if conv.state() is ConversationState.ACTIVE:
             # As we are in an active conversation, safe to create msg
             print('Sending chat')
             self.send(peer, chat_message)
         else:
             print_err(
                 4, "Will not send {}... on {}.".format(
                     chat_message.message[:10], conv.state()))
示例#9
0
    def show_conversation(self, index: QModelIndex):
        """
        On double click, show the conversation of the associated peer
        :param index:
        :return:
        """

        friend = self._peer_model.at(index.row())

        if self._client.conversation(friend):
            self._client.start_chat_signal.emit(friend)
        else:
            print_err(4, "No conversation exists!")
示例#10
0
 def listen(self):
     """
     Binds the socket to its address and listens for incoming messages
     """
     try:
         self.__sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
         self.__sock.bind(self.__address)
         self.__sock.setblocking(False)
         self.__sock.listen()
         print('Client listening on: {}'.format(self.__address))
     except OSError as os_err:
         print_err(
             2, "Error raised on attempt to establish listening socket\n" +
             str(os_err))
示例#11
0
    def poll_connection_accept(self, listening_sock: TcpSocket):
        """
        Conditionally accepts a new TCP connection to communicate with another client
        """
        new_sock = listening_sock.accept_conn(
        )  # We must have had bound and listened to get here

        if new_sock:
            new_peer = Peer(new_sock.get_remote_addr(), False,
                            new_sock.get_remote_addr()[0])
            self.create_conversation(new_peer, new_sock)
            # Poll for accept / decline
            self.tcp_conn_received_signal.emit(new_peer, new_sock)
        else:
            print_err(2, "Unable to accept incoming connection\n")
示例#12
0
文件: logger.py 项目: capuanob/Uchat
def write_list_to_data_file(data_type: DataType, file_name: FileName,
                            obj_list: Any):
    """
    Saves a list of objects as json
    :param data_type:
    :param file_name: File to save to
    :param obj_list: Object to be serialized as json
    """
    file_path = get_file_path(data_type, file_name)

    try:
        with open(file_path, 'wb') as file:
            for obj in obj_list:
                pickle.dump(obj, file, pickle.HIGHEST_PROTOCOL)
    except OSError as err:
        print_err(1, repr(err))
示例#13
0
文件: logger.py 项目: capuanob/Uchat
def write_to_data_file(data_type: DataType, file_name: FileName, obj: Any,
                       append_mode: bool):
    """
    Saves an object as json
    :param data_type: Folder to save to
    :param file_name: File to save to
    :param obj: Object to be serialized as json
    :param append_mode: Whether or not the data should be appended or overwrite existing content
    """

    try:
        file_path = get_file_path(data_type, file_name)
        with open(file_path, 'ab' if append_mode else 'wb') as file:
            pickle.dump(obj, file, pickle.HIGHEST_PROTOCOL)
    except OSError as err:
        print_err(1, repr(err))
示例#14
0
    def connect(self, conn_addr) -> bool:
        """
        Connects the tcp socket to a remote address

        :param conn_addr: Address of host to connect to
        :return: whether a connection could successfully be established
        """
        try:
            self.__sock.connect(conn_addr)
            print('New connection: \n L {} -> R {}'.format(
                self.get_local_addr(), self.get_remote_addr()))
            return True
        except InterruptedError as int_err:
            print_err(
                2,
                "Connection time-out. Failure to connect to host: {}\n".format(
                    self.get_remote_addr()) + str(int_err))
            return False
        except OSError as os_err:
            print_err(
                2, "Failure to connect to host: {}\n".format(
                    self.get_remote_addr()) + str(os_err))
            return False
示例#15
0
    def handle_receipt(self, peer: Peer, comm_sock: TcpSocket):
        if conv := self.conversation(peer):
            msg = comm_sock.recv_message()
            pre_expecting_types = conv.expecting_types()

            # Construct message context
            context = MessageContext(msg, conv.peer())
            conv.add_message(context)

            if msg and msg.m_type in pre_expecting_types:
                if msg.m_type is MessageType.GREETING:
                    if msg.ack:
                        self.handle_greeting_response_receipt(peer, msg)
                    else:
                        self.handle_greeting_receipt(peer, msg)
                elif msg.m_type is MessageType.FAREWELL:
                    self.handle_farewell_receipt(peer)
                elif msg.m_type is MessageType.CHAT:
                    self.handle_chat_receipt(peer, msg)
                else:
                    print_err(
                        3, "Handling unknown msg type: {}".format(msg.m_type))
            else:
                print_err(3, "Received unexpected message type")
示例#16
0
    def send_chat(self, peer: Peer, chat_message: ChatMessage):
        """
        Gets a line of input from stdin and sends it to another client as a wrapped ChatMessage
        """
        if conv := self.conversation(peer):
            if conv.state() is ConversationState.ACTIVE:
                # As we are in an active conversation, safe to create msg
                print('Sending chat')
                self.send(peer, chat_message)
            else:
                print_err(
                    4, "Will not send {}... on {}.".format(
                        chat_message.message[:10], conv.state()))
        else:
            print_err(4, "Conversation does not yet exist.")

    def send_farewell(self, peer: Peer):
        if conv := self.conversation(peer):
            if conv.state() is not ConversationState.CLOSED:
                print("Sending farewell")
                farewell_msg = FarewellMessage()
                self.send(peer, farewell_msg)
            else:
                print_err(4,
                          "Will not send farewell on {}".format(conv.state()))

    def send(self, peer: Peer, message: Message):
        """
        Generic function, used to send bytes to the peer
        """