Esempio n. 1
0
class BluetoothReceive:
    def __init__(self, port=3, size=1024):
        self.port = port
        self.size = size
        self.client_socket = None
        self.stopped = False

    @inlineCallbacks
    def find_key(self, bt_mac, mac):
        self.client_socket = BluetoothSocket(RFCOMM)
        message = b""
        try:
            self.client_socket.setblocking(False)
            try:
                self.client_socket.connect((bt_mac, self.port))
            except BluetoothError as be:
                if be.args[0] == "(115, 'Operation now in progress')":
                    pass
                else:
                    raise be
            success = False
            while not self.stopped and not success:
                r, w, e = yield threads.deferToThread(select.select, [self.client_socket], [], [], 0.5)
                if r:
                    log.info("Connection established")
                    self.client_socket.setblocking(True)
                    success = True
                    # try to receive until the sender closes the connection
                    try:
                        while True:
                            part_message = self.client_socket.recv(self.size)
                            message += part_message
                    except BluetoothError as be:
                        if be.args[0] == "(104, 'Connection reset by peer')":
                            log.info("Bluetooth connection closed, let's check if we downloaded the key")
                        else:
                            raise be
            mac_key = fingerprint_from_keydata(message)
            verified = None
            if mac:
                verified = mac_verify(mac_key.encode('ascii'), message, mac)
            if verified:
                success = True
            else:
                log.info("MAC validation failed: %r", verified)
                success = False
                message = b""
        except BluetoothError as be:
            if be.args[0] == "(16, 'Device or resource busy')":
                log.info("Probably has been provided a partial bt mac")
            elif be.args[0] == "(111, 'Connection refused')":
                log.info("The sender refused our connection attempt")
            elif be.args[0] == "(112, 'Host is down')":
                log.info("The sender's Bluetooth is not available")
            elif be.args[0] == "(113, 'No route to host')":
                log.info("An error occurred with Bluetooth, if present probably the device is not powered")
            else:
                log.info("An unknown bt error occurred: %s" % be.args[0])
            key_data = None
            success = False
            returnValue((key_data, success, be))
        except Exception as e:
            log.error("An error occurred connecting or receiving: %s" % e)
            key_data = None
            success = False
            returnValue((key_data, success, e))

        if self.client_socket:
            self.client_socket.close()
        returnValue((message.decode("utf-8"), success, None))

    def stop(self):
        self.stopped = True
        if self.client_socket:
            try:
                self.client_socket.shutdown(socket.SHUT_RDWR)
                self.client_socket.close()
            except BluetoothError as be:
                if be.args[0] == "(9, 'Bad file descriptor')":
                    log.info("The old Bluetooth connection was already closed")
                else:
                    log.warning("An unknown bt error occurred: %s" % be.args[0])
Esempio n. 2
0
class BluetoothOffer:
    def __init__(self, key, port=3, size=1024):
        self.key = key
        self.port = port
        self.size = size
        self.server_socket = None
        self.message_def = None
        self.stopped = False

    @inlineCallbacks
    def start(self):
        self.stopped = False
        message = "Back"
        success = False
        try:
            while not self.stopped and not success:
                # server_socket.accept() is not stoppable. So with select we can call accept()
                # only when we are sure that there is already a waiting connection
                ready_to_read, ready_to_write, in_error = yield threads.deferToThread(
                    select.select, [self.server_socket], [], [], 0.5)
                if ready_to_read:
                    # We are sure that a connection is available, so we can call
                    # accept() without deferring it to a thread
                    client_socket, address = self.server_socket.accept()
                    key_data = get_public_key_data(self.key.fingerprint)
                    kd_decoded = key_data.decode('utf-8')
                    yield threads.deferToThread(client_socket.sendall,
                                                kd_decoded)
                    log.info("Key has been sent")
                    client_socket.shutdown(socket.SHUT_RDWR)
                    client_socket.close()
                    success = True
                    message = None
        except Exception as e:
            log.error("An error occurred: %s" % e)
            success = False
            message = e

        returnValue((success, message))

    def allocate_code(self):
        """Acquires and returns a string suitable for finding the key via Bluetooth.
        Returns None if no powered on adapter could be found."""
        # TODO: when we have magic-wormhole we should perform this operation in async
        # and show the loading spinning wheel
        bt_data = None
        try:
            code = get_local_bt_address().upper()
        except NoBluezDbus as e:
            log.debug("Bluetooth service seems to be unavailable: %s", e)
        except NoAdapter as e:
            log.debug("Bluetooth adapter is not available: %s", e)
        except UnpoweredAdapter as e:
            log.debug("Bluetooth adapter is turned off: %s", e)
        else:
            if self.server_socket is None:
                self.server_socket = BluetoothSocket(RFCOMM)
                # We create a bind with the Bluetooth address we have in the system
                self.server_socket.bind((code, PORT_ANY))
                # Number of unaccepted connections that the system will allow before refusing new connections
                backlog = 1
                self.server_socket.listen(backlog)
                log.info("sockname: %r", self.server_socket.getsockname())
            port = self.server_socket.getsockname()[1]
            log.info("BT Code: %s %s", code, port)
            bt_data = "BT={0};PT={1}".format(code, port)
        return bt_data

    def stop(self):
        log.debug("Stopping bt receive")
        self.stopped = True
        if self.server_socket:
            self.server_socket.shutdown(socket.SHUT_RDWR)
            self.server_socket.close()
            self.server_socket = None
