events: fix parsing events with empty parameters
Empty parameter value is encoded as b'parameter\0\0', so we can't simply read the data until b'\0\0', because it isn't necessary event end. Instead, read event parts separately, according to specification.
This commit is contained in:
parent
96b27fdf14
commit
065eb036df
@ -147,25 +147,32 @@ class EventsDispatcher(object):
|
|||||||
some_event_received = False
|
some_event_received = False
|
||||||
while not reader.at_eof():
|
while not reader.at_eof():
|
||||||
try:
|
try:
|
||||||
event_data = yield from reader.readuntil(b'\0\0')
|
event_header = yield from reader.readuntil(b'\0')
|
||||||
if event_data == b'1\0\0':
|
if event_header != b'1\0':
|
||||||
# event with non-VM subject contains \0\0 inside of
|
raise qubesadmin.exc.QubesDaemonCommunicationError(
|
||||||
# event, need to receive rest of the data
|
'Non-event received on events connection: '
|
||||||
event_data += yield from reader.readuntil(b'\0\0')
|
+ repr(event_header))
|
||||||
|
subject = (yield from reader.readuntil(b'\0'))[:-1].decode(
|
||||||
|
'utf-8')
|
||||||
|
event = (yield from reader.readuntil(b'\0'))[:-1].decode(
|
||||||
|
'utf-8')
|
||||||
|
kwargs = {}
|
||||||
|
while True:
|
||||||
|
key = (yield from reader.readuntil(b'\0'))[:-1].decode(
|
||||||
|
'utf-8')
|
||||||
|
if not key:
|
||||||
|
break
|
||||||
|
value = (yield from reader.readuntil(b'\0'))[:-1].\
|
||||||
|
decode('utf-8')
|
||||||
|
kwargs[key] = value
|
||||||
except asyncio.IncompleteReadError as err:
|
except asyncio.IncompleteReadError as err:
|
||||||
if err.partial == b'':
|
if err.partial == b'':
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
raise
|
raise
|
||||||
|
|
||||||
if not event_data.startswith(b'1\0'):
|
if not subject:
|
||||||
raise qubesadmin.exc.QubesDaemonCommunicationError(
|
subject = None
|
||||||
'Non-event received on events connection: '
|
|
||||||
+ repr(event_data))
|
|
||||||
event_data = event_data.decode('utf-8')
|
|
||||||
_, subject, event, *kwargs = event_data.split('\0')
|
|
||||||
# convert list to dict, remove last empty entry
|
|
||||||
kwargs = dict(zip(kwargs[:-2:2], kwargs[1:-2:2]))
|
|
||||||
self.handle(subject, event, **kwargs)
|
self.handle(subject, event, **kwargs)
|
||||||
|
|
||||||
some_event_received = True
|
some_event_received = True
|
||||||
|
@ -107,7 +107,7 @@ class TC_00_Events(qubesadmin.tests.QubesTestCase):
|
|||||||
events = [
|
events = [
|
||||||
b'1\0\0some-event\0arg1\0value1\0\0',
|
b'1\0\0some-event\0arg1\0value1\0\0',
|
||||||
b'1\0some-vm\0some-event\0arg1\0value1\0\0',
|
b'1\0some-vm\0some-event\0arg1\0value1\0\0',
|
||||||
b'1\0some-vm\0some-event\0\0',
|
b'1\0some-vm\0some-event\0arg_without_value\0\0arg2\0value\0\0',
|
||||||
b'1\0some-vm\0other-event\0\0',
|
b'1\0some-vm\0other-event\0\0',
|
||||||
]
|
]
|
||||||
asyncio.ensure_future(self.send_events(stream, events))
|
asyncio.ensure_future(self.send_events(stream, events))
|
||||||
@ -117,7 +117,9 @@ class TC_00_Events(qubesadmin.tests.QubesTestCase):
|
|||||||
unittest.mock.call(None, 'some-event', arg1='value1'),
|
unittest.mock.call(None, 'some-event', arg1='value1'),
|
||||||
unittest.mock.call(
|
unittest.mock.call(
|
||||||
self.app.domains['some-vm'], 'some-event', arg1='value1'),
|
self.app.domains['some-vm'], 'some-event', arg1='value1'),
|
||||||
unittest.mock.call(self.app.domains['some-vm'], 'some-event'),
|
unittest.mock.call(
|
||||||
|
self.app.domains['some-vm'], 'some-event',
|
||||||
|
arg_without_value='', arg2='value'),
|
||||||
])
|
])
|
||||||
cleanup_func.assert_called_once_with()
|
cleanup_func.assert_called_once_with()
|
||||||
loop.close()
|
loop.close()
|
||||||
|
Loading…
Reference in New Issue
Block a user