feat: speed up to processing bluez passive data (#221)
This commit is contained in:
parent
71e6fdfc97
commit
8e7432d31b
@ -27,6 +27,8 @@ cdef object LITTLE_ENDIAN
|
||||
cdef object PROTOCOL_VERSION
|
||||
|
||||
cdef object MESSAGE_FLAG
|
||||
cdef object MESSAGE_FLAG_NONE
|
||||
cdef object MESSAGE_TYPE_METHOD_CALL
|
||||
|
||||
cdef get_signature_tree
|
||||
|
||||
|
||||
@ -30,6 +30,9 @@ HEADER_UNIX_FDS = HeaderField.UNIX_FDS.value
|
||||
|
||||
MESSAGE_FLAG = MessageFlag
|
||||
|
||||
MESSAGE_FLAG_NONE = MessageFlag.NONE
|
||||
MESSAGE_TYPE_METHOD_CALL = MessageType.METHOD_CALL
|
||||
|
||||
|
||||
class Message:
|
||||
"""A class for sending and receiving messages through the
|
||||
@ -101,8 +104,8 @@ class Message:
|
||||
path: Optional[str] = None,
|
||||
interface: Optional[str] = None,
|
||||
member: Optional[str] = None,
|
||||
message_type: MessageType = MessageType.METHOD_CALL,
|
||||
flags: Union[MessageFlag, int] = MessageFlag.NONE,
|
||||
message_type: MessageType = MESSAGE_TYPE_METHOD_CALL,
|
||||
flags: Union[MessageFlag, int] = MESSAGE_FLAG_NONE,
|
||||
error_name: Optional[Union[str, ErrorType]] = None,
|
||||
reply_serial: int = 0,
|
||||
sender: Optional[str] = None,
|
||||
@ -153,6 +156,22 @@ class Message:
|
||||
if not getattr(self, field):
|
||||
raise InvalidMessageError(f"missing required field: {field}")
|
||||
|
||||
def __repr__(self) -> str:
|
||||
"""Return a string representation of this message."""
|
||||
return (
|
||||
f"<Message {self.message_type.name} "
|
||||
f"serial={self.serial} "
|
||||
f"reply_serial={self.reply_serial} "
|
||||
f"sender={self.sender} "
|
||||
f"destination={self.destination} "
|
||||
f"path={self.path} "
|
||||
f"interface={self.interface} "
|
||||
f"member={self.member} "
|
||||
f"error_name={self.error_name} "
|
||||
f"signature={self.signature} "
|
||||
f"body={self.body}>"
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def new_error(
|
||||
msg: "Message", error_name: Union[str, ErrorType], error_text: str
|
||||
|
||||
@ -10,12 +10,14 @@ cdef object MessageFlag
|
||||
|
||||
cdef object MESSAGE_TYPE_CALL
|
||||
cdef object MESSAGE_TYPE_SIGNAL
|
||||
cdef object NO_REPLY_EXPECTED_VALUE
|
||||
cdef object NO_REPLY_EXPECTED
|
||||
cdef object BLOCK_UNEXPECTED_REPLY
|
||||
cdef object assert_object_path_valid
|
||||
cdef object assert_bus_name_valid
|
||||
|
||||
cdef _expects_reply(Message msg)
|
||||
|
||||
|
||||
cdef class SendReply:
|
||||
|
||||
cdef object _bus
|
||||
@ -28,12 +30,12 @@ cdef class BaseMessageBus:
|
||||
cdef public object _user_disconnect
|
||||
cdef public object _method_return_handlers
|
||||
cdef public object _serial
|
||||
cdef public object _path_exports
|
||||
cdef public cython.dict _path_exports
|
||||
cdef public cython.list _user_message_handlers
|
||||
cdef public object _name_owners
|
||||
cdef public cython.dict _name_owners
|
||||
cdef public object _bus_address
|
||||
cdef public object _name_owner_match_rule
|
||||
cdef public object _match_rules
|
||||
cdef public cython.dict _match_rules
|
||||
cdef public object _high_level_client_initialized
|
||||
cdef public object _ProxyObject
|
||||
cdef public object _machine_id
|
||||
@ -45,7 +47,9 @@ cdef class BaseMessageBus:
|
||||
cpdef _process_message(self, Message msg)
|
||||
|
||||
@cython.locals(
|
||||
methods=cython.list,
|
||||
method=_Method,
|
||||
interface=ServiceInterface
|
||||
interface=ServiceInterface,
|
||||
interfaces=cython.list,
|
||||
)
|
||||
cdef _find_message_handler(self, Message msg)
|
||||
|
||||
@ -27,13 +27,34 @@ from .validators import assert_bus_name_valid, assert_object_path_valid
|
||||
|
||||
MESSAGE_TYPE_CALL = MessageType.METHOD_CALL
|
||||
MESSAGE_TYPE_SIGNAL = MessageType.SIGNAL
|
||||
NO_REPLY_EXPECTED_VALUE = MessageFlag.NO_REPLY_EXPECTED.value
|
||||
NO_REPLY_EXPECTED = MessageFlag.NO_REPLY_EXPECTED
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
_Message = Message
|
||||
|
||||
|
||||
def _expects_reply(msg: _Message) -> bool:
|
||||
return not (msg.flags.value & NO_REPLY_EXPECTED_VALUE)
|
||||
"""Whether a message expects a reply."""
|
||||
return not (msg.flags & NO_REPLY_EXPECTED)
|
||||
|
||||
|
||||
def _block_unexpected_reply(reply: _Message) -> None:
|
||||
"""Block a reply if it's not expected.
|
||||
|
||||
Previously we silently ignored replies that were not expected, but this
|
||||
lead to implementation errors that were hard to debug. Now we log a
|
||||
debug message instead.
|
||||
"""
|
||||
_LOGGER.debug(
|
||||
"Blocked attempt to send a reply from handler "
|
||||
"that received a message with flag "
|
||||
"MessageFlag.NO_REPLY_EXPECTED: %s",
|
||||
reply,
|
||||
)
|
||||
|
||||
|
||||
BLOCK_UNEXPECTED_REPLY = _block_unexpected_reply
|
||||
|
||||
|
||||
class SendReply:
|
||||
@ -50,8 +71,7 @@ class SendReply:
|
||||
return self
|
||||
|
||||
def __call__(self, reply: Message) -> None:
|
||||
if _expects_reply(self._msg):
|
||||
self._bus.send(reply)
|
||||
self._bus.send(reply)
|
||||
|
||||
def _exit(
|
||||
self,
|
||||
@ -855,9 +875,19 @@ class BaseMessageBus:
|
||||
if msg.message_type is MESSAGE_TYPE_CALL:
|
||||
if not handled:
|
||||
handler = self._find_message_handler(msg)
|
||||
if not _expects_reply(msg):
|
||||
if handler:
|
||||
handler(msg, BLOCK_UNEXPECTED_REPLY)
|
||||
else:
|
||||
_LOGGER.error(
|
||||
'"%s.%s" with signature "%s" could not be found',
|
||||
msg.interface,
|
||||
msg.member,
|
||||
msg.signature,
|
||||
)
|
||||
return
|
||||
|
||||
send_reply = SendReply(self, msg)
|
||||
|
||||
with send_reply:
|
||||
if handler:
|
||||
handler(msg, send_reply)
|
||||
@ -892,8 +922,11 @@ class BaseMessageBus:
|
||||
def _callback_method_handler(
|
||||
msg: Message, send_reply: Callable[[Message], None]
|
||||
) -> None:
|
||||
result = method_fn(interface, *msg_body_to_args(msg))
|
||||
if not _expects_reply(msg):
|
||||
return
|
||||
body, fds = fn_result_to_body(
|
||||
method_fn(interface, *msg_body_to_args(msg)),
|
||||
result,
|
||||
signature_tree=out_signature_tree,
|
||||
replace_fds=negotiate_unix_fd,
|
||||
)
|
||||
@ -911,8 +944,8 @@ class BaseMessageBus:
|
||||
return _callback_method_handler
|
||||
|
||||
def _find_message_handler(
|
||||
self, msg
|
||||
) -> Optional[Callable[[Message, Callable], None]]:
|
||||
self, msg: _Message
|
||||
) -> Optional[Callable[[Message, Callable[[Message], None]], None]]:
|
||||
if (
|
||||
msg.interface == "org.freedesktop.DBus.Introspectable"
|
||||
and msg.member == "Introspect"
|
||||
@ -937,8 +970,12 @@ class BaseMessageBus:
|
||||
|
||||
msg_path = msg.path
|
||||
if msg_path:
|
||||
for interface in self._path_exports.get(msg_path, []):
|
||||
for method in ServiceInterface._get_methods(interface):
|
||||
interfaces = self._path_exports.get(msg_path)
|
||||
if not interfaces:
|
||||
return None
|
||||
for interface in interfaces:
|
||||
methods = ServiceInterface._get_methods(interface)
|
||||
for method in methods:
|
||||
if method.disabled:
|
||||
continue
|
||||
|
||||
|
||||
@ -2,17 +2,19 @@
|
||||
|
||||
import cython
|
||||
|
||||
from .signature cimport SignatureTree
|
||||
|
||||
|
||||
cdef class _Method:
|
||||
|
||||
cdef public object name
|
||||
cdef public str name
|
||||
cdef public object fn
|
||||
cdef public object disabled
|
||||
cdef public object introspection
|
||||
cdef public object in_signature
|
||||
cdef public object out_signature
|
||||
cdef public object in_signature_tree
|
||||
cdef public object out_signature_tree
|
||||
cdef public str in_signature
|
||||
cdef public str out_signature
|
||||
cdef public SignatureTree in_signature_tree
|
||||
cdef public SignatureTree out_signature_tree
|
||||
|
||||
cdef class ServiceInterface:
|
||||
|
||||
|
||||
@ -36,7 +36,7 @@ if TYPE_CHECKING:
|
||||
|
||||
|
||||
class _Method:
|
||||
def __init__(self, fn, name, disabled=False):
|
||||
def __init__(self, fn, name: str, disabled=False):
|
||||
in_signature = ""
|
||||
out_signature = ""
|
||||
|
||||
|
||||
@ -602,5 +602,6 @@ def test_unmarshall_bluez_passive_message():
|
||||
unmarshaller = Unmarshaller(stream)
|
||||
unmarshaller.unmarshall()
|
||||
message = unmarshaller.message
|
||||
assert "/org/bluez/hci0/dev_58_D3_49_E6_02_6E" in str(message)
|
||||
unpacked = unpack_variants(message.body)
|
||||
assert unpacked == ["/org/bluez/hci0/dev_58_D3_49_E6_02_6E"]
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user