~azzar1/unity/add-show-desktop-key

« back to all changes in this revision

Viewing changes to ivle/chat.py

  • Committer: Matt Giuca
  • Date: 2010-02-18 00:19:48 UTC
  • Revision ID: matt.giuca@gmail.com-20100218001948-8079xhwqvrf2ul15
ivle.webapp.tutorial: Fixed unqualified reference to exception ExerciseNotFound.

Show diffs side-by-side

added added

removed removed

Lines of Context:
27
27
import socket
28
28
import traceback
29
29
 
30
 
SOCKETTIMEOUT = 60
31
 
BLOCKSIZE = 1024
32
 
 
33
30
class Terminate(Exception):
34
 
    """Exception thrown when server is to be shut down. It will attempt to
35
 
    send the final_response to the client and then exits"""
 
31
    """Exception thrown when server is to be shut down. It will attempt to sned 
 
32
    the final_response to the client and then exits"""
36
33
    def __init__(self, final_response=None):
37
34
        self.final_response = final_response
38
35
 
39
36
    def __str__(self):
40
37
        return repr(self.final_response)
41
38
 
42
 
class ProtocolError(Exception):
43
 
    """Exception thrown when client violates the the chat protocol"""
44
 
    pass
45
39
 
46
40
def start_server(port, magic, daemon_mode, handler, initializer = None):
47
41
    # Attempt to open the socket.
87
81
 
88
82
    while True:
89
83
        (conn, addr) = s.accept()
90
 
        conn.settimeout(SOCKETTIMEOUT)
91
84
        try:
92
85
            # Grab the input
93
 
            inp = recv_netstring(conn)
 
86
            buf = cStringIO.StringIO()
 
87
            blk = conn.recv(1024)
 
88
            while blk:
 
89
                buf.write(blk)
 
90
                try:
 
91
                    blk = conn.recv(1024, socket.MSG_DONTWAIT)
 
92
                except:
 
93
                    # Exception thrown if it WOULD block (but we
 
94
                    # told it not to wait) - ie. we are done
 
95
                    blk = None
 
96
            inp = buf.getvalue()
94
97
            env = cjson.decode(inp)
95
 
 
 
98
            
96
99
            # Check that the message is 
97
100
            digest = hashlib.md5(env['content'] + magic).hexdigest()
98
101
            if env['digest'] != digest:
103
106
 
104
107
            response = handler(content)
105
108
 
106
 
            send_netstring(conn, cjson.encode(response))
 
109
            conn.sendall(cjson.encode(response))
107
110
 
108
111
            conn.close()
109
112
 
110
113
        except Terminate, t:
111
114
            # Try and send final response and then terminate
112
115
            if t.final_response:
113
 
                send_netstring(conn, cjson.encode(t.final_response))
 
116
                conn.sendall(cjson.encode(t.final_response))
114
117
            conn.close()
115
118
            sys.exit(0)
116
119
        except Exception:
123
126
                "value": str(e_val),
124
127
                "traceback": tb_dump.getvalue()
125
128
            }
126
 
            send_netstring(conn, cjson.encode(json_exc))
 
129
            conn.sendall(cjson.encode(json_exc))
127
130
            conn.close()
128
131
 
129
132
 
130
133
def chat(host, port, msg, magic, decode = True):
131
134
    sok = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
132
135
    sok.connect((host, port))
133
 
    sok.settimeout(SOCKETTIMEOUT)
134
136
    content = cjson.encode(msg)
135
137
    digest = hashlib.md5(content + magic).hexdigest()
136
138
    env = {'digest':digest,'content':content}
137
 
    json = cjson.encode(env)
138
 
 
139
 
    send_netstring(sok, json)
140
 
    inp = recv_netstring(sok)
141
 
 
 
139
    sok.send(cjson.encode(env))
 
140
 
 
141
    buf = cStringIO.StringIO()
 
142
    blk = sok.recv(1024)
 
143
    while blk:
 
144
        buf.write(blk)
 
145
        try:
 
146
            blk = sok.recv(1024, socket.MSG_DONTWAIT)
 
147
        except socket.error, e:
 
148
            if e[0] != 11:
 
149
                raise
 
150
            # Exception thrown if it WOULD block (but we
 
151
            # told it not to wait) - ie. we are done
 
152
            blk = None
 
153
    inp = buf.getvalue()
142
154
    sok.close()
143
155
 
144
156
    if decode:
146
158
    else:
147
159
        return inp
148
160
 
149
 
 
150
 
def send_netstring(sok, data):
151
 
    netstring = "%d:%s,"%(len(data),data)
152
 
    sok.sendall(netstring)
153
 
 
154
 
 
155
 
def recv_netstring(sok):
156
 
    # Decode netstring
157
 
    size_buffer = []
158
 
    c = sok.recv(1)
159
 
    while c != ':':
160
 
        # Limit the Netstring to less than 10^10 bytes (~1GB).
161
 
        if len(size_buffer) >= 10:
162
 
            raise ProtocolError(
163
 
                    "Could not read Netstring size in first 9 bytes: '%s'"%(
164
 
                    ''.join(size_buffer)))
165
 
        size_buffer.append(c)
166
 
        c = sok.recv(1)
167
 
    try:
168
 
        # Message should be length plus ',' terminator
169
 
        recv_expected = int(''.join(size_buffer)) + 1
170
 
    except ValueError, e:
171
 
        raise ProtocolError("Could not decode Netstring size as int: '%s'"%(
172
 
                ''.join(size_buffer)))
173
 
 
174
 
    # Read data
175
 
    buf = []
176
 
    recv_data = sok.recv(min(recv_expected, BLOCKSIZE))
177
 
    recv_size = len(recv_data)
178
 
    while recv_size < recv_expected:
179
 
        buf.append(recv_data)
180
 
        recv_data = sok.recv(min(recv_expected-recv_size, 1024))
181
 
        recv_size = recv_size + len(recv_data)
182
 
    assert(recv_size == recv_expected)
183
 
 
184
 
    # Did we receive the correct amount?
185
 
    if recv_data[-1] != ',':
186
 
        raise ProtocolError("Netstring did not end with ','")
187
 
    buf.append(recv_data[:-1])
188
 
 
189
 
    return ''.join(buf)