def websocket(): print('im in ws') env = request.environ uwsgi.websocket_handshake(env['HTTP_SEC_WEBSOCKET_KEY'], env.get('HTTP_ORIGIN', '')) r = redis.StrictRedis(host='localhost', port=6379, db=0) channel = r.pubsub() channel.subscribe('teste_ws') websocket_fd = uwsgi.connection_fd() redis_fd = channel.connection._sock.fileno() while True: print("here in the loop") # wait max 4 seconds to allow ping to be sent ready = gevent.select.select([websocket_fd, redis_fd], [], [], 4.0) # send ping on timeout if not ready[0]: uwsgi.websocket_recv_nb() for fd in ready[0]: if fd == websocket_fd: msg = uwsgi.websocket_recv_nb() if msg: r.publish('teste_ws', msg) elif fd == redis_fd: msg = channel.parse_response() # only interested in user messages if msg[0] == b'message': uwsgi.websocket_send(msg[2])
def __call__(self, environ, start_response): uwsgi.websocket_handshake(environ['HTTP_SEC_WEBSOCKET_KEY'], environ.get('HTTP_ORIGIN', '')) self.r = redis.StrictRedis(host=self.redis_host, port=self.redis_port, db=0) channel = self.r.pubsub() channel.subscribe(self.room) websocket_fd = uwsgi.connection_fd() redis_fd = channel.connection._sock.fileno() core_id = environ['uwsgi.core'] self.setup(core_id) while True: ready = gevent.select.select([websocket_fd, redis_fd], [], [], 4.0) if not ready[0]: uwsgi.websocket_recv_nb() for fd in ready[0]: if fd == websocket_fd: try: msg = uwsgi.websocket_recv_nb() except IOError: self.end(core_id) return "" if msg: self.websocket(core_id, msg) elif fd == redis_fd: msg = channel.parse_response() if msg[0] == 'message': uwsgi.websocket_send(msg[2])
def serve_handler(self, handler, values): def invoke_handler(handler, sock): try: handler(sock, **values) finally: sock.close() th = Thread(target=invoke_handler, args=(handler, self,)) th.setDaemon(True) th.start() try: fd = uwsgi.connection_fd() while not self.evt_close.is_set(): uwsgi.wait_fd_read(fd, 0.3) uwsgi.suspend() _fd = uwsgi.ready_fd() msg = uwsgi.websocket.recv_nb() if msg: self.q_recv.put(msg) try: msg = self.q.get(True, 0.1) if msg: uwsgi.websocket_send(msg) except Empty: pass finally: self.close() th.join() return []
def get_request_socket(self, env): if not self.ca: return None sock = None if env.get('uwsgi.version'): # pragma: no cover try: import uwsgi fd = uwsgi.connection_fd() conn = socket.fromfd(fd, socket.AF_INET, socket.SOCK_STREAM) try: sock = socket.socket(_sock=conn) except: sock = conn except Exception as e: pass elif env.get('gunicorn.socket'): # pragma: no cover sock = env['gunicorn.socket'] if not sock: # attempt to find socket from wsgi.input input_ = env.get('wsgi.input') if input_: if hasattr(input_, '_sock'): # pragma: no cover raw = input_._sock sock = socket.socket(_sock=raw) # pragma: no cover elif hasattr(input_, 'raw'): sock = input_.raw._sock return sock
def get_file_descriptor(self): """Return the file descriptor for the given websocket""" try: return uwsgi.connection_fd() except IOError, e: self.close() raise WebSocketError(e)
def __init__(self, environ, start_response, application): self.environ = environ self.socket = socket.fromfd(uwsgi.connection_fd(), socket.AF_INET, socket.SOCK_STREAM) self.rfile = makefile(self.socket) self.application = application self.start_response = start_response self.request_version = environ['SERVER_PROTOCOL']
def get_raw_socket(cls, env): #pragma: no cover sock = None if env.get('uwsgi.version'): try: import uwsgi fd = uwsgi.connection_fd() sock = socket.fromfd(fd, socket.AF_INET, socket.SOCK_STREAM) except Exception as e: pass elif env.get('gunicorn.socket'): sock = env['gunicorn.socket'] if not sock: # attempt to find socket from wsgi.input input_ = env.get('wsgi.input') if input_: if hasattr(input_, '_sock'): raw = input_._sock sock = socket.socket(_sock=raw) elif hasattr(input_, 'raw'): sock = input_.raw._sock elif hasattr(input_, 'rfile'): # PY3 if hasattr(input_.rfile, 'raw'): sock = input_.rfile.raw._sock # PY2 else: sock = input_.rfile._sock return sock
def __call__(self, environ, start_response): self._sock = uwsgi.connection_fd() self.environ = environ uwsgi.websocket_handshake() self._req_ctx = None if hasattr(uwsgi, 'request_context'): # uWSGI >= 2.1.x with support for api access across-greenlets self._req_ctx = uwsgi.request_context() else: # use event and queue for sending messages from gevent.event import Event from gevent.queue import Queue from gevent.select import select self._event = Event() self._send_queue = Queue() # spawn a select greenlet def select_greenlet_runner(fd, event): """Sets event when data becomes available to read on fd.""" while True: event.set() try: select([fd], [], [])[0] except ValueError: break self._select_greenlet = gevent.spawn( select_greenlet_runner, self._sock, self._event) self.app(self)
def chat(request): try: room = Room.objects.get(pk=1) except: room = None uwsgi.websocket_handshake(request['HTTP_SEC_WEBSOCKET_KEY'], request.get('HTTP_ORIGIN', '')) r = redis.StrictRedis(host='localhost', port=6379, db=0) channel = r.pubsub() channel.subscribe(room.name) websocket_fd = uwsgi.connection_fd() redis_fd = channel.connection._sock.fileno() while True: ready = gevent.select.select([websocket_fd, redis_fd], [], [], 4.0) if not ready[0]: uwsgi.websocket_recv_nb() for fd in ready[0]: if fd == websocket_fd: msg = uwsgi.websocket_recv_nb() if msg: msg = json.loads(msg) if msg['c'] == 'm': first_msg = "%s: %s" % (msg['u'], msg['ms']) second_msg = None if first_msg and not second_msg: r.publish(room.name, first_msg) elif second_msg and first_msg: r.publish(room.name, "%s <br> %s" % (first_msg, second_msg)) elif fd == redis_fd: msg = channel.parse_response() if msg[0] == 'message': uwsgi.websocket_send("[%s] %s" % (time.time(), msg[2]))
def get_file_descriptor(self): """Return the file descriptor for the given websocket""" try: return uwsgi.connection_fd() except IOError as e: self.close() raise WebSocketError(e)
def __call__(self, environ, start_response): uwsgi.websocket_handshake(environ['HTTP_SEC_WEBSOCKET_KEY'], environ.get('HTTP_ORIGIN', '')) print "websockets..." self.r = redis.StrictRedis(host=self.redis_host, port=self.redis_port, db=0) channel = self.r.pubsub() channel.subscribe(self.room) websocket_fd = uwsgi.connection_fd() redis_fd = channel.connection._sock.fileno() core_id = environ['uwsgi.core'] self.setup(core_id) while True: ready = gevent.select.select([websocket_fd, redis_fd], [], [], 4.0) if not ready[0]: uwsgi.websocket_recv_nb() for fd in ready[0]: if fd == websocket_fd: try: msg = uwsgi.websocket_recv_nb() except IOError: self.end(core_id) return "" if msg: self.websocket(core_id, msg) elif fd == redis_fd: msg = channel.parse_response() if msg[0] == 'message': uwsgi.websocket_send(msg[2])
def __call__(self, environ, start_response): self._sock = uwsgi.connection_fd() self.environ = environ uwsgi.websocket_handshake() self._req_ctx = None if hasattr(uwsgi, 'request_context'): # uWSGI >= 2.1.x with support for api access across-greenlets self._req_ctx = uwsgi.request_context() else: # use event and queue for sending messages self._event = Event() self._send_queue = queue.Queue() # spawn a select greenlet def select_greenlet_runner(fd, event): """Sets event when data becomes available to read on fd.""" sel = selectors.DefaultSelector() sel.register(fd, selectors.EVENT_READ) try: while True: sel.select() event.set() except gevent.GreenletExit: sel.unregister(fd) self._select_greenlet = gevent.spawn( select_greenlet_runner, self._sock, self._event) self.app(self)
def application(env, start_response): # complete the handshake uwsgi.websocket_handshake(env['HTTP_SEC_WEBSOCKET_KEY'], env.get('HTTP_ORIGIN', '')) r = redis.StrictRedis(host='redis-gandamu', port=6379, db=0) channel = r.pubsub() channel.subscribe('portfolio') websocket_fd = uwsgi.connection_fd() redis_fd = channel.connection._sock.fileno() while True: uwsgi.wait_fd_read(websocket_fd, 3) uwsgi.wait_fd_read(redis_fd) uwsgi.suspend() fd = uwsgi.ready_fd() if fd > -1: if fd == websocket_fd: msg = uwsgi.websocket_recv_nb() if msg: r.publish('portfolio', msg) elif fd == redis_fd: msg = channel.parse_response() # only interested in user messages t = 'message' if sys.version_info[0] > 2: t = b'message' if msg[0] == t: json = msg[2].decode('utf-8') uwsgi.websocket_send("%s" % json) # uwsgi.websocket_send("[%s] %s" % (time.time(), msg)) else: # on timeout call websocket_recv_nb again to manage ping/pong msg = uwsgi.websocket_recv_nb() if msg: r.publish('portfolio', msg)
def __call__(self, environ, start_response): self.environ = environ uwsgi.websocket_handshake() self._req_ctx = None if hasattr(uwsgi, 'request_context'): # uWSGI >= 2.1.x with support for api access across-greenlets self._req_ctx = uwsgi.request_context() else: # use event and queue for sending messages from gevent.event import Event from gevent.queue import Queue from gevent.select import select self._event = Event() self._send_queue = Queue() # spawn a select greenlet def select_greenlet_runner(fd, event): """Sets event when data becomes available to read on fd.""" while True: event.set() select([fd], [], [])[0] self._select_greenlet = gevent.spawn( select_greenlet_runner, uwsgi.connection_fd(), self._event) return self.app(self)
def __init__(self, env, startresponse): if env['PATH_INFO'] == '/': print('in init method') uwsgi.websocket_handshake(env['HTTP_SEC_WEBSOCKET_KEY'], env.get('HTTP_ORIGIN', '')) r = redis.StrictRedis(host='localhost', port=6379, db=0) channel = r.pubsub() channel.subscribe('websocket') websocket_fd = uwsgi.connection_fd() redis_fd = channel.connection._sock.fileno() while True: # wait max 4 seconds to allow ping to be sent ready = gevent.select.select([websocket_fd, redis_fd], [], [], 4.0) # send ping on timeout if not ready[0]: uwsgi.websocket_recv_nb() for fd in ready[0]: if fd == websocket_fd: # receiving msg = uwsgi.websocket_recv_nb() if msg: # getting message from browser, publishing to redis # receive, sending back answer print('websocket_fd', msg) r.publish('websocket', msg) elif fd == redis_fd: msg = channel.parse_response() # self.send_to_client(msg) if msg[0].decode() == 'message': self.send_pong(msg[2].decode())
def application(env, start_response): '''https://github.com/unbit/uwsgi/blob/master/tests/websockets_chat.py''' uwsgi.websocket_handshake(env['HTTP_SEC_WEBSOCKET_KEY'], env.get('HTTP_ORIGIN', '')) print 'websocket relay connecting...' r = redis.StrictRedis(host='redis', port=6379, db=0) channel = r.pubsub() channel.subscribe('broadcast') websocket_fd = uwsgi.connection_fd() redis_fd = channel.connection._sock.fileno() while True: # wait max 4 seconds to allow ping to be sent ready = gevent.select.select([websocket_fd, redis_fd], [], [], 4.0) # send ping on timeout if not ready[0]: uwsgi.websocket_recv_nb() for fd in ready[0]: if fd == websocket_fd: msg = uwsgi.websocket_recv_nb() if msg: r.publish('incoming', msg) elif fd == redis_fd: msg = channel.parse_response() # only interested in user messages if msg[0] == 'message': uwsgi.websocket_send(msg[-1])
def websocket_view(context, request): uwsgi.websocket_handshake() this = greenlet.getcurrent() this.has_message = False q_in = asyncio.Queue() q_out = asyncio.Queue() # make socket proxy if inspect.isclass(view): view_callable = view(context, request) else: view_callable = view ws = UWSGIWebsocket(this, q_in, q_out) # start monitoring websocket events asyncio.get_event_loop().add_reader( uwsgi.connection_fd(), uwsgi_recv_msg, this ) # NOTE: don't use synchronize because we aren't waiting # for this future, instead we are using the reader to return # to the child greenlet. future = asyncio.Future() asyncio.async( run_in_greenlet(this, future, view_callable, ws) ) # switch to open this.parent.switch() while True: if future.done(): if future.exception() is not None: raise future.exception() raise WebsocketClosed # message in if this.has_message: this.has_message = False try: msg = uwsgi.websocket_recv_nb() except OSError: msg = None if msg or msg is None: q_in.put_nowait(msg) # message out if not q_out.empty(): msg = q_out.get_nowait() try: uwsgi.websocket_send(msg) except OSError: q_in.put_nowait(None) this.parent.switch()
def websocket_view(context, request): uwsgi.websocket_handshake() this = greenlet.getcurrent() this.has_message = False q_in = asyncio.Queue() q_out = asyncio.Queue() # make socket proxy if inspect.isclass(view): view_callable = view(context, request) else: view_callable = view ws = UWSGIWebsocket(this, q_in, q_out) # start monitoring websocket events asyncio.get_event_loop().add_reader(uwsgi.connection_fd(), uwsgi_recv_msg, this) # NOTE: don't use synchronize because we aren't waiting # for this future, instead we are using the reader to return # to the child greenlet. future = asyncio.Future() asyncio. async (run_in_greenlet(this, future, view_callable, ws)) # switch to open this.parent.switch() while True: if future.done(): if future.exception() is not None: raise WebsocketClosed from future.exception() raise WebsocketClosed # message in if this.has_message: this.has_message = False try: msg = uwsgi.websocket_recv_nb() except OSError: msg = None if UWSGIWebsocketMapper.use_str: with suppress(Exception): print('howdy') msg = bytes.decode(msg) if msg or msg is None: q_in.put_nowait(msg) # message out if not q_out.empty(): msg = q_out.get_nowait() try: uwsgi.websocket_send(msg) except OSError: q_in.put_nowait(None) this.parent.switch()
def request_id(): """ uwsgi.request_id is broken on async mode This function, used along with request_id_inc return a unique request id in current worker. """ fd = uwsgi.connection_fd() return fd * uwsgi.opt.get("async-cores", 64) + _fd_count[fd]
def application(e, sr): if e['PATH_INFO'] == '/phys': uwsgi.websocket_handshake() w = World() me = Box('box0', w, 1000, 250, -1000, 250, 0) box1 = Box('box1', w, 20, 50, -1000, 250, 0) box2 = Box('box2', w, 20, 50, -1500, 350, 0) box3 = Box('box3', w, 20, 50, -1500, 450, 0) box4 = Box('box4', w, 200, 150, -1500, 550, 0) ramp = Ramp('ramp0', w, 400, 0, 100, 7000, 10, 400) print "BOX DRAWING COMPLETE" gevent.spawn(physic_engine, w) ufd = uwsgi.connection_fd() while True: ready = gevent.select.select([ufd, w.redis_fd], [], [], timeout=4.0) if not ready[0]: uwsgi.websocket_recv_nb() for fd in ready[0]: if fd == ufd: try: msg = uwsgi.websocket_recv_nb() if msg == 'fw': orientation = me.body.getOrientation() v = Vector3(0, 0, 5000).rotate(orientation.getAxis(), orientation.getAngle()) me.body.activate(True) me.body.applyCentralImpulse( v ) elif msg == 'bw': orientation = me.body.getOrientation() v = Vector3(0, 0, -5000).rotate(orientation.getAxis(), orientation.getAngle()) me.body.activate(True) me.body.applyCentralImpulse( v ) elif msg == 'rl': orientation = me.body.getOrientation() v = Vector3(0, 2000000, 0).rotate(orientation.getAxis(), orientation.getAngle()) me.body.activate(True) me.body.applyTorqueImpulse( v ) elif msg == 'rr': orientation = me.body.getOrientation() v = Vector3(0, -2000000, 0).rotate(orientation.getAxis(), orientation.getAngle()) me.body.activate(True) me.body.applyTorqueImpulse( v ) #me.body.applyForce( Vector3(0, 0, 10000), Vector3(-200, 0, 0)) #me.body.applyForce( Vector3(0, 0, -10000), Vector3(200, 0, 0)) except IOError: import sys print sys.exc_info() return [""] elif fd == w.redis_fd: msg = w.channel.parse_response() if msg[0] == 'message': uwsgi.websocket_send(msg[2])
def __init__(self, ws, channel, fawn): if uwsgi is None: abort(412) self.websocket_fd = uwsgi.connection_fd() self.fawn = fawn self.ws = ws self.handle_connection(fawn.connection_factory, fawn.channels) self.db_fd = os.dup(self.connection.fileno()) self.channel = channel
def request_id_inc(): """ uwsgi.request_id is broken on async mode This function, called on every request, ensures that ours request_id return value is unique for current worker. """ fd = uwsgi.connection_fd() count = _fd_count.get(fd, -1) + 1 _fd_count[fd] = count % uwsgi.opt.get("async-cores", 64)
def application(self, request): if 'HTTP_SEC_WEBSOCKET_KEY' not in request.environ: return JSONResponse(self.http_error, status=status.HTTP_400_BAD_REQUEST) uwsgi.websocket_handshake(request.environ['HTTP_SEC_WEBSOCKET_KEY'], request.environ.get('HTTP_ORIGIN', '')) # setup events send_event = Event() send_queue = Queue() recv_event = Event() recv_queue = Queue() client = self.client(request, uwsgi.connection_fd(), send_event, send_queue, recv_event, recv_queue) # spawn handler handler = gevent.spawn(self.ws_handler, request, client) # spawn recv listener listener = gevent.spawn(self.listener_func, client, recv_event) while True: if not client.connected: recv_queue.put(None) if listener is not None: listener.kill() handler.join(client.timeout) return '' # wait for event to draw our attention gevent.wait([handler, send_event, recv_event], None, 1) # handle receive events if recv_event.is_set(): listener = self.handle_recv_event(client, recv_event, recv_queue) # handle send events elif send_event.is_set(): self.handle_send_event(client, send_event, send_queue) # handler done, we're outta here elif handler.ready(): listener.kill() return ''
def GET(self): env = web.ctx.env uwsgi.websocket_handshake(env['HTTP_SEC_WEBSOCKET_KEY'], env.get('HTTP_ORIGIN', '')) websocket_fd = uwsgi.connection_fd() inputs = [websocket_fd] while True: readable, _, _ = select.select(inputs, [], [], 1.0) for fid in readable: if fid == websocket_fd: data = uwsgi.websocket_recv_nb() now = datetime.datetime.now() print("{0}: Received ws message: '{1}'".format(now, data))
def recv(server, sock): while not sock.evt_open.is_set(): time.sleep(0.05) if hasattr(server, 'on_open'): server.on_open(self) try: fd = uwsgi.connection_fd() while not sock.evt_close.is_set(): uwsgi.wait_fd_read(fd, 1.0) uwsgi.suspend() _fd = uwsgi.ready_fd() msg = uwsgi.websocket_recv_nb() if msg: frame = (1, OP_TEXT, msg) server.on_message(sock, frame) finally: sock.evt_close.set()
def app(environ, start_response): match = re.match('/(?P<job_id>.+)/', environ['PATH_INFO']) if not match: start_response('404', [('Content-Type', 'text/plain')]) job_id = match.group('job_id') uwsgi.websocket_handshake(environ['HTTP_SEC_WEBSOCKET_KEY'], environ.get('HTTP_ORIGIN', '')) # Emit the backlog of messages lines = redis.lrange(job_id, 0, -1) send_message('message', ''.join(lines)) channel = redis.pubsub() channel.subscribe(job_id) channel_socket_fd = channel.connection._sock.fileno() websocket_fd = uwsgi.connection_fd() while True: rlist, _, _ = gevent.select.select([channel_socket_fd, websocket_fd], [], [], 5.0) if rlist: for fd in rlist: if fd == channel_socket_fd: message = channel.parse_response() # See http://redis.io/topics/pubsub for format of `message` if message[0] == 'message': send_message('message', message[2]) elif fd == websocket_fd: # Let uwsgi do it's job to receive pong and send ping uwsgi.websocket_recv_nb() else: # Have not heard from the channel and the client in 5 seconds... try: # Check if the client is still here by sending ping # (`websocket_recv` sends ping implicitly, # `websocket_recv_nb` -- non-blocking variant of it) uwsgi.websocket_recv_nb() except IOError: break # Check if the job is still ongoing if not redis.exists(job_id): send_message('status', 'finished') break return ''
def start(self): self.init_context() if self.context['access_level'] < self.channel.min_access_level: raise ClientError('Insufficient privileges.') uwsgi.websocket_handshake() self.websocket_fd = uwsgi.connection_fd() logger.info(f'<Client {self.id}> Opening websocket connection') client_count = self.redis.get('websocket-clients') if client_count: client_count = int(client_count.decode('utf-8')) if client_count >= config.websockets_max_clients: raise ClientError('No available slots.') self.redis.incr('websocket-clients') self.state = ClientState.started self.fd_select_job = gevent.spawn(self._fd_select) self.spawn_jobs() self.main_loop()
def application(e, sr): if e['PATH_INFO'] == '/phys': uwsgi.websocket_handshake() w = World() me = Box('box0', w, 900, 200) me.set_pos(0, 1150, 0) box1 = Box('box1', w, 20, 50) box1.set_pos(0, 250, 0) box2 = Box('box2', w, 20, 50) box2.set_pos(0, 350, 0) box3 = Box('box3', w, 20, 50) box3.set_pos(0, 450, 0) box4 = Box('box4', w, 200, 150) box4.set_pos(0, 550, 0) gevent.spawn(physic_engine, w) ufd = uwsgi.connection_fd() while True: ready = gevent.select.select([ufd, w.redis_fd], [], [], timeout=4.0) if not ready[0]: uwsgi.websocket_recv_nb() for fd in ready[0]: if fd == ufd: try: msg = uwsgi.websocket_recv_nb() if msg == 'fw': me.body.addForce((0, 250, 0)) except IOError: import sys print sys.exc_info() return [""] elif fd == w.redis_fd: msg = w.channel.parse_response() if msg[0] == 'message': uwsgi.websocket_send(msg[2])
def _start_websocket(): """ This is the most important piece of the code. It's the only one that is allowed to use the uwsgi websocket api. It deals with receiving: - spawn a _listen greenlet _ when notified that the websocket fd is ready, it will fetch the message, and push it to the right handler and writing: - spawns a handler whenever necessary - when notified that a handler wants to writes, does the writing :return: """ assert request.headers.get('Upgrade') == "websocket", "/websockets is only available for websocket protocol" assert uwsgi is not None, "You must run your app using uwsgi if you want to use the /websockets route" env = request.headers.environ uwsgi.websocket_handshake(env['HTTP_SEC_WEBSOCKET_KEY'], env.get('HTTP_ORIGIN', '')) # engage in websocket _websocket_handlers['_websocket_listen'] = spawn(_listen, uwsgi.connection_fd()) # Spawn greenlet that will listen to fd while True: ready = wait([_websocket_send_event, _websocket_recv_event], None, 1) # wait for events if ready: # an event was set if ready[0] == _websocket_recv_event: try: msg = uwsgi.websocket_recv_nb() except IOError: _kill_all() return if msg: json_msg = json.loads(msg) handler = _websocket_handlers[json_msg['namespace']] handler.go(json_msg) _websocket_recv_event.clear() elif ready[0] == _websocket_send_event: # One or more handlers requested a message to be sent while True: try: msg = _websocket_send_queue.get_nowait() except Empty: break uwsgi.websocket_send(json.dumps(msg)) _websocket_send_event.clear()
def application(env, start_response): parse = parse_qs(env['QUERY_STRING']) if 'uid' not in parse: print('Connection error: uid not found') return '' uid = parse['uid'][0] uwsgi.websocket_handshake(env['HTTP_SEC_WEBSOCKET_KEY'], env.get('HTTP_ORIGIN', '')) print('Connection to websocket %s', uid) channel = rd.pubsub() channel.subscribe(uid) print('Subscribe to channel %s', uid) ws_fd = uwsgi.connection_fd() rd_fd = channel.connection._sock.fileno() while True: # wait max 4 seconds to allow ping to be sent ready = select.select([ws_fd, rd_fd], [], [], 4.0) # send ping on timeout if not ready[0]: uwsgi.websocket_recv_nb() for fd in ready[0]: if fd == ws_fd: try: msg = uwsgi.websocket_recv_nb() if msg: print('Pub msg %s', msg) rd.publish(uid, msg) except IOError: print('Websocket Closed: %s', uid) return '' elif fd == rd_fd: msg = channel.parse_response() # only interested in user messages if msg[0] == 'message': print('Send msg %s', msg[2]) uwsgi.websocket_send(msg[2])
def run(self): websocket_fd = uwsgi.connection_fd() channel_fd = self.channel.connection._sock.fileno() fds = [websocket_fd, channel_fd] try: while True: readable, _, _ = select.select(fds, [], [], TIMEOUT) if not readable: self.recv() continue self.recv() data = self.channel.get_message(ignore_subscribe_messages=True) if data: self.on_channel_data(data) except self.WebSocketError: return HttpResponse('ws ok') finally: self.channel.unsubscribe() self.on_connection_lost()
def wsSubData_nb(self): """Websocket subscribe redis pubsub nonbolocking. Keepalive websocket connection with client.""" uwsgi.websocket_handshake(self.environ['HTTP_SEC_WEBSOCKET_KEY'], self.environ.get('HTTP_ORIGIN', '')) channel = self.r.pubsub() channel.subscribe(self.channel) channel.parse_response() websocket_fd = uwsgi.connection_fd() redis_fd = channel.connection._sock.fileno() while True: uwsgi.wait_fd_read(websocket_fd, 3) uwsgi.wait_fd_read(redis_fd) uwsgi.suspend() fd = uwsgi.ready_fd() if fd > -1: if fd == websocket_fd: uwsgi.websocket_recv_nb() elif fd == redis_fd: wsdata = channel.parse_response()[2] uwsgi.websocket_send(wsdata) else: uwsgi.websocket_recv_nb() time.sleep(1)
def get(self): def handle_request(r, msg): """Handle request for more messages received from websocket.""" request = json.loads(msg) first = int(request["first_id"]) last = int(request["last_id"]) # Don't fetch more than 50 messages at once: if (last > 0 and (last - 50 > first)) or (last < 0): first = last - 50 pickled_messages = r.lrange(REDIS_MESSAGES_KEY, first, last) messages = [] for pickled_message in pickled_messages: message = pickle.loads(pickled_message) messages.append(message) uwsgi.websocket_send(encode_messages(messages)) # The first thing we need to do is take what seems like a normal HTTP # request and upgrade it to be a websocket request: uwsgi.websocket_handshake(os.getenv('HTTP_SEC_WEBSOCKET_KEY', ''), os.getenv('HTTP_ORIGIN', '')) # Open a connection to the Redis server, and ask to be notified of any # messages on the channel REDIS_CHANNEL: r = redis.StrictRedis(host='localhost', port=6379, db=0) channel = r.pubsub() channel.subscribe(REDIS_CHANNEL) # We then want to go to sleep and wait for messages either from Redis, # or from this websocket. So we need to know their file descriptors: websocket_fd = uwsgi.connection_fd() redis_fd = channel.connection._sock.fileno() while True: # Setup both FDs with epoll so we can wait for messages. Wake up # every 3 seconds to ensure that ping messages get exchanged on the # websocket connection to keep it alive: uwsgi.wait_fd_read(websocket_fd, 3) uwsgi.wait_fd_read(redis_fd) # Put thread to sleep until message arrives or timeout. Note that # if you do not use a suspend engine (such as ugreen) this will just # immediately return without suspending, nothing will work, and you # will get horribly confused. uwsgi.suspend() fd = uwsgi.ready_fd() if fd > -1: if fd == websocket_fd: try: msg = uwsgi.websocket_recv_nb() if msg: handle_request(r, msg) except IOError, e: # Websocket has failed in some way (such as a browser # reload), just close it and let the app re-open if it # is still there to do so: return elif fd == redis_fd: # Got a message from Redis, pass it on to the browser # through the websocket. msg = channel.parse_response() # Redis sends both control messages and user messages # through this fd. Send only user-generated messages to all # clients: if msg[0] == b'message': uwsgi.websocket_send(msg[2]) else: # We got a timeout. Call websocket_recv_nb again to manage # ping/pong: try: msg = uwsgi.websocket_recv_nb() if msg: handle_request(r, msg) except IOError, e: # Websocket has failed in some way (such as a browser # reload), just close it and let the app re-open if it is # still there to do so: return
def application(env, start_response): request = Request(env) try: uwsgi.websocket_handshake(env['HTTP_SEC_WEBSOCKET_KEY'], env.get('HTTP_ORIGIN', '')) except OSError as err: logging.info('handshake_failed') else: with cursor_for_request(request) as cursor: db_connection = cursor.connection db_connection.set_isolation_level(ISOLATION_LEVEL_AUTOCOMMIT) session_id = get_session_id(request, cursor) logging.info('event/table/session/row/%s:connected (role: %s)' % (session_id, env['DB_USER'])) db_conn_fd = db_connection.fileno() websocket_fd = uwsgi.connection_fd() cursor.execute('listen "event/table/session/rows/%i"' % session_id) try: while True: uwsgi.wait_fd_read(websocket_fd) uwsgi.wait_fd_read(db_conn_fd) uwsgi.suspend() fd = uwsgi.ready_fd() if fd == websocket_fd: cmd_json = uwsgi.websocket_recv_nb() if cmd_json: cmd = json.loads(cmd_json.decode('utf-8')) if cmd: try: if cmd['method'] == 'subscribe': selector, type = cmd['args'][ 'selector'].rsplit(':', 1) cursor.execute( "select event.subscribe_session(%s, %s, %s);", (session_id, selector, type)) elif cmd['method'] == 'unsubscribe': selector, type = cmd['args'][ 'selector'].rsplit(':', 1) cursor.execute( "select event.unsubscribe_session(%s, %s, %s);", (session_id, selector, type)) except Warning as err: logging.error(str(err)) uwsgi.websocket_send( json.dumps({ "method": "log", "args": { "level": "warning", "message": err.diag.message_primary } })) elif fd == db_conn_fd: db_connection.poll() if db_connection.notifies: del db_connection.notifies[:] cursor.execute( ''' select * from event.session_queued_events_json(%s) ''', (session_id, )) qe_ids = [] logging.info( 'event/table/session/row/%s:flushing_queue (role: %s)' % (session_id, env['DB_USER'])) for row in cursor: uwsgi.websocket_send(json.dumps( row.event_json)) logging.info( 'event/table/session/row/%s:sent_json (role: %s)' % (session_id, env['DB_USER'])) qe_ids.append(row.queued_event_id) cursor.execute( ''' delete from event.queued_event qe where qe.id = any(%s) ''', (qe_ids, )) else: # handle timeout of above wait_fd_read for ping/pong uwsgi.websocket_recv_nb() except OSError as err: logging.info( 'event/table/session/row/%s:disconnected (role: %s)' % (session_id, env['DB_USER'])) return []
def application(env, start_response): request = Request(env) try: uwsgi.websocket_handshake(env['HTTP_SEC_WEBSOCKET_KEY'], env.get('HTTP_ORIGIN', '')) except OSError as err: logging.info('handshake_failed') else: with cursor_for_request(request) as cursor: db_connection = cursor.connection db_connection.set_isolation_level(ISOLATION_LEVEL_AUTOCOMMIT) db_conn_fd = db_connection.fileno() websocket_fd = uwsgi.connection_fd() logging.info('connection established') try: while True: uwsgi.wait_fd_read(websocket_fd) uwsgi.wait_fd_read(db_conn_fd) uwsgi.suspend() fd = uwsgi.ready_fd() if fd == websocket_fd: cmd_json = uwsgi.websocket_recv_nb() if cmd_json: cmd = json.loads(cmd_json.decode('utf-8')) if cmd: try: if cmd['method'] != 'ping': logging.info('command received: %s' % cmd['method']) if cmd['method'] == 'request': request_method(cmd, cursor) elif cmd['method'] == 'attach': attach_method(cmd, cursor, db_connection, env) elif cmd['method'] == 'detach': detach_method(cmd, cursor, db_connection, env) except Warning as err: logging.error(str(err)) # uwsgi.websocket_send(json.dumps({ # "method": "log", # "args": { # "level": "warning", # "message": err.diag.message_primary # } # })) elif fd == db_conn_fd: handle_db_notifications(db_connection) else: logging.info('timeout reached') # This is never reached # handle timeout of above wait_fd_read for ping/pong uwsgi.websocket_recv_nb() except (OSError, IOError) as err: logging.info('connection closed (role: %s)' % env['DB_USER']) return []
def application(e, sr): if e['PATH_INFO'] == '/phys': uwsgi.websocket_handshake() w = World() me = Box('box0', w, 1000, 250, -1000, 250, 0) box1 = Box('box1', w, 20, 50, -1000, 250, 0) box2 = Box('box2', w, 20, 50, -1500, 350, 0) box3 = Box('box3', w, 20, 50, -1500, 450, 0) box4 = Box('box4', w, 200, 150, -1500, 550, 0) ramp = Ramp('ramp0', w, 400, 0, 100, 7000, 10, 400) print "BOX DRAWING COMPLETE" gevent.spawn(physic_engine, w) ufd = uwsgi.connection_fd() while True: ready = gevent.select.select([ufd, w.redis_fd], [], [], timeout=4.0) if not ready[0]: uwsgi.websocket_recv_nb() for fd in ready[0]: if fd == ufd: try: msg = uwsgi.websocket_recv_nb() if msg == 'fw': orientation = me.body.getOrientation() v = Vector3(0, 0, 5000).rotate(orientation.getAxis(), orientation.getAngle()) me.body.activate(True) me.body.applyCentralImpulse(v) elif msg == 'bw': orientation = me.body.getOrientation() v = Vector3(0, 0, -5000).rotate(orientation.getAxis(), orientation.getAngle()) me.body.activate(True) me.body.applyCentralImpulse(v) elif msg == 'rl': orientation = me.body.getOrientation() v = Vector3(0, 2000000, 0).rotate(orientation.getAxis(), orientation.getAngle()) me.body.activate(True) me.body.applyTorqueImpulse(v) elif msg == 'rr': orientation = me.body.getOrientation() v = Vector3(0, -2000000, 0).rotate(orientation.getAxis(), orientation.getAngle()) me.body.activate(True) me.body.applyTorqueImpulse(v) #me.body.applyForce( Vector3(0, 0, 10000), Vector3(-200, 0, 0)) #me.body.applyForce( Vector3(0, 0, -10000), Vector3(200, 0, 0)) except IOError: import sys print sys.exc_info() return [""] elif fd == w.redis_fd: msg = w.channel.parse_response() if msg[0] == 'message': uwsgi.websocket_send(msg[2])
def application(env, start_response): request = Request(env) try: uwsgi.websocket_handshake(env['HTTP_SEC_WEBSOCKET_KEY'], env.get('HTTP_ORIGIN', '')) except OSError as err: logging.info('handshake_failed') else: with cursor_for_request(request) as cursor: db_connection = cursor.connection db_connection.set_isolation_level(ISOLATION_LEVEL_AUTOCOMMIT) db_conn_fd = db_connection.fileno() websocket_fd = uwsgi.connection_fd() logging.info('connection established') try: while True: uwsgi.wait_fd_read(websocket_fd) uwsgi.wait_fd_read(db_conn_fd) uwsgi.suspend() fd = uwsgi.ready_fd() if fd == websocket_fd: cmd_json = uwsgi.websocket_recv_nb() if cmd_json: cmd = json.loads(cmd_json.decode('utf-8')) if cmd: try: if cmd['method'] != 'ping': logging.info('command received: %s' % cmd['method']) if cmd['method'] == 'request': request_method(cmd, cursor) elif cmd['method'] == 'attach': attach_method(cmd, cursor, db_connection, env) elif cmd['method'] == 'detach': detach_method(cmd, cursor, db_connection, env) except Warning as err: logging.error(str(err)) # uwsgi.websocket_send(json.dumps({ # "method": "log", # "args": { # "level": "warning", # "message": err.diag.message_primary # } # })) elif fd == db_conn_fd: handle_db_notifications(db_connection) else: logging.info( 'timeout reached') # This is never reached # handle timeout of above wait_fd_read for ping/pong uwsgi.websocket_recv_nb() except (OSError, IOError) as err: logging.info('connection closed (role: %s)' % env['DB_USER']) return []
def application(env, sr): ws_scheme = 'ws' if 'HTTPS' in env or env['wsgi.url_scheme'] == 'https': ws_scheme = 'wss' if env['PATH_INFO'] == '/': sr('200 OK', [('Content-Type','text/html')]) output = """ <!doctype html> <html> <head> <meta charset="utf-8"> <script language="Javascript"> var s = new WebSocket("%s://%s/foobar/"); s.onopen = function() { console.log("connected !!!"); s.send("hello"); }; s.onmessage = function(e) { var bb = document.getElementById('blackboard') var html = bb.innerHTML; bb.innerHTML = html + '<br/>' + e.data; }; s.onerror = function(e) { console.log(e); } s.onclose = function(e) { console.log("connection closed"); } function invia() { var value = document.getElementById('testo').value; s.send(value); } </script> </head> <body> <h1>WebSocket</h1> <input type="text" id="testo"/> <input type="button" value="invia" onClick="invia();"/> <div id="blackboard" style="width:640px;height:480px;background-color:black;color:white;border: solid 2px red;overflow:auto"> </div> </body> </html> """ % (ws_scheme, env['HTTP_HOST']) return output.encode() elif env['PATH_INFO'] == '/favicon.ico': return "" elif env['PATH_INFO'] == '/foobar/': uwsgi.websocket_handshake(env['HTTP_SEC_WEBSOCKET_KEY'], env.get('HTTP_ORIGIN', '')) print("websockets...") msg_srv_fd = uwsgi.async_connect("127.0.0.1:8888") websocket_fd = uwsgi.connection_fd() while True: uwsgi.wait_fd_read(websocket_fd, 3) uwsgi.wait_fd_read(msg_srv_fd) uwsgi.suspend() fd = uwsgi.ready_fd() if fd > -1: if fd == websocket_fd: msg = uwsgi.websocket_recv_nb() print("got message over ws: {}".format(msg)) if msg: uwsgi.send(msg_srv_fd, msg) elif fd == msg_srv_fd: msg = uwsgi.recv(msg_srv_fd) print("got message over msg_srv: {}".format(msg)) uwsgi.websocket_send("[%s] %s" % (time.time(), msg.decode())) else: # on timeout call websocket_recv_nb again to manage ping/pong msg = uwsgi.websocket_recv_nb() print("ws ping/pong") if msg: print("got message over ws: {}".format(msg)) uwsgi.send(msg_srv_fd, msg)
def application(env, sr): ws_scheme = 'ws' if 'HTTPS' in env or env['wsgi.url_scheme'] == 'https': ws_scheme = 'wss' if env['PATH_INFO'] == '/': sr('200 OK', [('Content-Type','text/html')]) data = { 'ws_scheme': ws_scheme, 'host': env['HTTP_HOST'], 'id': env['uwsgi.core'], } return HTML%(ws_scheme, data['host']) elif env['PATH_INFO'] == '/foobar/': connection_info = (env['HTTP_SEC_WEBSOCKET_KEY'], env.get('HTTP_ORIGIN', '')) uwsgi.websocket_handshake(env['HTTP_SEC_WEBSOCKET_KEY'], env.get('HTTP_ORIGIN', '')) redis_com = redis.StrictRedis(**redis_conf) channel = redis_com.pubsub() channel.subscribe(COMMON_ROOM_ID) websocket_fd = uwsgi.connection_fd() redis_fd = channel.connection._sock.fileno() core_id = str(env['uwsgi.core']) all_users_info[core_id] = {'redis_channel': channel} print "#########################websockets...", core_id print "REMOTE_ADDR:", env['REMOTE_ADDR'] while True: ready = gevent.select.select([websocket_fd, redis_fd], [], [], 4.0) if not ready[0]: try: msg = uwsgi.websocket_recv_nb() except IOError: print 'disconnect uid ***** no ready', core_id del_user(core_id, redis_com) continue for fd in ready[0]: if fd == websocket_fd: try: msg = uwsgi.websocket_recv_nb() except IOError: print 'disconnect uid ***** no msg', core_id del_user(core_id, redis_com) return '' if msg: print 'this msg str', msg msg_dict = json.loads(msg.replace("\n", "\\n ")) print "~~~~~~~~~~reseve", msg_dict if 'c' not in msg_dict: continue if msg_dict['c'] in ['s', 'rn']: if core_id not in all_users_info: return 'guochen' if msg_dict['u'].strip(): all_users_info[core_id]['user_name'] = msg_dict['u'] else: all_users_info[core_id]['user_name'] = u'游客' + str(core_id) response = get_response_user_msg(c=msg_dict['c']) redis_com.publish(COMMON_ROOM_ID, dumps(response)) response['uname'] = all_users_info[core_id]['user_name'] response['self_id'] = core_id if msg_dict['c'] == 's': response['history_msg'] = history_msg uwsgi.websocket_send(dumps(response)) elif msg_dict['c'] == 'chat': chat_msg = msg_dict['m'].strip() if not chat_msg: continue now_channel = COMMON_ROOM_ID if msg_dict['opp'] != COMMON_ROOM_ID: opp = msg_dict['opp'] now_channel = '|'.join(map(str, sorted(map(int, [core_id, opp])))) if now_channel not in channels: channels.append(now_channel) channel.subscribe(now_channel) all_users_info[opp]['redis_channel'].subscribe(now_channel) redis_com.publish(now_channel,dumps({})) channel.parse_response() #all_users_info[opp]['redis_channel'].parse_response() response = { 'uname': all_users_info[core_id]['user_name'], 'time': str(datetime.datetime.now())[0:-7], 'msg': chat_msg, 'c': 'chat', 'channel': now_channel, } add_history(response) logging.info(response['uname'] +" :\n " + response['msg'] ) response = dumps(response) s = redis_com.publish(now_channel, response) print "why no send", s #print channel.parse_response() #uwsgi.websocket_send(response) elif msg_dict['c'] == 'e': # end print 'disconnect uid ***** client close', core_id del_user(core_id, redis_com) return '' elif fd == redis_fd: msg = channel.parse_response() if msg[0] == 'message': uwsgi.websocket_send(msg[2])
def application(env, sr): ws_scheme = 'ws' if 'HTTPS' in env or env['wsgi.url_scheme'] == 'https': ws_scheme = 'wss' if env['PATH_INFO'] == '/': sr('200 OK', [('Content-Type', 'text/html')]) return (""" <html> <head> <script language="Javascript"> var s = new WebSocket("%s://%s/foobar/"); s.onopen = function() { alert("connected !!!"); s.send("ciao"); }; s.onmessage = function(e) { var bb = document.getElementById('blackboard') var html = bb.innerHTML; bb.innerHTML = html + '<br/>' + e.data; }; s.onerror = function(e) { alert(e); } s.onclose = function(e) { alert("connection closed"); } function invia() { var value = document.getElementById('testo').value; s.send(value); } </script> </head> <body> <h1>WebSocket</h1> <input type="text" id="testo"/> <input type="button" value="invia" onClick="invia();"/> <div id="blackboard" style="width:640px;height:480px;background-color:black;color:white;border: solid 2px red;overflow:auto"> </div> </body> </html> """ % (ws_scheme, env['HTTP_HOST'])).encode() elif env['PATH_INFO'] == '/favicon.ico': return b"" elif env['PATH_INFO'] == '/foobar/': uwsgi.websocket_handshake() print("websockets...") # a future for waiting for redis connection f = GreenFuture() asyncio.Task(redis_subscribe(f)) # the result() method will switch greenlets if needed subscriber = f.result() # open another redis connection for publishing messages f0 = GreenFuture() t = asyncio.Task(redis_open(f0)) connection = f0.result() myself = greenlet.getcurrent() myself.has_ws_msg = False # start monitoring websocket events asyncio.get_event_loop().add_reader(uwsgi.connection_fd(), ws_recv_msg, myself) # add a 4 seconds timer to manage ping/pong asyncio.get_event_loop().call_later(4, ws_recv_msg, myself) # add a coroutine for redis messages f = GreenFuture() asyncio.Task(redis_wait(subscriber, f)) # switch again f.greenlet.parent.switch() while True: # any redis message in the queue ? if f.done(): msg = f.result() uwsgi.websocket_send("[%s] %s" % (time.time(), msg)) # restart coroutine f = GreenFuture() asyncio.Task(redis_wait(subscriber, f)) if myself.has_ws_msg: myself.has_ws_msg = False msg = uwsgi.websocket_recv_nb() if msg: asyncio.Task(redis_publish(connection, msg)) # switch again f.greenlet.parent.switch()
def application(env, sr): ws_scheme = 'ws' if 'HTTPS' in env or env['wsgi.url_scheme'] == 'https': ws_scheme = 'wss' if env['PATH_INFO'] == '/': sr('200 OK', [('Content-Type', 'text/html')]) output = """ <html> <head> <script language="Javascript"> var s = new WebSocket("%s://%s/foobar/"); s.onopen = function() { alert("connected !!!"); s.send("ciao"); }; s.onmessage = function(e) { var bb = document.getElementById('blackboard') var html = bb.innerHTML; bb.innerHTML = html + '<br/>' + e.data; }; s.onerror = function(e) { alert(e); } s.onclose = function(e) { alert("connection closed"); } function invia() { var value = document.getElementById('testo').value; s.send(value); } </script> </head> <body> <h1>WebSocket</h1> <input type="text" id="testo"/> <input type="button" value="invia" onClick="invia();"/> <div id="blackboard" style="width:640px;height:480px;background-color:black;color:white;border: solid 2px red;overflow:auto"> </div> </body> </html> """ % (ws_scheme, env['HTTP_HOST']) if sys.version_info[0] > 2: return output.encode('latin1') return output elif env['PATH_INFO'] == '/favicon.ico': return "" elif env['PATH_INFO'] == '/foobar/': uwsgi.websocket_handshake(env['HTTP_SEC_WEBSOCKET_KEY'], env.get('HTTP_ORIGIN', '')) print("websockets...") r = redis.StrictRedis(host='localhost', port=6379, db=0) channel = r.pubsub() channel.subscribe('foobar') websocket_fd = uwsgi.connection_fd() redis_fd = channel.connection._sock.fileno() while True: uwsgi.wait_fd_read(websocket_fd, 3) uwsgi.wait_fd_read(redis_fd) uwsgi.suspend() fd = uwsgi.ready_fd() if fd > -1: if fd == websocket_fd: msg = uwsgi.websocket_recv_nb() if msg: r.publish('foobar', msg) elif fd == redis_fd: msg = channel.parse_response() print(msg) # only interested in user messages t = 'message' if sys.version_info[0] > 2: t = b'message' if msg[0] == t: uwsgi.websocket_send("[%s] %s" % (time.time(), msg)) else: # on timeout call websocket_recv_nb again to manage ping/pong msg = uwsgi.websocket_recv_nb() if msg: r.publish('foobar', msg)
def application(env, sr): ws_scheme = 'ws' if 'HTTPS' in env or env['wsgi.url_scheme'] == 'https': ws_scheme = 'wss' if env['PATH_INFO'] == '/': sr('200 OK', [('Content-Type','text/html')]) return """ <!DOCTYPE html> <!-- paulirish.com/2008/conditional-stylesheets-vs-css-hacks-answer-neither/ --> <!-- Consider specifying the language of your content by adding the `lang` attribute to <html> --> <!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]--> <!--[if IE 7]> <html class="no-js lt-ie9 lt-ie8"> <![endif]--> <!--[if IE 8]> <html class="no-js lt-ie9"> <![endif]--> <!--[if gt IE 8]><!--> <html class="no-js"> <!--<![endif]--> <head> <!-- hey all! i made this as a prototype thinking of collective instruments and real time web interactivity. A couple days ago I started playing with the web audio api, so this is pretty minimal. I'm putting this out to see how people feel playing with it, and how it fares scaling up. It was built with socketio and node. let me know what you think tweet me at @whichlight, or whichlight at gmail dot com see other projects at http://whichlight.com/ --> <meta charset="utf-8"> <title>dancey dots</title> <meta name="description" content=""> <!-- Mobile viewport optimized: h5bp.com/viewport --> <meta name="viewport" content="width=device-width"> <style type="text/css"> #container{ font-family:helvetica; margin: 0px auto; width:650px; } .synth{ background-color:pink; position: absolute; height: 40px; min-width: 40px; border-radius:20px; z-index:-1; } #info{ position: absolute; right: 10px; bottom: 10px; z-index: 2; padding: 16px 24px; color:grey; font-size:15px; font-family: helvetica; } #fun{ position:absolute; width:100%; height:100%; } </style> </head> <body> <div id="fun"> <div id="info">dancey dots by <a href="http://www.whichlight.com">whichlight</a></div> </div> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script> <script type="text/javascript" src="bower_components/hammerjs/hammer.min.js"></script> <script type="text/javascript" src="main.js"></script> </body> </html> """ elif env['PATH_INFO'] == '/favicon.ico': return "" elif env['PATH_INFO'] == '/foobar/': uwsgi.websocket_handshake(env['HTTP_SEC_WEBSOCKET_KEY'], env.get('HTTP_ORIGIN', '')) print "websockets..." r = redis.StrictRedis(host='localhost', port=6379, db=0) channel = r.pubsub() channel.subscribe('foobar') websocket_fd = uwsgi.connection_fd() redis_fd = channel.connection._sock.fileno() while True: # wait max 4 seconds to allow ping to be sent ready = gevent.select.select([websocket_fd, redis_fd], [], [], 4.0) # send ping on timeout if not ready[0]: uwsgi.websocket_recv_nb() for fd in ready[0]: if fd == websocket_fd: msg = uwsgi.websocket_recv_nb() if msg: r.publish('foobar', msg) elif fd == redis_fd: msg = channel.parse_response() # only interested in user messages if msg[0] == 'message': uwsgi.websocket_send("[%s] %s" % (time.time(), msg))
def ws_async_cgi(self, work, ws_args): try: import uwsgi import greenlet uwsgi.websocket_handshake() print("websockets...") me = greenlet.getcurrent() me.has_ws_msg = False me.task_ending = False me.sq_unregist = False me.rq_unregist = False self.ws = WSClient() for k, v in ws_args.items(): setattr(self.ws, k, v) self.t = asyncio.Task(self.ws_work(me, work)) asyncio.get_event_loop().add_reader(uwsgi.connection_fd(), self.ws_recv_msg, me) f = asyncio.Future() asyncio.Task(self.ws_get_sq_msg(me, self.ws.sq, f)) while not (me.task_ending and me.sq_unregist): me.parent.switch() if f.done(): r = f.result() if r == Exception: me.sq_unregist = True else: uwsgi.websocket_send(r) f = asyncio.Future() asyncio.Task(self.ws_get_sq_msg(me, self.ws.sq, f)) if me.has_ws_msg: me.has_ws_msg = False try: msg = uwsgi.websocket_recv_nb() except OSError: print('.......') self.ws.sq.put(Exception) asyncio.get_event_loop().remove_reader( uwsgi.connection_fd()) me.rq_unregist = True self.t.cancel() continue msg = msg.decode('utf-8') self.ws.rq.put_nowait(msg) if me.rq_unregist == False: asyncio.get_event_loop().remove_reader(uwsgi.connection_fd()) print('exit') except: import traceback traceback.print_exc() return
def application(env, start_response): request = Request(env) try: uwsgi.websocket_handshake(env['HTTP_SEC_WEBSOCKET_KEY'], env.get('HTTP_ORIGIN', '')) except OSError as err: logging.info('handshake_failed') else: with cursor_for_request(request) as cursor: db_connection = cursor.connection db_connection.set_isolation_level(ISOLATION_LEVEL_AUTOCOMMIT) db_conn_fd = db_connection.fileno() websocket_fd = uwsgi.connection_fd() logging.info('connection established') try: while True: uwsgi.wait_fd_read(websocket_fd) uwsgi.wait_fd_read(db_conn_fd) uwsgi.suspend() fd = uwsgi.ready_fd() if fd == websocket_fd: cmd_json = uwsgi.websocket_recv_nb() if cmd_json: cmd = json.loads(cmd_json.decode('utf-8')) if cmd: try: if cmd['method'] != 'ping': logging.info('command received: %s' % cmd['method']) if cmd['method'] == 'request': logging.info( 'websocket endpoint request: %s, %s, %s, %s' % ( cmd['verb'], # HTTP method - GET, POST, PATCH, DELETE cmd['uri'], # selector - '/relation/widget/dependency_js' ImmutableMultiDict( json.loads(cmd['query']) ), # query string arguments - including event.session id json.dumps( cmd['data']) # post data )) cursor.execute( 'select status, message, response, mimetype from endpoint.request2(%s, %s, %s::json, %s::json);', ( cmd['verb'], # HTTP method - GET, POST, PATCH, DELETE cmd['uri'], # selector - '/relation/widget/dependency_js' json.dumps( ImmutableMultiDict( json.loads( cmd['query']) ).to_dict(flat=False) ), # query string arguments - including event.session id json.dumps( cmd['data']) # post data )) result = cursor.fetchone() uwsgi.websocket_send('''{ "method": "response", "request_id": "%s", "data": %s }''' % (cmd['request_id'], result.response)) elif cmd['method'] == 'attach': session_id = cmd['session_id'] if session_id is not None: cursor.execute( 'select event.session_attach(%s);', (session_id, )) logging.info( 'session attached: %s (role: %s)' % (session_id, env['DB_USER'])) handle_db_notifications( db_connection) uwsgi.websocket_send('''{ "method": "response", "request_id": "%s", "data": "true" }''' % (cmd['request_id'], )) elif cmd['method'] == 'detach': session_id = cmd['session_id'] if session_id is not None: cursor.execute( 'select event.session_detach(%s);', (session_id, )) logging.info( 'session detached: %s (role: %s)' % (session_id, env['DB_USER'])) uwsgi.websocket_send('''{ "method": "response", "request_id": "%s", "data": "true" }''' % (cmd['request_id'], )) #uwsgi.websocket_send('''{ # "method": "response", # "request_id": "%s", # "data": %s #}''' % (cmd['request_id'], result.response)) except Warning as err: logging.error(str(err)) # uwsgi.websocket_send(json.dumps({ # "method": "log", # "args": { # "level": "warning", # "message": err.diag.message_primary # } # })) elif fd == db_conn_fd: handle_db_notifications(db_connection) else: logging.info( 'timeout reached') # This is never reached # handle timeout of above wait_fd_read for ping/pong uwsgi.websocket_recv_nb() except (OSError, IOError) as err: logging.info('connection closed (role: %s)' % env['DB_USER']) return []
def __call__(self, e, sr): if e['PATH_INFO'] == '/': sr('200 OK', [('Content-Type', 'text/html')]) return [open('robotab_ws.html').read()] if e['PATH_INFO'] == '/robotab.js': sr('200 OK', [('Content-Type', 'application/javascript')]) return [open('static/js/robotab.js').read()] if e['PATH_INFO'] == '/robotab': uwsgi.websocket_handshake() username, avatar = uwsgi.websocket_recv().split(':') try: robot_coordinates = self.spawn_iterator.next() except StopIteration: self.spawn_iterator = iter(self.spawn_points) robot_coordinates = self.spawn_iterator.next() uwsgi.websocket_send('posters:{}'.format(';'.join(self.posters))) for wall in self.walls: uwsgi.websocket_send('wall:{},{},{},{},{},{},{}'.format(*wall)) player = Player(self, username, avatar, uwsgi.connection_fd(), *robot_coordinates) if (self.started or self.finished or len(self.players) > self.max_players or len(self.waiting_players) > 0): print('{}:{}:{}:{}'.format( self.started, self.finished, len(self.players) > self.max_players, len(self.waiting_players) > 0)) self.waiting_players.append(player) uwsgi.websocket_send("arena:hey {}, wait for next game".format( player.name)) player.wait_for_game() self.waiting_players.remove(player) else: self.players[player.name] = player self.spawn_greenlets() for p in self.players.keys(): self.players[p].update_gfx() while True: ready = gevent.select.select([player.fd, player.redis_fd], [], [], timeout=4.0) if not ready[0]: uwsgi.websocket_recv_nb() for fd in ready[0]: if fd == player.fd: try: msg = uwsgi.websocket_recv_nb() except IOError: import sys print sys.exc_info() if player.name in self.players: player.end('leaver') return [""] if msg and not self.finished: self.msg_handler(player, msg) elif fd == player.redis_fd: msg = player.channel.parse_response() if msg[0] == 'message': uwsgi.websocket_send(msg[2])
def websockets_wrapper(environ, start_response): handler = self.routes.get(environ['PATH_INFO']) if not handler: return app(environ, start_response) # do handshake uwsgi.websocket_handshake( environ['HTTP_SEC_WEBSOCKET_KEY'], environ.get('HTTP_ORIGIN', '')) # setup events send_event = Event() send_queue = Queue(maxsize=1) recv_event = Event() recv_queue = Queue(maxsize=1) # create websocket client wfd = uwsgi.connection_fd() client = self.create_worker( environ, wfd, send_event, send_queue, recv_event, recv_queue) # spawn handler handler = spawn(handler, client) # spawn recv listener def listener(client): ready = select([client.fd], [], [], client.timeout) recv_event.set() listening = spawn(listener, client) while True: if not client.connected: recv_queue.put(None) listening.kill() handler.join(client.timeout) return '' # wait for event to draw our attention ready = wait([handler, send_event, recv_event], None, 1) # handle send events if send_event.is_set(): try: uwsgi.websocket_send(send_queue.get()) send_event.clear() except IOError: client.connected = False # handle receive events elif recv_event.is_set(): recv_event.clear() try: recv_queue.put(uwsgi.websocket_recv_nb()) listening = spawn(listener, client) except IOError: client.close() self.unregister_worker(client) # handler done, we're outta here elif handler.ready(): listening.kill() return ''
def application(env, sr): ws_scheme = 'ws' if 'HTTPS' in env or env['wsgi.url_scheme'] == 'https': ws_scheme = 'wss' if env['PATH_INFO'] == '/': sr('200 OK', [('Content-Type','text/html')]) return """ <html> <head> <script language="Javascript"> var s = new WebSocket("%s://%s/foobar/"); s.onopen = function() { alert("connected !!!"); s.send("ciao"); }; s.onmessage = function(e) { var bb = document.getElementById('blackboard') var html = bb.innerHTML; bb.innerHTML = html + '<br/>' + e.data; }; s.onerror = function(e) { alert(e); } s.onclose = function(e) { alert("connection closed"); } function invia() { var value = document.getElementById('testo').value; s.send(value); } </script> </head> <body> <h1>WebSocket</h1> <input type="text" id="testo"/> <input type="button" value="invia" onClick="invia();"/> <div id="blackboard" style="width:640px;height:480px;background-color:black;color:white;border: solid 2px red;overflow:auto"> </div> </body> </html> """ % (ws_scheme, env['HTTP_HOST']) elif env['PATH_INFO'] == '/favicon.ico': return "" elif env['PATH_INFO'] == '/foobar/': uwsgi.websocket_handshake(env['HTTP_SEC_WEBSOCKET_KEY'], env.get('HTTP_ORIGIN', '')) print "websockets..." r = redis.StrictRedis(host='localhost', port=6379, db=0) channel = r.pubsub() channel.subscribe('foobar') websocket_fd = uwsgi.connection_fd() redis_fd = channel.connection._sock.fileno() while True: # wait max 4 seconds to allow ping to be sent ready = gevent.select.select([websocket_fd, redis_fd], [], [], 4.0) # send ping on timeout if not ready[0]: uwsgi.websocket_recv_nb() for fd in ready[0]: if fd == websocket_fd: msg = uwsgi.websocket_recv_nb() if msg: r.publish('foobar', msg) elif fd == redis_fd: msg = channel.parse_response() # only interested in user messages if msg[0] == 'message': uwsgi.websocket_send("[%s] %s" % (time.time(), msg))
def open_websocket(self, env): context = None try: user = self.authenticate(env) access_level = User.get_access_level(user) if access_level < self.min_access_level: return uwsgi.websocket_handshake() util.print_info('Opening websocket connection', False) client_count = self.redis.get('websocket-clients') if client_count: client_count = int(client_count.decode('utf-8')) if client_count >= config.websockets_max_clients: raise ClientError('No available slots.') self.redis.incr('websocket-clients') context = True channel = self.redis.pubsub() channel.subscribe(self.name) websocket_fd = uwsgi.connection_fd() redis_fd = channel.connection._sock.fileno() context = self.init_context(env, user, redis_fd) while True: ready = gevent.select.select([websocket_fd, redis_fd], [], [], 4.0) if not ready[0]: # send ping on timeout uwsgi.websocket_recv_nb() for fd in ready[0]: if fd == websocket_fd: # client message context = self.fetch_and_handle_client_message(context) elif fd == redis_fd: # channel message message = channel.parse_response() if message[0] == b'message': context = self.handle_channel_message( context, message[2]) except ClientTimeout: util.print_info('Websocket connection client timeout.') except ClientDisconnect: util.print_info('Websocket connection client disconnected.') except ClientError as error: util.print_exception('Websocket client error', error, False, print_traceback=False) except IOError as error: # Socket Error util.print_exception('Websocket connection closed', error, False, print_traceback=False) except DBError as error: # Database Error util.print_exception('Database Error occured: ', error) except OAuth2Error as error: # OAuth 2.0 Error util.print_exception('OAuth 2.0 Error occured: ', error) except Exception as error: # Unknown Exception util.print_exception('Unexpected Error occured: ', error, False) finally: self.cleanup(context)
def application(env, start_response): # At this point the server received a valid WebSocket Upgrade request, # and routed the request to this pseudo-WSGI app, # but has not yet send any response. def bad(why): start_response('400 Bad request (' + why + ')', []) if 'HTTP_SEC_WEBSOCKET_KEY' not in env: return bad('Missing Sec-WebSocket-Key header') match = uri_re.fullmatch(env['PATH_INFO']) if not match: return bad('Invalid/missing drop ID') drop_id = match.group('drop_id') # This uWSGI utility function sends the HTTP/101 Switching Protocols response # (it doesn't need *start_response*, because it directly accesses the requests' # output socket). uwsgi.websocket_handshake(env['HTTP_SEC_WEBSOCKET_KEY'], env.get('HTTP_ORIGIN', '')) redis_conn = get_redis() channel = redis_conn.pubsub() channel.subscribe(settings.REDIS_PREFIX + drop_id) websocket_fd = uwsgi.connection_fd() redis_fd = channel.connection._sock.fileno() monitoring.WEBSOCKET_CONNECTIONS.inc() try: while True: rable, wable, xfd = gevent.select.select([websocket_fd, redis_fd], [], [], 2) if not rable: # When the select times out, we do a non-blocking receive. This triggers a check # in uWSGI whether a PING should be send. It also handles various housekeeping # tasks, like closing the connection and stuff like that. # We don't really care what the client has to say. uwsgi.websocket_recv_nb() continue for fd in rable: if fd == websocket_fd: uwsgi.websocket_recv_nb() elif fd == redis_fd: # This is a reading block, but that's okay since we previously polled for # readability on the redis FD, so the server is sending us a message. msg = channel.handle_message(channel.parse_response()) if msg['type'] != 'message': print('Unexpected Redis message type:', msg['type']) continue uwsgi.websocket_send_binary(msg['data']) monitoring.WEBSOCKET_MESSAGES.inc() except OSError as ose: if str(ose) == 'unable to receive websocket message': # regular end of connection, nothing we want a trace for. pass else: raise finally: monitoring.WEBSOCKET_CONNECTIONS.dec() channel.close()
def application(env, sr): ws_scheme = 'ws' if 'HTTPS' in env or env['wsgi.url_scheme'] == 'https': ws_scheme = 'wss' if env['PATH_INFO'] == '/': sr('200 OK', [('Content-Type', 'text/html')]) return """ <html> <head> <script language="Javascript"> var s = new WebSocket("%s://%s/foobar/"); s.onopen = function() { alert("connected !!!"); s.send("ciao"); }; s.onmessage = function(e) { var bb = document.getElementById('blackboard') var html = bb.innerHTML; bb.innerHTML = html + '<br/>' + e.data; }; s.onerror = function(e) { alert(e); } s.onclose = function(e) { alert("connection closed"); } function invia() { var value = document.getElementById('testo').value; s.send(value); } </script> </head> <body> <h1>WebSocket</h1> <input type="text" id="testo"/> <input type="button" value="invia" onClick="invia();"/> <div id="blackboard" style="width:640px;height:480px;background-color:black;color:white;border: solid 2px red;overflow:auto"> </div> </body> </html> """ % (ws_scheme, env['HTTP_HOST']) elif env['PATH_INFO'] == '/foobar/': uwsgi.websocket_handshake(env['HTTP_SEC_WEBSOCKET_KEY'], env.get('HTTP_ORIGIN', '')) print "websockets..." while True: msg = uwsgi.websocket_recv_nb() if msg: queue.put(msg) else: try: wait_read(uwsgi.connection_fd(), 0.1) except gevent.socket.timeout: try: msg = queue.get_nowait() uwsgi.websocket_send(msg) except: pass return ""
def __call__(self, e, sr): if e['PATH_INFO'] == '/': sr('200 OK', [('Content-Type', 'text/html')]) return [open('robotab_bullet.html').read()] if e['PATH_INFO'] == '/robotab_bullet.js': sr('200 OK', [('Content-Type', 'application/javascript')]) return [open('static/js/robotab_bullet.js').read()] if e['PATH_INFO'] == '/robotab': uwsgi.websocket_handshake() username, avatar = uwsgi.websocket_recv().split(':') try: robot_coordinates = next(self.spawn_iterator) except StopIteration: self.spawn_iterator = iter(self.spawn_points) robot_coordinates = next(self.spawn_iterator) # uwsgi.websocket_send('posters:{}'.format(';'.join(self.posters))) for wall in self.walls_coordinates: uwsgi.websocket_send( 'wall:{},{},{},{},{},{},{}'.format(*wall)) player = Player(self, username, avatar, uwsgi.connection_fd(), *robot_coordinates) if(self.started or self.finished or len(self.players) > self.max_players or len(self.waiting_players) > 0): print('{}:{}:{}:{}'.format( self.started, self.finished, len(self.players) > self.max_players, len(self.waiting_players) > 0)) self.waiting_players.append(player) uwsgi.websocket_send( "arena:hey {}, wait for next game".format(player.name)) player.wait_for_game() self.waiting_players.remove(player) else: self.players[player.name] = player self.spawn_greenlets() player.update_gfx() for p in self.players.keys(): uwsgi.websocket_send(self.players[p].last_msg) while True: ready = gevent.select.select( [player.fd, player.redis_fd], [], [], timeout=4.0) if not ready[0]: uwsgi.websocket_recv_nb() for fd in ready[0]: if fd == player.fd: try: msg = uwsgi.websocket_recv_nb() except IOError: import sys print sys.exc_info() if player.name in self.players: player.end('leaver') return [""] if msg and not self.finished: self.msg_handler(player, msg) elif fd == player.redis_fd: msg = player.channel.parse_response() if msg[0] == 'message': uwsgi.websocket_send(msg[2])
def application(env, sr): ws_scheme = 'ws' if 'HTTPS' in env or env['wsgi.url_scheme'] == 'https': ws_scheme = 'wss' if env['PATH_INFO'] == '/': sr('200 OK', [('Content-Type', 'text/html')]) return """ <html> <head> <script language="Javascript"> var s = new WebSocket("%s://%s/foobar/"); s.onopen = function() { alert("connected !!!"); s.send("ciao"); }; s.onmessage = function(e) { var bb = document.getElementById('blackboard') var html = bb.innerHTML; bb.innerHTML = html + '<br/>' + e.data; }; s.onerror = function(e) { alert(e); } s.onclose = function(e) { alert("connection closed"); } function invia() { var value = document.getElementById('testo').value; s.send(value); } </script> </head> <body> <h1>WebSocket</h1> <input type="text" id="testo"/> <input type="button" value="invia" onClick="invia();"/> <div id="blackboard" style="width:640px;height:480px;background-color:black;color:white;border: solid 2px red;overflow:auto"> </div> </body> </html> """ % (ws_scheme, env['HTTP_HOST']) elif env['PATH_INFO'] == '/foobar/': uwsgi.websocket_handshake(env['HTTP_SEC_WEBSOCKET_KEY'], env.get('HTTP_ORIGIN', '')) print "websockets..." while True: msg = uwsgi.websocket_recv_nb() if msg: queue.put(msg) else: try: wait_read(uwsgi.connection_fd(), 0.1) except gevent.socket.timeout: try: msg = queue.get_nowait() uwsgi.websocket_send(msg) except Exception: pass return ""