Fix the coroutine response function
This commit is contained in:
parent
9667aa1c3e
commit
ac3fc81741
102
src/libkore.c
102
src/libkore.c
|
@ -45,127 +45,116 @@ lhttp_response(lua_State *L){
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char response[] = "0\r\n\r\n";
|
||||||
|
|
||||||
/*Helpers for response coroutines*/
|
/*Helpers for response coroutines*/
|
||||||
int
|
int
|
||||||
coroutine_iter_sent(struct netbuf *buf){
|
coroutine_iter_sent(struct netbuf *buf){
|
||||||
printf("Iter sent called\n");
|
|
||||||
struct co_obj *obj = (struct co_obj*)buf->extra;
|
struct co_obj *obj = (struct co_obj*)buf->extra;
|
||||||
|
int ret;
|
||||||
lua_State *L = obj->L;
|
lua_State *L = obj->L;
|
||||||
printf("\tbuf:%p\n",(void*)buf);
|
|
||||||
printf("\tobj:%p\n",(void*)obj);
|
|
||||||
printf("\tL:%p\n",(void*)L);
|
|
||||||
|
|
||||||
printf("Top is: %d\n",lua_gettop(L));
|
|
||||||
printf("Getting status...\n");
|
|
||||||
lua_getglobal(L,"coroutine");
|
lua_getglobal(L,"coroutine");
|
||||||
printf("Found coroutine...\n");
|
|
||||||
lua_getfield(L,-1,"status");
|
lua_getfield(L,-1,"status");
|
||||||
printf("Found status...\n");
|
|
||||||
lua_rawgeti(L,LUA_REGISTRYINDEX,obj->ref);
|
lua_rawgeti(L,LUA_REGISTRYINDEX,obj->ref);
|
||||||
printf("About to get status\n");
|
|
||||||
lua_call(L,1,1);
|
lua_call(L,1,1);
|
||||||
printf("Status got\n");
|
|
||||||
const char *status = luaL_checklstring(L,-1,NULL);
|
const char *status = luaL_checklstring(L,-1,NULL);
|
||||||
printf("status in sent: %s\n",status);
|
|
||||||
|
|
||||||
if(strcmp(status,"dead") == 0){
|
if(strcmp(status,"dead") == 0){
|
||||||
printf("Cleanup\n");
|
ret = KORE_RESULT_OK;
|
||||||
return KORE_RESULT_OK;
|
|
||||||
}else{
|
}else{
|
||||||
printf("About to call iter_next from iter_sent\n");
|
ret = coroutine_iter_next(obj);
|
||||||
return coroutine_iter_next(obj);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(ret == KORE_RESULT_RETRY){
|
||||||
|
ret = KORE_RESULT_OK;
|
||||||
|
}else{
|
||||||
|
if(obj->removed == 0){
|
||||||
|
http_start_recv(obj->c);
|
||||||
|
}
|
||||||
|
obj->c->hdlr_extra = NULL;
|
||||||
|
obj->c->disconnect = NULL;
|
||||||
|
obj->c->flags &= ~CONN_IS_BUSY;
|
||||||
|
net_send_queue(obj->c,response,strlen(response));
|
||||||
|
net_send_flush(obj->c);
|
||||||
|
free(obj);
|
||||||
|
}
|
||||||
|
return (ret);
|
||||||
}
|
}
|
||||||
char response[] = "0\r\n\r\n";
|
|
||||||
|
|
||||||
int coroutine_iter_next(struct co_obj *obj){
|
int coroutine_iter_next(struct co_obj *obj){
|
||||||
printf("Coroutine iter next called\n");
|
|
||||||
lua_State *L = obj->L;
|
lua_State *L = obj->L;
|
||||||
lua_getglobal(L,"coroutine");
|
lua_getglobal(L,"coroutine");
|
||||||
lua_getfield(L,-1,"status");
|
lua_getfield(L,-1,"status");
|
||||||
lua_rawgeti(L,LUA_REGISTRYINDEX,obj->ref);
|
lua_rawgeti(L,LUA_REGISTRYINDEX,obj->ref);
|
||||||
lua_call(L,1,1);
|
lua_call(L,1,1);
|
||||||
const char *status = luaL_checklstring(L,-1,NULL);
|
const char *status = luaL_checklstring(L,-1,NULL);
|
||||||
printf("status in next: %s\n",status);
|
|
||||||
lua_pop(L,lua_gettop(L));
|
lua_pop(L,lua_gettop(L));
|
||||||
printf("Calling resume\n");
|
|
||||||
lua_getglobal(L,"coroutine");
|
lua_getglobal(L,"coroutine");
|
||||||
printf("Getting resume()\n");
|
|
||||||
lua_getfield(L,-1,"resume");
|
lua_getfield(L,-1,"resume");
|
||||||
printf("Getting function\n");
|
|
||||||
lua_rawgeti(L,LUA_REGISTRYINDEX,obj->ref);
|
lua_rawgeti(L,LUA_REGISTRYINDEX,obj->ref);
|
||||||
printf("Checking type\n");
|
|
||||||
luaL_checktype(L,-1,LUA_TTHREAD);
|
luaL_checktype(L,-1,LUA_TTHREAD);
|
||||||
printf("About to call resume()\n");
|
|
||||||
int err = lua_pcall(L,1,2,0);
|
int err = lua_pcall(L,1,2,0);
|
||||||
if(err != 0){
|
if(err != 0){
|
||||||
printf("Call error: %d\n",err);
|
|
||||||
return (KORE_RESULT_ERROR);
|
return (KORE_RESULT_ERROR);
|
||||||
}
|
}
|
||||||
printf("Done calling resume()\n");
|
|
||||||
if(!lua_toboolean(L,-2)){ //Runtime error
|
if(!lua_toboolean(L,-2)){ //Runtime error
|
||||||
printf("Runtime error\n");
|
|
||||||
lua_pushstring(L,":\n");//"error",":"
|
lua_pushstring(L,":\n");//"error",":"
|
||||||
printf("top1:%d\n",lua_gettop(L));
|
|
||||||
lua_getglobal(L,"debug");//"error",":",{debug}
|
lua_getglobal(L,"debug");//"error",":",{debug}
|
||||||
printf("top2:%d\n",lua_gettop(L));
|
|
||||||
lua_getfield(L,-1,"traceback");//"error",":",{debug},debug.traceback()
|
lua_getfield(L,-1,"traceback");//"error",":",{debug},debug.traceback()
|
||||||
printf("top3:%d\n",lua_gettop(L));
|
|
||||||
lua_call(L,0,1);//"error",":",{debug},"traceback"
|
lua_call(L,0,1);//"error",":",{debug},"traceback"
|
||||||
printf("top4:%d\n",lua_gettop(L));
|
|
||||||
lua_remove(L,-2);//"error",":","traceback"
|
lua_remove(L,-2);//"error",":","traceback"
|
||||||
printf("top5:%d\n",lua_gettop(L));
|
|
||||||
lua_concat(L,3);
|
lua_concat(L,3);
|
||||||
printf("top6:%d\n",lua_gettop(L));
|
|
||||||
size_t size;
|
size_t size;
|
||||||
const char *s = luaL_checklstring(L,-1,&size);
|
const char *s = luaL_checklstring(L,-1,&size);
|
||||||
printf("Error: %s\n",s);
|
kore_log(LOG_ERR,"Error: %s\n",s);
|
||||||
lua_pop(L,lua_gettop(L));
|
lua_pop(L,lua_gettop(L));
|
||||||
return (KORE_RESULT_ERROR);
|
return (KORE_RESULT_ERROR);
|
||||||
}
|
}
|
||||||
//No runtime error
|
//No runtime error
|
||||||
if(lua_type(L,-1) == LUA_TSTRING){
|
if(lua_type(L,-1) == LUA_TSTRING){
|
||||||
printf("Data yielded\n");
|
|
||||||
size_t size;
|
size_t size;
|
||||||
const char *data = luaL_checklstring(L,-1,&size);
|
const char *data = luaL_checklstring(L,-1,&size);
|
||||||
struct netbuf *nb;
|
struct netbuf *nb;
|
||||||
printf("Yielding data stream size %zu\n",size);
|
struct kore_buf *kb = kore_buf_alloc(4096);
|
||||||
struct kore_buf *kb = kore_buf_alloc(0);
|
|
||||||
kore_buf_appendf(kb,"%x\r\n",size);
|
kore_buf_appendf(kb,"%x\r\n",size);
|
||||||
kore_buf_append(kb,data,size);
|
kore_buf_append(kb,data,size);
|
||||||
size_t ssize;
|
kore_buf_appendf(kb,"\r\n");
|
||||||
char *sstr = kore_buf_stringify(kb,&ssize);
|
//size_t ssize;
|
||||||
net_send_stream(obj->c, sstr, ssize, coroutine_iter_sent, &nb);
|
//char *sstr = kore_buf_stringify(kb,&ssize);
|
||||||
|
net_send_stream(obj->c, kb->data, kb->offset, coroutine_iter_sent, &nb);
|
||||||
nb->extra = obj;
|
nb->extra = obj;
|
||||||
lua_pop(L,lua_gettop(L));
|
lua_pop(L,lua_gettop(L));
|
||||||
kore_buf_free(kb);
|
kore_buf_free(kb);
|
||||||
return (KORE_RESULT_RETRY);
|
return (KORE_RESULT_RETRY);
|
||||||
//return err == 0 ? (KORE_RESULT_OK) : (KORE_RESULT_RETRY);
|
//return err == 0 ? (KORE_RESULT_OK) : (KORE_RESULT_RETRY);
|
||||||
}else if(lua_type(L,-1) == LUA_TNIL){
|
}else if(lua_type(L,-1) == LUA_TNIL){
|
||||||
printf("Done with function\n");
|
|
||||||
struct netbuf *nb;
|
struct netbuf *nb;
|
||||||
printf("About to send final bit\n");
|
struct kore_buf *kb = kore_buf_alloc(4096);
|
||||||
net_send_stream(obj->c, response, strlen(response) + 1, coroutine_iter_sent, &nb);
|
kore_buf_appendf(kb,"0\r\n\r\n");
|
||||||
|
net_send_queue(obj->c, kb->data, kb->offset);
|
||||||
|
net_send_stream(obj->c, response, strlen(response) + 0, coroutine_iter_sent, &nb);
|
||||||
nb->extra = obj;
|
nb->extra = obj;
|
||||||
printf("Done sending final bit\n");
|
|
||||||
lua_pop(L,lua_gettop(L));
|
lua_pop(L,lua_gettop(L));
|
||||||
printf("Poped everything\n");
|
kore_buf_free(kb);
|
||||||
return (KORE_RESULT_OK);
|
return (KORE_RESULT_OK);
|
||||||
}else{
|
}else{
|
||||||
printf("Coroutine used for response returned something that was not a string:%s\n",lua_typename(L,lua_type(L,-1)));
|
kore_log(LOG_CRIT,"Coroutine used for response returned something that was not a string:%s\n",lua_typename(L,lua_type(L,-1)));
|
||||||
return (KORE_RESULT_ERROR);
|
return (KORE_RESULT_ERROR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
static void
|
static void
|
||||||
coroutine_disconnect(struct connection *c){
|
coroutine_disconnect(struct connection *c){
|
||||||
printf("Disconnect routine called\n");
|
kore_log(LOG_ERR,"Disconnect routine called\n");
|
||||||
struct co_obj *obj = (struct co_obj*)c->hdlr_extra;
|
struct co_obj *obj = (struct co_obj*)c->hdlr_extra;
|
||||||
lua_State *L = obj->L;
|
lua_State *L = obj->L;
|
||||||
int ref = obj->ref;
|
int ref = obj->ref;
|
||||||
|
int Lref = obj->Lref;
|
||||||
|
obj->removed = 1;
|
||||||
luaL_unref(L,LUA_REGISTRYINDEX,ref);
|
luaL_unref(L,LUA_REGISTRYINDEX,ref);
|
||||||
free(obj);
|
luaL_unref(L,LUA_REGISTRYINDEX,Lref);
|
||||||
printf("Done with disconnect\n");
|
c->hdlr_extra = NULL;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
The coroutine passed to this function should yield() the data to send to the
|
The coroutine passed to this function should yield() the data to send to the
|
||||||
|
@ -176,20 +165,29 @@ http_response_co(request::userdata, co::coroutine)
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
lhttp_response_co(lua_State *L){
|
lhttp_response_co(lua_State *L){
|
||||||
|
struct connection *c;
|
||||||
printf("Start response coroutine\n");
|
printf("Start response coroutine\n");
|
||||||
int coroutine_ref = luaL_ref(L,LUA_REGISTRYINDEX);
|
int coroutine_ref = luaL_ref(L,LUA_REGISTRYINDEX);
|
||||||
struct http_request *req = luaL_checkrequest(L,-1);
|
struct http_request *req = luaL_checkrequest(L,-1);
|
||||||
|
c = req->owner;
|
||||||
|
if(c->state == CONN_STATE_DISCONNECTING){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
lua_pop(L,1);
|
lua_pop(L,1);
|
||||||
req->flags |= HTTP_REQUEST_NO_CONTENT_LENGTH;
|
|
||||||
struct co_obj *obj = (struct co_obj*)malloc(sizeof(struct co_obj));
|
struct co_obj *obj = (struct co_obj*)malloc(sizeof(struct co_obj));
|
||||||
|
obj->removed = 0;
|
||||||
obj->L = lua_newthread(L);
|
obj->L = lua_newthread(L);
|
||||||
|
obj->Lref = luaL_ref(L,LUA_REGISTRYINDEX);
|
||||||
obj->ref = coroutine_ref;
|
obj->ref = coroutine_ref;
|
||||||
obj->c = req->owner;
|
obj->c = c;
|
||||||
obj->c->flags |= CONN_IS_BUSY;
|
|
||||||
obj->c->disconnect = coroutine_disconnect;
|
obj->c->disconnect = coroutine_disconnect;
|
||||||
|
|
||||||
obj->c->hdlr_extra = obj;
|
obj->c->hdlr_extra = obj;
|
||||||
printf("About to call iter next\n");
|
obj->c->flags |= CONN_IS_BUSY;
|
||||||
|
req->flags |= HTTP_REQUEST_NO_CONTENT_LENGTH;
|
||||||
|
http_response_header(req,"transfer-encoding","chunked");
|
||||||
http_response(req,200,NULL,0);
|
http_response(req,200,NULL,0);
|
||||||
|
printf("About to call iter next\n");
|
||||||
coroutine_iter_next(obj);
|
coroutine_iter_next(obj);
|
||||||
printf("Done calling iter next\n");
|
printf("Done calling iter next\n");
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
struct co_obj {
|
struct co_obj {
|
||||||
lua_State *L;
|
lua_State *L;
|
||||||
int ref;
|
int ref;
|
||||||
|
int Lref;
|
||||||
|
int removed;
|
||||||
struct connection *c;
|
struct connection *c;
|
||||||
};
|
};
|
||||||
int lhttp_response(lua_State *L);
|
int lhttp_response(lua_State *L);
|
||||||
|
|
Loading…
Reference in New Issue