def handle_chunks(headers): '''Generic chunk handling code, used by both client and server. Modifies the passed-in HttpHeaders instance. ''' chunks = [] while True: chunk_head = yield until_eol() if ';' in chunk_head: # we don't support any chunk extensions chunk_head = chunk_head[:chunk_head.find(';')] size = int(chunk_head, 16) if size == 0: break else: chunks.append((yield bytes(size))) _ = yield bytes(2) # ignore trailing CRLF while True: trailer = yield until_eol() if trailer.strip(): headers.add(*tuple(trailer.split(':', 1))) else: body = ''.join(chunks) headers.set('Content-Length', len(body)) headers.remove('Transfer-Encoding') yield up(body) break
def chat_server(addr): my_nick = (yield until_eol()).strip() while True: my_message, other_message = yield (until_eol(), wait('chat_message')) if my_message: yield fire('chat_message', (my_nick, my_message.strip())) else: nick, message = other_message yield "<%s> %s\r\n" % (nick, message)
def _handle_value(self, data): '''Handle function status for successful response for get key. data_size for the size of response i.e value of the key. ''' key = data[0] data_size = int(data[-1]) value = receive(data_size) # After value is received fetch \r\n. until_eol() return key, value
def handle_con(unused): while True: line = until_eol() if line == "": break parts = line.split() cmd = parts[0] if cmd == "get": key = parts[1] try: val = CACHE[key] send("VALUE %s 0 %d\r\n" % (key, len(val))) send(val + "\r\n") except KeyError: pass send("END\r\n") elif cmd == "set": key = parts[1] #exp = parts[2] #flags = parts[3] length = int(parts[4]) val = receive(length + 2)[:length] CACHE[key] = val send("STORED\r\n")
def delay_echo_server(addr): inp = until_eol() for x in xrange(4): sleep(2) send(str(x) + '\r\n') send("you said %s" % inp)
def get_command_header(self): line = until_eol().strip("\r\n") atoms = line.split() cmd = atoms[0].upper() args = make_nulls(atoms[1:]) return cmd, args
def unlock(self, key): send("unlock %s\r\n" % (key, )) response = until_eol() if response[0] == 'u': return if response[0] == 'e': raise DreadlockError(response[2:].strip()) assert False, response
def unlock(self, key): send("unlock %s\r\n" % (key,)) response = until_eol() if response[0] == 'u': return if response[0] == 'e': raise DreadlockError(response[2:].strip()) assert False, response
def chat_server(addr): my_nick = until_eol().strip() while True: evt, data = first(until_eol=True, waits=['chat_message']) if evt == 'until_eol': fire('chat_message', (my_nick, data.strip())) else: nick, message = data send("<%s> %s\r\n" % (nick, message))
def chat_server(addr): my_nick = until_eol().strip() while True: evt, data = first(until_eol=True, waits=["chat_message"]) if evt == "until_eol": fire("chat_message", (my_nick, data.strip())) else: nick, message = data send("<%s> %s\r\n" % (nick, message))
def handle_echo(conn): said = until_eol() out = 'YS:' + said send( out ) for c in out: send( c ) touch()
def chat_server(addr): my_nick = until_eol().strip() while True: ev, val = first(until_eol=True, waits=['chat_message']) if ev == 'until_eol': fire('chat_message', (my_nick, val.strip())) else: nick, message = val send("<%s> %s\r\n" % (nick, message))
def handler(self, remote_addr): host, port = remote_addr[0], remote_addr[1] print "Echo client connected from: %s:%d" % (host, port) while True: try: msg = diesel.until_eol() y = ': '.join(["you said", msg]) diesel.send(y) except Exception as e: print e
def handle_client(*args): type = until_eol().strip().upper() if type == "CLIENT": return ClientHandler()() elif type == "PEER": assert PeerHandler()() elif type == "QUIT": pass else: assert 0, "unknown connection type"
def handler(self, remote_addr): host, port = remote_addr[0], remote_addr[1] print('Echo client connected from: %s:%d' % (host, port)) while True: try: message = diesel.until_eol() your_message = ': '.join(['You said', message]) diesel.send(your_message) except Exception as e: print('Exception:', e)
def lock(self, key, timeout=10.0): ms_timeout = int(timeout * 1000) send("lock %s %d\r\n" % (key, ms_timeout)) response = until_eol() if response[0] == 'l': return if response[0] == 't': raise DreadlockTimeout(key) if response[0] == 'e': raise DreadlockError(response[2:].strip()) assert False, response
def handler(self, remote_addr): host, port = remote_addr[0], remote_addr[1] print "[*] Echo client connected from: %s:%d" % (host, port) while True: try: message = diesel.until_eol() your_message = ": ".join(["You said", message]) diesel.send(your_message) except Exception, e: print "[-] Exception:", e
def keep_clients_alive(self): alive = [] TIMEOUT = 15 # XXX now = time.time() for c, t in clients.items(): if c is None or time.time() - t > TIMEOUT: del clients[c] send("PEER-KEEPALIVE %s\r\n" % (' '.join(clients))) res = until_eol().strip().upper() assert res == "PEER-KEEPALIVE-OKAY"
def handler(self,remote_addr): host,port = remote_addr[0],remote_addr[1] print "[*] Echo client connected from: %s:%d" %(host,port) while True: try: message = diesel.until_eol() your_message = ": ".join(["You said",message]) diesel.send(your_message) except Exception,e: print "[-] Exception:",e
def handler(self, remote_addr): host, port = remote_addr[0], remote_addr[1] print "Echo Client connected from: %s:%d" % (host, port) while True: try: message = diesel.until_eol() your_message = ':'.join(['You said', message]) diesel.send(your_message) except Exception, e: print "error:", e break
def handler(self, remote_addr): """Runs the echo server""" host, port = remote_addr[0], remote_addr[1] print "Echo client connected from: %s:%d" % (host, port) while True: try: message = diesel.until_eol() your_message = ': '.join(['You said', message]) diesel.send(your_message) except Exception as e: print "Exception:", e
def handle_hi(self): line = until_eol().strip() atoms = line.split() cmd = atoms[0].upper() if cmd == "QUIT": return assert cmd == "HI" assert len(atoms) == 2 client_id = atoms[1] self.send_header("HI-HOLA") return client_id
def handler(self, remote_addr): """ Runs the echo server """ host, port = remote_addr[0], remote_addr[1] print "Echo client connected from: %s: %d" %(host, port) while True: try: message = diesel.until_eol() your_message = ':'.join(['You said', message]) diesel.send(your_message) except Exception, e: print "Exceptioin:", e
def keep_clients_alive(self): alive = [] TIMEOUT = 15 # XXX now = time.time() for c, t in clients.items(): if c is None or time.time() - t > TIMEOUT: del clients[c] send("PEER-KEEPALIVE %s\r\n" % ( ' '.join(clients))) res = until_eol().strip().upper() assert res == "PEER-KEEPALIVE-OKAY"
def get(self, key): send("PEER-GET %s\r\n" % (key,)) res = until_eol().strip() parts = res.split(None, 1) cmd = parts[0].upper() if cmd == 'PEER-GET-MISSING': return None else: assert cmd == 'PEER-GET-VALUE' rest = parts[1] value = StoredValue.from_peer_wire(rest) return value
def handler(self, remoteAddr): host = remoteAddr[0] port = remoteAddr[1] print 'Echo client connected %s:%d' % (host, port) while True: try: message = diesel.until_eol() yourMsg = 'You said: ' + message diesel.send(yourMsg) except Exception as e: print '[-]', e break #书中没有这个break,在断开客户端连接的时候会导致服务端进入死循环。加上之后客户端断开连接,服务端并没有结束,而是等待下一个连接
def wait(self, timeout, clocks): parts = chain([timeout], *clocks.iteritems()) rest = ' '.join(map(str, parts)) send("BLOCKON " + rest + "\r\n") response = until_eol().strip() parts = response.split() result, rest = parts[0].upper(), parts[1:] if result == "BLOCKON-DONE": return ConvoyWaitDone(rest[0]) assert result == "BLOCKON-TIMEOUT" return ConvoyWaitTimeout()
def get(self, key): send("PEER-GET %s\r\n" % (key, )) res = until_eol().strip() parts = res.split(None, 1) cmd = parts[0].upper() if cmd == 'PEER-GET-MISSING': return None else: assert cmd == 'PEER-GET-VALUE' rest = parts[1] value = StoredValue.from_peer_wire(rest) return value
def test_pending_events_dont_break_ordering_when_handling_early_values(): # This test confirms that "early values" returned from a Waiter do # not give other pending event sources the chance to switch their # values into the greenlet while it context switches to give other # greenlets a chance to run. # First we setup a fake connection. It mimics a connection that does # not have data waiting in the buffer, and has to wait for the system # to call it back when data is ready on the socket. The delay argument # specifies how long the test should wait before simulating that data # is ready. conn1 = FakeConnection(1, delay=[None, 0.1]) # Next we setup a Queue instance and prime it with a value, so it will # be ready early and return an EarlyValue. q = Queue() q.put(1) # Force our fake connection into the connection stack for the current # loop so we can make network calls (like until_eol). loop = core.current_loop loop.connection_stack.append(conn1) try: # OK, this first() call does two things. # 1) It calls until_eol, finds that no data is ready, and sets up a # callback to be triggered when data is ready (which our # FakeConnection will simulate). # 2) Fetches from the 'q' which will result in an EarlyValue. source, value = diesel.first(until_eol=True, waits=[q]) assert source == q, source # What must happen is that the callback registered to handle data # from the FakeConnection when it arrives MUST BE CANCELED/DISCARDED/ # FORGOTTEN/NEVER CALLED. If it gets called, it will muck with # internal state, and possibly switch back into the running greenlet # with an unexpected value, which will throw off the ordering of # internal state and basically break everything. v = diesel.until_eol() assert v == 'expected value 1\r\n', 'actual value == %r !!!' % (v, ) finally: loop.connection_stack = []
def test_pending_events_dont_break_ordering_when_handling_early_values(): # This test confirms that "early values" returned from a Waiter do # not give other pending event sources the chance to switch their # values into the greenlet while it context switches to give other # greenlets a chance to run. # First we setup a fake connection. It mimics a connection that does # not have data waiting in the buffer, and has to wait for the system # to call it back when data is ready on the socket. The delay argument # specifies how long the test should wait before simulating that data # is ready. conn1 = FakeConnection(1, delay=[None, 0.1]) # Next we setup a Queue instance and prime it with a value, so it will # be ready early and return an EarlyValue. q = Queue() q.put(1) # Force our fake connection into the connection stack for the current # loop so we can make network calls (like until_eol). loop = core.current_loop loop.connection_stack.append(conn1) try: # OK, this first() call does two things. # 1) It calls until_eol, finds that no data is ready, and sets up a # callback to be triggered when data is ready (which our # FakeConnection will simulate). # 2) Fetches from the 'q' which will result in an EarlyValue. source, value = diesel.first(until_eol=True, waits=[q]) assert source == q, source # What must happen is that the callback registered to handle data # from the FakeConnection when it arrives MUST BE CANCELED/DISCARDED/ # FORGOTTEN/NEVER CALLED. If it gets called, it will muck with # internal state, and possibly switch back into the running greenlet # with an unexpected value, which will throw off the ordering of # internal state and basically break everything. v = diesel.until_eol() assert v == 'expected value 1\r\n', 'actual value == %r !!!' % (v,) finally: loop.connection_stack = []
def send_raw_command(self, arguments): cmd, rest = arguments[0], arguments[1:] self._send(cmd, list=rest) line_one = until_eol() if line_one[0] in ('+', '-', ':'): return line_one if line_one[0] == '$': amt = int(line_one[1:]) if amt == -1: return line_one return line_one + receive(amt) + until_eol() if line_one[0] == '*': nargs = int(line_one[1:]) if nargs == -1: return line_one out = line_one for x in xrange(nargs): head = until_eol() out += head out += receive(int(head[1:])) + until_eol() return out
def respond(whois, _addr): """Respond to a single request.""" query = diesel.until_eol().rstrip(CRLF).lower() if FQDN_PATTERN.match(query) is None: diesel.send("; Bad request: '%s'\r\n" % query) return try: diesel.send(whois(query)) except diesel.ClientConnectionError: logger.info("Connection refused") diesel.send("; Connection refused by downstream server\r\n") except Timeout, ex: logger.info("Slow response") diesel.send("; Slow response from %s.\r\n" % ex.server)
def get(self, key): send("GET %s\r\n" % key) response = until_eol().strip() parts = response.split() result, rest = parts[0].upper(), parts[1:] if result == "GET-MISSING": return ConsensusSet([]) elif result == "GET-NULL": clock = rest[0] return ConsensusSet([], clock) else: assert result == "GET-VALUE" clock = rest[0] values = rest[1:] return ConsensusSet(values, clock)
def __call__(self, addr): '''Since an instance of HttpServer is passed to the Service class (with appropriate request_handler established during initialization), this __call__ method is what's actually invoked by diesel. This is our generator, this is our protocol handler. It does protocol work, then calls the request_handler, looking for HttpClose if necessary. ''' while True: chunks = [] try: header_line = yield until_eol() except ConnectionClosed: break method, url, version = parse_request_line(header_line) req = HttpRequest(method, url, version, remote_addr=addr) header_block = yield until('\r\n\r\n') heads = HttpHeaders() heads.parse(header_block) req.headers = heads if req.version >= '1.1' and heads.get_one('Expect') == '100-continue': yield 'HTTP/1.1 100 Continue\r\n\r\n' more_mode = self.check_for_http_body(heads) if more_mode is self.BODY_NONE: req.body = None elif more_mode is self.BODY_CL: req.body = yield bytes(int(heads['Content-Length'])) elif more_mode is self.BODY_CHUNKED: req.body = handle_chunks(heads) leave_loop = False try: yield self.request_handler(req) except HttpClose: leave_loop = True if leave_loop: break
def _get_response(self): '''Identifies whether call status from memcache socket protocol response. Always return response calling _handle_`status` function ''' fl = until_eol().strip() resp_list = fl.split(' ') status = resp_list[0] if status in ERROR_MESSAGES: # Error has occured raise MemCacheError(status) elif status in STATUS_MESSAGES: if hasattr(self, '_handle_%s'%status.lower()): return getattr(self, '_handle_%s'%status.lower())( resp_list[1:]) else: e_message = 'UNKNOWN ERROR' raise MemCacheNotFoundError(e_message)
def __call__(self, addr): '''Since an instance of HttpServer is passed to the Service class (with appropriate request_handler established during initialization), this __call__ method is what's actually invoked by diesel. This is our generator, this is our protocol handler. It does protocol work, then calls the request_handler, looking for HttpClose if necessary. ''' while True: chunks = [] try: header_line = until_eol() except ConnectionClosed: break method, url, version = parse_request_line(header_line) req = HttpRequest(method, url, version, remote_addr=addr) header_block = until('\r\n\r\n') heads = HttpHeaders() heads.parse(header_block) req.headers = heads if req.version >= '1.1' and heads.get_one( 'Expect') == '100-continue': send('HTTP/1.1 100 Continue\r\n\r\n') more_mode = self.check_for_http_body(heads) if more_mode is self.BODY_NONE: req.body = None elif more_mode is self.BODY_CL: req.body = receive(int(heads.get_one('Content-Length'))) elif more_mode is self.BODY_CHUNKED: req.body = handle_chunks(heads) if not self.request_handler(req): break
def getreply(self): """Get a reply from the server. Returns a tuple consisting of: - server response code (e.g. '250', or such, if all goes well) Note: returns -1 if it can't read response code. - server response string corresponding to response code (multiline responses are converted to a single, multiline string). Raises SMTPServerDisconnected if end-of-file is reached. """ resp = [] while 1: try: line = until_eol() except ClientConnectionClosed as e: self.close() raise SMTPServerDisconnected("Connection unexpectedly closed: " + str(e)) if line == '': self.close() raise SMTPServerDisconnected("Connection unexpectedly closed") if self.debuglevel > 0: print>>stderr, 'reply:', repr(line) resp.append(line[4:].strip()) code = line[:3] # Check that the error code is syntactically correct. # Don't attempt to read a continuation line if it is broken. try: errcode = int(code) except ValueError: errcode = -1 break # Check if multiline response. if line[3:4] != "-": break errmsg = "\n".join(resp) if self.debuglevel > 0: print>>stderr, 'reply: retcode (%s); Msg: %s' % (errcode, errmsg) return errcode, errmsg
def respond(whois, addr): """ Respond to a single request. """ query = diesel.until_eol().rstrip(CRLF).lower() if not utils.is_well_formed_fqdn(query): diesel.send("; Bad request: '%s'\r\n" % query) return try: diesel.send(whois(query)) except diesel.ClientConnectionError: logger.info("Connection refused") diesel.send("; Connection refused by downstream server\r\n") except diesel.ConnectionClosed: logger.info("Connection closed by %s", addr) except Timeout, ex: logger.info("Slow response") diesel.send("; Slow response from %s.\r\n" % ex.server)
def recv_command(self): cmd = None while True: raw = until_eol().rstrip() if raw.startswith(':'): prefix, raw = raw[1:].split(' ', 1) else: prefix = None command, raw = raw.split(' ', 1) cmd = IrcCommand(prefix, command, raw) if cmd.command == 'PING': self.send_command('PONG', *cmd.params) elif cmd.command == 'ERROR': raise IrcError(cmd.params[0]) elif type(cmd.command) is int and cmd.command == 433: self.nick += '_' self.do_login() else: break return cmd
def request(self, method, path, headers, body=None): '''Issues a `method` request to `path` on the connected server. Sends along `headers`, and body. Very low level--you must set "host" yourself, for example. It will set Content-Length, however. ''' req = HttpRequest(method, path, '1.1') if body: headers.set('Content-Length', len(body)) yield '%s\r\n%s\r\n\r\n' % (req.format(), headers.format()) if body: yield body resp_line = yield until_eol() version, code, status = resp_line.split(None, 2) code = int(code) header_block = yield until('\r\n\r\n') heads = HttpHeaders() heads.parse(header_block) if heads.get_one('Transfer-Encoding') == 'chunked': body = yield handle_chunks(heads) else: cl = int(heads.get_one('Content-Length', 0)) if cl: body = yield bytes(cl) else: body = None if version < '1.0' or heads.get_one('Connection') == 'close': self.close() yield response((code, heads, body))
def _get_response(self, wake_sig=None): if wake_sig: ev, val = first(until_eol=True, waits=[wake_sig]) if ev != 'until_eol': return None fl = val.strip() else: fl = until_eol().strip() c = fl[0] if c == '+': return fl[1:] elif c == '$': l = int(fl[1:]) if l == -1: resp = None else: resp = receive(l) until_eol() # noop return resp elif c == '*': count = int(fl[1:]) resp = [] if count == -1: return None for x in xrange(count): hl = until_eol() assert hl[0] in ['$', ':', '+'] if hl[0] == '$': l = int(hl[1:]) if l == -1: resp.append(None) else: resp.append(receive(l)) until_eol() # noop elif hl[0] == ':': resp.append(int(hl[1:])) elif hl[0] == '+': resp.append(hl[1:].strip()) return resp elif c == ':': return int(fl[1:]) elif c == '-': e_message = fl[1:] raise RedisError(e_message)
def add_to_set(self, key, value, cap, timeout, lock): send("SET %s %s %s %s %s\r\n" % ( key, value or '_', cap, timeout, int(lock))) response = until_eol().strip() parts = response.split() result, rest = parts[0].upper(), parts[1:] if result == 'SET-TIMEOUT': if timeout == 0: cls = ConvoySetFailed else: cls = ConvoySetTimeout if rest: clock = rest[0] values = rest[1:] return cls(ConsensusSet(values, clock)) else: return cls() else: assert result == "SET-OKAY" clock = rest[0] values = rest[1:] return ConsensusSet(values, clock)
def keep_alive(self): send("KEEPALIVE\r\n") assert until_eol().strip().upper() == "KEEPALIVE-OKAY"
def on_connect(self): send("CLIENT\r\n") send("HI %s\r\n" % nodeid) assert until_eol().strip().upper() == "HI-HOLA"
def save(self, id, key, value, client, rollback): send("SAVE %s %s %s %s %s\r\n" % (id, key, value or '_', client or '_', rollback or '_')) res = until_eol().strip().upper() assert res == "SAVED"