Esempio n. 3
0
class BluetoothOffer:
    def __init__(self, key, port=3, size=1024):
        self.key = key
        self.port = port
        self.size = size
        self.server_socket = None
        self.message_def = None
        self.stopped = False
        self.code = None

    @inlineCallbacks
    def start(self):
        self.stopped = False
        message = "Back"
        success = False
        try:
            while not self.stopped and not success:
                # server_socket.accept() is not stoppable. So with select we can call accept()
                # only when we are sure that there is already a waiting connection
                ready_to_read, ready_to_write, in_error = yield threads.deferToThread(
                    select.select, [self.server_socket], [], [], 0.5)
                if ready_to_read:
                    # We are sure that a connection is available, so we can call
                    # accept() without deferring it to a thread
                    client_socket, address = self.server_socket.accept()
                    key_data = get_public_key_data(self.key.fingerprint)
                    kd_decoded = key_data.decode('utf-8')
                    yield threads.deferToThread(client_socket.sendall, kd_decoded)
                    log.info("Key has been sent")
                    client_socket.shutdown(socket.SHUT_RDWR)
                    client_socket.close()
                    success = True
                    message = None
        except Exception as e:
            log.error("An error occurred: %s" % e)
            success = False
            message = e

        returnValue((success, message))

    def allocate_code(self):
        try:
            code = get_local_bt_address().upper()
        except dbus.exceptions.DBusException as e:
            if e.get_dbus_name() == "org.freedesktop.systemd1.NoSuchUnit":
                log.info("No Bluetooth devices found, probably the bluetooth service is not running")
            elif e.get_dbus_name() == "org.freedesktop.DBus.Error.UnknownObject":
                log.info("No Bluetooth devices available")
            else:
                log.error("An unexpected error occurred %s", e.get_dbus_name())
            self.code = None
            return None
        if self.server_socket is None:
            self.server_socket = BluetoothSocket(RFCOMM)
            # We can also bind only the mac found with get_local_bt_address(), anyway
            # even with multiple bt in a single system BDADDR_ANY is not a problem
            self.server_socket.bind((socket.BDADDR_ANY, PORT_ANY))
            # Number of unaccepted connections that the system will allow before refusing new connections
            backlog = 1
            self.server_socket.listen(backlog)
            log.info("sockname: %r", self.server_socket.getsockname())
        port = self.server_socket.getsockname()[1]
        log.info("BT Code: %s %s", code, port)
        bt_data = "BT={0};PT={1}".format(code, port)
        return bt_data

    def stop(self):
        log.debug("Stopping bt receive")
        self.stopped = True
        if self.server_socket:
            self.server_socket.shutdown(socket.SHUT_RDWR)
            self.server_socket.close()
            self.server_socket = None
Esempio n. 4
0
class BluetoothReceive:
    def __init__(self, port=3, size=1024):
        self.port = port
        self.size = size
        self.client_socket = None
        self.stopped = False

    @inlineCallbacks
    def find_key(self, bt_mac, mac):
        self.client_socket = BluetoothSocket(RFCOMM)
        message = b""
        try:
            self.client_socket.setblocking(False)
            try:
                self.client_socket.connect((bt_mac, self.port))
            except BluetoothError as be:
                if be.args[0] == "(115, 'Operation now in progress')":
                    pass
                else:
                    raise be
            success = False
            while not self.stopped and not success:
                r, w, e = yield threads.deferToThread(select.select, [self.client_socket], [], [], 0.5)
                if r:
                    log.info("Connection established")
                    self.client_socket.setblocking(True)
                    success = True
                    # try to receive until the sender closes the connection
                    try:
                        while True:
                            part_message = self.client_socket.recv(self.size)
                            log.debug("Read %d bytes: %r", len(part_message), part_message)
                            message += part_message
                    except BluetoothError as be:
                        if be.args[0] == "(104, 'Connection reset by peer')":
                            log.info("Bluetooth connection closed, let's check if we downloaded the key")
                        else:
                            raise be
            mac_key = fingerprint_from_keydata(message)
            verified = None
            if mac:
                verified = mac_verify(mac_key.encode('ascii'), message, mac)
            if verified:
                success = True
            else:
                log.info("MAC validation failed: %r", verified)
                success = False
                message = b""
        except BluetoothError as be:
            if be.args[0] == "(16, 'Device or resource busy')":
                log.info("Probably has been provided a partial bt mac")
            elif be.args[0] == "(111, 'Connection refused')":
                log.info("The sender refused our connection attempt")
            elif be.args[0] == "(112, 'Host is down')":
                log.info("The sender's Bluetooth is not available")
            elif be.args[0] == "(113, 'No route to host')":
                log.info("An error occurred with Bluetooth, if present probably the device is not powered")
            else:
                log.info("An unknown bt error occurred: %s" % be.args[0])
            key_data = None
            success = False
            returnValue((key_data, success, be))
        except Exception as e:
            log.error("An error occurred connecting or receiving: %s" % e)
            key_data = None
            success = False
            returnValue((key_data, success, e))

        if self.client_socket:
            self.client_socket.close()
        returnValue((message.decode("utf-8"), success, None))

    def stop(self):
        self.stopped = True
        if self.client_socket:
            try:
                self.client_socket.shutdown(socket.SHUT_RDWR)
                self.client_socket.close()
            except BluetoothError as be:
                if be.args[0] == "(9, 'Bad file descriptor')":
                    log.info("The old Bluetooth connection was already closed")
                else:
                    log.exception("An unknown bt error occurred")