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