File: echo.py

package info (click to toggle)
mongrel2 1.12.0-2
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 5,976 kB
  • sloc: ansic: 39,083; python: 2,833; sql: 1,555; sh: 467; makefile: 360; asm: 189; yacc: 145; php: 73; awk: 28; sed: 5
file content (121 lines) | stat: -rw-r--r-- 3,488 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
import simplejson as json
from mongrel2 import handler
import wsutil
import sys
import time
import re

sender_id = "82209006-86FF-4982-B5EA-D1E29E55D480"

conn = handler.Connection(sender_id, "tcp://127.0.0.1:9990",
                          "tcp://127.0.0.1:9989")

CONNECTION_TIMEOUT=5

closingMessages={}

badUnicode=re.compile(u'[\ud800-\udfff]')

logf=open('echo.log','wb')
#logf=open('/dev/null','wb')
#logf=sys.stdout

def abortConnection(conn,req,reason='none',code=None):
    #print 'abort',conn,req,reason,code
    if code is not None:
        #print "Closing cleanly\n"
        conn.reply_websocket(req,code+reason,opcode=wsutil.OP_CLOSE)
        closingMessages[req.conn_id]=(time.time(),req.sender)
    else:
        conn.reply(req,'')
    print >>logf,'abort',code,reason

while True:
    now=time.time()
    logf.flush()
    for k,(t,uuid) in closingMessages.items():
        if now > t+CONNECTION_TIMEOUT:
            conn.send(uuid,k,'')
    try:
        req = conn.recv()
    except:
        print "FAILED RECV"
        continue


    if req.is_disconnect():
        #print "DISCONNECTED", req.conn_id
        continue

    if req.headers.get('METHOD') == 'WEBSOCKET_HANDSHAKE':
        #print "HANDSHAKE"
        conn.reply(req,
                '\r\n'.join([
                    "HTTP/1.1 101 Switching Protocols",
                    "Upgrade: websocket",
                    "Connection: Upgrade",
                    "Sec-WebSocket-Accept: %s\r\n\r\n"])%req.body)
        continue

    if req.headers.get('METHOD') != 'WEBSOCKET':
        print 'METHOD is Not WEBSOCKET:',req.headers#,req.body
        conn.reply(req,'')
        continue

    try:
        #print 'headers',req.headers
        flags = int(req.headers.get('FLAGS'),16)
        fin = flags&0x80==0x80
        rsvd=flags & 0x70
        opcode=flags & 0xf
        wsdata = req.body
        #print fin,rsvd,opcode,len(wsdata),wsdata
        #logf.write('\n')
    except:
        #print "Unable to decode FLAGS"
        abortConnection(conn,req,'WS decode failed')
        #continue

    if rsvd != 0:
        abortConnection(conn,req,'reserved non-zero',
                wsutil.CLOSE_PROTOCOL_ERROR)
        continue

    if opcode == wsutil.OP_CLOSE:
        if req.conn_id in closingMessages:
            del closingMessages[req.conn_id]
            conn.reply(req,'')
        else:
            conn.reply_websocket(req,wsdata,opcode)
            conn.reply(req,'')
        continue
    if req.conn_id in closingMessages:
        continue

    if opcode not in wsutil.opcodes:
        abortConnection(conn,req,'Unknown opcode',
                wsutil.CLOSE_PROTOCOL_ERROR)
        continue
        
    if (opcode & 0x8) != 0:
        if opcode ==wsutil.OP_PING:
            opcode = wsutil.OP_PONG
            conn.reply_websocket(req,wsdata,opcode)

        continue

    if opcode == wsutil.OP_PONG:
        continue # We don't send pings, so ignore pongs
    if(opcode == wsutil.OP_TEXT):
        try:
            x=wsdata.decode('utf-8')
            #Thank you for not fixing python issue8271 in 2.x :(
            if badUnicode.search(x):
                raise UnicodeError('Surrogates not allowed')
            #for c in x:
                #if (0xd800 <= ord(c) <= 0xdfff):
                    #raise UnicodeError('Surrogates not allowed')
        except:
            abortConnection(conn,req,'invalid UTF', wsutil.CLOSE_BAD_DATA)
            continue
    conn.reply_websocket(req,wsdata,opcode)