| 
						
					 | 
				
			
			 | 
			 | 
			
				@ -9,6 +9,7 @@
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				#include <fcntl.h>
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				#include <sys/stat.h>
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				#include <pthread.h>
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				#include <stdlib.h> /* setenv */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				#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
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					 * 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 */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
	
		
			
				
					
					| 
						
					 | 
				
			
			 | 
			 | 
			
				@ -180,7 +183,7 @@ if (mio_htre_getcontentlen(req) > 0)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							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) mio_dev_sck_halt (csck); /*TODO: redo this sendstatus */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							if (mio_svc_htts_sendstatus(htts, csck, req, 411, MIO_NULL) <= -1) goto oops;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						else
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
	
		
			
				
					
					| 
						
					 | 
				
			
			 | 
			 | 
			
				@ -189,35 +192,6 @@ if (mio_htre_getcontentlen(req) > 0)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							/*const mio_bch_t* qpath = mio_htre_getqpath(req);*/
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							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;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				oops:
 | 
			
		
		
	
	
		
			
				
					
					| 
						
					 | 
				
			
			 | 
			 | 
			
				@ -289,7 +263,6 @@ static void fini_client (mio_svc_htts_cli_t* cli)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if (cli->rsrc)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				printf ("TRYING TO KILL RSRC IN VARIABLE - ADDRESS %p\n", &cli->rsrc);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						mio_svc_htts_rsrc_kill (cli->rsrc);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						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)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						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;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					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) 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				/* 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);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						/* TODO: either send bad request or server failure ... */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						goto oops;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
	
		
			
				
					
					| 
						
					 | 
				
			
			 | 
			 | 
			
				@ -363,6 +337,7 @@ printf ("** HTTS - client htrd feed failure socket(%p) - %d\n", sck, x);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					return 0;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				oops:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				printf ("HALTING CLIENT SOCKEXXT %p\n", sck);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					mio_dev_sck_halt (sck);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					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)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					mio_t* mio = sck->mio;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					mio_svc_htts_cli_t* cli = mio_dev_sck_getxtn(sck);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					switch (MIO_DEV_SCK_GET_PROGRESS(sck))
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						case MIO_DEV_SCK_CONNECTING:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							/* 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;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						case MIO_DEV_SCK_CONNECTING_SSL:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							/* 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;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						case MIO_DEV_SCK_CONNECTED:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							/* 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;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						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;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						case MIO_DEV_SCK_ACCEPTING_SSL: /* special case. */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							/* this progress code indicates that the ssl-level accept failed.
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							 * on_disconnected() with this code is called without corresponding on_connect(). 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							 * the cli extension are is not initialized yet */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							MIO_ASSERT (sck->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_DEBUG2 (sck->mio, "LISTENER UNABLE TO SSL-ACCEPT CLIENT %p(%d) ....%p\n", sck, (int)sck->hnd);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							MIO_ASSERT (mio, sck != cli->sck);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							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 (mio, "LISTENER UNABLE TO SSL-ACCEPT CLIENT %p(%d) ....%p\n", sck, (int)sck->hnd);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							return;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						case MIO_DEV_SCK_ACCEPTED:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							/* 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() */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							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;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						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;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if (sck == cli->htts->lsck)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						/* the listener socket has these fields set to NULL */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						MIO_ASSERT (sck->mio, cli->htrd == MIO_NULL);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						MIO_ASSERT (sck->mio, cli->sbuf == MIO_NULL);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						MIO_ASSERT (mio, cli->htrd == 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 */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					else
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						/* client socket */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						MIO_DEBUG2 (sck->mio, "HTTS(%p) - client socket disconnect %p\n", cli->htts, sck);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						MIO_ASSERT (sck->mio, cli->sck == sck);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						MIO_DEBUG2 (mio, "HTTS(%p) - client socket disconnect %p\n", cli->htts, sck);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						MIO_ASSERT (mio, cli->sck == sck);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						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 keep_alive: 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 */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					cgi_state_res_mode_t res_mode_to_cli;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					mio_dev_sck_on_read_t client_org_on_read;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					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;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
	
		
			
				
					
					| 
						
					 | 
				
			
			 | 
			 | 
			
				@ -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->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);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					/* check for peer as it may not have been started */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					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)
 | 
			
		
		
	
	
		
			
				
					
					| 
						
					 | 
				
			
			 | 
			 | 
			
				@ -719,6 +695,16 @@ static int cgi_state_writev_to_client (cgi_state_t* cgi_state, mio_iovec_t* iov,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					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)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					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))
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						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 (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)
 | 
			
		
		
	
	
		
			
				
					
					| 
						
					 | 
				
			
			 | 
			 | 
			
				@ -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) 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							/* 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);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							MIO_SVC_HTTS_RSRC_DEASSIGN (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);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				printf ("DETACHING FROM THE MAIN CLIENT RSRC... state -> %p\n", cgi_state->client->rsrc);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							MIO_SVC_HTTS_RSRC_DETACH (cgi_state->client->rsrc);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							/* cgi_state must not be access from here down as it could have been destroyed */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						else
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						{
 | 
			
		
		
	
	
		
			
				
					
					| 
						
					 | 
				
			
			 | 
			 | 
			
				@ -826,11 +812,26 @@ printf ("**** CGI_STATE_ON_KILL \n");
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						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)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						mio_dev_sck_halt (cgi_state->client->sck);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						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);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				printf ("**** CGI_STATE_ON_KILL DONE\n");
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				static void cgi_peer_on_close (mio_dev_pro_t* pro, mio_dev_pro_sid_t sid)
 | 
			
		
		
	
	
		
			
				
					
					| 
						
					 | 
				
			
			 | 
			 | 
			
				@ -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:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							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 */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				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;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						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->res_mode_to_cli == CGI_STATE_RES_MODE_CHUNKED &&
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								    cgi_state_write_to_client(cgi_state, "0\r\n\r\n", 5) <= -1) 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								if (cgi_state_write_last_chunk_to_client(cgi_state) <= -1) 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									cgi_state_halt_participating_devices (cgi_state);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								cgi_state_mark_over (cgi_state, CGI_STATE_OVER_READ_FROM_PEER);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								else
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
									cgi_state_mark_over (cgi_state, CGI_STATE_OVER_READ_FROM_PEER);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							break;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						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.
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							 * it still has to read more but EOF is read.
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							 * otherwise client_peer_htrd_poke() should have been called */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							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;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							if (cgi_state_write_last_chunk_to_client(cgi_state) <= -1) goto oops;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							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
 | 
			
		
		
	
	
		
			
				
					
					| 
						
					 | 
				
			
			 | 
			 | 
			
				@ -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) 
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							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 &&
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							    !(cgi_state->over & CGI_STATE_OVER_WRITE_TO_CLIENT) &&
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							    cgi_state_send_final_status_to_client(cgi_state, 500) <= -1) goto oops;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							    !(cgi_state->over & CGI_STATE_OVER_WRITE_TO_CLIENT))
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
								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) 
 | 
			
		
		
	
	
		
			
				
					
					| 
						
					 | 
				
			
			 | 
			 | 
			
				@ -935,14 +942,6 @@ printf ("DEASSIGNING 33.....................peer %p state %p   %d\n", cgi_peer,
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				printf ("AAAAAAAAAAAAAAAAAa EEEEEXcessive DATA..................\n");
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				/* 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;
 | 
			
		
		
	
	
		
			
				
					
					| 
						
					 | 
				
			
			 | 
			 | 
			
				@ -1026,9 +1025,7 @@ printf ("CGI PEER HTRD PEEK...\n");
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							break;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
						case CGI_STATE_RES_MODE_LENGTH:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							/* TODO: Keep-Alive if explicit in http/1.0 .
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							 *       Keep-Alive not needed if http/1.1 or later */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							break;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
							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;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					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");
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					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;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					/* indicate EOF to the client */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if (cgi_state_write_to_client(cgi_state, MIO_NULL, 0) <= -1) return -1;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if (cgi_state_write_last_chunk_to_client(cgi_state) <= -1) return -1;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					cgi_state_mark_over (cgi_state, CGI_STATE_OVER_READ_FROM_PEER);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					return 0;
 | 
			
		
		
	
	
		
			
				
					
					| 
						
					 | 
				
			
			 | 
			 | 
			
				@ -1198,6 +1191,14 @@ oops:
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					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)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					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 */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				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)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				{
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					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_peer_xtn_t* cgi_peer;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					mio_dev_pro_make_t mi;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					cgi_peer_fork_ctx_t fc;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					/* ensure that you call this function before any contents is received */
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					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));
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					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.on_read = cgi_peer_on_read;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					mi.on_write = cgi_peer_on_write;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					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);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					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_write = csck->on_write;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					cgi_state->client_org_on_disconnect = csck->on_disconnect;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					csck->on_read = cgi_client_on_read;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					csck->on_write = cgi_client_on_write;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					csck->on_disconnect = cgi_client_on_disconnect;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					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:
 | 
			
		
		
	
	
		
			
				
					
					| 
						
					 | 
				
			
			 | 
			 | 
			
				@ -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);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					if (MIO_UNLIKELY(!cgi_state->peer)) goto oops;
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					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));
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					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);
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
					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 (cgi_state->req_content_length_unlimited)
 | 
			
		
		
	
	
		
			
				
					
					| 
						
					 | 
				
			
			 | 
			 | 
			
				
 
 |