in the midst of debugging http server code
This commit is contained in:
		| @ -377,7 +377,7 @@ static mio_bch_t* parse_initial_line (mio_htrd_t* htrd, mio_bch_t* line) | |||||||
| #else | #else | ||||||
| 		while (*p != '\0' && !is_space_octet(*p))  | 		while (*p != '\0' && !is_space_octet(*p))  | ||||||
| 		{ | 		{ | ||||||
| 			if (*p == '?' && param.ptr == MIO_NULL) | 			if (*p == '?' && !param.ptr) | ||||||
| 			{ | 			{ | ||||||
| 				tmp.len = p - tmp.ptr; /* length of the path part */ | 				tmp.len = p - tmp.ptr; /* length of the path part */ | ||||||
| 				*p++ = '\0'; /* null-terminate the path part */ | 				*p++ = '\0'; /* null-terminate the path part */ | ||||||
| @ -388,7 +388,15 @@ static mio_bch_t* parse_initial_line (mio_htrd_t* htrd, mio_bch_t* line) | |||||||
|  |  | ||||||
| 		/* the url must be followed by a space */ | 		/* the url must be followed by a space */ | ||||||
| 		if (!is_space_octet(*p)) goto badre; | 		if (!is_space_octet(*p)) goto badre; | ||||||
|  | 		if (param.ptr)  | ||||||
|  | 		{ | ||||||
| 			param.len = p - param.ptr; /* length of the param part */ | 			param.len = p - param.ptr; /* length of the param part */ | ||||||
|  | 		} | ||||||
|  | 		else  | ||||||
|  | 		{ | ||||||
|  | 			tmp.len = p - tmp.ptr; | ||||||
|  | 			param.len = 0; | ||||||
|  | 		} | ||||||
| 		*p = '\0';  /* null-terminate the path or param part */ | 		*p = '\0';  /* null-terminate the path or param part */ | ||||||
|  |  | ||||||
| 		if (param.ptr) | 		if (param.ptr) | ||||||
|  | |||||||
| @ -9,6 +9,7 @@ | |||||||
| #include <fcntl.h> | #include <fcntl.h> | ||||||
| #include <sys/stat.h> | #include <sys/stat.h> | ||||||
| #include <pthread.h> | #include <pthread.h> | ||||||
|  | #include <stdlib.h> /* setenv */ | ||||||
|  |  | ||||||
| #define CGI_ALLOW_UNLIMITED_REQ_CONTENT_LENGTH | #define CGI_ALLOW_UNLIMITED_REQ_CONTENT_LENGTH | ||||||
|  |  | ||||||
| @ -113,6 +114,8 @@ static int process_request (mio_svc_htts_t* htts, mio_dev_sck_t* csck, mio_htre_ | |||||||
| 	 * the decoded query path is made available in the | 	 * the decoded query path is made available in the | ||||||
| 	 * non-peek mode as well */ | 	 * non-peek mode as well */ | ||||||
|  |  | ||||||
|  | 	MIO_DEBUG2 (htts->mio, "[RAW-REQ] %s %s\n", mio_htre_getqmethodname(req), mio_htre_getqpath(req)); | ||||||
|  |  | ||||||
| 	mio_htre_perdecqpath(req); | 	mio_htre_perdecqpath(req); | ||||||
| 	/* TODO: proper request logging */ | 	/* TODO: proper request logging */ | ||||||
|  |  | ||||||
| @ -180,7 +183,7 @@ if (mio_htre_getcontentlen(req) > 0) | |||||||
| 			mio_htre_discardcontent (req);  | 			mio_htre_discardcontent (req);  | ||||||
| 			/* 411 Length Required - can't keep alive. Force disconnect */ | 			/* 411 Length Required - can't keep alive. Force disconnect */ | ||||||
| 			req->flags &= ~MIO_HTRE_ATTR_KEEPALIVE; /* to cause sendstatus() to close */ | 			req->flags &= ~MIO_HTRE_ATTR_KEEPALIVE; /* to cause sendstatus() to close */ | ||||||
| 			if (mio_svc_htts_sendstatus(htts, csck, req, 411, MIO_NULL) <= -1) mio_dev_sck_halt (csck); /*TODO: redo this sendstatus */ | 			if (mio_svc_htts_sendstatus(htts, csck, req, 411, MIO_NULL) <= -1) goto oops; | ||||||
| 		} | 		} | ||||||
| 		else | 		else | ||||||
|  |  | ||||||
| @ -189,35 +192,6 @@ if (mio_htre_getcontentlen(req) > 0) | |||||||
| 			/*const mio_bch_t* qpath = mio_htre_getqpath(req);*/ | 			/*const mio_bch_t* qpath = mio_htre_getqpath(req);*/ | ||||||
| 			if (mio_svc_htts_docgi(htts, csck, req, "") <= -1) goto oops; | 			if (mio_svc_htts_docgi(htts, csck, req, "") <= -1) goto oops; | ||||||
|  |  | ||||||
| #if 0 |  | ||||||
| /* |  | ||||||
| 			if (mio_comp_bcstr(qpath, "/testfunc", 0) == 0) |  | ||||||
| 			{ |  | ||||||
| 				if (mio_svc_htts_sendcgi(htts, csck, test_func_handler, req) <= -1) |  | ||||||
| 				{ |  | ||||||
| 					mio_htre_discardcontent (req); |  | ||||||
| 					mio_dev_sck_halt (csck); |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
| 			else */if (mio_svc_htts_sendfile(htts, csck, qpath, 200, mth, mio_htre_getversion(req), (req->flags & MIO_HTRE_ATTR_KEEPALIVE)) <= -1) |  | ||||||
| 			{ |  | ||||||
| 				mio_htre_discardcontent (req); |  | ||||||
| 				mio_dev_sck_halt (csck); |  | ||||||
| 			} |  | ||||||
|  |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	if (!(req->flags & MIO_HTRE_ATTR_KEEPALIVE) || mth == MIO_HTTP_CONNECT) |  | ||||||
| 	{ |  | ||||||
| 		if (!peek) |  | ||||||
| 		{ |  | ||||||
| ////			task = mio_htts_entaskdisconnect(htts, client, MIO_NULL); |  | ||||||
| ////			if (MIO_UNLIKELY(!task)) goto oops; |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| 	return 0; | 	return 0; | ||||||
|  |  | ||||||
| oops: | oops: | ||||||
| @ -289,7 +263,6 @@ static void fini_client (mio_svc_htts_cli_t* cli) | |||||||
|  |  | ||||||
| 	if (cli->rsrc) | 	if (cli->rsrc) | ||||||
| 	{ | 	{ | ||||||
| printf ("TRYING TO KILL RSRC IN VARIABLE - ADDRESS %p\n", &cli->rsrc); |  | ||||||
| 		mio_svc_htts_rsrc_kill (cli->rsrc); | 		mio_svc_htts_rsrc_kill (cli->rsrc); | ||||||
| 		cli->rsrc = MIO_NULL; | 		cli->rsrc = MIO_NULL; | ||||||
| 	} | 	} | ||||||
| @ -333,18 +306,19 @@ static int listener_on_read (mio_dev_sck_t* sck, const void* buf, mio_iolen_t le | |||||||
|  |  | ||||||
| 	if (len <= -1) | 	if (len <= -1) | ||||||
| 	{ | 	{ | ||||||
| 		MIO_DEBUG3 (mio, "HTTS(%p) - unable to read client socket %p(%d)\n", cli->htts, sck, (int)sck->hnd); | 		MIO_DEBUG3 (mio, "HTTS(%p) - unable to read client %p(%d)\n", cli->htts, sck, (int)sck->hnd); | ||||||
| 		goto oops; | 		goto oops; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if (len == 0) goto oops; | 	if (len == 0)  | ||||||
|  | 	{ | ||||||
|  | 		MIO_DEBUG3 (mio, "HTTS(%p) - EOF on client %p(%d)\n", cli->htts, sck, (int)sck->hnd); | ||||||
|  | 		goto oops; | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	if ((x = mio_htrd_feed(cli->htrd, buf, len, &rem)) <= -1)  | 	if ((x = mio_htrd_feed(cli->htrd, buf, len, &rem)) <= -1)  | ||||||
| 	{ | 	{ | ||||||
| /* in some cases, we may have to send  some http response depending on the failure type */ |  | ||||||
| /* BADRE -> bad request? */ |  | ||||||
| printf ("** HTTS - client htrd feed failure socket(%p) - %d\n", sck, x); | printf ("** HTTS - client htrd feed failure socket(%p) - %d\n", sck, x); | ||||||
| 		/* TODO: either send bad request or server failure ... */ |  | ||||||
| 		goto oops; | 		goto oops; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @ -363,6 +337,7 @@ printf ("** HTTS - client htrd feed failure socket(%p) - %d\n", sck, x); | |||||||
| 	return 0; | 	return 0; | ||||||
|  |  | ||||||
| oops: | oops: | ||||||
|  | printf ("HALTING CLIENT SOCKEXXT %p\n", sck); | ||||||
| 	mio_dev_sck_halt (sck); | 	mio_dev_sck_halt (sck); | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| @ -401,63 +376,64 @@ static void listener_on_connect (mio_dev_sck_t* sck) | |||||||
|  |  | ||||||
| static void listener_on_disconnect (mio_dev_sck_t* sck) | static void listener_on_disconnect (mio_dev_sck_t* sck) | ||||||
| { | { | ||||||
|  | 	mio_t* mio = sck->mio; | ||||||
| 	mio_svc_htts_cli_t* cli = mio_dev_sck_getxtn(sck); | 	mio_svc_htts_cli_t* cli = mio_dev_sck_getxtn(sck); | ||||||
|  |  | ||||||
| 	switch (MIO_DEV_SCK_GET_PROGRESS(sck)) | 	switch (MIO_DEV_SCK_GET_PROGRESS(sck)) | ||||||
| 	{ | 	{ | ||||||
| 		case MIO_DEV_SCK_CONNECTING: | 		case MIO_DEV_SCK_CONNECTING: | ||||||
| 			/* only for connecting sockets */ | 			/* only for connecting sockets */ | ||||||
| 			MIO_DEBUG1 (sck->mio, "OUTGOING SESSION DISCONNECTED - FAILED TO CONNECT (%d) TO REMOTE SERVER\n", (int)sck->hnd); | 			MIO_DEBUG1 (mio, "OUTGOING SESSION DISCONNECTED - FAILED TO CONNECT (%d) TO REMOTE SERVER\n", (int)sck->hnd); | ||||||
| 			break; | 			break; | ||||||
|  |  | ||||||
| 		case MIO_DEV_SCK_CONNECTING_SSL: | 		case MIO_DEV_SCK_CONNECTING_SSL: | ||||||
| 			/* only for connecting sockets */ | 			/* only for connecting sockets */ | ||||||
| 			MIO_DEBUG1 (sck->mio, "OUTGOING SESSION DISCONNECTED - FAILED TO SSL-CONNECT (%d) TO REMOTE SERVER\n", (int)sck->hnd); | 			MIO_DEBUG1 (mio, "OUTGOING SESSION DISCONNECTED - FAILED TO SSL-CONNECT (%d) TO REMOTE SERVER\n", (int)sck->hnd); | ||||||
| 			break; | 			break; | ||||||
|  |  | ||||||
| 		case MIO_DEV_SCK_CONNECTED: | 		case MIO_DEV_SCK_CONNECTED: | ||||||
| 			/* only for connecting sockets */ | 			/* only for connecting sockets */ | ||||||
| 			MIO_DEBUG1 (sck->mio, "OUTGOING CLIENT CONNECTION GOT TORN DOWN %p(%d).......\n", (int)sck->hnd); | 			MIO_DEBUG1 (mio, "OUTGOING CLIENT CONNECTION GOT TORN DOWN %p(%d).......\n", (int)sck->hnd); | ||||||
| 			break; | 			break; | ||||||
|  |  | ||||||
| 		case MIO_DEV_SCK_LISTENING: | 		case MIO_DEV_SCK_LISTENING: | ||||||
| 			MIO_DEBUG2 (sck->mio, "LISTNER SOCKET %p(%d) - SHUTTUING DOWN\n", sck, (int)sck->hnd); | 			MIO_DEBUG2 (mio, "LISTNER SOCKET %p(%d) - SHUTTUING DOWN\n", sck, (int)sck->hnd); | ||||||
| 			break; | 			break; | ||||||
|  |  | ||||||
| 		case MIO_DEV_SCK_ACCEPTING_SSL: /* special case. */ | 		case MIO_DEV_SCK_ACCEPTING_SSL: /* special case. */ | ||||||
| 			/* this progress code indicates that the ssl-level accept failed. | 			/* this progress code indicates that the ssl-level accept failed. | ||||||
| 			 * on_disconnected() with this code is called without corresponding on_connect().  | 			 * on_disconnected() with this code is called without corresponding on_connect().  | ||||||
| 			 * the cli extension are is not initialized yet */ | 			 * the cli extension are is not initialized yet */ | ||||||
| 			MIO_ASSERT (sck->mio, sck != cli->sck); | 			MIO_ASSERT (mio, sck != cli->sck); | ||||||
| 			MIO_ASSERT (sck->mio, cli->sck == cli->htts->lsck); /* the field is a copy of the extension are of the listener socket. so it should point to the listner socket */ | 			MIO_ASSERT (mio, cli->sck == cli->htts->lsck); /* the field is a copy of the extension are of the listener socket. so it should point to the listner socket */ | ||||||
| 			MIO_DEBUG2 (sck->mio, "LISTENER UNABLE TO SSL-ACCEPT CLIENT %p(%d) ....%p\n", sck, (int)sck->hnd); | 			MIO_DEBUG2 (mio, "LISTENER UNABLE TO SSL-ACCEPT CLIENT %p(%d) ....%p\n", sck, (int)sck->hnd); | ||||||
| 			return; | 			return; | ||||||
|  |  | ||||||
| 		case MIO_DEV_SCK_ACCEPTED: | 		case MIO_DEV_SCK_ACCEPTED: | ||||||
| 			/* only for sockets accepted by the listeners. will never come here because | 			/* only for sockets accepted by the listeners. will never come here because | ||||||
| 			 * the disconnect call for such sockets have been changed in listener_on_connect() */ | 			 * the disconnect call for such sockets have been changed in listener_on_connect() */ | ||||||
| 			MIO_DEBUG2 (sck->mio, "ACCEPTED CLIENT SOCKET %p(%d) GOT DISCONNECTED.......\n", sck, (int)sck->hnd); | 			MIO_DEBUG2 (mio, "ACCEPTED CLIENT SOCKET %p(%d) GOT DISCONNECTED.......\n", sck, (int)sck->hnd); | ||||||
| 			break; | 			break; | ||||||
|  |  | ||||||
| 		default: | 		default: | ||||||
| 			MIO_DEBUG2 (sck->mio, "SOCKET %p(%d) DISCONNECTED AFTER ALL.......\n", sck, (int)sck->hnd); | 			MIO_DEBUG2 (mio, "SOCKET %p(%d) DISCONNECTED AFTER ALL.......\n", sck, (int)sck->hnd); | ||||||
| 			break; | 			break; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if (sck == cli->htts->lsck) | 	if (sck == cli->htts->lsck) | ||||||
| 	{ | 	{ | ||||||
| 		/* the listener socket has these fields set to NULL */ | 		/* the listener socket has these fields set to NULL */ | ||||||
| 		MIO_ASSERT (sck->mio, cli->htrd == MIO_NULL); | 		MIO_ASSERT (mio, cli->htrd == MIO_NULL); | ||||||
| 		MIO_ASSERT (sck->mio, cli->sbuf == MIO_NULL); | 		MIO_ASSERT (mio, cli->sbuf == MIO_NULL); | ||||||
|  |  | ||||||
| 		MIO_DEBUG2 (sck->mio, "HTTS(%p) - listener socket disconnect %p\n", cli->htts, sck); | 		MIO_DEBUG2 (mio, "HTTS(%p) - listener socket disconnect %p\n", cli->htts, sck); | ||||||
| 		cli->htts->lsck = MIO_NULL; /* let the htts service forget about this listening socket */ | 		cli->htts->lsck = MIO_NULL; /* let the htts service forget about this listening socket */ | ||||||
| 	} | 	} | ||||||
| 	else | 	else | ||||||
| 	{ | 	{ | ||||||
| 		/* client socket */ | 		/* client socket */ | ||||||
| 		MIO_DEBUG2 (sck->mio, "HTTS(%p) - client socket disconnect %p\n", cli->htts, sck); | 		MIO_DEBUG2 (mio, "HTTS(%p) - client socket disconnect %p\n", cli->htts, sck); | ||||||
| 		MIO_ASSERT (sck->mio, cli->sck == sck); | 		MIO_ASSERT (mio, cli->sck == sck); | ||||||
| 		fini_client (cli); | 		fini_client (cli); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| @ -653,12 +629,14 @@ struct cgi_state_t | |||||||
| 	unsigned int over: 4; /* must be large enough to accomodate CGI_STATE_OVER_ALL */ | 	unsigned int over: 4; /* must be large enough to accomodate CGI_STATE_OVER_ALL */ | ||||||
| 	unsigned int keep_alive: 1; | 	unsigned int keep_alive: 1; | ||||||
| 	unsigned int req_content_length_unlimited: 1; | 	unsigned int req_content_length_unlimited: 1; | ||||||
| 	unsigned int ever_attempted_to_write_to_client; | 	unsigned int ever_attempted_to_write_to_client: 1; | ||||||
|  | 	unsigned int client_disconnected: 1; | ||||||
| 	mio_oow_t req_content_length; /* client request content length */ | 	mio_oow_t req_content_length; /* client request content length */ | ||||||
| 	cgi_state_res_mode_t res_mode_to_cli; | 	cgi_state_res_mode_t res_mode_to_cli; | ||||||
|  |  | ||||||
| 	mio_dev_sck_on_read_t client_org_on_read; | 	mio_dev_sck_on_read_t client_org_on_read; | ||||||
| 	mio_dev_sck_on_write_t client_org_on_write; | 	mio_dev_sck_on_write_t client_org_on_write; | ||||||
|  | 	mio_dev_sck_on_disconnect_t client_org_on_disconnect; | ||||||
| }; | }; | ||||||
| typedef struct cgi_state_t cgi_state_t; | typedef struct cgi_state_t cgi_state_t; | ||||||
|  |  | ||||||
| @ -673,14 +651,12 @@ static void cgi_state_halt_participating_devices (cgi_state_t* cgi_state) | |||||||
| 	MIO_ASSERT (cgi_state->client->htts->mio, cgi_state->client != MIO_NULL); | 	MIO_ASSERT (cgi_state->client->htts->mio, cgi_state->client != MIO_NULL); | ||||||
| 	MIO_ASSERT (cgi_state->client->htts->mio, cgi_state->client->sck != MIO_NULL); | 	MIO_ASSERT (cgi_state->client->htts->mio, cgi_state->client->sck != MIO_NULL); | ||||||
|  |  | ||||||
| 	MIO_DEBUG4 (cgi_state->client->htts->mio, "HTTS(%p) - halting cgi state %p(client=%p,peer=%p)\n", cgi_state->client->htts, cgi_state, cgi_state->client->sck, cgi_state->peer); | 	MIO_DEBUG4 (cgi_state->client->htts->mio, "HTTS(%p) - Halting participating devices in cgi state %p(client=%p,peer=%p)\n", cgi_state->client->htts, cgi_state, cgi_state->client->sck, cgi_state->peer); | ||||||
|  |  | ||||||
|  |  | ||||||
| 	mio_dev_sck_halt (cgi_state->client->sck); | 	mio_dev_sck_halt (cgi_state->client->sck); | ||||||
| 	/* check for peer as it may not have been started */ | 	/* check for peer as it may not have been started */ | ||||||
| 	if (cgi_state->peer) mio_dev_pro_halt (cgi_state->peer); | 	if (cgi_state->peer) mio_dev_pro_halt (cgi_state->peer); | ||||||
|  |  | ||||||
| /* TODO: when to destroy cgi_state? */ |  | ||||||
|  |  | ||||||
| } | } | ||||||
|  |  | ||||||
| static int cgi_state_write_to_client (cgi_state_t* cgi_state, const void* data, mio_iolen_t dlen) | static int cgi_state_write_to_client (cgi_state_t* cgi_state, const void* data, mio_iolen_t dlen) | ||||||
| @ -719,6 +695,16 @@ static int cgi_state_writev_to_client (cgi_state_t* cgi_state, mio_iovec_t* iov, | |||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static int cgi_state_write_last_chunk_to_client (cgi_state_t* cgi_state) | ||||||
|  | { | ||||||
|  | 	if (cgi_state->res_mode_to_cli == CGI_STATE_RES_MODE_CHUNKED && | ||||||
|  | 	    cgi_state_write_to_client(cgi_state, "0\r\n\r\n", 5) <= -1) return -1; | ||||||
|  |  | ||||||
|  | 	if (!cgi_state->keep_alive && cgi_state_write_to_client(cgi_state, MIO_NULL, 0) <= -1) return -1; | ||||||
|  |  | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
| static int cgi_state_write_to_peer (cgi_state_t* cgi_state, const void* data, mio_iolen_t dlen) | static int cgi_state_write_to_peer (cgi_state_t* cgi_state, const void* data, mio_iolen_t dlen) | ||||||
| { | { | ||||||
| 	cgi_state->num_pending_writes_to_peer++; | 	cgi_state->num_pending_writes_to_peer++; | ||||||
| @ -763,12 +749,12 @@ static MIO_INLINE void cgi_state_mark_over (cgi_state_t* cgi_state, int over_bit | |||||||
|  |  | ||||||
| 	if (!(old_over & CGI_STATE_OVER_READ_FROM_CLIENT) && (cgi_state->over & CGI_STATE_OVER_READ_FROM_CLIENT)) | 	if (!(old_over & CGI_STATE_OVER_READ_FROM_CLIENT) && (cgi_state->over & CGI_STATE_OVER_READ_FROM_CLIENT)) | ||||||
| 	{ | 	{ | ||||||
| 		mio_dev_sck_read (cgi_state->client->sck, 0); /* TODO: error handling */ | 		if (mio_dev_sck_read(cgi_state->client->sck, 0) <= -1) mio_dev_sck_halt (cgi_state->client->sck); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if (!(old_over & CGI_STATE_OVER_READ_FROM_PEER) && (cgi_state->over & CGI_STATE_OVER_READ_FROM_PEER)) | 	if (!(old_over & CGI_STATE_OVER_READ_FROM_PEER) && (cgi_state->over & CGI_STATE_OVER_READ_FROM_PEER)) | ||||||
| 	{ | 	{ | ||||||
| 		if (cgi_state->peer) mio_dev_pro_read (cgi_state->peer, MIO_DEV_PRO_OUT, 0); /* TODO: error handling */ | 		if (cgi_state->peer && mio_dev_pro_read(cgi_state->peer, MIO_DEV_PRO_OUT, 0) <= -1) mio_dev_pro_halt (cgi_state->peer); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if (old_over != CGI_STATE_OVER_ALL && cgi_state->over == CGI_STATE_OVER_ALL) | 	if (old_over != CGI_STATE_OVER_ALL && cgi_state->over == CGI_STATE_OVER_ALL) | ||||||
| @ -779,11 +765,11 @@ static MIO_INLINE void cgi_state_mark_over (cgi_state_t* cgi_state, int over_bit | |||||||
| 		if (cgi_state->keep_alive)  | 		if (cgi_state->keep_alive)  | ||||||
| 		{ | 		{ | ||||||
| 			/* how to arrange to delete this cgi_state object and put the socket back to the normal waiting state??? */ | 			/* how to arrange to delete this cgi_state object and put the socket back to the normal waiting state??? */ | ||||||
| 			MIO_ASSERT (cgi_state->htts->mio, cgi_state->client->rsrc == cgi_state); | 			MIO_ASSERT (cgi_state->htts->mio, cgi_state->client->rsrc == (mio_svc_htts_rsrc_t*)cgi_state); | ||||||
|  |  | ||||||
| printf ("DEASSIGNING FROM THE MAIN CLIENT RSRC... state -> %p VARIABEL ADDRESSS %p\n", cgi_state->client->rsrc, &cgi_state->client->rsrc); | printf ("DETACHING FROM THE MAIN CLIENT RSRC... state -> %p\n", cgi_state->client->rsrc); | ||||||
| 			MIO_SVC_HTTS_RSRC_DEASSIGN (cgi_state->client->rsrc); | 			MIO_SVC_HTTS_RSRC_DETACH (cgi_state->client->rsrc); | ||||||
| printf ("AFTER DEASSIGNING FROM THE MAIN CLIENT RSRC... state -> %p VARIABEL ADDRESSS %p\n", cgi_state->client->rsrc, &cgi_state->client->rsrc); | 			/* cgi_state must not be access from here down as it could have been destroyed */ | ||||||
| 		} | 		} | ||||||
| 		else | 		else | ||||||
| 		{ | 		{ | ||||||
| @ -826,13 +812,28 @@ printf ("**** CGI_STATE_ON_KILL \n"); | |||||||
| 		cgi_state->client_org_on_write = MIO_NULL; | 		cgi_state->client_org_on_write = MIO_NULL; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	mio_htrd_setrecbs (cgi_state->client->htrd, &client_htrd_recbs); /* restore the callbacks */ |  | ||||||
| 	if (mio_dev_sck_read (cgi_state->client->sck, 1) <= -1) | 	if (cgi_state->client_org_on_disconnect) | ||||||
| 	{ | 	{ | ||||||
|  | 		cgi_state->client->sck->on_disconnect = cgi_state->client_org_on_disconnect; | ||||||
|  | 		cgi_state->client_org_on_disconnect = MIO_NULL; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	mio_htrd_setrecbs (cgi_state->client->htrd, &client_htrd_recbs); /* restore the callbacks */ | ||||||
|  |  | ||||||
|  | 	if (!cgi_state->client_disconnected) | ||||||
|  | 	{ | ||||||
|  | printf ("ENABLING INPUT WATCHING on CLIENT %p. \n", cgi_state->client->sck); | ||||||
|  | 		if (!cgi_state->keep_alive || mio_dev_sck_read(cgi_state->client->sck, 1) <= -1) | ||||||
|  | 		{ | ||||||
|  | printf ("FAILED TO ENABLE INPUT WATCHING on CLINET %p. SO HALTING CLIENT SOCKET>>>>>>>>>>>>>\n", cgi_state->client->sck); | ||||||
| 			mio_dev_sck_halt (cgi_state->client->sck); | 			mio_dev_sck_halt (cgi_state->client->sck); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | printf ("**** CGI_STATE_ON_KILL DONE\n"); | ||||||
|  | } | ||||||
|  |  | ||||||
| static void cgi_peer_on_close (mio_dev_pro_t* pro, mio_dev_pro_sid_t sid) | static void cgi_peer_on_close (mio_dev_pro_t* pro, mio_dev_pro_sid_t sid) | ||||||
| { | { | ||||||
| 	mio_t* mio = pro->mio; | 	mio_t* mio = pro->mio; | ||||||
| @ -846,8 +847,21 @@ static void cgi_peer_on_close (mio_dev_pro_t* pro, mio_dev_pro_sid_t sid) | |||||||
| 		case MIO_DEV_PRO_MASTER: | 		case MIO_DEV_PRO_MASTER: | ||||||
| 			MIO_DEBUG3 (mio, "HTTS(%p) - peer %p(pid=%d) closing master\n", cgi_state->client->htts, pro, (int)pro->child_pid); | 			MIO_DEBUG3 (mio, "HTTS(%p) - peer %p(pid=%d) closing master\n", cgi_state->client->htts, pro, (int)pro->child_pid); | ||||||
| 			cgi_state->peer = MIO_NULL; /* clear this peer from the state */ | 			cgi_state->peer = MIO_NULL; /* clear this peer from the state */ | ||||||
| printf ("DEASSIGNING 11.....................%p   %d\n", cgi_peer->state, (int)cgi_peer->state->rsrc_refcnt); |  | ||||||
| 			MIO_SVC_HTTS_RSRC_DEASSIGN (cgi_peer->state); | 			MIO_ASSERT (mio, cgi_peer->state != MIO_NULL); | ||||||
|  | printf ("DETACHING FROM CGI PEER DEVICE.....................%p   %d\n", cgi_peer->state, (int)cgi_peer->state->rsrc_refcnt); | ||||||
|  | 			MIO_SVC_HTTS_RSRC_DETACH (cgi_peer->state); | ||||||
|  |  | ||||||
|  | 			if (cgi_state->peer_htrd) | ||||||
|  | 			{ | ||||||
|  | 				/* once this peer device is closed, peer's htrd is also never used. | ||||||
|  | 				 * it's safe to detach the extra information attached on the htrd object. */ | ||||||
|  | 				cgi_peer = mio_htrd_getxtn(cgi_state->peer_htrd); | ||||||
|  | 				MIO_ASSERT (mio, cgi_peer->state != MIO_NULL); | ||||||
|  | printf ("DETACHING FROM CGI PEER HTRD.....................%p   %d\n", cgi_peer->state, (int)cgi_peer->state->rsrc_refcnt); | ||||||
|  | 				MIO_SVC_HTTS_RSRC_DETACH (cgi_peer->state); | ||||||
|  | 			} | ||||||
|  |  | ||||||
| 			break; | 			break; | ||||||
|  |  | ||||||
| 		case MIO_DEV_PRO_OUT: | 		case MIO_DEV_PRO_OUT: | ||||||
| @ -856,15 +870,11 @@ printf ("DEASSIGNING 11.....................%p   %d\n", cgi_peer->state, (int)cg | |||||||
|  |  | ||||||
| 			if (!(cgi_state->over & CGI_STATE_OVER_READ_FROM_PEER)) | 			if (!(cgi_state->over & CGI_STATE_OVER_READ_FROM_PEER)) | ||||||
| 			{ | 			{ | ||||||
| 				if (cgi_state->res_mode_to_cli == CGI_STATE_RES_MODE_CHUNKED && | 				if (cgi_state_write_last_chunk_to_client(cgi_state) <= -1)  | ||||||
| 				    cgi_state_write_to_client(cgi_state, "0\r\n\r\n", 5) <= -1)  |  | ||||||
| 				{ |  | ||||||
| 					cgi_state_halt_participating_devices (cgi_state); | 					cgi_state_halt_participating_devices (cgi_state); | ||||||
| 				} | 				else | ||||||
|  |  | ||||||
| 					cgi_state_mark_over (cgi_state, CGI_STATE_OVER_READ_FROM_PEER); | 					cgi_state_mark_over (cgi_state, CGI_STATE_OVER_READ_FROM_PEER); | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			break; | 			break; | ||||||
|  |  | ||||||
| 		case MIO_DEV_PRO_IN: | 		case MIO_DEV_PRO_IN: | ||||||
| @ -903,16 +913,8 @@ static int cgi_peer_on_read (mio_dev_pro_t* pro, mio_dev_pro_sid_t sid, const vo | |||||||
| 			/* the cgi script could be misbehaviing. | 			/* the cgi script could be misbehaviing. | ||||||
| 			 * it still has to read more but EOF is read. | 			 * it still has to read more but EOF is read. | ||||||
| 			 * otherwise client_peer_htrd_poke() should have been called */ | 			 * otherwise client_peer_htrd_poke() should have been called */ | ||||||
|  | 			if (cgi_state_write_last_chunk_to_client(cgi_state) <= -1) goto oops; | ||||||
| 			if (cgi_state->res_mode_to_cli == CGI_STATE_RES_MODE_CHUNKED && |  | ||||||
| 			    cgi_state_write_to_client(cgi_state, "0\r\n\r\n", 5) <= -1) goto oops; |  | ||||||
|  |  | ||||||
| 			cgi_state_mark_over (cgi_state, CGI_STATE_OVER_READ_FROM_PEER); | 			cgi_state_mark_over (cgi_state, CGI_STATE_OVER_READ_FROM_PEER); | ||||||
|  |  | ||||||
| printf ("DEASSIGNING 33.....................peer %p state %p   %d\n", cgi_peer, cgi_peer->state, (int)cgi_peer->state->rsrc_refcnt); |  | ||||||
| 			/* peer_htrd isn't needed any longer. unlink the cgi state from it */ |  | ||||||
| 			cgi_peer = mio_htrd_getxtn(cgi_state->peer_htrd); |  | ||||||
| 			MIO_SVC_HTTS_RSRC_DEASSIGN (cgi_peer->state); |  | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	else | 	else | ||||||
| @ -924,9 +926,14 @@ printf ("DEASSIGNING 33.....................peer %p state %p   %d\n", cgi_peer, | |||||||
| 		if (mio_htrd_feed(cgi_state->peer_htrd, data, dlen, &rem) <= -1)  | 		if (mio_htrd_feed(cgi_state->peer_htrd, data, dlen, &rem) <= -1)  | ||||||
| 		{ | 		{ | ||||||
| 			MIO_DEBUG3 (mio, "HTTPS(%p) - unable to feed peer into to htrd - peer %p(pid=%u)\n", cgi_state->htts, pro, (unsigned int)pro->child_pid); | 			MIO_DEBUG3 (mio, "HTTPS(%p) - unable to feed peer into to htrd - peer %p(pid=%u)\n", cgi_state->htts, pro, (unsigned int)pro->child_pid); | ||||||
|  |  | ||||||
| 			if (!cgi_state->ever_attempted_to_write_to_client && | 			if (!cgi_state->ever_attempted_to_write_to_client && | ||||||
| 			    !(cgi_state->over & CGI_STATE_OVER_WRITE_TO_CLIENT) && | 			    !(cgi_state->over & CGI_STATE_OVER_WRITE_TO_CLIENT)) | ||||||
| 			    cgi_state_send_final_status_to_client(cgi_state, 500) <= -1) goto oops; | 			{ | ||||||
|  | 				cgi_state_send_final_status_to_client (cgi_state, 500); /* don't care about error because it jumps to oops below anyway */ | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			goto oops;  | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if (rem > 0)  | 		if (rem > 0)  | ||||||
| @ -935,14 +942,6 @@ printf ("DEASSIGNING 33.....................peer %p state %p   %d\n", cgi_peer, | |||||||
| printf ("AAAAAAAAAAAAAAAAAa EEEEEXcessive DATA..................\n"); | printf ("AAAAAAAAAAAAAAAAAa EEEEEXcessive DATA..................\n"); | ||||||
| /* TODO: or drop this request?? */ | /* TODO: or drop this request?? */ | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if (cgi_state->over & CGI_STATE_OVER_READ_FROM_PEER) |  | ||||||
| 		{ |  | ||||||
| printf ("DEASSIGNING 22.....................peer %p state %p   %d\n", cgi_peer, cgi_peer->state, (int)cgi_peer->state->rsrc_refcnt); |  | ||||||
| 			/* peer_htrd isn't needed any longer. unlink the cgi state from it */ |  | ||||||
| 			cgi_peer = mio_htrd_getxtn(cgi_state->peer_htrd); |  | ||||||
| 			MIO_SVC_HTTS_RSRC_DEASSIGN (cgi_peer->state); |  | ||||||
| 		} |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return 0; | 	return 0; | ||||||
| @ -1026,9 +1025,7 @@ printf ("CGI PEER HTRD PEEK...\n"); | |||||||
| 			break; | 			break; | ||||||
|  |  | ||||||
| 		case CGI_STATE_RES_MODE_LENGTH: | 		case CGI_STATE_RES_MODE_LENGTH: | ||||||
| 			/* TODO: Keep-Alive if explicit in http/1.0 . | 			if (mio_becs_cat(cli->sbuf, (cgi_state->keep_alive? "Connection: keep-alive\r\n": "Connection: close\r\n")) == (mio_oow_t)-1) return -1; | ||||||
| 			 *       Keep-Alive not needed if http/1.1 or later */ |  | ||||||
| 			break; |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if (mio_becs_cat(cli->sbuf, "\r\n") == (mio_oow_t)-1) return -1; | 	if (mio_becs_cat(cli->sbuf, "\r\n") == (mio_oow_t)-1) return -1; | ||||||
| @ -1043,11 +1040,7 @@ static int cgi_peer_htrd_poke (mio_htrd_t* htrd, mio_htre_t* req) | |||||||
|  |  | ||||||
| printf (">> PEER RESPONSE COMPLETED\n"); | printf (">> PEER RESPONSE COMPLETED\n"); | ||||||
|  |  | ||||||
| 	if (cgi_state->res_mode_to_cli == CGI_STATE_RES_MODE_CHUNKED && | 	if (cgi_state_write_last_chunk_to_client(cgi_state) <= -1) return -1; | ||||||
| 	    cgi_state_write_to_client(cgi_state, "0\r\n\r\n", 5) <= -1) return -1; |  | ||||||
|  |  | ||||||
| 	/* indicate EOF to the client */ |  | ||||||
| 	if (cgi_state_write_to_client(cgi_state, MIO_NULL, 0) <= -1) return -1; |  | ||||||
|  |  | ||||||
| 	cgi_state_mark_over (cgi_state, CGI_STATE_OVER_READ_FROM_PEER); | 	cgi_state_mark_over (cgi_state, CGI_STATE_OVER_READ_FROM_PEER); | ||||||
| 	return 0; | 	return 0; | ||||||
| @ -1198,6 +1191,14 @@ oops: | |||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static void cgi_client_on_disconnect (mio_dev_sck_t* sck) | ||||||
|  | { | ||||||
|  | 	mio_svc_htts_cli_t* cli = mio_dev_sck_getxtn(sck); | ||||||
|  | 	cgi_state_t* cgi_state = (cgi_state_t*)cli->rsrc; | ||||||
|  | 	cgi_state->client_disconnected = 1; | ||||||
|  | 	listener_on_disconnect (sck); | ||||||
|  | } | ||||||
|  |  | ||||||
| static int cgi_client_on_read (mio_dev_sck_t* sck, const void* buf, mio_iolen_t len, const mio_skad_t* srcaddr) | static int cgi_client_on_read (mio_dev_sck_t* sck, const void* buf, mio_iolen_t len, const mio_skad_t* srcaddr) | ||||||
| { | { | ||||||
| 	mio_t* mio = sck->mio; | 	mio_t* mio = sck->mio; | ||||||
| @ -1324,6 +1325,71 @@ static MIO_INLINE int get_request_content_length (mio_htre_t* req, mio_oow_t* le | |||||||
| 	return 0; /* limited to the length set in *len */ | 	return 0; /* limited to the length set in *len */ | ||||||
| } | } | ||||||
|  |  | ||||||
|  | struct cgi_peer_fork_ctx_t | ||||||
|  | { | ||||||
|  | 	mio_svc_htts_cli_t* cli; | ||||||
|  | 	mio_htre_t* req; | ||||||
|  | 	const mio_bch_t* docroot; | ||||||
|  | }; | ||||||
|  | typedef struct cgi_peer_fork_ctx_t cgi_peer_fork_ctx_t; | ||||||
|  |  | ||||||
|  | static int cgi_peer_on_fork (mio_dev_pro_t* pro, void* fork_ctx) | ||||||
|  | { | ||||||
|  | 	/*mio_t* mio = pro->mio;*/ /* in this callback, the pro device is not fully up. however, the mio field is guaranteed to be available */ | ||||||
|  | 	cgi_peer_fork_ctx_t* fc = (cgi_peer_fork_ctx_t*)fork_ctx; | ||||||
|  | 	mio_oow_t content_length; | ||||||
|  | 	mio_bch_t tmp[128]; | ||||||
|  | 	const mio_bch_t* qparam; | ||||||
|  |  | ||||||
|  | 	qparam = mio_htre_getqparam(fc->req); | ||||||
|  |  | ||||||
|  | 	clearenv (); | ||||||
|  |  | ||||||
|  | 	setenv ("GATEWAY_INTERFACE", "CGI/1.1", 1); | ||||||
|  |  | ||||||
|  | ///////// | ||||||
|  | printf (">>>>>>>>>> %d  pro->mio %p\n",  | ||||||
|  | 	mio_fmttobcstr (pro->mio, tmp, MIO_COUNTOF(tmp), "HTTP/%d.%d", (int)mio_htre_getmajorversion(fc->req), (int)mio_htre_getminorversion(fc->req)), pro->mio); | ||||||
|  | //////// | ||||||
|  |  | ||||||
|  | 	setenv ("SERVER_PROTOCOL", tmp, 1); | ||||||
|  |  | ||||||
|  | 	//setenv ("SCRIPT_FILENAME",   | ||||||
|  | 	//setenv ("SCRIPT_NAME", | ||||||
|  | 	setenv ("DOCUMENT_ROOT", fc->docroot, 1); | ||||||
|  |  | ||||||
|  | 	setenv ("REQUEST_METHOD", mio_htre_getqmethodname(fc->req), 1); | ||||||
|  | 	setenv ("REQUEST_URI", mio_htre_getqpath(fc->req), 1); | ||||||
|  | 	if (qparam) setenv ("QUERY_STRING", qparam, 1); | ||||||
|  |  | ||||||
|  | 	if (get_request_content_length(fc->req, &content_length) == 0) | ||||||
|  | 	{ | ||||||
|  | 		 | ||||||
|  | 		mio_fmt_uintmax_to_bcstr(tmp, MIO_COUNTOF(tmp), content_length, 10, 0, '\0', MIO_NULL); | ||||||
|  | 		setenv ("CONTENT_LENGTH", tmp, 1); | ||||||
|  | 	} | ||||||
|  | 	else | ||||||
|  | 	{ | ||||||
|  | 		/* content length unknown, neither is it 0 - this is not standard */ | ||||||
|  | 		setenv ("CONTENT_LENGTH", "-1", 1); | ||||||
|  | 	} | ||||||
|  | 	setenv ("SERVER_SOFTWARE", fc->cli->htts->server_name, 1); | ||||||
|  | #if 0 | ||||||
|  | 	setenv ("SERVER_PORT",  | ||||||
|  | 	setenv ("SERVER_ADDR", | ||||||
|  | 	setenv ("SERVER_NAME",   /* server host name */ | ||||||
|  |  | ||||||
|  | 	setenv ("REMOTE_PORT", | ||||||
|  | 	setenv ("REMOTE_ADDR", | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | 	//mio_htre_walkheaders(req,  | ||||||
|  | 	/* [NOTE] trailers are not available when this cgi resource is started. let's not call mio_htre_walktrailers() */ | ||||||
|  |  | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
| int mio_svc_htts_docgi (mio_svc_htts_t* htts, mio_dev_sck_t* csck, mio_htre_t* req, const mio_bch_t* docroot) | int mio_svc_htts_docgi (mio_svc_htts_t* htts, mio_dev_sck_t* csck, mio_htre_t* req, const mio_bch_t* docroot) | ||||||
| { | { | ||||||
| 	mio_t* mio = htts->mio; | 	mio_t* mio = htts->mio; | ||||||
| @ -1331,16 +1397,24 @@ int mio_svc_htts_docgi (mio_svc_htts_t* htts, mio_dev_sck_t* csck, mio_htre_t* r | |||||||
| 	cgi_state_t* cgi_state = MIO_NULL; | 	cgi_state_t* cgi_state = MIO_NULL; | ||||||
| 	cgi_peer_xtn_t* cgi_peer; | 	cgi_peer_xtn_t* cgi_peer; | ||||||
| 	mio_dev_pro_make_t mi; | 	mio_dev_pro_make_t mi; | ||||||
|  | 	cgi_peer_fork_ctx_t fc; | ||||||
|  |  | ||||||
| 	/* ensure that you call this function before any contents is received */ | 	/* ensure that you call this function before any contents is received */ | ||||||
| 	MIO_ASSERT (mio, mio_htre_getcontentlen(req) == 0); | 	MIO_ASSERT (mio, mio_htre_getcontentlen(req) == 0); | ||||||
|  |  | ||||||
|  | 	MIO_MEMSET (&fc, 0, MIO_SIZEOF(fc)); | ||||||
|  | 	fc.cli = cli; | ||||||
|  | 	fc.req = req; | ||||||
|  | 	fc.docroot = docroot; | ||||||
|  |  | ||||||
| 	MIO_MEMSET (&mi, 0, MIO_SIZEOF(mi)); | 	MIO_MEMSET (&mi, 0, MIO_SIZEOF(mi)); | ||||||
| 	mi.flags = MIO_DEV_PRO_READOUT | MIO_DEV_PRO_ERRTONUL | MIO_DEV_PRO_WRITEIN /*| MIO_DEV_PRO_FORGET_CHILD*/; | 	mi.flags = MIO_DEV_PRO_READOUT | MIO_DEV_PRO_ERRTONUL | MIO_DEV_PRO_WRITEIN /*| MIO_DEV_PRO_FORGET_CHILD*/; | ||||||
| 	mi.cmd = mio_htre_getqpath(req); /* TODO: combine it with docroot */ | 	mi.cmd = mio_htre_getqpath(req); /* TODO: combine it with docroot */ | ||||||
| 	mi.on_read = cgi_peer_on_read; | 	mi.on_read = cgi_peer_on_read; | ||||||
| 	mi.on_write = cgi_peer_on_write; | 	mi.on_write = cgi_peer_on_write; | ||||||
| 	mi.on_close = cgi_peer_on_close; | 	mi.on_close = cgi_peer_on_close; | ||||||
|  | 	mi.on_fork = cgi_peer_on_fork; | ||||||
|  | 	mi.fork_ctx = &fc; | ||||||
|  |  | ||||||
| 	cgi_state = (cgi_state_t*)mio_svc_htts_rsrc_make(htts, MIO_SIZEOF(*cgi_state), cgi_state_on_kill); | 	cgi_state = (cgi_state_t*)mio_svc_htts_rsrc_make(htts, MIO_SIZEOF(*cgi_state), cgi_state_on_kill); | ||||||
| 	if (MIO_UNLIKELY(!cgi_state)) goto oops; | 	if (MIO_UNLIKELY(!cgi_state)) goto oops; | ||||||
| @ -1353,11 +1427,13 @@ int mio_svc_htts_docgi (mio_svc_htts_t* htts, mio_dev_sck_t* csck, mio_htre_t* r | |||||||
|  |  | ||||||
| 	cgi_state->client_org_on_read = csck->on_read; | 	cgi_state->client_org_on_read = csck->on_read; | ||||||
| 	cgi_state->client_org_on_write = csck->on_write; | 	cgi_state->client_org_on_write = csck->on_write; | ||||||
|  | 	cgi_state->client_org_on_disconnect = csck->on_disconnect; | ||||||
| 	csck->on_read = cgi_client_on_read; | 	csck->on_read = cgi_client_on_read; | ||||||
| 	csck->on_write = cgi_client_on_write; | 	csck->on_write = cgi_client_on_write; | ||||||
|  | 	csck->on_disconnect = cgi_client_on_disconnect; | ||||||
|  |  | ||||||
| 	MIO_ASSERT (mio, cli->rsrc == MIO_NULL); | 	MIO_ASSERT (mio, cli->rsrc == MIO_NULL); | ||||||
| 	MIO_SVC_HTTS_RSRC_ASSIGN (cgi_state, cli->rsrc); | 	MIO_SVC_HTTS_RSRC_ATTACH (cgi_state, cli->rsrc); | ||||||
|  |  | ||||||
| /* TODO: create cgi environment variables... */ | /* TODO: create cgi environment variables... */ | ||||||
| /* TODO: | /* TODO: | ||||||
| @ -1372,7 +1448,7 @@ int mio_svc_htts_docgi (mio_svc_htts_t* htts, mio_dev_sck_t* csck, mio_htre_t* r | |||||||
| 	cgi_state->peer = mio_dev_pro_make(mio, MIO_SIZEOF(*cgi_peer), &mi); | 	cgi_state->peer = mio_dev_pro_make(mio, MIO_SIZEOF(*cgi_peer), &mi); | ||||||
| 	if (MIO_UNLIKELY(!cgi_state->peer)) goto oops; | 	if (MIO_UNLIKELY(!cgi_state->peer)) goto oops; | ||||||
| 	cgi_peer = mio_dev_pro_getxtn(cgi_state->peer); | 	cgi_peer = mio_dev_pro_getxtn(cgi_state->peer); | ||||||
| 	MIO_SVC_HTTS_RSRC_ASSIGN (cgi_state, cgi_peer->state); | 	MIO_SVC_HTTS_RSRC_ATTACH (cgi_state, cgi_peer->state); | ||||||
|  |  | ||||||
| 	cgi_state->peer_htrd = mio_htrd_open(mio, MIO_SIZEOF(*cgi_peer)); | 	cgi_state->peer_htrd = mio_htrd_open(mio, MIO_SIZEOF(*cgi_peer)); | ||||||
| 	if (MIO_UNLIKELY(!cgi_state->peer_htrd)) goto oops; | 	if (MIO_UNLIKELY(!cgi_state->peer_htrd)) goto oops; | ||||||
| @ -1380,7 +1456,7 @@ int mio_svc_htts_docgi (mio_svc_htts_t* htts, mio_dev_sck_t* csck, mio_htre_t* r | |||||||
| 	mio_htrd_setrecbs (cgi_state->peer_htrd, &cgi_peer_htrd_recbs); | 	mio_htrd_setrecbs (cgi_state->peer_htrd, &cgi_peer_htrd_recbs); | ||||||
|  |  | ||||||
| 	cgi_peer = mio_htrd_getxtn(cgi_state->peer_htrd); | 	cgi_peer = mio_htrd_getxtn(cgi_state->peer_htrd); | ||||||
| 	MIO_SVC_HTTS_RSRC_ASSIGN (cgi_state, cgi_peer->state); | 	MIO_SVC_HTTS_RSRC_ATTACH (cgi_state, cgi_peer->state); | ||||||
|  |  | ||||||
| #if !defined(CGI_ALLOW_UNLIMITED_REQ_CONTENT_LENGTH) | #if !defined(CGI_ALLOW_UNLIMITED_REQ_CONTENT_LENGTH) | ||||||
| 	if (cgi_state->req_content_length_unlimited) | 	if (cgi_state->req_content_length_unlimited) | ||||||
|  | |||||||
| @ -178,8 +178,8 @@ struct mio_svc_htts_rsrc_t | |||||||
| 	MIO_SVC_HTTS_RSRC_HEADER; | 	MIO_SVC_HTTS_RSRC_HEADER; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| #define MIO_SVC_HTTS_RSRC_ASSIGN(rsrc, var) do { (var) = (rsrc); ++(rsrc)->rsrc_refcnt; } while(0) | #define MIO_SVC_HTTS_RSRC_ATTACH(rsrc, var) do { (var) = (rsrc); ++(rsrc)->rsrc_refcnt; } while(0) | ||||||
| #define MIO_SVC_HTTS_RSRC_DEASSIGN(rsrc_var) do { if (--(rsrc_var)->rsrc_refcnt == 0) { mio_svc_htts_rsrc_t* __rsrc_tmp = (rsrc_var); (rsrc_var) = MIO_NULL; mio_svc_htts_rsrc_kill(__rsrc_tmp); } else { (rsrc_var) = MIO_NULL; } } while(0) | #define MIO_SVC_HTTS_RSRC_DETACH(rsrc_var) do { if (--(rsrc_var)->rsrc_refcnt == 0) { mio_svc_htts_rsrc_t* __rsrc_tmp = (rsrc_var); (rsrc_var) = MIO_NULL; mio_svc_htts_rsrc_kill(__rsrc_tmp); } else { (rsrc_var) = MIO_NULL; } } while(0) | ||||||
| /* -------------------------------------------------------------- */ | /* -------------------------------------------------------------- */ | ||||||
|  |  | ||||||
| #if defined(__cplusplus) | #if defined(__cplusplus) | ||||||
|  | |||||||
| @ -59,6 +59,11 @@ typedef void (*mio_dev_pro_on_close_t) ( | |||||||
| 	mio_dev_pro_sid_t sid | 	mio_dev_pro_sid_t sid | ||||||
| ); | ); | ||||||
|  |  | ||||||
|  | typedef int (*mio_dev_pro_on_fork_t) ( | ||||||
|  | 	mio_dev_pro_t*    dev, | ||||||
|  | 	void*             fork_ctx | ||||||
|  | ); | ||||||
|  |  | ||||||
| struct mio_dev_pro_t | struct mio_dev_pro_t | ||||||
| { | { | ||||||
| 	MIO_DEV_HEADER; | 	MIO_DEV_HEADER; | ||||||
| @ -121,6 +126,8 @@ struct mio_dev_pro_make_t | |||||||
| 	mio_dev_pro_on_write_t on_write; /* mandatory */ | 	mio_dev_pro_on_write_t on_write; /* mandatory */ | ||||||
| 	mio_dev_pro_on_read_t on_read; /* mandatory */ | 	mio_dev_pro_on_read_t on_read; /* mandatory */ | ||||||
| 	mio_dev_pro_on_close_t on_close; /* optional */ | 	mio_dev_pro_on_close_t on_close; /* optional */ | ||||||
|  | 	mio_dev_pro_on_fork_t on_fork; /* optional */ | ||||||
|  | 	void* fork_ctx; | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | |||||||
| @ -1045,17 +1045,18 @@ int mio_dev_watch (mio_dev_t* dev, mio_dev_watch_cmd_t cmd, int events) | |||||||
| 			break; | 			break; | ||||||
|  |  | ||||||
| 		case MIO_DEV_WATCH_STOP: | 		case MIO_DEV_WATCH_STOP: | ||||||
|  | 			if (!(dev->dev_cap & DEV_CAP_ALL_WATCHED)) return 0; /* the device is not being watched */ | ||||||
| 			events = 0; /* override events */ | 			events = 0; /* override events */ | ||||||
| 			mux_cmd = MIO_SYS_MUX_CMD_DELETE; | 			mux_cmd = MIO_SYS_MUX_CMD_DELETE; | ||||||
| 			break; | 			dev_cap = dev->dev_cap & ~(DEV_CAP_ALL_WATCHED); | ||||||
|  | 			goto ctrl_mux; | ||||||
|  |  | ||||||
| 		default: | 		default: | ||||||
| 			mio_seterrnum (dev->mio, MIO_EINVAL); | 			mio_seterrnum (dev->mio, MIO_EINVAL); | ||||||
| 			return -1; | 			return -1; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	dev_cap = dev->dev_cap; | 	dev_cap = dev->dev_cap & ~(DEV_CAP_ALL_WATCHED); | ||||||
| 	dev_cap &= ~(DEV_CAP_ALL_WATCHED); |  | ||||||
|  |  | ||||||
| 	/* this function honors MIO_DEV_EVENT_IN and MIO_DEV_EVENT_OUT only | 	/* this function honors MIO_DEV_EVENT_IN and MIO_DEV_EVENT_OUT only | ||||||
| 	 * as valid input event bits. it intends to provide simple abstraction | 	 * as valid input event bits. it intends to provide simple abstraction | ||||||
| @ -1081,6 +1082,7 @@ int mio_dev_watch (mio_dev_t* dev, mio_dev_watch_cmd_t cmd, int events) | |||||||
| 	} | 	} | ||||||
| 	else | 	else | ||||||
| 	{ | 	{ | ||||||
|  | 	ctrl_mux: | ||||||
| 		if (mio_sys_ctrlmux(mio, mux_cmd, dev, dev_cap) <= -1) return -1; | 		if (mio_sys_ctrlmux(mio, mux_cmd, dev, dev_cap) <= -1) return -1; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | |||||||
| @ -31,7 +31,7 @@ | |||||||
|  *       support \\?\UNC\server\path which is equivalent to \\server\path.  |  *       support \\?\UNC\server\path which is equivalent to \\server\path.  | ||||||
|  * */ |  * */ | ||||||
| /* ------------------------------------------------------------------ */ | /* ------------------------------------------------------------------ */ | ||||||
| /*  WCS IMPLEMENTATION                                                */ | /*  UCH IMPLEMENTATION                                                */ | ||||||
| /* ------------------------------------------------------------------ */ | /* ------------------------------------------------------------------ */ | ||||||
|  |  | ||||||
| #if 0 | #if 0 | ||||||
| @ -335,7 +335,7 @@ mio_oow_t mio_canon_ucstr_path (const mio_uch_t* path, mio_uch_t* canon, int fla | |||||||
|  |  | ||||||
|  |  | ||||||
| /* ------------------------------------------------------------------ */ | /* ------------------------------------------------------------------ */ | ||||||
| /*  MBS IMPLEMENTATION                                                */ | /*  BCH IMPLEMENTATION                                                */ | ||||||
| /* ------------------------------------------------------------------ */ | /* ------------------------------------------------------------------ */ | ||||||
|  |  | ||||||
| #if 0 | #if 0 | ||||||
|  | |||||||
| @ -128,8 +128,9 @@ oops: | |||||||
| 	return -1; | 	return -1; | ||||||
| } | } | ||||||
|  |  | ||||||
| static pid_t standard_fork_and_exec (mio_t* mio, int pfds[], int flags, param_t* param) | static pid_t standard_fork_and_exec (mio_dev_pro_t* dev, int pfds[], mio_dev_pro_make_t* mi, param_t* param) | ||||||
| { | { | ||||||
|  | 	mio_t* mio = dev->mio; | ||||||
| 	pid_t pid; | 	pid_t pid; | ||||||
|  |  | ||||||
| 	pid = fork(); | 	pid = fork(); | ||||||
| @ -146,8 +147,9 @@ static pid_t standard_fork_and_exec (mio_t* mio, int pfds[], int flags, param_t* | |||||||
| 		mio_syshnd_t devnull = MIO_SYSHND_INVALID; | 		mio_syshnd_t devnull = MIO_SYSHND_INVALID; | ||||||
|  |  | ||||||
| /* TODO: close all uneeded fds */ | /* TODO: close all uneeded fds */ | ||||||
|  | 		if (mi->on_fork) mi->on_fork (dev, mi->fork_ctx); | ||||||
|  |  | ||||||
| 		if (flags & MIO_DEV_PRO_WRITEIN) | 		if (mi->flags & MIO_DEV_PRO_WRITEIN) | ||||||
| 		{ | 		{ | ||||||
| 			/* slave should read */ | 			/* slave should read */ | ||||||
| 			close (pfds[1]); | 			close (pfds[1]); | ||||||
| @ -160,7 +162,7 @@ static pid_t standard_fork_and_exec (mio_t* mio, int pfds[], int flags, param_t* | |||||||
| 			pfds[0] = MIO_SYSHND_INVALID; | 			pfds[0] = MIO_SYSHND_INVALID; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if (flags & MIO_DEV_PRO_READOUT) | 		if (mi->flags & MIO_DEV_PRO_READOUT) | ||||||
| 		{ | 		{ | ||||||
| 			/* slave should write */ | 			/* slave should write */ | ||||||
| 			close (pfds[2]); | 			close (pfds[2]); | ||||||
| @ -168,7 +170,7 @@ static pid_t standard_fork_and_exec (mio_t* mio, int pfds[], int flags, param_t* | |||||||
|  |  | ||||||
| 			if (dup2(pfds[3], 1) == -1) goto slave_oops; | 			if (dup2(pfds[3], 1) == -1) goto slave_oops; | ||||||
|  |  | ||||||
| 			if (flags & MIO_DEV_PRO_ERRTOOUT) | 			if (mi->flags & MIO_DEV_PRO_ERRTOOUT) | ||||||
| 			{ | 			{ | ||||||
| 				if (dup2(pfds[3], 2) == -1) goto slave_oops; | 				if (dup2(pfds[3], 2) == -1) goto slave_oops; | ||||||
| 			} | 			} | ||||||
| @ -177,14 +179,14 @@ static pid_t standard_fork_and_exec (mio_t* mio, int pfds[], int flags, param_t* | |||||||
| 			pfds[3] = MIO_SYSHND_INVALID; | 			pfds[3] = MIO_SYSHND_INVALID; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if (flags & MIO_DEV_PRO_READERR) | 		if (mi->flags & MIO_DEV_PRO_READERR) | ||||||
| 		{ | 		{ | ||||||
| 			close (pfds[4]); | 			close (pfds[4]); | ||||||
| 			pfds[4] = MIO_SYSHND_INVALID; | 			pfds[4] = MIO_SYSHND_INVALID; | ||||||
|  |  | ||||||
| 			if (dup2(pfds[5], 2) == -1) goto slave_oops; | 			if (dup2(pfds[5], 2) == -1) goto slave_oops; | ||||||
|  |  | ||||||
| 			if (flags & MIO_DEV_PRO_OUTTOERR) | 			if (mi->flags & MIO_DEV_PRO_OUTTOERR) | ||||||
| 			{ | 			{ | ||||||
| 				if (dup2(pfds[5], 1) == -1) goto slave_oops; | 				if (dup2(pfds[5], 1) == -1) goto slave_oops; | ||||||
| 			} | 			} | ||||||
| @ -193,9 +195,9 @@ static pid_t standard_fork_and_exec (mio_t* mio, int pfds[], int flags, param_t* | |||||||
| 			pfds[5] = MIO_SYSHND_INVALID; | 			pfds[5] = MIO_SYSHND_INVALID; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if ((flags & MIO_DEV_PRO_INTONUL) || | 		if ((mi->flags & MIO_DEV_PRO_INTONUL) || | ||||||
| 		    (flags & MIO_DEV_PRO_OUTTONUL) || | 		    (mi->flags & MIO_DEV_PRO_OUTTONUL) || | ||||||
| 		    (flags & MIO_DEV_PRO_ERRTONUL)) | 		    (mi->flags & MIO_DEV_PRO_ERRTONUL)) | ||||||
| 		{ | 		{ | ||||||
| 		#if defined(O_LARGEFILE) | 		#if defined(O_LARGEFILE) | ||||||
| 			devnull = open("/dev/null", O_RDWR | O_LARGEFILE, 0); | 			devnull = open("/dev/null", O_RDWR | O_LARGEFILE, 0); | ||||||
| @ -270,7 +272,7 @@ static int dev_pro_make_master (mio_dev_t* dev, void* ctx) | |||||||
| 	if (make_param(mio, info->cmd, info->flags, ¶m) <= -1) goto oops; | 	if (make_param(mio, info->cmd, info->flags, ¶m) <= -1) goto oops; | ||||||
|  |  | ||||||
| /* TODO: more advanced fork and exec .. */ | /* TODO: more advanced fork and exec .. */ | ||||||
| 	pid = standard_fork_and_exec(mio, pfds, info->flags, ¶m); | 	pid = standard_fork_and_exec(dev, pfds, info, ¶m); | ||||||
| 	if (pid <= -1)  | 	if (pid <= -1)  | ||||||
| 	{ | 	{ | ||||||
| 		free_param (mio, ¶m); | 		free_param (mio, ¶m); | ||||||
| @ -582,6 +584,7 @@ static int dev_pro_write_slave (mio_dev_t* dev, const void* data, mio_iolen_t* l | |||||||
| 		//mio_dev_halt (dev); /* halt this slave device to indicate EOF on the lower-level handle */* | 		//mio_dev_halt (dev); /* halt this slave device to indicate EOF on the lower-level handle */* | ||||||
| 		if (MIO_LIKELY(pro->pfd != MIO_SYSHND_INVALID)) /* halt() doesn't close the pipe immediately. so close the underlying pipe */ | 		if (MIO_LIKELY(pro->pfd != MIO_SYSHND_INVALID)) /* halt() doesn't close the pipe immediately. so close the underlying pipe */ | ||||||
| 		{ | 		{ | ||||||
|  | 			mio_dev_watch (dev, MIO_DEV_WATCH_STOP, 0); | ||||||
| 			close (pro->pfd); | 			close (pro->pfd); | ||||||
| 			pro->pfd = MIO_SYSHND_INVALID; | 			pro->pfd = MIO_SYSHND_INVALID; | ||||||
| 		} | 		} | ||||||
| @ -618,6 +621,7 @@ static int dev_pro_writev_slave (mio_dev_t* dev, const mio_iovec_t* iov, mio_iol | |||||||
| 		/*mio_dev_halt (dev);*/ /* halt this slave device to indicate EOF on the lower-level handle  */ | 		/*mio_dev_halt (dev);*/ /* halt this slave device to indicate EOF on the lower-level handle  */ | ||||||
| 		if (MIO_LIKELY(pro->pfd != MIO_SYSHND_INVALID)) /* halt() doesn't close the pipe immediately. so close the underlying pipe */ | 		if (MIO_LIKELY(pro->pfd != MIO_SYSHND_INVALID)) /* halt() doesn't close the pipe immediately. so close the underlying pipe */ | ||||||
| 		{ | 		{ | ||||||
|  | 			mio_dev_watch (dev, MIO_DEV_WATCH_STOP, 0); | ||||||
| 			close (pro->pfd); | 			close (pro->pfd); | ||||||
| 			pro->pfd = MIO_SYSHND_INVALID; | 			pro->pfd = MIO_SYSHND_INVALID; | ||||||
| 		} | 		} | ||||||
|  | |||||||
| @ -4,4 +4,6 @@ echo "Content-Type: text/plain" | |||||||
| echo "Custom-Attribute: abcdef" | echo "Custom-Attribute: abcdef" | ||||||
| echo | echo | ||||||
|  |  | ||||||
|  | printenv | ||||||
| exec cat /home/hyung-hwan/projects/hawk/lib/run.c | exec cat /home/hyung-hwan/projects/hawk/lib/run.c | ||||||
|  |  | ||||||
|  | |||||||
| @ -5,8 +5,8 @@ | |||||||
| echo "Content-Type: text/plain" | echo "Content-Type: text/plain" | ||||||
| echo | echo | ||||||
|  |  | ||||||
| while read x | while IFS= read -r x | ||||||
| do | do | ||||||
| 	echo $x | 	echo "$x" | ||||||
| done | done | ||||||
| ##echo "<<EOF>>" | echo "<<EOF>>" | ||||||
|  | |||||||
							
								
								
									
										22
									
								
								mio/t/e.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										22
									
								
								mio/t/e.sh
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,22 @@ | |||||||
|  | #!/bin/sh | ||||||
|  |  | ||||||
|  | ## curl -v --http1.0 --data-binary @/etc/group --http1.1 http://127.0.0.1:9988/home/hyung-hwan/projects/mio/t/d.sh | ||||||
|  |  | ||||||
|  | echo "Content-Type: text/plain" | ||||||
|  | echo | ||||||
|  |  | ||||||
|  | if IFS= read -r x | ||||||
|  | then | ||||||
|  | 	q="${x}" | ||||||
|  | 	while IFS= read -r x | ||||||
|  | 	do | ||||||
|  | 	q="${q} | ||||||
|  | ${x}" | ||||||
|  | 	done | ||||||
|  | else | ||||||
|  | 	q = "" | ||||||
|  | fi | ||||||
|  |  | ||||||
|  | sleep 3 | ||||||
|  | printf "%s" "$q" | ||||||
|  | ##echo "<<EOF>>" | ||||||
| @ -6,7 +6,11 @@ BEGIN { | |||||||
|  |  | ||||||
| msg = b"GET /home/hyung-hwan/projects/mio/t/b.sh HTTP/1.1\r\n\ | msg = b"GET /home/hyung-hwan/projects/mio/t/b.sh HTTP/1.1\r\n\ | ||||||
| Host: www.google.com\r\n\ | Host: www.google.com\r\n\ | ||||||
| Connection: Keep-Alive\r\n\r\n"; | Connection: close\r\n\r\n"; | ||||||
|  |  | ||||||
|  | #msg = b"GET /home/hyung-hwan/projects/mio/t/b.sh HTTP/1.1\r\n\ | ||||||
|  | #Host: www.google.com\r\n\ | ||||||
|  | #Connection: Keep-Alive\r\n\r\n"; | ||||||
|  |  | ||||||
|  |  | ||||||
| 	sys::write (x, msg); | 	sys::write (x, msg); | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user