def receive(self): length, = struct.unpack("!I", receive(4)) if length > 4: allbytes = receive(length - 4) else: allbytes = "" self.unpack(allbytes)
def receive(self): length, = struct.unpack('!I', receive(4)) if length > 4: allbytes = receive(length-4) else: allbytes = '' self.unpack(allbytes)
def handle_rfc_6455_frames(self, inq, outq): disconnecting = False while True: typ, val = first(receive=2, waits=[outq]) if typ == 'receive': b1, b2 = unpack(">BB", val) opcode = b1 & 0x0f fin = (b1 & 0x80) >> 7 has_mask = (b2 & 0x80) >> 7 assert has_mask == 1, "Frames must be masked" if opcode == 8: inq.put(WebSocketDisconnect()) if disconnecting: break disconnecting = True assert opcode in [1,8], "Currently only opcodes 1 & 8 are supported (opcode=%s)" % opcode length = b2 & 0x7f if length == 126: length = unpack('>H', receive(2))[0] elif length == 127: length = unpack('>L', receive(8))[0] mask = unpack('>BBBB', receive(4)) if length: payload = array('B', receive(length)) if disconnecting: continue for i in xrange(len(payload)): payload[i] ^= mask[i % 4] try: data = loads(payload.tostring()) inq.put(data) except JSONDecodeError: pass elif typ == outq: if type(val) is WebSocketDisconnect: b1 = 0x80 | (8 & 0x0f) # FIN + opcode send(pack('>BB', b1, 0)) if disconnecting: break disconnecting = True else: payload = dumps(val) b1 = 0x80 | (1 & 0x0f) # FIN + opcode payload_len = len(payload) if payload_len <= 125: header = pack('>BB', b1, payload_len) elif payload_len > 125 and payload_len < 65536: header = pack('>BBH', b1, 126, payload_len) elif payload_len >= 65536: header = pack('>BBQ', b1, 127, payload_len) send(header + payload)
def _put_request_get_response(self, op, data): self._put_request(op, data) header = receive(HEADER_SIZE) length, id, to, code = struct.unpack('<4i', header) message = receive(length - HEADER_SIZE) cutoff = struct.calcsize('<iqii') flag, cid, start, numret = struct.unpack('<iqii', message[:cutoff]) body = decode_all(message[cutoff:]) return (cid, start, numret, body)
def send(self, data, respond=False): """Send raw mongodb data and optionally yield the server's response.""" send(data) if not respond: return '' else: header = receive(HEADER_SIZE) length, id, to, opcode = struct.unpack('<4i', header) body = receive(length - HEADER_SIZE) return header + body
def handle_command(self): header = diesel.receive(8) (sz,) = struct.unpack('>Q', header) data = diesel.receive(sz) stdout_patch = StdoutDispatcher() with stdout_patch: self.interpreter.runsource(data) output = stdout_patch.contents outsz = len(output) outheader = struct.pack('>Q', outsz) diesel.send("%s%s" % (outheader, output))
def handle_data(self): (size, n) = unpack("!ih", receive(6)) values = PgDataRow() for x in xrange(n): (l,) = unpack('!i', receive(4)) if l == -1: values.append(None) else: values.append(receive(l)) return values
def handle_data(self): (size, n) = unpack("!ih", receive(6)) values = PgDataRow() for x in xrange(n): (l, ) = unpack('!i', receive(4)) if l == -1: values.append(None) else: values.append(receive(l)) return values
def runcode(self, ignored_codeobj): if self.current_source: sz = len(self.current_source) header = struct.pack('>Q', sz) diesel.send("%s%s" % (header, self.current_source)) self.current_source = None header = diesel.receive(8) (sz, ) = struct.unpack('>Q', header) if sz: data = diesel.receive(sz) print data.rstrip()
def handle_command(self): header = diesel.receive(8) (sz, ) = struct.unpack('>Q', header) data = diesel.receive(sz) stdout_patch = StdoutDispatcher() with stdout_patch: self.interpreter.runsource(data) output = stdout_patch.contents outsz = len(output) outheader = struct.pack('>Q', outsz) diesel.send("%s%s" % (outheader, output))
def runcode(self, ignored_codeobj): if self.current_source: sz = len(self.current_source) header = struct.pack('>Q', sz) diesel.send("%s%s" % (header, self.current_source)) self.current_source = None header = diesel.receive(8) (sz,) = struct.unpack('>Q', header) if sz: data = diesel.receive(sz) print data.rstrip()
def handle_conn(*args): from diesel.convoy import convoy while True: head = receive(8) typ, size = unpack('=II', head) body = receive(size) if typ == MESSAGE_OUT: env = MessageEnvelope(body) convoy.local_dispatch(env) else: resp = MessageResponse(body) convoy.local_response(resp)
def handle_authentication(self): (size, stat) = unpack("!ii", receive(8)) if stat == 0: return PgAuthOkay() elif stat == 5: return PgAuthClear() elif stat == 5: salt = receive(4) return PgAuthMD5(salt) else: raise NotImplementedError("Only MD5 authentication supported")
def _receive(self): # Receive a protocol buffer from the wire as a response. response_size, = struct.unpack('!i', diesel.receive(4)) raw_response = diesel.receive(response_size) message_code, = struct.unpack('B', raw_response[0]) response = raw_response[1:] if response: pb_cls = MESSAGE_CODE_TO_PB[message_code] pb = pb_cls(response) if message_code == 0: # RpbErrorResp - raise an exception raise RiakErrorResp(pb) return pb
def _receive(self): # Receive a protocol buffer from the wire as a response. response_size, = struct.unpack('!i', diesel.receive(4)) raw_response = diesel.receive(response_size) message_code, = struct.unpack('B',raw_response[0]) response = raw_response[1:] if response: pb_cls = MESSAGE_CODE_TO_PB[message_code] pb = pb_cls(response) if message_code == 0: # RpbErrorResp - raise an exception raise RiakErrorResp(pb) return pb
def handle_error(self): (size,) = unpack("!i", receive(4)) size -= 4 d = {} while size: (key,) = unpack('!b', receive(1)) if key == 0: break value = until('\0') size -= (1 + len(value)) d[key] = value[:-1] raise PgServerError(d[ord('M')])
def handle_error(self): (size, ) = unpack("!i", receive(4)) size -= 4 d = {} while size: (key, ) = unpack('!b', receive(1)) if key == 0: break value = until('\0') size -= (1 + len(value)) d[key] = value[:-1] raise PgServerError(d[ord('M')])
def connect(self, user="", password="", database=""): StartupMessage(user=user, database=database).send() response = receive(1) msg = MessageTypes[response]() msg.receive() if msg.authtype == "md5": pmsg = PasswordMessage(user=user, password=password, salt=msg.salt) pmsg.send() response = receive(1) msg = MessageTypes[response]() msg.receive() if msg.authtype != "ok": raise Exception("Authentication failed") for msg in self._fetch_until_ready(): pass
def handle_row_description(self): (size, n) = unpack("!ih", receive(6)) names = [] types = [] for x in xrange(n): name = until('\0')[:-1] names.append(name) taboid, fattnum, typoid, sz, typmod, fmt = \ unpack('!ihihih', receive(18)) assert fmt == 0 types.append(typoid) return PgRowDescriptor(names, types)
def connect(self, user='', password='', database=''): StartupMessage(user=user, database=database).send() response = receive(1) msg = MessageTypes[response]() msg.receive() if msg.authtype == 'md5': pmsg = PasswordMessage(user=user, password=password, salt=msg.salt) pmsg.send() response = receive(1) msg = MessageTypes[response]() msg.receive() if msg.authtype != 'ok': raise Exception('Authentication failed') for msg in self._fetch_until_ready(): pass
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. ''' data = None while True: try: h = HttpParser() body = [] while True: if data: used = h.execute(data, len(data)) if h.is_headers_complete(): body.append(h.recv_body()) if h.is_message_complete(): data = data[used:] break data = receive() env = h.get_wsgi_environ() if 'HTTP_CONTENT_LENGTH' in env: env['CONTENT_LENGTH'] = env.pop("HTTP_CONTENT_LENGTH") if 'HTTP_CONTENT_TYPE' in env: env['CONTENT_TYPE'] = env.pop("HTTP_CONTENT_TYPE") env.update({ 'wsgi.version': (1, 0), 'wsgi.url_scheme': 'http', # XXX incomplete 'wsgi.input': cStringIO.StringIO(''.join(body)), 'wsgi.errors': FileLikeErrorLogger(hlog), 'wsgi.multithread': False, 'wsgi.multiprocess': False, 'wsgi.run_once': False, 'REMOTE_ADDR': addr[0], 'SERVER_NAME': HOSTNAME, 'SERVER_PORT': str(self.port), }) req = Request(env) resp = self.request_handler(req) if 'Server' not in resp.headers: resp.headers.add('Server', SERVER_TAG) if 'Date' not in resp.headers: resp.headers.add( 'Date', utcnow().strftime("%a, %d %b %Y %H:%M:%S UTC")) assert resp, "HTTP request handler _must_ return a response" self.send_response(resp, version=h.get_version()) if (not h.should_keep_alive()) or \ resp.headers.get('Connection', '').lower() == "close" or \ resp.headers.get('Content-Length') == None: return except ConnectionClosed: break
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 handle_param(self): (size, ) = unpack("!i", receive(4)) size -= 4 key = until('\0') value = until('\0') assert len(key) + len(value) == size self.params[key[:-1]] = value[:-1]
def handle_param(self): (size,) = unpack("!i", receive(4)) size -= 4 key = until('\0') value = until('\0') assert len(key) + len(value) == size self.params[key[:-1]] = value[:-1]
def _fetch_until_ready(self): while True: response = receive(1) msg = MessageTypes[response]() msg.receive() yield msg if isinstance(msg, ReadyForQueryMessage): break
def handle_echo(conn): size = int((until('|'))[:-1]) said = receive(size) out = 'YS:' + said send(out) touch()
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 request(self, method, path, headers, body=None, timeout=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. ''' timeout_handler = TimeoutHandler(timeout or 60) req = HttpRequest(method, path, '1.1') if body: headers.set('Content-Length', len(body)) send('%s\r\n%s\r\n\r\n' % (req.format(), headers.format())) if body: send(body) ev, val = first(until_eol=True, sleep=timeout_handler.remaining()) if ev == 'sleep': timeout_handler.timeout() resp_line = val try: version, code, reason = resp_line.split(None, 2) except ValueError: # empty reason string version, code = resp_line.split(None, 1) reason = '' code = int(code) ev, val = first(until="\r\n\r\n", sleep=timeout_handler.remaining()) if ev == 'sleep': timeout_handler.timeout() header_block = val heads = HttpHeaders() heads.parse(header_block) if method == 'HEAD': body = None elif heads.get_one('Transfer-Encoding') == 'chunked': body = handle_chunks(heads, timeout_handler.remaining()) elif heads.get_one( 'Connection') == 'close' and 'Content-Length' not in heads: body = '' try: while True: s = receive(2**16) body += s except ConnectionClosed, e: if e.buffer: body += e.buffer
def request(self, method, path, headers, body=None, timeout=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. ''' timeout_handler = TimeoutHandler(timeout or 60) req = HttpRequest(method, path, '1.1') if body: headers.set('Content-Length', len(body)) send('%s\r\n%s\r\n\r\n' % (req.format(), headers.format())) if body: send(body) ev, val = first(until_eol=True, sleep=timeout_handler.remaining()) if ev == 'sleep': timeout_handler.timeout() resp_line = val try: version, code, reason = resp_line.split(None, 2) except ValueError: # empty reason string version, code = resp_line.split(None, 1) reason = '' code = int(code) ev, val = first(until="\r\n\r\n", sleep=timeout_handler.remaining()) if ev == 'sleep': timeout_handler.timeout() header_block = val heads = HttpHeaders() heads.parse(header_block) if method == 'HEAD': body = None elif heads.get_one('Transfer-Encoding') == 'chunked': body = handle_chunks(heads, timeout_handler.remaining()) elif heads.get_one('Connection') == 'close' and 'Content-Length' not in heads: body = '' try: while True: s = receive(2**16) body += s except ConnectionClosed, e: if e.buffer: body += e.buffer
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 holla_back(addr): while True: #message = diesel.receive() #print '%x\n' % message #print '%r\n' % message buffer = diesel.receive(4) print "%r\n" % buffer query_size, = struct.unpack('<i', buffer) print "query size %r" % query_size message = diesel.receive(query_size) print "receive :%r" % message command = Command(config.config['command']) result = command.handle(message) print "reply : %r" % result result_size = len(result) total_size = result_size fmt = "<i%ds" % result_size print result_size diesel.send(struct.pack(fmt, total_size, result))
def _read_frame(self, timeout=-1): self.timeout = timeout frame = StompFrame(None, { }, None) # command is first frame.command = self._readline().strip() # read headers content_length = 0 line = self._readline() while line.strip() != "": pos = line.find(":") if pos >= 0: key = line[:pos].strip() val = line[(pos+1):].strip() frame.headers[key] = val if key.lower() == "content-length": content_length = int(val) line = self._readline() # read body if content_length > 0: frame.body = diesel.receive(content_length) while True: if diesel.receive(1) == chr(0): break else: body = [ ] c = diesel.receive(1) while c != chr(0): body.append(c) c = diesel.receive(1) frame.body = "".join(body).rstrip("\n").rstrip("\r") # TODO: ActiveMQ sends an extra \n after the null terminator # RabbitMQ doesn't.. spec doesn't seem to mention it. # need a way to detect this anomoly and deal.. #line = self._readline() #print "RECV: command=%s headers=%s body=%s" % \ # (frame.command, frame.headers, frame.body) return frame
def _read_frame(self, timeout=-1): self.timeout = timeout frame = StompFrame(None, {}, None) # command is first frame.command = self._readline().strip() # read headers content_length = 0 line = self._readline() while line.strip() != "": pos = line.find(":") if pos >= 0: key = line[:pos].strip() val = line[(pos + 1):].strip() frame.headers[key] = val if key.lower() == "content-length": content_length = int(val) line = self._readline() # read body if content_length > 0: frame.body = diesel.receive(content_length) while True: if diesel.receive(1) == chr(0): break else: body = [] c = diesel.receive(1) while c != chr(0): body.append(c) c = diesel.receive(1) frame.body = "".join(body).rstrip("\n").rstrip("\r") # TODO: ActiveMQ sends an extra \n after the null terminator # RabbitMQ doesn't.. spec doesn't seem to mention it. # need a way to detect this anomoly and deal.. #line = self._readline() #print "RECV: command=%s headers=%s body=%s" % \ # (frame.command, frame.headers, frame.body) return frame
def echo_server(): """The UDPService callback. Unlike a standard Service callback that represents a connection and takes the remote addr as the first function, a UDPService callback takes no arguments. It is responsible for receiving datagrams from the wire and acting upon them. """ while True: data = receive(datagram) send("you said %s" % data)
def handle_chunks(headers, timeout=None): '''Generic chunk handling code, used by both client and server. Modifies the passed-in HttpHeaders instance. ''' timeout_handler = TimeoutHandler(timeout or 60) chunks = [] while True: ev, val = first(until_eol=True, sleep=timeout_handler.remaining()) if ev == 'sleep': timeout_handler.timeout() chunk_head = val 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(receive(size)) _ = receive(2) # ignore trailing CRLF while True: ev, val = first(until_eol=True, sleep=timeout_handler.remaining()) if ev == 'sleep': timeout_handler.timeout() trailer = val if trailer.strip(): headers.add(*tuple(trailer.split(':', 1))) else: body = ''.join(chunks) headers.set('Content-Length', len(body)) headers.remove('Transfer-Encoding') break return body
def holla(self, message): print "mesage %r" % message #print "json dump %r" % simplejson.loads(message) message = {"command": "login", "sequence_id": 1, "user_name": "blzhang", "password": "******"} message1 = {"command": "publish_notice", "sequence_id": 1, "content": "test"} message2 = {"command": "get_notices", "sequence_id": 1} message3 = {"command": "get_proposal_list", "sequence_id": 1, "start":0, "count":10} message4 = {"command": "publish_reconsider", "sequence_id": 1, "proposal_id":7} message5 = {"command": "get_reconsider_list", "sequence_id": 1, "start":0, "count":10} message6 = {"command": "publish_proposal", "sequence_id": 1, "title": "test", "content": "test"} message7 = {"command": "add_comment", "sequence_id": 7, "proposal_id": 7, "user_name":"name", "comment":"comment comment"} request = msgpack.dumps(message4) length = len(request) fmt = "<i%ds" % length diesel.send(struct.pack(fmt, length, request)) buffer = diesel.receive(4) print "%r\n" % buffer query_size, = struct.unpack('<i', buffer) reply = diesel.receive(query_size) result = msgpack.loads(reply) return result
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. ''' data = None while True: try: h = HttpParser() body = [] while True: if data: used = h.execute(data, len(data)) if h.is_headers_complete(): body.append(h.recv_body()) if h.is_message_complete(): data = data[used:] break data = receive() env = h.get_wsgi_environ() env.update({ 'wsgi.version' : (1,0), 'wsgi.url_scheme' : 'http', # XXX incomplete 'wsgi.input' : cStringIO.StringIO(''.join(body)), 'wsgi.errors' : FileLikeErrorLogger(hlog), 'wsgi.multithread' : False, 'wsgi.multiprocess' : False, 'wsgi.run_once' : False, }) req = Request(env) resp = self.request_handler(req) if 'Server' not in resp.headers: resp.headers.add('Server', SERVER_TAG) if 'Date' not in resp.headers: resp.headers.add('Date', utcnow().strftime("%a, %d %b %Y %H:%M:%S UTC")) assert resp, "HTTP request handler _must_ return a response" self.send_response(resp, version=h.get_version()) if (not h.should_keep_alive()) or \ resp.headers.get('Connection', '').lower() == "close" or \ resp.headers.get('Content-Length') == None: return except ConnectionClosed: break
def __call__(self, addr): """A persistent client<--proxy-->backend connection handler.""" try: backend = None while True: header = receive(HEADER_SIZE) info = struct.unpack('<4i', header) length, id, to, opcode = info body = receive(length - HEADER_SIZE) resp, info, body = self.handle_request(info, body) if resp is not None: # our proxy will respond without talking to the backend send(resp) else: # pass the (maybe modified) request on to the backend length, id, to, opcode = info is_query = opcode in [Ops.OP_QUERY, Ops.OP_GET_MORE] payload = header + body (backend, resp) = self.from_backend(payload, is_query, backend) self.handle_response(resp) except ConnectionClosed: if backend: backend.close()
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 __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) leave_loop = False if not self.request_handler(req): break
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 handle_bind_complete(self): (size, ) = unpack("!i", receive(4)) return PgBindComplete()
def handle_nodata(self): (size, ) = unpack("!i", receive(4))
def handle_portal_suspended(self): (size, ) = unpack("!i", receive(4)) return PgPortalSuspended()
def handle_parameter_description(self): oids = [] (size, n) = unpack("!ih", receive(6)) rest = unpack('!' + ('i' * n), receive(size - 6)) return PgParameterDescription(rest)
def do_upgrade(self, req): if req.headers.get_one('Upgrade') != 'WebSocket': return self.web_handler(req) # do upgrade response org = req.headers.get_one('Origin') if 'Sec-WebSocket-Key1' in req.headers: protocol = (req.headers.get_one('Sec-WebSocket-Protocol') if 'Sec-WebSocket-Protocol' in req.headers else None) key1 = req.headers.get_one('Sec-WebSocket-Key1') key2 = req.headers.get_one('Sec-WebSocket-Key2') key3 = receive(8) num1 = int(''.join(c for c in key1 if c in '0123456789')) num2 = int(''.join(c for c in key2 if c in '0123456789')) assert num1 % key1.count(' ') == 0 assert num2 % key2.count(' ') == 0 final = pack('!II8s', num1 / key1.count(' '), num2 / key2.count(' '), key3) secure_response = hashlib.md5(final).digest() send('''HTTP/1.1 101 Web Socket Protocol Handshake\r Upgrade: WebSocket\r Connection: Upgrade\r Sec-WebSocket-Origin: %s\r Sec-WebSocket-Location: %s\r ''' % (org, self.ws_location)) if protocol: send("Sec-WebSocket-Protocol: %s\r\n" % (protocol, )) send("\r\n") send(secure_response) else: send('''HTTP/1.1 101 Web Socket Protocol Handshake\r Upgrade: WebSocket\r Connection: Upgrade\r WebSocket-Origin: %s\r WebSocket-Location: %s\r WebSocket-Protocol: diesel-generic\r \r ''' % (org, self.ws_location)) inq = Queue() outq = Queue() def wrap(inq, outq): self.web_socket_handler(inq, outq) outq.put(WebSocketDisconnect()) fork(wrap, inq, outq) while True: try: typ, val = first(receive=1, waits=[outq.wait_id]) if typ == 'receive': assert val == '\x00' val = until('\xff')[:-1] if val == '': inq.put(WebSocketDisconnect()) else: data = dict((k, v[0]) if len(v) == 1 else (k, v) for k, v in cgi.parse_qs(val).iteritems()) inq.put(WebSocketData(data)) else: try: v = outq.get(waiting=False) except QueueEmpty: pass else: if type(v) is WebSocketDisconnect: send('\x00\xff') break else: data = dumps(dict(v)) send('\x00%s\xff' % data) except ConnectionClosed: inq.put(WebSocketDisconnect()) raise ConnectionClosed("remote disconnected")
def read_message(self): b = receive(1) return self.msg_handlers[b](self)