diff --git a/plugins/python/uwsgi_pymodule.c b/plugins/python/uwsgi_pymodule.c index 04da9a0e..c2494ea5 100644 --- a/plugins/python/uwsgi_pymodule.c +++ b/plugins/python/uwsgi_pymodule.c @@ -166,6 +166,105 @@ PyObject *py_uwsgi_close(PyObject * self, PyObject * args) { } +PyObject *py_uwsgi_recv_frame(PyObject * self, PyObject * args) { + + struct wsgi_request *wsgi_req = current_wsgi_req(); + + char *bufptr; + char prefix = 0x00; + char suffix = 0xff; + int i; + char frame[4096]; + char *frame_ptr; + int frame_size = 0; + int fd; + int rlen; + + int found_start = 0; + char *null1, *null2; + + + if (!PyArg_ParseTuple(args, "icc:recv_frame", &fd, &null1, &null2)) { + return NULL; + } + +get_data: + frame_ptr = frame; + if (wsgi_req->frame_len > 0) { + // we have already some data buffered + // search for the prefix and adjust frame_pos + bufptr = wsgi_req->buffer+wsgi_req->frame_pos; + for(i=0;iframe_len;i++) { + if (bufptr[i] == prefix) { + bufptr++; + found_start = 1; + break; + } + bufptr++; + wsgi_req->frame_pos++; + } + + wsgi_req->frame_len -= i; + if (found_start) { + // we have found the prefix, copy it in the frame area until suffix or end of the buffer + for(i=0;iframe_len;i++) { + uwsgi_log("%d %d\n", bufptr[i], frame_size); + if (bufptr[i] == suffix) { + wsgi_req->frame_len -= i; + goto return_a_frame; + } + *frame_ptr++= bufptr[i]; + frame_size++; + wsgi_req->frame_pos++; + } + } + } + + // we have already get the prefix ? + if (found_start) { + + // wait for more data +read_more_data: + rlen = uwsgi_waitfd(fd, -1); + if (rlen > 0) { + wsgi_req->frame_pos = 0; + wsgi_req->frame_len = read(fd, wsgi_req->buffer, uwsgi.buffer_size); + bufptr = wsgi_req->buffer; + for(i=0;iframe_len;i++) { + if (bufptr[i] == suffix) { + goto return_a_frame; + } + *frame_ptr++= bufptr[i]; + frame_size++; + } + goto read_more_data; + } + else if (rlen == 0) { + uwsgi_log("timeout waiting for frame\n"); + } + + } + else { + // read a whole frame directly from the socket + rlen = uwsgi_waitfd(fd, -1); + if (rlen > 0) { + wsgi_req->frame_pos = 0; + wsgi_req->frame_len = read(fd, wsgi_req->buffer, uwsgi.buffer_size); + uwsgi_log("read %d bytes %.*s\n", wsgi_req->frame_len, wsgi_req->frame_len, wsgi_req->buffer); + if (wsgi_req->frame_len == 0) goto return_a_frame; + goto get_data; + } + else if (rlen == 0) { + uwsgi_log("timeout waiting for frame\n"); + } + + } +return_a_frame: + uwsgi_log("returning a frame\n"); + return PyString_FromStringAndSize(frame, frame_size); + +} + PyObject *py_uwsgi_recv_block(PyObject * self, PyObject * args) { char buf[4096]; @@ -1693,6 +1792,7 @@ static PyMethodDef uwsgi_advanced_methods[] = { {"send", py_uwsgi_send, METH_VARARGS, ""}, {"recv", py_uwsgi_recv, METH_VARARGS, ""}, {"recv_block", py_uwsgi_recv_block, METH_VARARGS, ""}, + {"recv_frame", py_uwsgi_recv_frame, METH_VARARGS, ""}, {"close", py_uwsgi_close, METH_VARARGS, ""}, {"parsefile", py_uwsgi_parse_file, METH_VARARGS, ""}, diff --git a/uwsgi.h b/uwsgi.h index 1cc60138..399dc3a7 100644 --- a/uwsgi.h +++ b/uwsgi.h @@ -542,10 +542,13 @@ struct wsgi_request { char *post_buffering_buf; uint64_t post_buffering_read; - //for generic use - off_t buf_pos; + //for generic use + off_t buf_pos; char *buffer; + + off_t frame_pos; + int frame_len; }; #define LOADER_DYN 0 diff --git a/websockets.py b/websockets.py index ec41d82e..05fbef33 100644 --- a/websockets.py +++ b/websockets.py @@ -1,6 +1,21 @@ import uwsgi +import string +import hashlib +import struct -def application(e, s): +def to_ws_num(value): + num = '' + div = 0 + + for c in value: + if c in string.digits: + num += c + elif c == ' ': + div += 1 + + return int(num)/div + +def application(e, start_response): print e @@ -12,37 +27,28 @@ def application(e, s): print "data", data, len(data) - key1 = e['HTTP_SEC_WEBSOCKET_KEY1'] - key2 = e['HTTP_SEC_WEBSOCKET_KEY2'] + key1 = to_ws_num(e['HTTP_SEC_WEBSOCKET_KEY1']) + key2 = to_ws_num(e['HTTP_SEC_WEBSOCKET_KEY2']) - total1 = '' - div1 = 0 - for c in key1: - if c in '0'..'9': - total1 += c - - for c in key1: - if c == ' ': - div1 += 1 - - if div1 == 0: - raise StopIteration - - total1 = int(total1) / div1 - - total2 = '' - div2 = 0 - for c in key2: - if c in '0'..'9': - total2 += c - - for c in key2: - if c == ' ': - div2 += 1 - - if div2 == 0: - raise StopIteration - - total2 = int(total2) / div1 + response = hashlib.md5( struct.pack('>II', key1, key2) + data).digest() + print response + + start_response('101 WebSocket Protocol Handshake',[ + ('Upgrade', 'WebSocket'), + ('Connection', 'Upgrade'), + ('Sec-WebSocket-Origin', e.get('HTTP_ORIGIN')), + ('Sec-WebSocket-Location','ws://%s%s%s' % (e.get('HTTP_HOST'), e.get('SCRIPT_NAME'), e.get('PATH_INFO')) ), + ('Sec-WebSocket-Protocol', e.get('HTTP_SEC_WEBSOCKET_PROTOCOL', 'default')) + ]) + + yield response + + message = uwsgi.recv_frame(client, '\x00', '\xff') + while message: + print message + yield '\x00' + message + '\xff' + if len(message) == 0: + raise StopIteration + message = uwsgi.recv_frame(client, '\x00', '\xff')