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.
Cette révision appartient à :
Marek Marczykowski-Górecki 2017-05-30 01:31:13 +02:00
Parent 96b27fdf14
révision 065eb036df
Signature inconnue de Gitea
ID de la clé GPG: 063938BA42CFA724
2 fichiers modifiés avec 24 ajouts et 15 suppressions

Voir le fichier

@ -147,25 +147,32 @@ class EventsDispatcher(object):
some_event_received = False
while not reader.at_eof():
try:
event_data = yield from reader.readuntil(b'\0\0')
if event_data == b'1\0\0':
# event with non-VM subject contains \0\0 inside of
# event, need to receive rest of the data
event_data += yield from reader.readuntil(b'\0\0')
event_header = yield from reader.readuntil(b'\0')
if event_header != b'1\0':
raise qubesadmin.exc.QubesDaemonCommunicationError(
'Non-event received on events connection: '
+ 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:
if err.partial == b'':
break
else:
raise
if not event_data.startswith(b'1\0'):
raise qubesadmin.exc.QubesDaemonCommunicationError(
'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]))
if not subject:
subject = None
self.handle(subject, event, **kwargs)
some_event_received = True

Voir le fichier

@ -107,7 +107,7 @@ class TC_00_Events(qubesadmin.tests.QubesTestCase):
events = [
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\0\0',
b'1\0some-vm\0some-event\0arg_without_value\0\0arg2\0value\0\0',
b'1\0some-vm\0other-event\0\0',
]
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(
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()
loop.close()