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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
char response[] = "0\r\n\r\n";
 | 
			
		||||
 | 
			
		||||
/*Helpers for response coroutines*/
 | 
			
		||||
int
 | 
			
		||||
coroutine_iter_sent(struct netbuf *buf){
 | 
			
		||||
	printf("Iter sent called\n");
 | 
			
		||||
	struct co_obj *obj = (struct co_obj*)buf->extra;
 | 
			
		||||
	int ret;
 | 
			
		||||
	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");
 | 
			
		||||
	printf("Found coroutine...\n");
 | 
			
		||||
	lua_getfield(L,-1,"status");
 | 
			
		||||
	printf("Found status...\n");
 | 
			
		||||
	lua_rawgeti(L,LUA_REGISTRYINDEX,obj->ref);
 | 
			
		||||
	printf("About to get status\n");
 | 
			
		||||
	lua_call(L,1,1);
 | 
			
		||||
	printf("Status got\n");
 | 
			
		||||
	const char *status = luaL_checklstring(L,-1,NULL);
 | 
			
		||||
	printf("status in sent: %s\n",status);
 | 
			
		||||
 | 
			
		||||
	if(strcmp(status,"dead") == 0){
 | 
			
		||||
		printf("Cleanup\n");
 | 
			
		||||
		return KORE_RESULT_OK;
 | 
			
		||||
		ret = KORE_RESULT_OK;
 | 
			
		||||
	}else{
 | 
			
		||||
		printf("About to call iter_next from iter_sent\n");
 | 
			
		||||
		return coroutine_iter_next(obj);
 | 
			
		||||
		ret = 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){
 | 
			
		||||
	printf("Coroutine iter next called\n");
 | 
			
		||||
	lua_State *L = obj->L;
 | 
			
		||||
	lua_getglobal(L,"coroutine");
 | 
			
		||||
	lua_getfield(L,-1,"status");
 | 
			
		||||
	lua_rawgeti(L,LUA_REGISTRYINDEX,obj->ref);
 | 
			
		||||
	lua_call(L,1,1);
 | 
			
		||||
	const char *status = luaL_checklstring(L,-1,NULL);
 | 
			
		||||
	printf("status in next: %s\n",status);
 | 
			
		||||
	lua_pop(L,lua_gettop(L));
 | 
			
		||||
	printf("Calling resume\n");
 | 
			
		||||
	lua_getglobal(L,"coroutine");
 | 
			
		||||
	printf("Getting resume()\n");
 | 
			
		||||
	lua_getfield(L,-1,"resume");
 | 
			
		||||
	printf("Getting function\n");
 | 
			
		||||
	lua_rawgeti(L,LUA_REGISTRYINDEX,obj->ref);
 | 
			
		||||
	printf("Checking type\n");
 | 
			
		||||
	luaL_checktype(L,-1,LUA_TTHREAD);
 | 
			
		||||
	printf("About to call resume()\n");
 | 
			
		||||
	int err = lua_pcall(L,1,2,0);
 | 
			
		||||
	if(err != 0){
 | 
			
		||||
		printf("Call error: %d\n",err);
 | 
			
		||||
		return (KORE_RESULT_ERROR);
 | 
			
		||||
	}
 | 
			
		||||
	printf("Done calling resume()\n");
 | 
			
		||||
	if(!lua_toboolean(L,-2)){ //Runtime error
 | 
			
		||||
		printf("Runtime error\n");
 | 
			
		||||
		lua_pushstring(L,":\n");//"error",":"
 | 
			
		||||
		printf("top1:%d\n",lua_gettop(L));
 | 
			
		||||
		lua_getglobal(L,"debug");//"error",":",{debug}
 | 
			
		||||
		printf("top2:%d\n",lua_gettop(L));
 | 
			
		||||
		lua_getfield(L,-1,"traceback");//"error",":",{debug},debug.traceback()
 | 
			
		||||
		printf("top3:%d\n",lua_gettop(L));
 | 
			
		||||
		lua_call(L,0,1);//"error",":",{debug},"traceback"
 | 
			
		||||
		printf("top4:%d\n",lua_gettop(L));
 | 
			
		||||
		lua_remove(L,-2);//"error",":","traceback"
 | 
			
		||||
		printf("top5:%d\n",lua_gettop(L));
 | 
			
		||||
		lua_concat(L,3);
 | 
			
		||||
		printf("top6:%d\n",lua_gettop(L));
 | 
			
		||||
		size_t 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));
 | 
			
		||||
		return (KORE_RESULT_ERROR);
 | 
			
		||||
	}
 | 
			
		||||
	//No runtime error
 | 
			
		||||
	if(lua_type(L,-1) == LUA_TSTRING){
 | 
			
		||||
		printf("Data yielded\n");
 | 
			
		||||
		size_t size;
 | 
			
		||||
		const char *data = luaL_checklstring(L,-1,&size);
 | 
			
		||||
		struct netbuf *nb;
 | 
			
		||||
		printf("Yielding data stream size %zu\n",size);
 | 
			
		||||
		struct kore_buf *kb = kore_buf_alloc(0);
 | 
			
		||||
		struct kore_buf *kb = kore_buf_alloc(4096);
 | 
			
		||||
		kore_buf_appendf(kb,"%x\r\n",size);
 | 
			
		||||
		kore_buf_append(kb,data,size);
 | 
			
		||||
		size_t ssize;
 | 
			
		||||
		char *sstr = kore_buf_stringify(kb,&ssize);
 | 
			
		||||
		net_send_stream(obj->c, sstr, ssize, coroutine_iter_sent, &nb);
 | 
			
		||||
		kore_buf_appendf(kb,"\r\n");
 | 
			
		||||
		//size_t ssize;
 | 
			
		||||
		//char *sstr = kore_buf_stringify(kb,&ssize);
 | 
			
		||||
		net_send_stream(obj->c, kb->data, kb->offset, coroutine_iter_sent, &nb);
 | 
			
		||||
		nb->extra = obj;
 | 
			
		||||
		lua_pop(L,lua_gettop(L));
 | 
			
		||||
		kore_buf_free(kb);
 | 
			
		||||
		return (KORE_RESULT_RETRY);
 | 
			
		||||
		//return err == 0 ? (KORE_RESULT_OK) : (KORE_RESULT_RETRY);
 | 
			
		||||
	}else if(lua_type(L,-1) == LUA_TNIL){
 | 
			
		||||
		printf("Done with function\n");
 | 
			
		||||
		struct netbuf *nb;
 | 
			
		||||
		printf("About to send final bit\n");
 | 
			
		||||
		net_send_stream(obj->c, response, strlen(response) + 1, coroutine_iter_sent, &nb);
 | 
			
		||||
		struct kore_buf *kb = kore_buf_alloc(4096);
 | 
			
		||||
		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;
 | 
			
		||||
		printf("Done sending final bit\n");
 | 
			
		||||
 | 
			
		||||
		lua_pop(L,lua_gettop(L));
 | 
			
		||||
		printf("Poped everything\n");
 | 
			
		||||
		kore_buf_free(kb);
 | 
			
		||||
		return (KORE_RESULT_OK);
 | 
			
		||||
	}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);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
