added mio_dupbcstrs() and mio_dupucstrs()
changed mio_svc_htts_start() to access the main processor callback
This commit is contained in:
		| @ -748,6 +748,102 @@ static void on_dnc_resolve_brief (mio_svc_dnc_t* dnc, mio_dns_msg_t* reqmsg, mio | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | /* ========================================================================= */ | ||||||
|  | int process_http_request (mio_svc_htts_t* htts, mio_dev_sck_t* csck, mio_htre_t* req) | ||||||
|  | { | ||||||
|  | 	mio_t* mio = mio_svc_htts_getmio(htts); | ||||||
|  | //	mio_svc_htts_cli_t* cli = mio_dev_sck_getxtn(csck); | ||||||
|  | 	mio_http_method_t mth; | ||||||
|  |  | ||||||
|  | 	/* percent-decode the query path to the original buffer | ||||||
|  | 	 * since i'm not going to need it in the original form | ||||||
|  | 	 * any more. once it's decoded in the peek mode, | ||||||
|  | 	 * the decoded query path is made available in the | ||||||
|  | 	 * non-peek mode as well */ | ||||||
|  |  | ||||||
|  | 	MIO_DEBUG2 (mio, "[RAW-REQ] %s %s\n", mio_htre_getqmethodname(req), mio_htre_getqpath(req)); | ||||||
|  |  | ||||||
|  | 	mio_htre_perdecqpath(req); | ||||||
|  | 	/* TODO: proper request logging */ | ||||||
|  |  | ||||||
|  | 	MIO_DEBUG2 (mio, "[REQ] %s %s\n", mio_htre_getqmethodname(req), mio_htre_getqpath(req)); | ||||||
|  |  | ||||||
|  | #if 0 | ||||||
|  | mio_printf (MIO_T("================================\n")); | ||||||
|  | mio_printf (MIO_T("[%lu] %hs REQUEST ==> [%hs] version[%d.%d %hs] method[%hs]\n"), | ||||||
|  | 	(unsigned long)time(NULL), | ||||||
|  | 	(peek? MIO_MT("PEEK"): MIO_MT("HANDLE")), | ||||||
|  | 	mio_htre_getqpath(req), | ||||||
|  | 	mio_htre_getmajorversion(req), | ||||||
|  | 	mio_htre_getminorversion(req), | ||||||
|  | 	mio_htre_getverstr(req), | ||||||
|  | 	mio_htre_getqmethodname(req) | ||||||
|  | ); | ||||||
|  | if (mio_htre_getqparam(req)) | ||||||
|  | 	mio_printf (MIO_T("PARAMS ==> [%hs]\n"), mio_htre_getqparam(req)); | ||||||
|  |  | ||||||
|  | mio_htb_walk (&req->hdrtab, walk, MIO_NULL); | ||||||
|  | if (mio_htre_getcontentlen(req) > 0) | ||||||
|  | { | ||||||
|  | 	mio_printf (MIO_T("CONTENT [%.*S]\n"), (int)mio_htre_getcontentlen(req), mio_htre_getcontentptr(req)); | ||||||
|  | } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | 	mth = mio_htre_getqmethodtype(req); | ||||||
|  | 	/* determine what to do once the header fields are all received. | ||||||
|  | 	 * i don't want to delay this until the contents are received. | ||||||
|  | 	 * if you don't like this behavior, you must implement your own | ||||||
|  | 	 * callback function for request handling. */ | ||||||
|  | #if 0 | ||||||
|  | 	/* TODO support X-HTTP-Method-Override */ | ||||||
|  | 	if (data.method == MIO_HTTP_POST) | ||||||
|  | 	{ | ||||||
|  | 		tmp = mio_htre_getheaderval(req, MIO_MT("X-HTTP-Method-Override")); | ||||||
|  | 		if (tmp) | ||||||
|  | 		{ | ||||||
|  | 			/*while (tmp->next) tmp = tmp->next;*/ /* get the last value */ | ||||||
|  | 			data.method = mio_mbstohttpmethod (tmp->ptr); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #if 0 | ||||||
|  | 	if (mth == MIO_HTTP_CONNECT) | ||||||
|  | 	{ | ||||||
|  | 		/* CONNECT method must not have content set.  | ||||||
|  | 		 * however, arrange to discard it if so.  | ||||||
|  | 		 * | ||||||
|  | 		 * NOTE: CONNECT is implemented to ignore many headers like | ||||||
|  | 		 *       'Expect: 100-continue' and 'Connection: keep-alive'. */ | ||||||
|  | 		mio_htre_discardcontent (req); | ||||||
|  | 	} | ||||||
|  | 	else  | ||||||
|  | 	{ | ||||||
|  | /* this part can be checked in actual mio_svc_htts_doXXX() functions. | ||||||
|  |  * some doXXX handlers may not require length for POST. | ||||||
|  |  * it may be able to simply accept till EOF? or  treat as if CONTENT_LENGTH is 0*/ | ||||||
|  | 		if (mth == MIO_HTTP_POST && !(req->flags & (MIO_HTRE_ATTR_LENGTH | MIO_HTRE_ATTR_CHUNKED))) | ||||||
|  | 		{ | ||||||
|  | 			/* POST without Content-Length nor not chunked */ | ||||||
|  | 			mio_htre_discardcontent (req);  | ||||||
|  | 			/* 411 Length Required - can't keep alive. Force disconnect */ | ||||||
|  | 			req->flags &= ~MIO_HTRE_ATTR_KEEPALIVE; /* to cause sendstatus() to close */ | ||||||
|  | 			if (mio_svc_htts_sendstatus(htts, csck, req, 411, MIO_NULL) <= -1) goto oops; | ||||||
|  | 		} | ||||||
|  | 		else | ||||||
|  |  | ||||||
|  | 		{ | ||||||
|  | #endif | ||||||
|  | 			/*const mio_bch_t* qpath = mio_htre_getqpath(req);*/ | ||||||
|  | 			if (mio_svc_htts_docgi(htts, csck, req, "", mio_htre_getqpath(req)) <= -1) goto oops; | ||||||
|  |  | ||||||
|  | 	return 0; | ||||||
|  |  | ||||||
|  | oops: | ||||||
|  | 	mio_dev_sck_halt (csck); | ||||||
|  | 	return -1; | ||||||
|  | } | ||||||
|  |  | ||||||
| /* ========================================================================= */ | /* ========================================================================= */ | ||||||
|  |  | ||||||
| static mio_t* g_mio; | static mio_t* g_mio; | ||||||
| @ -976,7 +1072,7 @@ for (i = 0; i < 5; i++) | |||||||
| 	mio_bcstrtoskad (mio, "127.0.0.1:9988", &htts_bind_addr); | 	mio_bcstrtoskad (mio, "127.0.0.1:9988", &htts_bind_addr); | ||||||
|  |  | ||||||
| 	dnc = mio_svc_dnc_start(mio, &servaddr, MIO_NULL, &send_tmout, &reply_tmout, 2); /* option - send to all, send one by one */ | 	dnc = mio_svc_dnc_start(mio, &servaddr, MIO_NULL, &send_tmout, &reply_tmout, 2); /* option - send to all, send one by one */ | ||||||
| 	htts = mio_svc_htts_start(mio, &htts_bind_addr); | 	htts = mio_svc_htts_start(mio, &htts_bind_addr, process_http_request); | ||||||
| 	mio_svc_htts_setservernamewithbcstr (htts, "MIO-HTTP"); | 	mio_svc_htts_setservernamewithbcstr (htts, "MIO-HTTP"); | ||||||
|  |  | ||||||
| #if 1 | #if 1 | ||||||
|  | |||||||
| @ -1217,43 +1217,9 @@ int mio_htrd_feed (mio_htrd_t* htrd, const mio_bch_t* req, mio_oow_t len, mio_oo | |||||||
| 						/* need to clear request on error?  | 						/* need to clear request on error?  | ||||||
| 						clear_feed (htrd); */ | 						clear_feed (htrd); */ | ||||||
| 						return -1; | 						return -1; | ||||||
| /// TODO: PEEKONLY doens't seem to be neede. delete it... |  | ||||||
| 					} | 					} | ||||||
| //////////////////////////////////////////////////////////////////////////////////////////////////// | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||||||
|  |  | ||||||
| 					if (htrd->option & MIO_HTRD_PEEKONLY) |  | ||||||
| 					{ |  | ||||||
| 						/* when MIO_HTRD_PEEKONLY is set, |  | ||||||
| 						 * the peek callback is invoked once |  | ||||||
| 						 * a complete header is seen. the caller |  | ||||||
| 						 * should not feed more data by calling |  | ||||||
| 						 * this function again once the callback is |  | ||||||
| 						 * invoked. the trailing data is appended |  | ||||||
| 						 * to the content buffer. |  | ||||||
| 						 * |  | ||||||
| 						 * NOTE: if the current feed that completed  |  | ||||||
| 						 *  the header contains the next request,  |  | ||||||
| 						 *  the next request is treated as if it  |  | ||||||
| 						 *  belongs to the current request. |  | ||||||
| 						 * |  | ||||||
| 						 * In priciple, this option was added for |  | ||||||
| 						 * reading CGI outputs. So it comes with |  | ||||||
| 						 * awkwardity described above. |  | ||||||
| 						 */ |  | ||||||
| 						if (ptr < end && push_content(htrd, ptr, end - ptr) <= -1) return -1; |  | ||||||
|  |  | ||||||
| 						/* i don't really know if it is really completed  |  | ||||||
| 						 * with content. MIO_HTRD_PEEKONLY is not compatible |  | ||||||
| 						 * with the completed state. anyway, let me complete |  | ||||||
| 						 * it. */ |  | ||||||
| 						mio_htre_completecontent (&htrd->re); |  | ||||||
|  |  | ||||||
| 						/* this jump is only to invoke the peek  |  | ||||||
| 						 * callback. this function should not be fed |  | ||||||
| 						 * more. */ |  | ||||||
| 						goto feedme_more;  |  | ||||||
| 					} |  | ||||||
|  |  | ||||||
| 					/* carry on processing content body fed together with the header */ | 					/* carry on processing content body fed together with the header */ | ||||||
| 					if (htrd->re.flags & MIO_HTRE_ATTR_CHUNKED) | 					if (htrd->re.flags & MIO_HTRE_ATTR_CHUNKED) | ||||||
| 					{ | 					{ | ||||||
|  | |||||||
| @ -3,6 +3,7 @@ | |||||||
| #include "mio-pro.h" /* for cgi */ | #include "mio-pro.h" /* for cgi */ | ||||||
| #include "mio-fmt.h" | #include "mio-fmt.h" | ||||||
| #include "mio-chr.h" | #include "mio-chr.h" | ||||||
|  | #include "mio-path.h" | ||||||
| #include "mio-prv.h" | #include "mio-prv.h" | ||||||
|  |  | ||||||
|  |  | ||||||
| @ -35,6 +36,8 @@ struct mio_svc_htts_t | |||||||
| { | { | ||||||
| 	MIO_SVC_HEADER; | 	MIO_SVC_HEADER; | ||||||
|  |  | ||||||
|  | 	mio_svc_htts_proc_req_t proc_req; | ||||||
|  |  | ||||||
| 	mio_dev_sck_t* lsck; | 	mio_dev_sck_t* lsck; | ||||||
| 	mio_svc_htts_cli_t cli; /* list head for client list */ | 	mio_svc_htts_cli_t cli; /* list head for client list */ | ||||||
|  |  | ||||||
| @ -98,110 +101,11 @@ static int test_func_handler (int rfd, int wfd) | |||||||
| 	return -1; | 	return -1; | ||||||
| } | } | ||||||
|  |  | ||||||
| static int process_request (mio_svc_htts_t* htts, mio_dev_sck_t* csck, mio_htre_t* req) |  | ||||||
| { |  | ||||||
| 	//server_xtn_t* server_xtn = GET_SERVER_XTN(htts, client->server); |  | ||||||
| 	//mio_htts_task_t* task; |  | ||||||
| 	mio_svc_htts_cli_t* cli = mio_dev_sck_getxtn(csck); |  | ||||||
| 	mio_http_method_t mth; |  | ||||||
| 	//mio_htts_rsrc_t rsrc; |  | ||||||
|  |  | ||||||
| 	/* percent-decode the query path to the original buffer |  | ||||||
| 	 * since i'm not going to need it in the original form |  | ||||||
| 	 * any more. once it's decoded in the peek mode, |  | ||||||
| 	 * the decoded query path is made available in the |  | ||||||
| 	 * 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); |  | ||||||
| 	/* TODO: proper request logging */ |  | ||||||
|  |  | ||||||
| 	MIO_DEBUG2 (htts->mio, "[REQ] %s %s\n", mio_htre_getqmethodname(req), mio_htre_getqpath(req)); |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| #if 0 |  | ||||||
| mio_printf (MIO_T("================================\n")); |  | ||||||
| mio_printf (MIO_T("[%lu] %hs REQUEST ==> [%hs] version[%d.%d %hs] method[%hs]\n"), |  | ||||||
| 	(unsigned long)time(NULL), |  | ||||||
| 	(peek? MIO_MT("PEEK"): MIO_MT("HANDLE")), |  | ||||||
| 	mio_htre_getqpath(req), |  | ||||||
| 	mio_htre_getmajorversion(req), |  | ||||||
| 	mio_htre_getminorversion(req), |  | ||||||
| 	mio_htre_getverstr(req), |  | ||||||
| 	mio_htre_getqmethodname(req) |  | ||||||
| ); |  | ||||||
| if (mio_htre_getqparam(req)) |  | ||||||
| 	mio_printf (MIO_T("PARAMS ==> [%hs]\n"), mio_htre_getqparam(req)); |  | ||||||
|  |  | ||||||
| mio_htb_walk (&req->hdrtab, walk, MIO_NULL); |  | ||||||
| if (mio_htre_getcontentlen(req) > 0) |  | ||||||
| { |  | ||||||
| 	mio_printf (MIO_T("CONTENT [%.*S]\n"), (int)mio_htre_getcontentlen(req), mio_htre_getcontentptr(req)); |  | ||||||
| } |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| 	mth = mio_htre_getqmethodtype(req); |  | ||||||
| 	/* determine what to do once the header fields are all received. |  | ||||||
| 	 * i don't want to delay this until the contents are received. |  | ||||||
| 	 * if you don't like this behavior, you must implement your own |  | ||||||
| 	 * callback function for request handling. */ |  | ||||||
| #if 0 |  | ||||||
| 	/* TODO support X-HTTP-Method-Override */ |  | ||||||
| 	if (data.method == MIO_HTTP_POST) |  | ||||||
| 	{ |  | ||||||
| 		tmp = mio_htre_getheaderval(req, MIO_MT("X-HTTP-Method-Override")); |  | ||||||
| 		if (tmp) |  | ||||||
| 		{ |  | ||||||
| 			/*while (tmp->next) tmp = tmp->next;*/ /* get the last value */ |  | ||||||
| 			data.method = mio_mbstohttpmethod (tmp->ptr); |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| #if 0 |  | ||||||
| 	if (mth == MIO_HTTP_CONNECT) |  | ||||||
| 	{ |  | ||||||
| 		/* CONNECT method must not have content set.  |  | ||||||
| 		 * however, arrange to discard it if so.  |  | ||||||
| 		 * |  | ||||||
| 		 * NOTE: CONNECT is implemented to ignore many headers like |  | ||||||
| 		 *       'Expect: 100-continue' and 'Connection: keep-alive'. */ |  | ||||||
| 		mio_htre_discardcontent (req); |  | ||||||
| 	} |  | ||||||
| 	else  |  | ||||||
| 	{ |  | ||||||
| /* this part can be checked in actual mio_svc_htts_doXXX() functions. |  | ||||||
|  * some doXXX handlers may not require length for POST. |  | ||||||
|  * it may be able to simply accept till EOF? or  treat as if CONTENT_LENGTH is 0*/ |  | ||||||
| 		if (mth == MIO_HTTP_POST && !(req->flags & (MIO_HTRE_ATTR_LENGTH | MIO_HTRE_ATTR_CHUNKED))) |  | ||||||
| 		{ |  | ||||||
| 			/* POST without Content-Length nor not chunked */ |  | ||||||
| 			mio_htre_discardcontent (req);  |  | ||||||
| 			/* 411 Length Required - can't keep alive. Force disconnect */ |  | ||||||
| 			req->flags &= ~MIO_HTRE_ATTR_KEEPALIVE; /* to cause sendstatus() to close */ |  | ||||||
| 			if (mio_svc_htts_sendstatus(htts, csck, req, 411, MIO_NULL) <= -1) goto oops; |  | ||||||
| 		} |  | ||||||
| 		else |  | ||||||
|  |  | ||||||
| 		{ |  | ||||||
| #endif |  | ||||||
| 			/*const mio_bch_t* qpath = mio_htre_getqpath(req);*/ |  | ||||||
| 			if (mio_svc_htts_docgi(htts, csck, req, "") <= -1) goto oops; |  | ||||||
|  |  | ||||||
| 	return 0; |  | ||||||
|  |  | ||||||
| oops: |  | ||||||
| 	mio_dev_sck_halt (csck); |  | ||||||
| 	return -1; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static int client_htrd_peek_request (mio_htrd_t* htrd, mio_htre_t* req) | static int client_htrd_peek_request (mio_htrd_t* htrd, mio_htre_t* req) | ||||||
| { | { | ||||||
| 	htrd_xtn_t* htrdxtn = (htrd_xtn_t*)mio_htrd_getxtn(htrd); | 	htrd_xtn_t* htrdxtn = (htrd_xtn_t*)mio_htrd_getxtn(htrd); | ||||||
| 	mio_svc_htts_cli_t* sckxtn = (mio_svc_htts_cli_t*)mio_dev_sck_getxtn(htrdxtn->sck); | 	mio_svc_htts_cli_t* sckxtn = (mio_svc_htts_cli_t*)mio_dev_sck_getxtn(htrdxtn->sck); | ||||||
| 	return process_request(sckxtn->htts, htrdxtn->sck, req); | 	return sckxtn->htts->proc_req(sckxtn->htts, htrdxtn->sck, req); | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| @ -439,7 +343,7 @@ static void listener_on_disconnect (mio_dev_sck_t* sck) | |||||||
|  |  | ||||||
| /* ------------------------------------------------------------------------ */ | /* ------------------------------------------------------------------------ */ | ||||||
|  |  | ||||||
| mio_svc_htts_t* mio_svc_htts_start (mio_t* mio, const mio_skad_t* bind_addr) | mio_svc_htts_t* mio_svc_htts_start (mio_t* mio, const mio_skad_t* bind_addr, mio_svc_htts_proc_req_t proc_req) | ||||||
| { | { | ||||||
| 	mio_svc_htts_t* htts = MIO_NULL; | 	mio_svc_htts_t* htts = MIO_NULL; | ||||||
| 	union | 	union | ||||||
| @ -455,6 +359,7 @@ mio_svc_htts_t* mio_svc_htts_start (mio_t* mio, const mio_skad_t* bind_addr) | |||||||
|  |  | ||||||
| 	htts->mio = mio; | 	htts->mio = mio; | ||||||
| 	htts->svc_stop = mio_svc_htts_stop; | 	htts->svc_stop = mio_svc_htts_stop; | ||||||
|  | 	htts->proc_req = proc_req; | ||||||
|  |  | ||||||
| 	MIO_MEMSET (&info, 0, MIO_SIZEOF(info)); | 	MIO_MEMSET (&info, 0, MIO_SIZEOF(info)); | ||||||
| 	switch (mio_skad_family(bind_addr)) | 	switch (mio_skad_family(bind_addr)) | ||||||
| @ -1314,6 +1219,8 @@ struct cgi_peer_fork_ctx_t | |||||||
| 	mio_svc_htts_cli_t* cli; | 	mio_svc_htts_cli_t* cli; | ||||||
| 	mio_htre_t* req; | 	mio_htre_t* req; | ||||||
| 	const mio_bch_t* docroot; | 	const mio_bch_t* docroot; | ||||||
|  | 	const mio_bch_t* script; | ||||||
|  | 	mio_bch_t* actual_script; | ||||||
| }; | }; | ||||||
| typedef struct cgi_peer_fork_ctx_t cgi_peer_fork_ctx_t; | typedef struct cgi_peer_fork_ctx_t cgi_peer_fork_ctx_t; | ||||||
|  |  | ||||||
| @ -1362,24 +1269,27 @@ static int cgi_peer_on_fork (mio_dev_pro_t* pro, void* fork_ctx) | |||||||
| 	cgi_peer_fork_ctx_t* fc = (cgi_peer_fork_ctx_t*)fork_ctx; | 	cgi_peer_fork_ctx_t* fc = (cgi_peer_fork_ctx_t*)fork_ctx; | ||||||
| 	mio_oow_t content_length; | 	mio_oow_t content_length; | ||||||
| 	const mio_bch_t* qparam; | 	const mio_bch_t* qparam; | ||||||
| 	const char* path; | 	const char* path, * lang; | ||||||
| 	mio_bch_t tmp[256]; | 	mio_bch_t tmp[256]; | ||||||
| 	mio_becs_t dbuf; | 	mio_becs_t dbuf; | ||||||
|  |  | ||||||
| 	qparam = mio_htre_getqparam(fc->req); | 	qparam = mio_htre_getqparam(fc->req); | ||||||
|  |  | ||||||
| 	path = getenv("PATH"); | 	path = getenv("PATH"); | ||||||
|  | 	lang = getenv("LANG"); | ||||||
| 	clearenv (); | 	clearenv (); | ||||||
| 	if (path) setenv ("PATH", path, 1); | 	if (path) setenv ("PATH", path, 1); | ||||||
|  | 	if (lang) setenv ("LANG", lang, 1); | ||||||
|  |  | ||||||
| 	setenv ("GATEWAY_INTERFACE", "CGI/1.1", 1); | 	setenv ("GATEWAY_INTERFACE", "CGI/1.1", 1); | ||||||
|  |  | ||||||
| 	mio_fmttobcstr (pro->mio, tmp, MIO_COUNTOF(tmp), "HTTP/%d.%d", (int)mio_htre_getmajorversion(fc->req), (int)mio_htre_getminorversion(fc->req)); | 	mio_fmttobcstr (pro->mio, tmp, MIO_COUNTOF(tmp), "HTTP/%d.%d", (int)mio_htre_getmajorversion(fc->req), (int)mio_htre_getminorversion(fc->req)); | ||||||
| 	setenv ("SERVER_PROTOCOL", tmp, 1); | 	setenv ("SERVER_PROTOCOL", tmp, 1); | ||||||
|  |  | ||||||
| 	//setenv ("SCRIPT_FILENAME",   |  | ||||||
| 	//setenv ("SCRIPT_NAME", |  | ||||||
| 	setenv ("DOCUMENT_ROOT", fc->docroot, 1); | 	setenv ("DOCUMENT_ROOT", fc->docroot, 1); | ||||||
|  | 	setenv ("SCRIPT_NAME", fc->script, 1); | ||||||
|  | 	setenv ("SCRIPT_FILENAME", fc->actual_script, 1); | ||||||
|  | 	/* TODO: PATH_INFO */ | ||||||
|  |  | ||||||
| 	setenv ("REQUEST_METHOD", mio_htre_getqmethodname(fc->req), 1); | 	setenv ("REQUEST_METHOD", mio_htre_getqmethodname(fc->req), 1); | ||||||
| 	setenv ("REQUEST_URI", mio_htre_getqpath(fc->req), 1); | 	setenv ("REQUEST_URI", mio_htre_getqpath(fc->req), 1); | ||||||
| @ -1422,8 +1332,7 @@ static int cgi_peer_on_fork (mio_dev_pro_t* pro, void* fork_ctx) | |||||||
| 	return 0; | 	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, const mio_bch_t* script) | ||||||
| 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; | ||||||
| 	mio_svc_htts_cli_t* cli = mio_dev_sck_getxtn(csck); | 	mio_svc_htts_cli_t* cli = mio_dev_sck_getxtn(csck); | ||||||
| @ -1439,10 +1348,13 @@ int mio_svc_htts_docgi (mio_svc_htts_t* htts, mio_dev_sck_t* csck, mio_htre_t* r | |||||||
| 	fc.cli = cli; | 	fc.cli = cli; | ||||||
| 	fc.req = req; | 	fc.req = req; | ||||||
| 	fc.docroot = docroot; | 	fc.docroot = docroot; | ||||||
|  | 	fc.script = script; | ||||||
|  | 	fc.actual_script = mio_svc_htts_dupmergepaths(htts, docroot, script); | ||||||
|  | 	if (!fc.actual_script) goto oops; | ||||||
|  |  | ||||||
| 	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 = fc.actual_script; | ||||||
| 	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; | ||||||
| @ -1468,10 +1380,6 @@ int mio_svc_htts_docgi (mio_svc_htts_t* htts, mio_dev_sck_t* csck, mio_htre_t* r | |||||||
| 	MIO_ASSERT (mio, cli->rsrc == MIO_NULL); | 	MIO_ASSERT (mio, cli->rsrc == MIO_NULL); | ||||||
| 	MIO_SVC_HTTS_RSRC_ATTACH (cgi_state, cli->rsrc); | 	MIO_SVC_HTTS_RSRC_ATTACH (cgi_state, cli->rsrc); | ||||||
|  |  | ||||||
| /* TODO: create cgi environment variables... */ |  | ||||||
| /* TODO: |  | ||||||
|  * never put Expect: 100-continue  to environment variable |  | ||||||
|  */ |  | ||||||
| 	if (access(mi.cmd, X_OK) == -1) | 	if (access(mi.cmd, X_OK) == -1) | ||||||
| 	{ | 	{ | ||||||
| 		cgi_state_send_final_status_to_client (cgi_state, 403); /* 403 Forbidden */ | 		cgi_state_send_final_status_to_client (cgi_state, 403); /* 403 Forbidden */ | ||||||
| @ -1588,17 +1496,29 @@ int mio_svc_htts_docgi (mio_svc_htts_t* htts, mio_dev_sck_t* csck, mio_htre_t* r | |||||||
|  |  | ||||||
| 	/* TODO: store current input watching state and use it when destroying the cgi_state data */ | 	/* TODO: store current input watching state and use it when destroying the cgi_state data */ | ||||||
| 	if (mio_dev_sck_read(csck, !(cgi_state->over & CGI_STATE_OVER_READ_FROM_CLIENT)) <= -1) goto oops; | 	if (mio_dev_sck_read(csck, !(cgi_state->over & CGI_STATE_OVER_READ_FROM_CLIENT)) <= -1) goto oops; | ||||||
|  | 	mio_freemem (mio, fc.actual_script); | ||||||
| 	return 0; | 	return 0; | ||||||
|  |  | ||||||
| oops: | oops: | ||||||
| 	MIO_DEBUG2 (mio, "HTTS(%p) - FAILURE in docgi - socket(%p)\n", htts, csck); | 	MIO_DEBUG2 (mio, "HTTS(%p) - FAILURE in docgi - socket(%p)\n", htts, csck); | ||||||
| 	if (cgi_state) cgi_state_halt_participating_devices (cgi_state); | 	if (cgi_state) cgi_state_halt_participating_devices (cgi_state); | ||||||
|  | 	if (fc.actual_script) mio_freemem (mio, fc.actual_script); | ||||||
| 	return -1; | 	return -1; | ||||||
| } | } | ||||||
|  |  | ||||||
| /* ----------------------------------------------------------------- */ | /* ----------------------------------------------------------------- */ | ||||||
|  |  | ||||||
| int mio_svc_htts_dofile (mio_svc_htts_t* htts, mio_dev_sck_t* csck, mio_htre_t* req, const mio_bch_t* docroot) | #if 0 | ||||||
|  | int mio_svc_htts_dothrfunc (mio_svc_htts_t* htts, mio_dev_sck_t* csck, mio_htre_t* req, mio_svc_htts_func_t func) | ||||||
|  | { | ||||||
|  | 	 | ||||||
|  | } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /* ----------------------------------------------------------------- */ | ||||||
|  |  | ||||||
|  | int mio_svc_htts_dofile (mio_svc_htts_t* htts, mio_dev_sck_t* csck, mio_htre_t* req, const mio_bch_t* docroot, const mio_bch_t* file) | ||||||
| { | { | ||||||
| 	switch (mio_htre_getqmethodtype(req)) | 	switch (mio_htre_getqmethodtype(req)) | ||||||
| 	{ | 	{ | ||||||
| @ -1668,6 +1588,26 @@ void mio_svc_htts_fmtgmtime (mio_svc_htts_t* htts, const mio_ntime_t* nt, mio_bc | |||||||
| 	mio_fmt_http_time_to_bcstr(nt, buf, len); | 	mio_fmt_http_time_to_bcstr(nt, buf, len); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | mio_bch_t* mio_svc_htts_dupmergepaths (mio_svc_htts_t* htts, const mio_bch_t* base, const mio_bch_t* path) | ||||||
|  | { | ||||||
|  | 	mio_bch_t* xpath; | ||||||
|  | 	const mio_bch_t* ta[4]; | ||||||
|  | 	mio_oow_t idx = 0; | ||||||
|  |  | ||||||
|  | 	ta[idx++] = base; | ||||||
|  | 	if (path[0] != '\0') | ||||||
|  | 	{ | ||||||
|  | 		ta[idx++] = "/"; | ||||||
|  | 		ta[idx++] = path; | ||||||
|  | 	} | ||||||
|  | 	ta[idx++] = MIO_NULL; | ||||||
|  | 	xpath = mio_dupbcstrs(htts->mio, ta, MIO_NULL); | ||||||
|  | 	if (MIO_UNLIKELY(!xpath)) return MIO_NULL; | ||||||
|  |  | ||||||
|  | 	mio_canon_bcstr_path (xpath, xpath, 0); | ||||||
|  | 	return xpath; | ||||||
|  | } | ||||||
|  |  | ||||||
| /* ----------------------------------------------------------------- */ | /* ----------------------------------------------------------------- */ | ||||||
|  |  | ||||||
| #if 0 | #if 0 | ||||||
|  | |||||||
| @ -387,15 +387,7 @@ typedef void (*mio_svc_dnc_on_resolve_t) ( | |||||||
| 	mio_oow_t      len | 	mio_oow_t      len | ||||||
| ); | ); | ||||||
|  |  | ||||||
| #if defined(MIO_HAVE_INLINE) |  | ||||||
| static MIO_INLINE mio_t* mio_svc_dns_getmio(mio_svc_dns_t* svc) { return mio_svc_getmio((mio_svc_t*)svc); } |  | ||||||
| static MIO_INLINE mio_t* mio_svc_dnc_getmio(mio_svc_dnc_t* svc) { return mio_svc_getmio((mio_svc_t*)svc); } |  | ||||||
| static MIO_INLINE mio_t* mio_svc_dnr_getmio(mio_svc_dnr_t* svc) { return mio_svc_getmio((mio_svc_t*)svc); } |  | ||||||
| #else |  | ||||||
| #	define mio_svc_dns_getmio(svc) mio_svc_getmio(svc) |  | ||||||
| #	define mio_svc_dnc_getmio(svc) mio_svc_getmio(svc) |  | ||||||
| #	define mio_svc_dnr_getmio(svc) mio_svc_getmio(svc) |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| enum mio_svc_dnc_send_flag_t | enum mio_svc_dnc_send_flag_t | ||||||
| { | { | ||||||
| @ -476,6 +468,16 @@ MIO_EXPORT void mio_svc_dnc_stop ( | |||||||
| 	mio_svc_dnc_t* dnc | 	mio_svc_dnc_t* dnc | ||||||
| ); | ); | ||||||
|  |  | ||||||
|  | #if defined(MIO_HAVE_INLINE) | ||||||
|  | static MIO_INLINE mio_t* mio_svc_dns_getmio(mio_svc_dns_t* svc) { return mio_svc_getmio((mio_svc_t*)svc); } | ||||||
|  | static MIO_INLINE mio_t* mio_svc_dnc_getmio(mio_svc_dnc_t* svc) { return mio_svc_getmio((mio_svc_t*)svc); } | ||||||
|  | static MIO_INLINE mio_t* mio_svc_dnr_getmio(mio_svc_dnr_t* svc) { return mio_svc_getmio((mio_svc_t*)svc); } | ||||||
|  | #else | ||||||
|  | #	define mio_svc_dns_getmio(svc) mio_svc_getmio(svc) | ||||||
|  | #	define mio_svc_dnc_getmio(svc) mio_svc_getmio(svc) | ||||||
|  | #	define mio_svc_dnr_getmio(svc) mio_svc_getmio(svc) | ||||||
|  | #endif | ||||||
|  |  | ||||||
| MIO_EXPORT mio_dns_msg_t* mio_svc_dnc_sendmsg ( | MIO_EXPORT mio_dns_msg_t* mio_svc_dnc_sendmsg ( | ||||||
| 	mio_svc_dnc_t*         dnc, | 	mio_svc_dnc_t*         dnc, | ||||||
| 	mio_dns_bhdr_t*        bdns, | 	mio_dns_bhdr_t*        bdns, | ||||||
|  | |||||||
| @ -55,11 +55,10 @@ enum mio_htrd_option_t | |||||||
| 	MIO_HTRD_SKIPEMPTYLINES  = (1 << 0), /**< skip leading empty lines before the initial line */ | 	MIO_HTRD_SKIPEMPTYLINES  = (1 << 0), /**< skip leading empty lines before the initial line */ | ||||||
| 	MIO_HTRD_SKIPINITIALLINE = (1 << 1), /**< skip processing an initial line */ | 	MIO_HTRD_SKIPINITIALLINE = (1 << 1), /**< skip processing an initial line */ | ||||||
| 	MIO_HTRD_CANONQPATH      = (1 << 2), /**< canonicalize the query path */ | 	MIO_HTRD_CANONQPATH      = (1 << 2), /**< canonicalize the query path */ | ||||||
| 	MIO_HTRD_PEEKONLY        = (1 << 3), /**< trigger a peek callback after headers without processing contents */ | 	MIO_HTRD_REQUEST         = (1 << 3), /**< parse input as a request */ | ||||||
| 	MIO_HTRD_REQUEST         = (1 << 4), /**< parse input as a request */ | 	MIO_HTRD_RESPONSE        = (1 << 4), /**< parse input as a response */ | ||||||
| 	MIO_HTRD_RESPONSE        = (1 << 5), /**< parse input as a response */ | 	MIO_HTRD_TRAILERS        = (1 << 5), /**< store trailers in a separate table */ | ||||||
| 	MIO_HTRD_TRAILERS        = (1 << 6), /**< store trailers in a separate table */ | 	MIO_HTRD_STRICT          = (1 << 6)  /**< be more picky */ | ||||||
| 	MIO_HTRD_STRICT          = (1 << 7)  /**< be more picky */ |  | ||||||
| }; | }; | ||||||
|  |  | ||||||
| typedef enum mio_htrd_option_t mio_htrd_option_t; | typedef enum mio_htrd_option_t mio_htrd_option_t; | ||||||
|  | |||||||
| @ -27,8 +27,74 @@ | |||||||
| #ifndef _MIO_HTRE_H_ | #ifndef _MIO_HTRE_H_ | ||||||
| #define _MIO_HTRE_H_ | #define _MIO_HTRE_H_ | ||||||
|  |  | ||||||
| #include <mio-http.h> |  | ||||||
| #include <mio-htb.h> | #include <mio-htb.h> | ||||||
|  | #include <mio-ecs.h> | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * The mio_http_version_t type defines http version. | ||||||
|  |  */ | ||||||
|  | struct mio_http_version_t | ||||||
|  | { | ||||||
|  | 	short major; /**< major version */ | ||||||
|  | 	short minor; /**< minor version */ | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | typedef struct mio_http_version_t mio_http_version_t; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * The mio_http_method_t type defines http methods . | ||||||
|  |  */ | ||||||
|  | enum mio_http_method_t | ||||||
|  | { | ||||||
|  | 	MIO_HTTP_OTHER, | ||||||
|  |  | ||||||
|  | 	/* rfc 2616 */ | ||||||
|  | 	MIO_HTTP_HEAD, | ||||||
|  | 	MIO_HTTP_GET, | ||||||
|  | 	MIO_HTTP_POST, | ||||||
|  | 	MIO_HTTP_PUT, | ||||||
|  | 	MIO_HTTP_DELETE, | ||||||
|  | 	MIO_HTTP_OPTIONS, | ||||||
|  | 	MIO_HTTP_TRACE, | ||||||
|  | 	MIO_HTTP_CONNECT | ||||||
|  |  | ||||||
|  | #if 0 | ||||||
|  | 	/* rfc 2518 */ | ||||||
|  | 	MIO_HTTP_PROPFIND, | ||||||
|  | 	MIO_HTTP_PROPPATCH, | ||||||
|  | 	MIO_HTTP_MKCOL, | ||||||
|  | 	MIO_HTTP_COPY, | ||||||
|  | 	MIO_HTTP_MOVE, | ||||||
|  | 	MIO_HTTP_LOCK, | ||||||
|  | 	MIO_HTTP_UNLOCK, | ||||||
|  |  | ||||||
|  | 	/* rfc 3253 */ | ||||||
|  | 	MIO_HTTP_VERSION_CONTROL, | ||||||
|  | 	MIO_HTTP_REPORT, | ||||||
|  | 	MIO_HTTP_CHECKOUT, | ||||||
|  | 	MIO_HTTP_CHECKIN, | ||||||
|  | 	MIO_HTTP_UNCHECKOUT, | ||||||
|  | 	MIO_HTTP_MKWORKSPACE, | ||||||
|  | 	MIO_HTTP_UPDATE, | ||||||
|  | 	MIO_HTTP_LABEL, | ||||||
|  | 	MIO_HTTP_MERGE, | ||||||
|  | 	MIO_HTTP_BASELINE_CONTROL, | ||||||
|  | 	MIO_HTTP_MKACTIVITY, | ||||||
|  | 	 | ||||||
|  | 	/* microsoft */ | ||||||
|  | 	MIO_HTTP_BPROPFIND, | ||||||
|  | 	MIO_HTTP_BPROPPATCH, | ||||||
|  | 	MIO_HTTP_BCOPY, | ||||||
|  | 	MIO_HTTP_BDELETE, | ||||||
|  | 	MIO_HTTP_BMOVE, | ||||||
|  | 	MIO_HTTP_NOTIFY, | ||||||
|  | 	MIO_HTTP_POLL, | ||||||
|  | 	MIO_HTTP_SUBSCRIBE, | ||||||
|  | 	MIO_HTTP_UNSUBSCRIBE, | ||||||
|  | #endif | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | typedef enum mio_http_method_t mio_http_method_t; | ||||||
|  |  | ||||||
| /*  | /*  | ||||||
|  * You should not manipulate an object of the #mio_htre_t  |  * You should not manipulate an object of the #mio_htre_t  | ||||||
| @ -37,7 +103,7 @@ | |||||||
|  */ |  */ | ||||||
|  |  | ||||||
| /* header and contents of request/response */ | /* header and contents of request/response */ | ||||||
| /*typedef struct mio_htre_t mio_htre_t; <--- defined in mio-http.h TODO: remove recursive definition */ | typedef struct mio_htre_t mio_htre_t; | ||||||
| typedef struct mio_htre_hdrval_t mio_htre_hdrval_t; | typedef struct mio_htre_hdrval_t mio_htre_hdrval_t; | ||||||
|  |  | ||||||
| enum mio_htre_state_t | enum mio_htre_state_t | ||||||
|  | |||||||
| @ -27,77 +27,12 @@ | |||||||
|  |  | ||||||
| #include <mio-ecs.h> | #include <mio-ecs.h> | ||||||
| #include <mio-sck.h> | #include <mio-sck.h> | ||||||
|  | #include <mio-htre.h> | ||||||
|  |  | ||||||
| /** \file | /** \file | ||||||
|  * This file provides basic data types and functions for the http protocol. |  * This file provides basic data types and functions for the http protocol. | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * The mio_http_version_t type defines http version. |  | ||||||
|  */ |  | ||||||
| struct mio_http_version_t |  | ||||||
| { |  | ||||||
| 	short major; /**< major version */ |  | ||||||
| 	short minor; /**< minor version */ |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| typedef struct mio_http_version_t mio_http_version_t; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * The mio_http_method_t type defines http methods . |  | ||||||
|  */ |  | ||||||
| enum mio_http_method_t |  | ||||||
| { |  | ||||||
| 	MIO_HTTP_OTHER, |  | ||||||
|  |  | ||||||
| 	/* rfc 2616 */ |  | ||||||
| 	MIO_HTTP_HEAD, |  | ||||||
| 	MIO_HTTP_GET, |  | ||||||
| 	MIO_HTTP_POST, |  | ||||||
| 	MIO_HTTP_PUT, |  | ||||||
| 	MIO_HTTP_DELETE, |  | ||||||
| 	MIO_HTTP_OPTIONS, |  | ||||||
| 	MIO_HTTP_TRACE, |  | ||||||
| 	MIO_HTTP_CONNECT |  | ||||||
|  |  | ||||||
| #if 0 |  | ||||||
| 	/* rfc 2518 */ |  | ||||||
| 	MIO_HTTP_PROPFIND, |  | ||||||
| 	MIO_HTTP_PROPPATCH, |  | ||||||
| 	MIO_HTTP_MKCOL, |  | ||||||
| 	MIO_HTTP_COPY, |  | ||||||
| 	MIO_HTTP_MOVE, |  | ||||||
| 	MIO_HTTP_LOCK, |  | ||||||
| 	MIO_HTTP_UNLOCK, |  | ||||||
|  |  | ||||||
| 	/* rfc 3253 */ |  | ||||||
| 	MIO_HTTP_VERSION_CONTROL, |  | ||||||
| 	MIO_HTTP_REPORT, |  | ||||||
| 	MIO_HTTP_CHECKOUT, |  | ||||||
| 	MIO_HTTP_CHECKIN, |  | ||||||
| 	MIO_HTTP_UNCHECKOUT, |  | ||||||
| 	MIO_HTTP_MKWORKSPACE, |  | ||||||
| 	MIO_HTTP_UPDATE, |  | ||||||
| 	MIO_HTTP_LABEL, |  | ||||||
| 	MIO_HTTP_MERGE, |  | ||||||
| 	MIO_HTTP_BASELINE_CONTROL, |  | ||||||
| 	MIO_HTTP_MKACTIVITY, |  | ||||||
| 	 |  | ||||||
| 	/* microsoft */ |  | ||||||
| 	MIO_HTTP_BPROPFIND, |  | ||||||
| 	MIO_HTTP_BPROPPATCH, |  | ||||||
| 	MIO_HTTP_BCOPY, |  | ||||||
| 	MIO_HTTP_BDELETE, |  | ||||||
| 	MIO_HTTP_BMOVE, |  | ||||||
| 	MIO_HTTP_NOTIFY, |  | ||||||
| 	MIO_HTTP_POLL, |  | ||||||
| 	MIO_HTTP_SUBSCRIBE, |  | ||||||
| 	MIO_HTTP_UNSUBSCRIBE, |  | ||||||
| #endif |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| typedef enum mio_http_method_t mio_http_method_t; |  | ||||||
|  |  | ||||||
| /**  | /**  | ||||||
|  * The #mio_http_range_int_t type defines an integer that can represent |  * The #mio_http_range_int_t type defines an integer that can represent | ||||||
|  * a range offset. Depening on the size of #mio_foff_t, it is defined to |  * a range offset. Depening on the size of #mio_foff_t, it is defined to | ||||||
| @ -155,7 +90,6 @@ typedef enum mio_perenc_http_opt_t mio_perenc_bcstr_opt_t; | |||||||
|  |  | ||||||
|  |  | ||||||
| /* -------------------------------------------------------------- */ | /* -------------------------------------------------------------- */ | ||||||
| typedef struct mio_htre_t mio_htre_t; |  | ||||||
| typedef struct mio_svc_htts_t mio_svc_htts_t; | typedef struct mio_svc_htts_t mio_svc_htts_t; | ||||||
| typedef struct mio_svc_httc_t mio_svc_httc_t; | typedef struct mio_svc_httc_t mio_svc_httc_t; | ||||||
|  |  | ||||||
| @ -180,6 +114,14 @@ struct mio_svc_htts_rsrc_t | |||||||
|  |  | ||||||
| #define MIO_SVC_HTTS_RSRC_ATTACH(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_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) | #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) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | typedef int (*mio_svc_htts_proc_req_t) ( | ||||||
|  | 	mio_svc_htts_t* htts, | ||||||
|  | 	mio_dev_sck_t*  sck, | ||||||
|  | 	mio_htre_t*     req | ||||||
|  | ); | ||||||
|  |  | ||||||
| /* -------------------------------------------------------------- */ | /* -------------------------------------------------------------- */ | ||||||
|  |  | ||||||
| #if defined(__cplusplus) | #if defined(__cplusplus) | ||||||
| @ -279,42 +221,32 @@ MIO_EXPORT mio_bch_t* mio_perenc_http_bcstrdup ( | |||||||
| /* ------------------------------------------------------------------------- */ | /* ------------------------------------------------------------------------- */ | ||||||
|  |  | ||||||
| MIO_EXPORT mio_svc_htts_t* mio_svc_htts_start ( | MIO_EXPORT mio_svc_htts_t* mio_svc_htts_start ( | ||||||
| 	mio_t*            mio, | 	mio_t*                   mio, | ||||||
| 	const mio_skad_t* bind_addr | 	const mio_skad_t*        bind_addr, | ||||||
|  | 	mio_svc_htts_proc_req_t  proc_req | ||||||
| ); | ); | ||||||
|  |  | ||||||
| MIO_EXPORT void mio_svc_htts_stop ( | MIO_EXPORT void mio_svc_htts_stop ( | ||||||
| 	mio_svc_htts_t* htts | 	mio_svc_htts_t* htts | ||||||
| ); | ); | ||||||
|  |  | ||||||
|  | #if defined(MIO_HAVE_INLINE) | ||||||
|  | static MIO_INLINE mio_t* mio_svc_htts_getmio(mio_svc_htts_t* svc) { return mio_svc_getmio((mio_svc_t*)svc); } | ||||||
|  | #else | ||||||
|  | #	define mio_svc_htts_getmio(svc) mio_svc_getmio(svc) | ||||||
|  | #endif | ||||||
|  |  | ||||||
| MIO_EXPORT int mio_svc_htts_setservernamewithbcstr ( | MIO_EXPORT int mio_svc_htts_setservernamewithbcstr ( | ||||||
| 	mio_svc_htts_t*  htts, | 	mio_svc_htts_t*  htts, | ||||||
| 	const mio_bch_t* server_name | 	const mio_bch_t* server_name | ||||||
| ); | ); | ||||||
|  |  | ||||||
| MIO_EXPORT int mio_svc_htts_docgi ( | MIO_EXPORT int mio_svc_htts_docgi ( | ||||||
| 	mio_svc_htts_t* htts, | 	mio_svc_htts_t*  htts, | ||||||
| 	mio_dev_sck_t*  csck, | 	mio_dev_sck_t*   csck, | ||||||
| 	mio_htre_t*     req, | 	mio_htre_t*      req, | ||||||
| 	const mio_bch_t* docroot | 	const mio_bch_t* docroot, | ||||||
| ); | 	const mio_bch_t* script | ||||||
|  |  | ||||||
|  |  | ||||||
| MIO_EXPORT int mio_svc_htts_sendfile ( |  | ||||||
| 	mio_svc_htts_t*           htts, |  | ||||||
| 	mio_dev_sck_t*            csck, |  | ||||||
| 	const mio_bch_t*          file_path, |  | ||||||
| 	int                       status_code, |  | ||||||
| 	mio_http_method_t         method, |  | ||||||
| 	const mio_http_version_t* version, |  | ||||||
| 	int                       keepalive |  | ||||||
| ); |  | ||||||
|  |  | ||||||
| MIO_EXPORT void mio_svc_htts_fmtgmtime ( |  | ||||||
| 	mio_svc_htts_t*           htts, |  | ||||||
| 	const mio_ntime_t*        nt, |  | ||||||
| 	mio_bch_t*                buf, |  | ||||||
| 	mio_oow_t                 len |  | ||||||
| ); | ); | ||||||
|  |  | ||||||
| MIO_EXPORT mio_svc_htts_rsrc_t* mio_svc_htts_rsrc_make ( | MIO_EXPORT mio_svc_htts_rsrc_t* mio_svc_htts_rsrc_make ( | ||||||
| @ -335,6 +267,12 @@ MIO_EXPORT void mio_svc_htts_fmtgmtime ( | |||||||
| 	mio_oow_t          len | 	mio_oow_t          len | ||||||
| ); | ); | ||||||
|  |  | ||||||
|  | MIO_EXPORT mio_bch_t* mio_svc_htts_dupmergepaths ( | ||||||
|  | 	mio_svc_htts_t*    htts, | ||||||
|  | 	const mio_bch_t*   base, | ||||||
|  | 	const mio_bch_t*   path | ||||||
|  | ); | ||||||
|  |  | ||||||
| #if defined(__cplusplus) | #if defined(__cplusplus) | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
|  | |||||||
| @ -1776,7 +1776,6 @@ static int fmt_put_bchars_to_bch_buf (mio_fmtout_t* fmtout, const mio_bch_t* ptr | |||||||
| 	return 1; /* success */ | 	return 1; /* success */ | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| static int fmt_put_uchars_to_bch_buf (mio_fmtout_t* fmtout, const mio_uch_t* ptr, mio_oow_t len) | static int fmt_put_uchars_to_bch_buf (mio_fmtout_t* fmtout, const mio_uch_t* ptr, mio_oow_t len) | ||||||
| { | { | ||||||
| 	fmt_bch_buf_t* b = (fmt_bch_buf_t*)fmtout->ctx; | 	fmt_bch_buf_t* b = (fmt_bch_buf_t*)fmtout->ctx; | ||||||
|  | |||||||
| @ -1113,6 +1113,18 @@ MIO_EXPORT mio_bch_t* mio_dupbcstr ( | |||||||
| 	mio_oow_t*       bcslen /* [OUT] length */ | 	mio_oow_t*       bcslen /* [OUT] length */ | ||||||
| ); | ); | ||||||
|  |  | ||||||
|  | MIO_EXPORT mio_uch_t* mio_dupucstrs ( | ||||||
|  | 	mio_t*           mio, | ||||||
|  | 	const mio_uch_t* ucs[], | ||||||
|  | 	mio_oow_t*       ucslen | ||||||
|  | ); | ||||||
|  |  | ||||||
|  | MIO_EXPORT mio_bch_t* mio_dupbcstrs ( | ||||||
|  | 	mio_t*           mio, | ||||||
|  | 	const mio_bch_t* bcs[], | ||||||
|  | 	mio_oow_t*       bcslen | ||||||
|  | ); | ||||||
|  |  | ||||||
| #if defined(MIO_OOCH_IS_UCH) | #if defined(MIO_OOCH_IS_UCH) | ||||||
| #	define mio_dupoochars(mio,oocs,oocslen) mio_dupuchars(mio,oocs,oocslen) | #	define mio_dupoochars(mio,oocs,oocslen) mio_dupuchars(mio,oocs,oocslen) | ||||||
| #	define mio_dupoocstr(mio,oocs,oocslen) mio_dupucstr(mio,oocs,oocslen) | #	define mio_dupoocstr(mio,oocs,oocslen) mio_dupucstr(mio,oocs,oocslen) | ||||||
|  | |||||||
| @ -1729,5 +1729,39 @@ mio_bch_t* mio_dupbcstr (mio_t* mio, const mio_bch_t* bcs, mio_oow_t* bcslen) | |||||||
| 	return ptr; | 	return ptr; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | mio_uch_t* mio_dupucstrs (mio_t* mio, const mio_uch_t* ucs[], mio_oow_t* ucslen) | ||||||
|  | { | ||||||
|  | 	mio_uch_t* ptr; | ||||||
|  | 	mio_oow_t len, i; | ||||||
|  |  | ||||||
|  | 	for (i = 0, len = 0; ucs[i]; i++) len += mio_count_ucstr(ucs[i]); | ||||||
|  |  | ||||||
|  | 	ptr = (mio_uch_t*)mio_allocmem(mio, (len + 1) * MIO_SIZEOF(mio_uch_t)); | ||||||
|  | 	if (!ptr) return MIO_NULL; | ||||||
|  |  | ||||||
|  | 	for (i = 0, len = 0; ucs[i]; i++)  | ||||||
|  | 		len += mio_copy_ucstr_unlimited(&ptr[len], ucs[i]); | ||||||
|  | 	ptr[len] = '\0'; | ||||||
|  |  | ||||||
|  | 	if (ucslen) *ucslen = len; | ||||||
|  | 	return ptr; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | mio_bch_t* mio_dupbcstrs (mio_t* mio, const mio_bch_t* bcs[], mio_oow_t* bcslen) | ||||||
|  | { | ||||||
|  | 	mio_bch_t* ptr; | ||||||
|  | 	mio_oow_t len, i; | ||||||
|  |  | ||||||
|  | 	for (i = 0, len = 0; bcs[i]; i++) len += mio_count_bcstr(bcs[i]); | ||||||
|  |  | ||||||
|  | 	ptr = (mio_bch_t*)mio_allocmem(mio, (len + 1) * MIO_SIZEOF(mio_bch_t)); | ||||||
|  | 	if (!ptr) return MIO_NULL; | ||||||
|  |  | ||||||
|  | 	for (i = 0, len = 0; bcs[i]; i++)  | ||||||
|  | 		len += mio_copy_bcstr_unlimited(&ptr[len], bcs[i]); | ||||||
|  | 	ptr[len] = '\0'; | ||||||
|  |  | ||||||
|  | 	if (bcslen) *bcslen = len; | ||||||
|  | 	return ptr; | ||||||
|  | } | ||||||
| /* ========================================================================= */ | /* ========================================================================= */ | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user