0
static ebb_server server;
0
+struct ev_timer check_stop_watcher;
0
static PyThreadState *libev_thread_state;
0
+static PyObject *py_request_cb;
0
static PyObject *application;
0
+static int server_running;
0
+static int server_error;
0
static PyObject *base_env;
0
static PyObject *global_http_prefix;
0
static PyObject *global_request_method;
0
@@ -37,27 +42,78 @@ static PyObject *global_http_host;
0
/* A callable type called Client. __call__(status, response_headers)
0
* is the second argument to an appplcation
0
- * Client.environ is the first argument.
0
+ * Client.env is the first argument.
0
-py_start_response(py_client *self, PyObject *args, PyObject *kw);
0
static void py_client_dealloc(PyObject *obj)
0
py_client *self = (py_client*) obj;
0
ebb_client_release(self->client);
0
obj->ob_type->tp_free(obj);
0
- printf("dealloc called!\n");
0
+write_status(py_client *self, PyObject *args)
0
+ if(!PyArg_ParseTuple(args, "is", &status, &status_human))
0
+ ebb_client_write_status(self->client, status, status_human);
0
+write_header(py_client *self, PyObject *args)
0
+ if(!PyArg_ParseTuple(args, "ss", &field, &value))
0
+ ebb_client_write_header(self->client, field, value);
0
+write_body(py_client *self, PyObject *args)
0
+ if(!PyArg_ParseTuple(args, "s#", &body, &body_length))
0
+ ebb_client_write_body(self->client, body, body_length);
0
+client_release(py_client *self)
0
+ ebb_client_release(self->client);
0
+client_env(py_client *self)
0
static PyMethodDef client_methods[] =
0
- { {"start_response" , (PyCFunction)py_start_response, METH_VARARGS, NULL }
0
- // , {"write" , (PyCFunction)write, METH_VARARGS, NULL }
0
+ { {"write_status", (PyCFunction)write_status, METH_VARARGS, NULL }
0
+ , {"write_header", (PyCFunction)write_header, METH_VARARGS, NULL }
0
+ , {"write_body", (PyCFunction)write_body, METH_VARARGS, NULL }
0
+ , {"release", (PyCFunction)client_release, METH_NOARGS, NULL }
0
+ , {"env", (PyCFunction)client_env, METH_NOARGS, NULL }
0
, {NULL, NULL, 0, NULL}
0
@@ -71,38 +127,6 @@ static PyTypeObject py_client_t =
0
, tp_dealloc: py_client_dealloc
0
-py_start_response(py_client *self, PyObject *args, PyObject *kw)
0
- PyObject *response_headers;
0
- if(!PyArg_ParseTuple(args, "sO", &status_string, &response_headers))
0
- /* do this goofy split(' ') operation. wsgi is such a terrible api. */
0
- status = 100 * (status_string[0] - '0')
0
- + 10 * (status_string[1] - '0')
0
- + 1 * (status_string[2] - '0');
0
- assert(0 <= status && status < 1000);
0
- ebb_client_write_status(self->client, status, status_string+4);
0
- PyObject *iterator = PyObject_GetIter(response_headers);
0
- PyObject *header_pair;
0
- while(( header_pair = PyIter_Next(iterator) )) {
0
- if(!PyArg_ParseTuple(header_pair, "ss", &field, &value))
0
- ebb_client_write_header(self->client, field, value);
0
- Py_DECREF(header_pair);
0
- /* return write object */
0
static PyObject* env_field(struct ebb_env_item *item)
0
@@ -164,9 +188,7 @@ static py_client* py_client_new(ebb_client *client)
0
py_client *self = PyObject_New(py_client, &py_client_t);
0
if(self == NULL) return NULL;
0
- //if(0 < PyObject_SetAttrString((PyObject*)self, "environ", py_client_env(client)))
0
+ self->env = py_client_env(client);
0
@@ -174,62 +196,70 @@ static py_client* py_client_new(ebb_client *client)
0
void request_cb(ebb_client *client, void *_)
0
PyEval_RestoreThread(libev_thread_state); /* acquire GIL for this thread */
0
- PyObject *environ, *start_response;
0
py_client *pclient = py_client_new(client);
0
assert(pclient != NULL);
0
- //environ = PyObject_GetAttrString((PyObject*)pclient, "environ");
0
- environ = py_client_env(client);
0
- assert(environ != NULL);
0
- start_response = PyObject_GetAttrString((PyObject*)pclient, "start_response");
0
- assert(start_response != NULL);
0
- PyObject *arglist = Py_BuildValue("OO", environ, start_response);
0
- assert(arglist != NULL);
0
assert(application != NULL);
0
- PyObject *body = PyEval_CallObject(application, arglist);
0
- PyObject *iterator = PyObject_GetIter(body);
0
- while (body_item = PyIter_Next(iterator)) {
0
- char *body_string = PyString_AsString(body_item);
0
- int body_length = PyString_Size(body_item);
0
- /* Todo support streaming! */
0
- ebb_client_write_body(client, body_string, body_length);
0
+ PyObject *arglist = Py_BuildValue("(OO)", application, pclient);
0
+ assert(arglist != NULL);
0
+ PyObject *rv = PyEval_CallObject(py_request_cb, arglist);
0
+ ebb_client_close(pclient->client);
0
- ebb_client_release(client);
0
libev_thread_state = PyEval_SaveThread(); /* allow other python threads to run again */
0
+check_stop (struct ev_loop *loop, struct ev_timer *w, int revents)
0
+ if(PyErr_CheckSignals() < 0 || server_running == FALSE || server_error == TRUE) {
0
+ ev_timer_stop(loop, w);
0
+ ev_unloop(loop, EVUNLOOP_ALL);
0
static PyObject *process_connections(PyObject *_, PyObject *args)
0
- assert(application == NULL);
0
- if(!PyArg_ParseTuple(args, "O", &application))
0
+ assert(py_request_cb == NULL);
0
+ if(!PyArg_ParseTuple(args, "OO", &application, &py_request_cb))
0
if(!PyCallable_Check(application)) {
0
PyErr_SetString(PyExc_TypeError, "parameter must be callable");
0
+ if(!PyCallable_Check(py_request_cb)) {
0
+ PyErr_SetString(PyExc_TypeError, "parameter must be callable");
0
Py_XINCREF(application);
0
+ Py_XINCREF(py_request_cb);
0
+ server_running = TRUE;
0
+ ev_timer_init (&check_stop_watcher, check_stop, 0.5, 0.5);
0
+ ev_timer_start (loop, &check_stop_watcher);
0
libev_thread_state = PyEval_SaveThread(); /* allow other threads to run */
0
PyEval_RestoreThread(libev_thread_state); /* reacquire GIL */
0
+ /* TODO: exit properly */
0
+ if(server_error) return NULL;
0
+ //ebb_server_unlisten(&server);
0
+ Py_XDECREF(py_request_cb);
0
Py_XDECREF(application);
0
@@ -244,10 +274,16 @@ static PyObject *listen_on_port(PyObject *_, PyObject *args)
0
+static PyObject *server_stop(PyObject *_)
0
+ server_running = FALSE;
0
static PyMethodDef ebb_module_methods[] =
0
{ {"listen_on_port", (PyCFunction)listen_on_port, METH_VARARGS, NULL}
0
, {"process_connections", (PyCFunction)process_connections, METH_VARARGS, NULL}
0
+ , {"server_stop", (PyCFunction)server_stop, METH_NOARGS, NULL}
0
, {NULL, NULL, 0, NULL}
0
@@ -289,6 +325,6 @@ PyMODINIT_FUNC initebb_ffi(void)
0
DEF_GLOBAL(content_length, "CONTENT_LENGTH");
0
DEF_GLOBAL(http_host, "HTTP_HOST");
0
- loop = ev_default_loop(0);
0
+ loop = ev_default_loop(0);
0
ebb_server_init(&server, loop, request_cb, NULL);
0
\ No newline at end of file
Comments
No one has commented yet.