mgmt: add support for events-sending methods
Standard methods return only one value, after operation is completed, but events-related methods may return multiple values during the method execution time. Provide a callback for such cases. Also, according to specification, avoid sending both event and non-event values. QubesOS/qubes-issues#2622
This commit is contained in:
parent
bd9f1d2e7c
commit
40a86efd66
@ -96,7 +96,7 @@ class AbstractQubesMgmt(object):
|
|||||||
There are also two helper functions for firing events associated with API
|
There are also two helper functions for firing events associated with API
|
||||||
calls.
|
calls.
|
||||||
'''
|
'''
|
||||||
def __init__(self, app, src, method, dest, arg):
|
def __init__(self, app, src, method, dest, arg, send_event=None):
|
||||||
#: :py:class:`qubes.Qubes` object
|
#: :py:class:`qubes.Qubes` object
|
||||||
self.app = app
|
self.app = app
|
||||||
|
|
||||||
@ -112,6 +112,9 @@ class AbstractQubesMgmt(object):
|
|||||||
#: name of the method
|
#: name of the method
|
||||||
self.method = method.decode('ascii')
|
self.method = method.decode('ascii')
|
||||||
|
|
||||||
|
#: callback for sending events if applicable
|
||||||
|
self.send_event = send_event
|
||||||
|
|
||||||
#: is this operation cancellable?
|
#: is this operation cancellable?
|
||||||
self.cancellable = False
|
self.cancellable = False
|
||||||
|
|
||||||
|
@ -32,6 +32,7 @@ class QubesDaemonProtocol(asyncio.Protocol):
|
|||||||
self.len_untrusted_buffer = 0
|
self.len_untrusted_buffer = 0
|
||||||
self.transport = None
|
self.transport = None
|
||||||
self.debug = debug
|
self.debug = debug
|
||||||
|
self.event_sent = False
|
||||||
self.mgmt = None
|
self.mgmt = None
|
||||||
|
|
||||||
def connection_made(self, transport):
|
def connection_made(self, transport):
|
||||||
@ -81,6 +82,7 @@ class QubesDaemonProtocol(asyncio.Protocol):
|
|||||||
self.send_event)
|
self.send_event)
|
||||||
response = yield from self.mgmt.execute(
|
response = yield from self.mgmt.execute(
|
||||||
untrusted_payload=untrusted_payload)
|
untrusted_payload=untrusted_payload)
|
||||||
|
assert not (self.event_sent and response)
|
||||||
if self.transport is None:
|
if self.transport is None:
|
||||||
return
|
return
|
||||||
|
|
||||||
@ -116,6 +118,7 @@ class QubesDaemonProtocol(asyncio.Protocol):
|
|||||||
src, method, dest, arg, len(untrusted_payload))
|
src, method, dest, arg, len(untrusted_payload))
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
if not self.event_sent:
|
||||||
self.send_response(response)
|
self.send_response(response)
|
||||||
try:
|
try:
|
||||||
self.transport.write_eof()
|
self.transport.write_eof()
|
||||||
@ -133,11 +136,13 @@ class QubesDaemonProtocol(asyncio.Protocol):
|
|||||||
self.transport.write(self.header.pack(*args))
|
self.transport.write(self.header.pack(*args))
|
||||||
|
|
||||||
def send_response(self, content):
|
def send_response(self, content):
|
||||||
|
assert not self.event_sent
|
||||||
self.send_header(0x30)
|
self.send_header(0x30)
|
||||||
if content is not None:
|
if content is not None:
|
||||||
self.transport.write(content.encode('utf-8'))
|
self.transport.write(content.encode('utf-8'))
|
||||||
|
|
||||||
def send_event(self, subject, event, **kwargs):
|
def send_event(self, subject, event, **kwargs):
|
||||||
|
self.event_sent = True
|
||||||
self.send_header(0x31)
|
self.send_header(0x31)
|
||||||
|
|
||||||
if subject is not self.app:
|
if subject is not self.app:
|
||||||
|
Loading…
Reference in New Issue
Block a user