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:
Marek Marczykowski-Górecki 2017-04-10 01:01:40 +02:00
parent bd9f1d2e7c
commit 40a86efd66
No known key found for this signature in database
GPG Key ID: 063938BA42CFA724
2 changed files with 10 additions and 2 deletions

View File

@ -96,7 +96,7 @@ class AbstractQubesMgmt(object):
There are also two helper functions for firing events associated with API
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
self.app = app
@ -112,6 +112,9 @@ class AbstractQubesMgmt(object):
#: name of the method
self.method = method.decode('ascii')
#: callback for sending events if applicable
self.send_event = send_event
#: is this operation cancellable?
self.cancellable = False

View File

@ -32,6 +32,7 @@ class QubesDaemonProtocol(asyncio.Protocol):
self.len_untrusted_buffer = 0
self.transport = None
self.debug = debug
self.event_sent = False
self.mgmt = None
def connection_made(self, transport):
@ -81,6 +82,7 @@ class QubesDaemonProtocol(asyncio.Protocol):
self.send_event)
response = yield from self.mgmt.execute(
untrusted_payload=untrusted_payload)
assert not (self.event_sent and response)
if self.transport is None:
return
@ -116,7 +118,8 @@ class QubesDaemonProtocol(asyncio.Protocol):
src, method, dest, arg, len(untrusted_payload))
else:
self.send_response(response)
if not self.event_sent:
self.send_response(response)
try:
self.transport.write_eof()
except NotImplementedError:
@ -133,11 +136,13 @@ class QubesDaemonProtocol(asyncio.Protocol):
self.transport.write(self.header.pack(*args))
def send_response(self, content):
assert not self.event_sent
self.send_header(0x30)
if content is not None:
self.transport.write(content.encode('utf-8'))
def send_event(self, subject, event, **kwargs):
self.event_sent = True
self.send_header(0x31)
if subject is not self.app: