def __read(self): """ Read the next frame(s) from the socket. """ fastbuf = BytesIO() while self.running: try: try: c = self.receive() except exception.InterruptedException: log.debug("socket read interrupted, restarting") continue except Exception: c = b'' if len(c) == 0: raise exception.ConnectionClosedException() fastbuf.write(c) if b'\x00' in c: break elif c == b'\x0a': # heartbeat (special case) return [ c, ] self.__recvbuf += fastbuf.getvalue() fastbuf.close() result = [] if self.__recvbuf and self.running: while True: pos = self.__recvbuf.find(b'\x00') if pos >= 0: frame = self.__recvbuf[0:pos] preamble_end = frame.find(b'\n\n') if preamble_end >= 0: content_length_match = BaseTransport.__content_length_re.search( frame[0:preamble_end]) if content_length_match: content_length = int( content_length_match.group('value')) content_offset = preamble_end + 2 frame_size = content_offset + content_length if frame_size > len(frame): # # Frame contains NUL bytes, need to read more # if frame_size < len(self.__recvbuf): pos = frame_size frame = self.__recvbuf[0:pos] else: # # Haven't read enough data yet, exit loop and wait for more to arrive # break result.append(frame) self.__recvbuf = self.__recvbuf[pos + 1:] else: break return result
def __read(self): """ Read the next frame(s) from the socket. :return: list of frames read :rtype: list(bytes) """ fastbuf = BytesIO() while self.running: try: try: c = self.receive() except exception.InterruptedException: log.debug("socket read interrupted, restarting") continue except Exception: log.debug("socket read error", exc_info=True) c = b'' if c is None or len(c) == 0: raise exception.ConnectionClosedException() if c == b'\x0a' and not self.__recvbuf and not fastbuf.tell(): # # EOL to an empty receive buffer: treat as heartbeat. # Note that this may misdetect an optional EOL at end of frame as heartbeat in case the # previous receive() got a complete frame whose NUL at end of frame happened to be the # last byte of that read. But that should be harmless in practice. # fastbuf.close() return [c] fastbuf.write(c) if b'\x00' in c: # # Possible end of frame # break self.__recvbuf += fastbuf.getvalue() fastbuf.close() result = [] if self.__recvbuf and self.running: while True: pos = self.__recvbuf.find(b'\x00') if pos >= 0: frame = self.__recvbuf[0:pos] preamble_end_match = utils.PREAMBLE_END_RE.search(frame) if preamble_end_match: preamble_end = preamble_end_match.start() content_length_match = BaseTransport.__content_length_re.search( frame[0:preamble_end]) if content_length_match: content_length = int( content_length_match.group('value')) content_offset = preamble_end_match.end() frame_size = content_offset + content_length if frame_size > len(frame): # # Frame contains NUL bytes, need to read more # if frame_size < len(self.__recvbuf): pos = frame_size frame = self.__recvbuf[0:pos] else: # # Haven't read enough data yet, exit loop and wait for more to arrive # break result.append(frame) pos += 1 # # Ignore optional EOLs at end of frame # while self.__recvbuf[pos:pos + 1] == b'\x0a': pos += 1 self.__recvbuf = self.__recvbuf[pos:] else: break return result