mirror of
https://github.com/frappe/gunicorn.git
synced 2026-01-14 11:09:11 +08:00
Adapting gevent_websocket.py sample for websocket protocol 076.
This commit is contained in:
parent
3ad7c1b395
commit
94df88ca7c
@ -7,19 +7,35 @@
|
|||||||
|
|
||||||
import collections
|
import collections
|
||||||
import errno
|
import errno
|
||||||
from gunicorn.workers.async import ALREADY_HANDLED
|
import re
|
||||||
|
from md5 import md5
|
||||||
import socket
|
import socket
|
||||||
|
import struct
|
||||||
|
|
||||||
import gevent
|
import gevent
|
||||||
from gevent.pool import Pool
|
from gevent.pool import Pool
|
||||||
|
from gunicorn.workers.async import ALREADY_HANDLED
|
||||||
|
|
||||||
|
# Parts adapted from http://code.google.com/p/pywebsocket/
|
||||||
|
# mod_pywebsocket/handshake/handshake.py
|
||||||
|
|
||||||
class WebSocketWSGI(object):
|
class WebSocketWSGI(object):
|
||||||
def __init__(self, handler, origin):
|
def __init__(self, handler):
|
||||||
self.handler = handler
|
self.handler = handler
|
||||||
self.origin = origin
|
|
||||||
|
|
||||||
def verify_client(self, ws):
|
def verify_client(self, ws):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def _get_key_value(self, key_value):
|
||||||
|
if not key_value:
|
||||||
|
return
|
||||||
|
key_number = int(re.sub("\\D", "", key_value))
|
||||||
|
spaces = re.subn(" ", "", key_value)[1]
|
||||||
|
if key_number % spaces != 0:
|
||||||
|
return
|
||||||
|
part = key_number / spaces
|
||||||
|
return part
|
||||||
|
|
||||||
def __call__(self, environ, start_response):
|
def __call__(self, environ, start_response):
|
||||||
if not (environ['HTTP_CONNECTION'] == 'Upgrade' and
|
if not (environ['HTTP_CONNECTION'] == 'Upgrade' and
|
||||||
environ['HTTP_UPGRADE'] == 'WebSocket'):
|
environ['HTTP_UPGRADE'] == 'WebSocket'):
|
||||||
@ -28,20 +44,46 @@ class WebSocketWSGI(object):
|
|||||||
return []
|
return []
|
||||||
|
|
||||||
sock = environ['gunicorn.socket']
|
sock = environ['gunicorn.socket']
|
||||||
|
sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_CORK, 0)
|
||||||
ws = WebSocket(sock,
|
ws = WebSocket(sock,
|
||||||
environ.get('HTTP_ORIGIN'),
|
environ.get('HTTP_ORIGIN'),
|
||||||
environ.get('HTTP_WEBSOCKET_PROTOCOL'),
|
environ.get('HTTP_WEBSOCKET_PROTOCOL'),
|
||||||
environ.get('PATH_INFO'))
|
environ.get('PATH_INFO'))
|
||||||
self.verify_client(ws)
|
|
||||||
|
key1 = self._get_key_value(environ.get('HTTP_SEC_WEBSOCKET_KEY1'))
|
||||||
|
key2 = self._get_key_value(environ.get('HTTP_SEC_WEBSOCKET_KEY2'))
|
||||||
|
|
||||||
handshake_reply = ("HTTP/1.1 101 Web Socket Protocol Handshake\r\n"
|
handshake_reply = ("HTTP/1.1 101 Web Socket Protocol Handshake\r\n"
|
||||||
"Upgrade: WebSocket\r\n"
|
"Upgrade: WebSocket\r\n"
|
||||||
"Connection: Upgrade\r\n"
|
"Connection: Upgrade\r\n")
|
||||||
"WebSocket-Origin: %s\r\n"
|
|
||||||
"WebSocket-Location: ws://%s%s\r\n\r\n" % (
|
if key1 and key2:
|
||||||
self.origin,
|
challenge = ""
|
||||||
environ.get('HTTP_HOST'),
|
challenge += struct.pack("!I", key1) # network byteorder int
|
||||||
ws.path))
|
challenge += struct.pack("!I", key2) # network byteorder int
|
||||||
|
challenge += environ['wsgi.input'].read()
|
||||||
|
handshake_reply += (
|
||||||
|
"Sec-WebSocket-Origin: %s\r\n"
|
||||||
|
"Sec-WebSocket-Location: ws://%s%s\r\n"
|
||||||
|
"Sec-WebSocket-Protocol: %s\r\n"
|
||||||
|
"\r\n%s" % (
|
||||||
|
environ.get('HTTP_ORIGIN'),
|
||||||
|
environ.get('HTTP_HOST'),
|
||||||
|
ws.path,
|
||||||
|
environ.get('HTTP_SEC_WEBSOCKET_PROTOCOL'),
|
||||||
|
md5(challenge).digest()))
|
||||||
|
|
||||||
|
else:
|
||||||
|
|
||||||
|
handshake_reply += (
|
||||||
|
"WebSocket-Origin: %s\r\n"
|
||||||
|
"WebSocket-Location: ws://%s%s\r\n\r\n" % (
|
||||||
|
environ.get('HTTP_ORIGIN'),
|
||||||
|
environ.get('HTTP_HOST'),
|
||||||
|
ws.path))
|
||||||
|
|
||||||
sock.sendall(handshake_reply)
|
sock.sendall(handshake_reply)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.handler(ws)
|
self.handler(ws)
|
||||||
except socket.error, e:
|
except socket.error, e:
|
||||||
@ -105,7 +147,7 @@ class WebSocket(object):
|
|||||||
msgs, self._buf = parse_messages(self._buf)
|
msgs, self._buf = parse_messages(self._buf)
|
||||||
self._msgs.extend(msgs)
|
self._msgs.extend(msgs)
|
||||||
return self._msgs.popleft()
|
return self._msgs.popleft()
|
||||||
|
|
||||||
|
|
||||||
# demo app
|
# demo app
|
||||||
import os
|
import os
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user