~cpick/mongrel2/release

« back to all changes in this revision

Viewing changes to examples/ws/python/echo.py

  • Committer: Chris Pick
  • Date: 2013-06-30 16:39:57 UTC
  • mfrom: (1106.1.15)
  • Revision ID: git-v1:ec39967acb6bc9867ed9b9dc3774304ca6b9c294
Merge tag 'v1.8.1' into debian

Hotfix for github issue 148

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
import simplejson as json
 
2
from mongrel2 import handler
 
3
import wsutil
 
4
import sys
 
5
import time
 
6
import re
 
7
 
 
8
sender_id = "82209006-86FF-4982-B5EA-D1E29E55D480"
 
9
 
 
10
conn = handler.Connection(sender_id, "tcp://127.0.0.1:9990",
 
11
                          "tcp://127.0.0.1:9989")
 
12
 
 
13
CONNECTION_TIMEOUT=5
 
14
 
 
15
closingMessages={}
 
16
 
 
17
badUnicode=re.compile(u'[\ud800-\udfff]')
 
18
 
 
19
logf=open('echo.log','wb')
 
20
#logf=open('/dev/null','wb')
 
21
#logf=sys.stdout
 
22
 
 
23
def abortConnection(conn,req,reason='none',code=None):
 
24
    #print 'abort',conn,req,reason,code
 
25
    if code is not None:
 
26
        #print "Closing cleanly\n"
 
27
        conn.reply_websocket(req,code+reason,opcode=wsutil.OP_CLOSE)
 
28
        closingMessages[req.conn_id]=(time.time(),req.sender)
 
29
    else:
 
30
        conn.reply(req,'')
 
31
    print >>logf,'abort',code,reason
 
32
 
 
33
while True:
 
34
    now=time.time()
 
35
    logf.flush()
 
36
    for k,(t,uuid) in closingMessages.items():
 
37
        if now > t+CONNECTION_TIMEOUT:
 
38
            conn.send(uuid,k,'')
 
39
    try:
 
40
        req = conn.recv()
 
41
    except:
 
42
        print "FAILED RECV"
 
43
        continue
 
44
 
 
45
 
 
46
    if req.is_disconnect():
 
47
        #print "DISCONNECTED", req.conn_id
 
48
        continue
 
49
 
 
50
    if req.headers.get('METHOD') == 'WEBSOCKET_HANDSHAKE':
 
51
        #print "HANDSHAKE"
 
52
        conn.reply(req,
 
53
                '\r\n'.join([
 
54
                    "HTTP/1.1 101 Switching Protocols",
 
55
                    "Upgrade: websocket",
 
56
                    "Connection: Upgrade",
 
57
                    "Sec-WebSocket-Accept: %s\r\n\r\n"])%req.body)
 
58
        continue
 
59
 
 
60
    if req.headers.get('METHOD') != 'WEBSOCKET':
 
61
        print 'METHOD is Not WEBSOCKET:',req.headers#,req.body
 
62
        conn.reply(req,'')
 
63
        continue
 
64
 
 
65
    try:
 
66
        #print 'headers',req.headers
 
67
        flags = int(req.headers.get('FLAGS'),16)
 
68
        fin = flags&0x80==0x80
 
69
        rsvd=flags & 0x70
 
70
        opcode=flags & 0xf
 
71
        wsdata = req.body
 
72
        #print fin,rsvd,opcode,len(wsdata),wsdata
 
73
        #logf.write('\n')
 
74
    except:
 
75
        #print "Unable to decode FLAGS"
 
76
        abortConnection(conn,req,'WS decode failed')
 
77
        #continue
 
78
 
 
79
    if rsvd != 0:
 
80
        abortConnection(conn,req,'reserved non-zero',
 
81
                wsutil.CLOSE_PROTOCOL_ERROR)
 
82
        continue
 
83
 
 
84
    if opcode == wsutil.OP_CLOSE:
 
85
        if req.conn_id in closingMessages:
 
86
            del closingMessages[req.conn_id]
 
87
            conn.reply(req,'')
 
88
        else:
 
89
            conn.reply_websocket(req,wsdata,opcode)
 
90
            conn.reply(req,'')
 
91
        continue
 
92
    if req.conn_id in closingMessages:
 
93
        continue
 
94
 
 
95
    if opcode not in wsutil.opcodes:
 
96
        abortConnection(conn,req,'Unknown opcode',
 
97
                wsutil.CLOSE_PROTOCOL_ERROR)
 
98
        continue
 
99
        
 
100
    if (opcode & 0x8) != 0:
 
101
        if opcode ==wsutil.OP_PING:
 
102
            opcode = wsutil.OP_PONG
 
103
            conn.reply_websocket(req,wsdata,opcode)
 
104
 
 
105
        continue
 
106
 
 
107
    if opcode == wsutil.OP_PONG:
 
108
        continue # We don't send pings, so ignore pongs
 
109
    if(opcode == wsutil.OP_TEXT):
 
110
        try:
 
111
            x=wsdata.decode('utf-8')
 
112
            #Thank you for not fixing python issue8271 in 2.x :(
 
113
            if badUnicode.search(x):
 
114
                raise UnicodeError('Surrogates not allowed')
 
115
            #for c in x:
 
116
                #if (0xd800 <= ord(c) <= 0xdfff):
 
117
                    #raise UnicodeError('Surrogates not allowed')
 
118
        except:
 
119
            abortConnection(conn,req,'invalid UTF', wsutil.CLOSE_BAD_DATA)
 
120
            continue
 
121
    conn.reply_websocket(req,wsdata,opcode)