static void
 | 
			
		||||
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;
 | 
			
		||||
	lua_State *L = obj->L;
 | 
			
		||||
	int ref = obj->ref;
 | 
			
		||||
	int Lref = obj->Lref;
 | 
			
		||||
	obj->removed = 1;
 | 
			
		||||
	luaL_unref(L,LUA_REGISTRYINDEX,ref);
 | 
			
		||||
	free(obj);
 | 
			
		||||
	printf("Done with disconnect\n");
 | 
			
		||||
	luaL_unref(L,LUA_REGISTRYINDEX,Lref);
 | 
			
		||||
	c->hdlr_extra = NULL;
 | 
			
		||||
}
 | 
			
		||||
/*
 | 
			
		||||
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
 | 
			
		||||
lhttp_response_co(lua_State *L){
 | 
			
		||||
	struct connection *c;
 | 
			
		||||
	printf("Start response coroutine\n");
 | 
			
		||||
	int coroutine_ref = luaL_ref(L,LUA_REGISTRYINDEX);
 | 
			
		||||
	struct http_request *req = luaL_checkrequest(L,-1);
 | 
			
		||||
	c = req->owner;
 | 
			
		||||
	if(c->state == CONN_STATE_DISCONNECTING){
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
	lua_pop(L,1);
 | 
			
		||||
	req->flags |= HTTP_REQUEST_NO_CONTENT_LENGTH;
 | 
			
		||||
	struct co_obj *obj = (struct co_obj*)malloc(sizeof(struct co_obj));
 | 
			
		||||
	obj->removed = 0;
 | 
			
		||||
	obj->L = lua_newthread(L);
 | 
			
		||||
	obj->Lref = luaL_ref(L,LUA_REGISTRYINDEX);
 | 
			
		||||
	obj->ref = coroutine_ref;
 | 
			
		||||
	obj->c = req->owner;
 | 
			
		||||
	obj->c->flags |= CONN_IS_BUSY;
 | 
			
		||||
	obj->c = c;
 | 
			
		||||
	obj->c->disconnect = coroutine_disconnect;
 | 
			
		||||
	
 | 
			
		||||
	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);
 | 
			
		||||
	printf("About to call iter next\n");
 | 
			
		||||
	coroutine_iter_next(obj);
 | 
			
		||||
	printf("Done calling iter next\n");
 | 
			
		||||
	return 0;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,6 +2,8 @@
 | 
			
		|||
struct co_obj {
 | 
			
		||||
	lua_State *L;
 | 
			
		||||
	int ref;
 | 
			
		||||
	int Lref;
 | 
			
		||||
	int removed;
 | 
			
		||||
	struct connection *c;
 | 
			
		||||
};
 | 
			
		||||
int lhttp_response(lua_State *L);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue