Skip to content

Commit 1dfc915

Browse files
committed
Split input stream according to JSON structure, not by newlines
For example, jsonrpc4j will not output newlines for each JSON structure it sends.
1 parent eb18ac4 commit 1dfc915

File tree

1 file changed

+50
-11
lines changed

1 file changed

+50
-11
lines changed

bjsonrpc/connection.py

Lines changed: 50 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,37 @@ def close(self):
167167

168168

169169

170+
171+
172+
def split_by_newline(s):
173+
""" Find split position simply by looking for newlines. """
174+
p=s.find('\n')
175+
return p+1 if p>=0 else None
176+
177+
def split_by_json(s):
178+
""" Find split position by looking at first (nested) JSON structure. """
179+
l=0
180+
in_string=False
181+
182+
i=0
183+
while i<len(s):
184+
c=s[i]
185+
186+
if c=='"':
187+
in_string=not in_string
188+
elif in_string:
189+
if c=='\\':
190+
i+=1
191+
else:
192+
if c in "[{":
193+
l+=1
194+
if c in "]}":
195+
l-=1
196+
if l<=0:
197+
return i+1
198+
i+=1
199+
return None
200+
170201
class Connection(object): # TODO: Split this class in simple ones
171202
"""
172203
Represents a communiation tunnel between two parties.
@@ -254,7 +285,9 @@ def getmaxtimeout(cls, operation):
254285
return cls._maxtimeout[operation]
255286

256287

257-
def __init__(self, sck, address = None, handler_factory = None, http=False):
288+
def __init__(self, sck, address = None, handler_factory = None,
289+
http=False):
290+
self.split=split_by_json
258291
self._debug_socket = False
259292
self._debug_dispatch = False
260293
self._buffer = b''
@@ -520,13 +553,14 @@ def dispatch_until_empty(self):
520553

521554
if not ready_to_read: return 0
522555

523-
newline_idx = 0
524556
count = 0
525-
while newline_idx != -1:
557+
while True:
526558
if not self.read_and_dispatch(timeout=0):
527559
break
528560
count += 1
529-
newline_idx = self._buffer.find(b'\n')
561+
if self.split(self._buffer)==None:
562+
break
563+
530564
return count
531565

532566
def read_and_dispatch(self, timeout=None, thread=True, condition=None):
@@ -877,13 +911,20 @@ def read(self, timeout = None):
877911

878912
def _readn(self):
879913
"""
880-
Internal function which reads from socket waiting for a newline
914+
Internal function which reads from socket and splits into
915+
individual JSON messages
881916
"""
917+
882918
streambuffer = self._buffer
883-
pos = streambuffer.find(b'\n')
884919
#_log.debug("read...")
885920
#retry = 0
886-
while pos == -1:
921+
pos=0
922+
923+
while True:
924+
pos = self.split(streambuffer)
925+
if pos!=None:
926+
break
927+
887928
data = b''
888929
try:
889930
data = self._sck.recv(2048)
@@ -915,12 +956,10 @@ def _readn(self):
915956
raise EofError(len(streambuffer))
916957
#_log.debug("readbuf+: %r", data)
917958
streambuffer += data
918-
pos = streambuffer.find(b'\n')
919959

920-
self._buffer = streambuffer[pos + 1:]
921-
streambuffer = streambuffer[:pos]
960+
self._buffer = streambuffer[pos:]
922961
#_log.debug("read: %r", buffer)
923-
return streambuffer
962+
return streambuffer[:pos]
924963

925964
def serve(self):
926965
"""

0 commit comments

Comments
 (0)