From 45b73d58930a2a66394a6797c94a50c34e8f96e7 Mon Sep 17 00:00:00 2001 From: Victor Shyba Date: Wed, 22 Mar 2017 21:43:07 -0300 Subject: [refactor] adds a PreamblePipe for preamble download Downloading until there is a space then splitting the content was a mess. Extracted this behaviour out of DecrypterBuffer into a new component so it eases testing by introducing a single responsibility class. --- client/src/leap/soledad/client/_blobs.py | 27 ++++++++------------------- client/src/leap/soledad/client/_pipes.py | 29 ++++++++++++++++++++++++++++- 2 files changed, 36 insertions(+), 20 deletions(-) (limited to 'client/src/leap') diff --git a/client/src/leap/soledad/client/_blobs.py b/client/src/leap/soledad/client/_blobs.py index c64c2bb2..7ecd4a4d 100644 --- a/client/src/leap/soledad/client/_blobs.py +++ b/client/src/leap/soledad/client/_blobs.py @@ -36,7 +36,7 @@ import treq from leap.soledad.client.sqlcipher import SQLCipherOptions from leap.soledad.client import pragmas -from leap.soledad.client._pipes import TruncatedTailPipe +from leap.soledad.client._pipes import TruncatedTailPipe, PreamblePipe from leap.soledad.common.errors import SoledadError from _crypto import DocInfo, BlobEncryptor, BlobDecryptor @@ -106,33 +106,22 @@ def check_http_status(code): class DecrypterBuffer(object): def __init__(self, doc_id, rev, secret, tag): - self.decrypter = None - self.preamble = BytesIO() self.doc_info = DocInfo(doc_id, rev) self.secret = secret self.tag = tag - self.d = None + self.preamble_pipe = PreamblePipe(self._make_decryptor) - def write(self, data): - if not self.decrypter: - return self.prepare_decrypter(data) - - self.output.write(data) - - def prepare_decrypter(self, data): - if ' ' not in data: - self.preamble.write(data) - return - preamble_chunk, remaining = data.split(' ', 1) - self.preamble.write(preamble_chunk) + def _make_decryptor(self, preamble): self.decrypter = BlobDecryptor( - self.doc_info, BytesIO(self.preamble.getvalue()), + self.doc_info, preamble, secret=self.secret, armor=False, start_stream=False, tag=self.tag) - self.output = TruncatedTailPipe(self.decrypter, tail_size=16) - self.output.write(remaining) + return TruncatedTailPipe(self.decrypter, tail_size=len(self.tag)) + + def write(self, data): + self.preamble_pipe.write(data) def close(self): return self.decrypter._end_stream(), self.decrypter.size diff --git a/client/src/leap/soledad/client/_pipes.py b/client/src/leap/soledad/client/_pipes.py index ed89e14d..443f4a70 100644 --- a/client/src/leap/soledad/client/_pipes.py +++ b/client/src/leap/soledad/client/_pipes.py @@ -20,7 +20,7 @@ Components for piping data on streams. from io import BytesIO -__all__ = ['TruncatedTailPipe'] +__all__ = ['TruncatedTailPipe', 'PreamblePipe'] class TruncatedTailPipe(object): @@ -49,3 +49,30 @@ class TruncatedTailPipe(object): def close(self): return self.output + + +class PreamblePipe(object): + """ + Consumes data until a space is found, then calls a callback with it and + starts forwarding data to consumer returned by this callback. + """ + + def __init__(self, callback): + self.callback = callback + self.preamble = BytesIO() + self.output = None + + def write(self, data): + if not self.output: + self._write_preamble(data) + else: + self.output.write(data) + + def _write_preamble(self, data): + if ' ' not in data: + self.preamble.write(data) + return + preamble_chunk, remaining = data.split(' ', 1) + self.preamble.write(preamble_chunk) + self.output = self.callback(self.preamble) + self.output.write(remaining) -- cgit v1.2.3