Skip to content

Commit

Permalink
client: darwin: add bluetooth
Browse files Browse the repository at this point in the history
  • Loading branch information
doronz88 committed Mar 14, 2022
1 parent a3a14c9 commit 6292fab
Show file tree
Hide file tree
Showing 6 changed files with 81 additions and 25 deletions.
11 changes: 11 additions & 0 deletions src/rpcclient/rpcclient/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,17 @@ def environ(self) -> typing.List[str]:
i += 1
return result

def setenv(self, name: str, value: str):
""" set process environment variable """
self.symbols.setenv(name, value)

def getenv(self, name: str) -> typing.Optional[str]:
""" get process environment variable """
value = self.symbols.getenv(name)
if not value:
return None
return value.peek_str()

@property
def pid(self):
return int(self.symbols.getpid())
Expand Down
64 changes: 64 additions & 0 deletions src/rpcclient/rpcclient/darwin/bluetooth.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
from typing import Optional

from rpcclient.exceptions import MissingLibraryError
from rpcclient.structs.consts import RTLD_NOW


class Bluetooth:
""" bluetooth utils """

# bugfix: +[BluetoothManager.setSharedInstanceQueue:] cannot be called twice in the same process,
# so we use this global to tell if it was already called
_ENV_QUEUE_SET = '_rpc_server_bluetooth_manager_dispatch_queue_set'

def __init__(self, client):
self._client = client
self._load_bluetooth_manager()

bluetooth_manager_class = client.symbols.objc_getClass('BluetoothManager')
if not client.getenv(self._ENV_QUEUE_SET):
bluetooth_manager_class.objc_call('setSharedInstanceQueue:',
self._client.symbols.dispatch_queue_create(0, 0))
client.setenv(self._ENV_QUEUE_SET, '1')
self._bluetooth_manager = bluetooth_manager_class.objc_call('sharedInstance')

def is_on(self):
return 1 == self._bluetooth_manager.objc_call('enabled')

def turn_on(self):
self._set(is_on=1)

def turn_off(self):
self._set(is_on=0)

@property
def address(self) -> Optional[str]:
return self._bluetooth_manager.objc_call('localAddress').py

@property
def connected(self) -> bool:
return bool(self._bluetooth_manager.objc_call('connected'))

@property
def discoverable(self) -> bool:
return bool(self._bluetooth_manager.objc_call('isDiscoverable'))

@discoverable.setter
def discoverable(self, value: bool):
self._bluetooth_manager.objc_call('setDiscoverable:', value)

def _load_bluetooth_manager(self):
options = [
'/System/Library/PrivateFrameworks/BluetoothManager.framework/BluetoothManager',
]
for option in options:
if self._client.dlopen(option, RTLD_NOW):
return
raise MissingLibraryError('failed to load BluetoothManager')

def _set(self, is_on):
self._bluetooth_manager.objc_call('setPowered:', is_on)
self._bluetooth_manager.objc_call('setEnabled:', is_on)

def __repr__(self):
return f"<Bluetooth state:{'ON' if self.is_on() else 'OFF'}>"
2 changes: 1 addition & 1 deletion src/rpcclient/rpcclient/darwin/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

from rpcclient.client import Client
from rpcclient.darwin import objective_c_class
from rpcclient.darwin.bluetooth import Bluetooth
from rpcclient.darwin.consts import kCFNumberSInt64Type, kCFNumberDoubleType, CFStringEncoding, kCFAllocatorDefault
from rpcclient.darwin.darwin_lief import DarwinLief
from rpcclient.darwin.fs import DarwinFs
Expand All @@ -25,7 +26,6 @@
from rpcclient.darwin.time import Time
from rpcclient.darwin.xpc import Xpc
from rpcclient.exceptions import RpcClientException, MissingLibraryError
from rpcclient.macos.bluetooth import Bluetooth
from rpcclient.structs.consts import RTLD_NOW

IsaMagic = namedtuple('IsaMagic', 'mask value')
Expand Down
22 changes: 0 additions & 22 deletions src/rpcclient/rpcclient/macos/bluetooth.py

This file was deleted.

2 changes: 0 additions & 2 deletions src/rpcclient/rpcclient/macos/client.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import typing

from rpcclient.darwin.client import DarwinClient
from rpcclient.macos.bluetooth import Bluetooth
from rpcclient.darwin.reports import Reports

CRASH_REPORTS_DIR = 'Library/Logs/DiagnosticReports'
Expand All @@ -11,7 +10,6 @@ class MacosClient(DarwinClient):

def __init__(self, sock, sysname: str, hostname: str, port: int = None):
super().__init__(sock, sysname, hostname, port)
self.bluetooth = Bluetooth(self)
self.reports = Reports(self, CRASH_REPORTS_DIR)

@property
Expand Down
5 changes: 5 additions & 0 deletions src/rpcserver/ents.plist
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,16 @@
<true/>
<key>task_for_pid-allow</key>
<true/>
<key>com.apple.driver.AppleBluetoothModule.user-access</key>
<true/>
<key>com.apple.bluetooth.system</key>
<true/>
<key>com.apple.private.tcc.allow</key>
<array>
<string>kTCCServiceMicrophone</string>
<string>kTCCServiceCamera</string>
<string>kTCCServiceLocation</string>
<string>kTCCServiceBluetoothPeripheral</string>
</array>
</dict>
</plist>

0 comments on commit 6292fab

Please sign in to comment.