def handle_readbuf(self): netid = self.server.netid while self.ac_in_buffer: if self.ac_in_buffer[:4] != netid: p = self.ac_in_buffer.find(netid) if p == -1: p = asynchat.find_prefix_at_end(self.ac_in_buffer, netid) if p: self.ac_in_buffer = self.ac_in_buffer[-p:] else: self.ac_in_buffer = b'' break self.ac_in_buffer = self.ac_in_buffer[p:] cmd = self.ac_in_buffer[4:0x10].rstrip(b'\0').decode('utf8') payloadLen = unpack('<L', self.ac_in_buffer[0x10:0x14])[0] if payloadLen > MAX_PACKET_PAYLOAD: raise RuntimeError('Packet payload is too long (%d bytes)' % (payloadLen,)) payloadEnd = payloadLen + 0x18 if len(self.ac_in_buffer) < payloadEnd: # Don't have the whole packet yet break method = 'doCmd_' + cmd cksum = self.ac_in_buffer[0x14:0x18] payload = self.ac_in_buffer[0x18:payloadEnd] self.ac_in_buffer = self.ac_in_buffer[payloadEnd:] realcksum = dblsha(payload)[:4] if realcksum != cksum: self.logger.debug('Wrong checksum on `%s\' message (%s vs actual:%s); ignoring' % (cmd, b2a_hex(cksum), b2a_hex(realcksum))) return if hasattr(self, method): getattr(self, method)(payload)
def process_data(self, data): self.ac_in_buffer = self.ac_in_buffer + data # Continue to search for self.terminator in self.ac_in_buffer, # while calling self.collect_incoming_data. The while loop # is necessary because we might read several data+terminator # combos with a single recv(1024). while self.ac_in_buffer: lb = len(self.ac_in_buffer) terminator = self.get_terminator() if not terminator: # no terminator, collect it all self.collect_incoming_data(self.ac_in_buffer) self.ac_in_buffer = '' elif isinstance(terminator, int) or isinstance(terminator, long): # numeric terminator n = terminator if lb < n: self.collect_incoming_data(self.ac_in_buffer) self.ac_in_buffer = '' self.terminator = self.terminator - lb else: self.collect_incoming_data(self.ac_in_buffer[:n]) self.ac_in_buffer = self.ac_in_buffer[n:] self.terminator = 0 self.found_terminator() else: # 3 cases: # 1) end of buffer matches terminator exactly: # collect data, transition # 2) end of buffer matches some prefix: # collect data to the prefix # 3) end of buffer does not match any prefix: # collect data terminator_len = len(terminator) index = self.ac_in_buffer.find(terminator) if index != -1: # we found the terminator if index > 0: # don't bother reporting the empty string (source of subtle bugs) self.collect_incoming_data(self.ac_in_buffer[:index]) self.ac_in_buffer = self.ac_in_buffer[index + terminator_len:] # This does the Right Thing if the terminator is changed here. self.found_terminator() else: # check for a prefix of the terminator index = find_prefix_at_end(self.ac_in_buffer, terminator) if index: if index != lb: # we found a prefix, collect up to the prefix self.collect_incoming_data( self.ac_in_buffer[:-index]) self.ac_in_buffer = self.ac_in_buffer[-index:] break else: # no prefix, collect it all self.collect_incoming_data(self.ac_in_buffer) self.ac_in_buffer = ''
def process_data(self, data): self.ac_in_buffer = self.ac_in_buffer + data # Continue to search for self.terminator in self.ac_in_buffer, # while calling self.collect_incoming_data. The while loop # is necessary because we might read several data+terminator # combos with a single recv(1024). while self.ac_in_buffer: lb = len(self.ac_in_buffer) terminator = self.get_terminator() if not terminator: # no terminator, collect it all self.collect_incoming_data (self.ac_in_buffer) self.ac_in_buffer = '' elif isinstance(terminator, int) or isinstance(terminator, long): # numeric terminator n = terminator if lb < n: self.collect_incoming_data (self.ac_in_buffer) self.ac_in_buffer = '' self.terminator = self.terminator - lb else: self.collect_incoming_data (self.ac_in_buffer[:n]) self.ac_in_buffer = self.ac_in_buffer[n:] self.terminator = 0 self.found_terminator() else: # 3 cases: # 1) end of buffer matches terminator exactly: # collect data, transition # 2) end of buffer matches some prefix: # collect data to the prefix # 3) end of buffer does not match any prefix: # collect data terminator_len = len(terminator) index = self.ac_in_buffer.find(terminator) if index != -1: # we found the terminator if index > 0: # don't bother reporting the empty string (source of subtle bugs) self.collect_incoming_data (self.ac_in_buffer[:index]) self.ac_in_buffer = self.ac_in_buffer[index+terminator_len:] # This does the Right Thing if the terminator is changed here. self.found_terminator() else: # check for a prefix of the terminator index = find_prefix_at_end (self.ac_in_buffer, terminator) if index: if index != lb: # we found a prefix, collect up to the prefix self.collect_incoming_data (self.ac_in_buffer[:-index]) self.ac_in_buffer = self.ac_in_buffer[-index:] break else: # no prefix, collect it all self.collect_incoming_data (self.ac_in_buffer) self.ac_in_buffer = ''
def handle_readbuf(self): netid = self.server.netid while self.ac_in_buffer: if self.ac_in_buffer[:4] != netid: p = self.ac_in_buffer.find(netid) if p == -1: p = asynchat.find_prefix_at_end(self.ac_in_buffer, netid) if p: self.ac_in_buffer = self.ac_in_buffer[-p:] else: self.ac_in_buffer = b'' break self.ac_in_buffer = self.ac_in_buffer[p:] cmd = self.ac_in_buffer[4:0x10].rstrip(b'\0').decode('utf8') payloadLen = unpack('<L', self.ac_in_buffer[0x10:0x14])[0] if payloadLen > MAX_PACKET_PAYLOAD: raise RuntimeError('Packet payload is too long (%d bytes)' % (payloadLen, )) payloadEnd = payloadLen + 0x18 if len(self.ac_in_buffer) < payloadEnd: # Don't have the whole packet yet break method = 'doCmd_' + cmd cksum = self.ac_in_buffer[0x14:0x18] payload = self.ac_in_buffer[0x18:payloadEnd] self.ac_in_buffer = self.ac_in_buffer[payloadEnd:] realcksum = dblsha(payload)[:4] if realcksum != cksum: self.logger.debug( 'Wrong checksum on `%s\' message (%s vs actual:%s); ignoring' % (cmd, b2a_hex(cksum), b2a_hex(realcksum))) return if hasattr(self, method): getattr(self, method)(payload)
def handle_readbuf(self): while self.ac_in_buffer: lb = len(self.ac_in_buffer) terminator = self.get_terminator() if not terminator: # no terminator, collect it all self.collect_incoming_data(self.ac_in_buffer) self.ac_in_buffer = b'' elif isinstance(terminator, int): # numeric terminator n = terminator if lb < n: self.collect_incoming_data(self.ac_in_buffer) self.ac_in_buffer = b'' self.terminator = self.terminator - lb else: self.collect_incoming_data(self.ac_in_buffer[:n]) self.ac_in_buffer = self.ac_in_buffer[n:] self.terminator = 0 self.found_terminator() else: # 3 cases: # 1) end of buffer matches terminator exactly: # collect data, transition # 2) end of buffer matches some prefix: # collect data to the prefix # 3) end of buffer does not match any prefix: # collect data # NOTE: this supports multiple different terminators, but # NOT ones that are prefixes of others... if isinstance(self.ac_in_buffer, type(terminator)): terminator = (terminator, ) termidx = tuple(map(self.ac_in_buffer.find, terminator)) try: index = min(x for x in termidx if x >= 0) except ValueError: index = -1 if index != -1: # we found the terminator if index > 0: # don't bother reporting the empty string (source of subtle bugs) self.collect_incoming_data(self.ac_in_buffer[:index]) specific_terminator = terminator[termidx.index(index)] terminator_len = len(specific_terminator) self.ac_in_buffer = self.ac_in_buffer[index + terminator_len:] # This does the Right Thing if the terminator is changed here. self.found_terminator() else: # check for a prefix of the terminator termidx = tuple( map( lambda a: asynchat.find_prefix_at_end( self.ac_in_buffer, a), terminator)) index = max(termidx) if index: if index != lb: # we found a prefix, collect up to the prefix self.collect_incoming_data( self.ac_in_buffer[:-index]) self.ac_in_buffer = self.ac_in_buffer[-index:] break else: # no prefix, collect it all self.collect_incoming_data(self.ac_in_buffer) self.ac_in_buffer = b''
def handle_readbuf(self): while self.ac_in_buffer: lb = len(self.ac_in_buffer) terminator = self.get_terminator() if not terminator: # no terminator, collect it all self.collect_incoming_data(self.ac_in_buffer) self.ac_in_buffer = b"" elif isinstance(terminator, int): # numeric terminator n = terminator if lb < n: self.collect_incoming_data(self.ac_in_buffer) self.ac_in_buffer = b"" self.terminator = self.terminator - lb else: self.collect_incoming_data(self.ac_in_buffer[:n]) self.ac_in_buffer = self.ac_in_buffer[n:] self.terminator = 0 self.found_terminator() else: # 3 cases: # 1) end of buffer matches terminator exactly: # collect data, transition # 2) end of buffer matches some prefix: # collect data to the prefix # 3) end of buffer does not match any prefix: # collect data # NOTE: this supports multiple different terminators, but # NOT ones that are prefixes of others... if isinstance(self.ac_in_buffer, type(terminator)): terminator = (terminator,) termidx = tuple(map(self.ac_in_buffer.find, terminator)) try: index = min(x for x in termidx if x >= 0) except ValueError: index = -1 if index != -1: # we found the terminator if index > 0: # don't bother reporting the empty string (source of subtle bugs) self.collect_incoming_data(self.ac_in_buffer[:index]) specific_terminator = terminator[termidx.index(index)] terminator_len = len(specific_terminator) self.ac_in_buffer = self.ac_in_buffer[index + terminator_len :] # This does the Right Thing if the terminator is changed here. self.found_terminator() else: # check for a prefix of the terminator termidx = tuple(map(lambda a: asynchat.find_prefix_at_end(self.ac_in_buffer, a), terminator)) index = max(termidx) if index: if index != lb: # we found a prefix, collect up to the prefix self.collect_incoming_data(self.ac_in_buffer[:-index]) self.ac_in_buffer = self.ac_in_buffer[-index:] break else: # no prefix, collect it all self.collect_incoming_data(self.ac_in_buffer) self.ac_in_buffer = b""
def handle_read(self): try: data = self.conn.recv(self.ac_in_buffer_size) if len(data) == 0: # issues 2 TCP connect closed will send a 0 size pack self.close_when_done() except socket.error: self.handle_error() return self.ac_in_buffer = self.ac_in_buffer + data.decode("utf-8") # Continue to search for self.terminator in self.ac_in_buffer, # while calling self.collect_incoming_data. The while loop # is necessary because we might read several data+terminator # combos with a single recv(4096). while self.ac_in_buffer: lb = len(self.ac_in_buffer) logger.debug(self.ac_in_buffer) if not self.terminator: # no terminator, collect it all self.collect_incoming_data(self.ac_in_buffer) self.ac_in_buffer = "" elif isinstance(self.terminator, int): # numeric terminator n = self.terminator if lb < n: self.collect_incoming_data(self.ac_in_buffer) self.ac_in_buffer = "" self.terminator = self.terminator - lb else: self.collect_incoming_data(self.ac_in_buffer[:n]) self.ac_in_buffer = self.ac_in_buffer[n:] self.terminator = 0 self.found_terminator() else: # 3 cases: # 1) end of buffer matches terminator exactly: # collect data, transition # 2) end of buffer matches some prefix: # collect data to the prefix # 3) end of buffer does not match any prefix: # collect data terminator_len = len(self.terminator) index = self.ac_in_buffer.find(self.terminator) if index != -1: # we found the terminator if index > 0: # don't bother reporting the empty string (source of subtle bugs) self.collect_incoming_data(self.ac_in_buffer[:index]) self.ac_in_buffer = self.ac_in_buffer[index + terminator_len:] # This does the Right Thing if the terminator is changed here. self.found_terminator() else: # check for a prefix of the terminator index = find_prefix_at_end(self.ac_in_buffer, self.terminator) if index: if index != lb: # we found a prefix, collect up to the prefix self.collect_incoming_data( self.ac_in_buffer[:-index]) self.ac_in_buffer = self.ac_in_buffer[-index:] break else: # no prefix, collect it all self.collect_incoming_data(self.ac_in_buffer) self.ac_in_buffer = ""
def update_event(self, inp=-1): self.set_output_val( 0, asynchat.find_prefix_at_end(self.input(0), self.input(1)))
class NSEScope(asynchat.async_chat): def __init__(self, addr='1.2.3.4', port=2000): asynchat.async_chat.__init__(self) self.create_socket(socket.AF_INET, socket.SOCK_STREAM) self.connect((addr, port)) self.ibuffer = [] self.obuffer = '' self.reading_headers = True self.handling = False self.set_terminator('*HELLO*') self.startup=True self.me=targets['APP'] # grab some more data from the socket, # throw it to the collector method, # check for the terminator, # if found, transition to the next state. # Modified from stdlib - we need empty # strings passed to collect data. def handle_read (self): try: data = self.recv (self.ac_in_buffer_size) except socket.error, why: if why.args[0] in _BLOCKING_IO_ERRORS: return self.handle_error() return self.ac_in_buffer = self.ac_in_buffer + data # Continue to search for self.terminator in self.ac_in_buffer, # while calling self.collect_incoming_data. The while loop # is necessary because we might read several data+terminator # combos with a single recv(4096). while self.ac_in_buffer: lb = len(self.ac_in_buffer) terminator = self.get_terminator() if not terminator: # no terminator, collect it all self.collect_incoming_data (self.ac_in_buffer) self.ac_in_buffer = '' elif isinstance(terminator, int) or isinstance(terminator, long): # numeric terminator n = terminator if lb < n: self.collect_incoming_data (self.ac_in_buffer) self.ac_in_buffer = '' self.terminator = self.terminator - lb else: self.collect_incoming_data (self.ac_in_buffer[:n]) self.ac_in_buffer = self.ac_in_buffer[n:] self.terminator = 0 self.found_terminator() else: # 3 cases: # 1) end of buffer matches terminator exactly: # collect data, transition # 2) end of buffer matches some prefix: # collect data to the prefix # 3) end of buffer does not match any prefix: # collect data terminator_len = len(terminator) index = self.ac_in_buffer.find(terminator) if index != -1: # we found the terminator if index > 0: # don't bother reporting the empty string (source of subtle bugs) # Sometimes one needs empty strings! pass sys.stdout.flush() self.collect_incoming_data (self.ac_in_buffer[:index]) self.ac_in_buffer = self.ac_in_buffer[index+terminator_len:] # This does the Right Thing if the terminator is changed here. self.found_terminator() else: # check for a prefix of the terminator index = asynchat.find_prefix_at_end (self.ac_in_buffer, terminator) if index: if index != lb: # we found a prefix, collect up to the prefix self.collect_incoming_data (self.ac_in_buffer[:-index]) self.ac_in_buffer = self.ac_in_buffer[-index:] break else: # no prefix, collect it all self.collect_incoming_data (self.ac_in_buffer) self.ac_in_buffer = ''
def test_find_prefix_at_end(self): self.assertEqual(asynchat.find_prefix_at_end('qwerty\r', '\r\n'), 1) self.assertEqual(asynchat.find_prefix_at_end('qwertydkjf', '\r\n'), 0)
class AsyncHTTPConnection(asynchat.async_chat): _http_vsn = 11 _http_vsn_str = 'HTTP/1.1' response_class = AsyncHTTPResponse default_port = HTTP_PORT auto_open = 1 debuglevel = 0 def __init__(self, host=None, port=None): asynchat.async_chat.__init__(self) self.socket = None # overload asynchat.found_terminator with the function # appropriate for each state self._TERMINATOR_MAP = { _STATE_IDLE: self._no_action, _STATE_CONNECTING: self._no_action, _STATE_ACTIVE: self._no_action, _STATE_ACCEPTING_HEADERS: self._header_data, _STATE_REQUESTING_BODY: self._body_data, _STATE_CHUNK_START: self._chunk_start_data, _STATE_CHUNK_BODY: self._chunk_body_data, _STATE_CHUNK_RESIDUE: self._chunk_residue_data } self.__state = None self.__set_state(_STATE_IDLE) # we accumulate headers in a dictionary so the # caller can write over the headers we supply # (or their own headers if they want) self._headerdict = None self._requestfp = None self._responsefp = None self._chunkfp = None self._set_hostport(host, port) self._willclose = 0 def _set_hostport(self, host, port): if host and port is None: i = string.find(host, ':') if i >= 0: port = int(host[i + 1:]) host = host[:i] else: port = self.default_port self.host = host self.port = port def set_debuglevel(self, level): self.debuglevel = level def connect(self): """ Connect to the host and port specified in __init__. Add ourselves to thhe asyncore polling group """ self.__set_state(_STATE_CONNECTING) self.create_socket(socket.AF_INET, socket.SOCK_STREAM) if self.debuglevel > 0: print "connecting: (%s, %s)" % (self.host, self.port) asyncore.dispatcher.connect(self, (self.host, self.port)) def close(self): """ Close the connection to the HTTP server. And remove ourselves from the asyncore polling group """ if self.debuglevel > 0: print "asynchttp.close() (%s, %s)" % (self.host, self.port) self.connected = 0 if self.socket: asynchat.async_chat.close(self) self._set_hostport(None, None) def send_entity(self, str): """ Send `str' to the server. Actually, we just append str to the block of text to be sent to the server when getresponse is called. Note: the name was changed from httplib's 'HTTPConnection.send()' because it conflicts with asynchat """ if self.debuglevel > 0: print "send_entity %s" self._requestfp.write(str) def putrequest(self, method, url): """Send a request to the server. `method' specifies an HTTP request method, e.g. 'GET'. `url' specifies the object being requested, e.g. '/index.html'. This function actually only starts accumulating the request: nothing gets sent to the server until getresponse() is called. """ if self.debuglevel > 0: print "putrequest %s %s" % (method, url) if not self.__state is _STATE_ACTIVE: raise RequestNotReady("Invalid putrequest() %s" % (self.__state), name=str(self)) self._requestfp = cStringIO.StringIO() if not url: url = '/' self._requestfp.write('%s %s %s\r\n' % (method, url, self._http_vsn_str)) self._headerdict = {} if self._http_vsn == 11: # Issue some standard headers for better HTTP/1.1 compliance # this header is issued *only* for HTTP/1.1 connections. more # specifically, this means it is only issued when the client uses # the new HTTPConnection() class. backwards-compat clients will # be using HTTP/1.0 and those clients may be issuing this header # themselves. we should NOT issue it twice; some web servers (such # as Apache) barf when they see two Host: headers self.putheader('Host', self.host) # note: we are assuming that clients will not attempt to set these # headers since *this* library must deal with the # consequences. this also means that when the supporting # libraries are updated to recognize other forms, then this # code should be changed (removed or updated). # we only want a Content-Encoding of "identity" since we don't # support encodings such as x-gzip or x-deflate. self.putheader('Accept-Encoding', 'identity') # we can accept "chunked" Transfer-Encodings, but no others # NOTE: no TE header implies *only* "chunked" #self.putheader('TE', 'chunked') # if TE is supplied in the header, then it must appear in a # Connection header. #self.putheader('Connection', 'TE') def putheader(self, header, value): """ Send a request header line to the server. For example: h.putheader('Accept', 'text/html') We don't actually send the header here, we stick it in a dictionary, to be sent when getresponse() is called. If you call putheader() with a duplicate key, it will wipe out the existing entry. """ if self.debuglevel > 0: print "putheader %s: %s" % (header, value) self._headerdict[header] = value def endheaders(self): """ Indicate that the last header line has been sent to the server. Actually, we just copy the header dictionary into the request stream to be sent when getresponse() is called. """ if self.debuglevel > 0: print "endheaders" for header, value in self._headerdict.items(): self._requestfp.write('%s: %s\r\n' % (header, value)) # store a blank line to indicate end of headers self._requestfp.write('\r\n') def request(self, method, url, body=None, headers={}): """ Send a complete request to the server. """ if self.debuglevel > 0: print "request" self._send_request(method, url, body, headers) def _send_request(self, method, url, body, headers): if self.debuglevel > 0: print "_send_request" self.putrequest(method, url) if body: self.putheader('Content-Length', str(len(body))) for hdr, value in headers.items(): self.putheader(hdr, value) self.endheaders() if body: self.send_entity(body) def getresponse(self): """ Get the response from the server. This actually starts the process of sending the request to the server. The response will be delivered in handle_response """ self.__set_state(_STATE_ACCEPTING_HEADERS) self.push(self._requestfp.getvalue()) self._requestfp = None # exit this state on a blank line self.set_terminator("\r\n\r\n") self._responsefp = cStringIO.StringIO() def handle_connect(self): """ Notification from asyncore that we are connected """ self.__set_state(_STATE_ACTIVE) if self.debuglevel > 0: print "connected: (%s, %s)" % (self.host, self.port) def handle_close(self): """ Notification from asyncore that the server has closed its end of the connection. If auto_open is TRUE, we will attempt to reopen the connection. """ if self.debuglevel > 0: print "closed by server: (%s, %s) %s" % (self.host, self.port, self.__state) # 2001-03-14 djf If the server closed the connection while we're # requesting body data, it may just be trying to tell us that # we're done if self.__state in [ _STATE_REQUESTING_BODY, _STATE_CHUNK_BODY, _STATE_CHUNK_RESIDUE ]: self.found_terminator() return asynchat.async_chat.handle_close(self) # if auto_open, attempt to reopen the connection if AsyncHTTPConnection.auto_open and self.host: self.connect() def handle_read(self): try: data = self.recv(self.ac_in_buffer_size) except socket.error, why: self.handle_error() return self.ac_in_buffer = self.ac_in_buffer + data # Continue to search for self.terminator in self.ac_in_buffer, # while calling self.collect_incoming_data. The while loop # is necessary because we might read several data+terminator # combos with a single recv(1024). while self.ac_in_buffer: lb = len(self.ac_in_buffer) terminator = self.get_terminator() if terminator is None: # no terminator, collect it all self.collect_incoming_data(self.ac_in_buffer) self.ac_in_buffer = '' elif type(terminator) == type(0): # numeric terminator n = terminator if lb < n: self.collect_incoming_data(self.ac_in_buffer) self.ac_in_buffer = '' self.terminator = self.terminator - lb else: # give back the whole pizza self.collect_incoming_data(self.ac_in_buffer) self.ac_in_buffer = '' self.terminator = 0 self.found_terminator() else: # 3 cases: # 1) end of buffer matches terminator exactly: # collect data, transition # 2) end of buffer matches some prefix: # collect data to the prefix # 3) end of buffer does not match any prefix: # collect data terminator_len = len(terminator) index = string.find(self.ac_in_buffer, terminator) if index != -1: # we found the terminator if index > 0: # don't bother reporting the empty string (source of subtle bugs) self.collect_incoming_data(self.ac_in_buffer[:index]) self.ac_in_buffer = self.ac_in_buffer[index + terminator_len:] # This does the Right Thing if the terminator is changed here. self.found_terminator() else: # check for a prefix of the terminator index = asynchat.find_prefix_at_end( self.ac_in_buffer, terminator) if index: if index != lb: # we found a prefix, collect up to the prefix self.collect_incoming_data( self.ac_in_buffer[:-index]) self.ac_in_buffer = self.ac_in_buffer[-index:] break else: # no prefix, collect it all self.collect_incoming_data(self.ac_in_buffer) self.ac_in_buffer = ''
# collect data to the prefix # 3) end of buffer does not match any prefix: # collect data terminator_len = len(terminator) index = self.ac_in_buffer.find(terminator) if index != -1: # we found the terminator if index > 0: # don't bother reporting the empty string (source of subtle bugs) self.collect_incoming_data (self.ac_in_buffer[:index]) self.ac_in_buffer = self.ac_in_buffer[index+terminator_len:] # This does the Right Thing if the terminator is changed here. self.found_terminator() else: # check for a prefix of the terminator index = find_prefix_at_end (self.ac_in_buffer, terminator) if index: if index != lb: # we found a prefix, collect up to the prefix self.collect_incoming_data (self.ac_in_buffer[:-index]) self.ac_in_buffer = self.ac_in_buffer[-index:] break else: # no prefix, collect it all self.collect_incoming_data (self.ac_in_buffer) self.ac_in_buffer = '' from sys import py3kwarning from warnings import filterwarnings, catch_warnings def initiate_send(self):
# 3) end of buffer does not match any prefix: # collect data terminator_len = len(terminator) index = self.ac_in_buffer.find(terminator) if index != -1: # we found the terminator if index > 0: # don't bother reporting the empty string (source of subtle bugs) self.collect_incoming_data(self.ac_in_buffer[:index]) self.ac_in_buffer = self.ac_in_buffer[index + terminator_len:] # This does the Right Thing if the terminator is changed here. self.found_terminator() else: # check for a prefix of the terminator index = find_prefix_at_end(self.ac_in_buffer, terminator) if index: if index != lb: # we found a prefix, collect up to the prefix self.collect_incoming_data( self.ac_in_buffer[:-index]) self.ac_in_buffer = self.ac_in_buffer[-index:] break else: # no prefix, collect it all self.collect_incoming_data(self.ac_in_buffer) self.ac_in_buffer = '' from sys import py3kwarning from warnings import filterwarnings, catch_warnings
def test_find_prefix_at_end(self): self.assertEqual(asynchat.find_prefix_at_end("qwerty\r", "\r\n"), 1) self.assertEqual(asynchat.find_prefix_at_end("qwertydkjf", "\r\n"), 0)
def handle_read(self): try: data = self.conn.recv(self.ac_in_buffer_size) if len(data) == 0: # issues 2 TCP connect closed will send a 0 size pack self.close_when_done() except socket.error: self.handle_error() return self.ac_in_buffer = self.ac_in_buffer + data # Continue to search for self.terminator in self.ac_in_buffer, # while calling self.collect_incoming_data. The while loop # is necessary because we might read several data+terminator # combos with a single recv(4096). while self.ac_in_buffer: lb = len(self.ac_in_buffer) logger.debug(self.ac_in_buffer) if not self.terminator: # no terminator, collect it all self.collect_incoming_data(self.ac_in_buffer) self.ac_in_buffer = '' elif isinstance(self.terminator, int) or isinstance(self.terminator, long): # numeric terminator n = self.terminator if lb < n: self.collect_incoming_data(self.ac_in_buffer) self.ac_in_buffer = '' self.terminator = self.terminator - lb else: self.collect_incoming_data (self.ac_in_buffer[:n]) self.ac_in_buffer = self.ac_in_buffer[n:] self.terminator = 0 self.found_terminator() else: # 3 cases: # 1) end of buffer matches terminator exactly: # collect data, transition # 2) end of buffer matches some prefix: # collect data to the prefix # 3) end of buffer does not match any prefix: # collect data terminator_len = len(self.terminator) index = self.ac_in_buffer.find(self.terminator) if index != -1: # we found the terminator if index > 0: # don't bother reporting the empty string (source of subtle bugs) self.collect_incoming_data (self.ac_in_buffer[:index]) self.ac_in_buffer = self.ac_in_buffer[index+terminator_len:] # This does the Right Thing if the terminator is changed here. self.found_terminator() else: # check for a prefix of the terminator index = find_prefix_at_end(self.ac_in_buffer, self.terminator) if index: if index != lb: # we found a prefix, collect up to the prefix self.collect_incoming_data (self.ac_in_buffer[:-index]) self.ac_in_buffer = self.ac_in_buffer[-index:] break else: # no prefix, collect it all self.collect_incoming_data(self.ac_in_buffer) self.ac_in_buffer = ''
def handle_read (self): try: data = self.recv (self.ac_in_buffer_size) except socket.error as why: self.handle_error() return self.ac_in_buffer = self.ac_in_buffer + data # Continue to search for self.terminator in self.ac_in_buffer, # while calling self.collect_incoming_data. The while loop # is necessary because we might read several data+terminator # combos with a single recv(1024). while self.ac_in_buffer: lb = len(self.ac_in_buffer) terminator = self.get_terminator() if terminator is None: # no terminator, collect it all self.collect_incoming_data (self.ac_in_buffer) self.ac_in_buffer = '' elif type(terminator) == type(0): # numeric terminator n = terminator if lb < n: self.collect_incoming_data (self.ac_in_buffer) self.ac_in_buffer = '' self.terminator = self.terminator - lb else: # give back the whole pizza self.collect_incoming_data (self.ac_in_buffer) self.ac_in_buffer = '' self.terminator = 0 self.found_terminator() else: # 3 cases: # 1) end of buffer matches terminator exactly: # collect data, transition # 2) end of buffer matches some prefix: # collect data to the prefix # 3) end of buffer does not match any prefix: # collect data terminator_len = len(terminator) index = string.find (self.ac_in_buffer, terminator) if index != -1: # we found the terminator if index > 0: # don't bother reporting the empty string (source of subtle bugs) self.collect_incoming_data (self.ac_in_buffer[:index]) self.ac_in_buffer = self.ac_in_buffer[index+terminator_len:] # This does the Right Thing if the terminator is changed here. self.found_terminator() else: # check for a prefix of the terminator index = asynchat.find_prefix_at_end (self.ac_in_buffer, terminator) if index: if index != lb: # we found a prefix, collect up to the prefix self.collect_incoming_data (self.ac_in_buffer[:-index]) self.ac_in_buffer = self.ac_in_buffer[-index:] break else: # no prefix, collect it all self.collect_incoming_data (self.ac_in_buffer) self.ac_in_buffer = ''