From 55a747059fed2cf74dd86b5e025da4693de57259 Mon Sep 17 00:00:00 2001 From: Adam Gibson Date: Fri, 25 Nov 2016 22:34:17 +0200 Subject: [PATCH] add BigString amp argument to accommodate huge offer list --- jmbase/bigstring.py | 64 +++++++++++++++++++++++++++++++++++++++++++++ jmbase/commands.py | 3 ++- 2 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 jmbase/bigstring.py diff --git a/jmbase/bigstring.py b/jmbase/bigstring.py new file mode 100644 index 0000000..b247baa --- /dev/null +++ b/jmbase/bigstring.py @@ -0,0 +1,64 @@ +try: + from cStringIO import StringIO +except ImportError: + from StringIO import StringIO +from itertools import count +from twisted.protocols import amp + +CHUNK_MAX = 0xffff + +class BigString(amp.Argument): + """ + A byte-string amp.Argument with no 65,535 length limit. + + Each value for a key/value pair in an AMP box may not + exceed 65,535 bytes in length. So if we *really* want to + send potentially larger values, this class will implicitly + encode/decode them to/from an arbitrary additional + number of key/value pairs that are given automatic key + names by prefixing this Argument's key name to a counter. + """ + def fromBox(self, name, strings, objects, proto): + value = StringIO() + value.write(strings.get(name)) + for counter in count(2): + chunk = strings.get("%s.%d" % (name, counter)) + if chunk is None: + break + value.write(chunk) + objects[name] = self.buildvalue(value.getvalue()) + + def buildvalue(self, value): + return value + + def toBox(self, name, strings, objects, proto): + value = StringIO(self.fromvalue(objects[name])) + firstChunk = value.read(CHUNK_MAX) + strings[name] = firstChunk + counter = 2 + while True: + nextChunk = value.read(CHUNK_MAX) + if not nextChunk: + break + strings["%s.%d" % (name, counter)] = nextChunk + counter += 1 + + def fromvalue(self, value): + return value + +class BigUnicode(BigString): + """ + A unicode-string amp.Argument with no 65,535 length limit. + + Each value for a key/value pair in an AMP box may not + exceed 65,535 bytes in length. So if we *really* want to + send potentially larger values, this class will implicitly + encode/decode them to/from an arbitrary additional + number of key/value pairs that are given automatic key + names by prefixing this Argument's key name to a counter. + """ + def buildvalue(self, value): + return value.decode('utf-8') + + def fromvalue(self, value): + return value.encode('utf-8') \ No newline at end of file diff --git a/jmbase/commands.py b/jmbase/commands.py index 27d0c06..da97763 100644 --- a/jmbase/commands.py +++ b/jmbase/commands.py @@ -5,6 +5,7 @@ messaging protocol (*not* Joinmarket p2p protocol). Used for AMP asynchronous messages. """ from twisted.protocols.amp import Integer, String, Unicode, Boolean, Command +from bigstring import BigString class DaemonNotReady(Exception): pass @@ -78,7 +79,7 @@ class JMSetupDone(JMCommand): arguments = [] class JMOffers(JMCommand): - arguments = [('orderbook', String())] + arguments = [('orderbook', BigString())] class JMFillResponse(JMCommand): arguments = [('success', Boolean()),