From 529363913fd896ce9f2f9f914fce35b2305c4e80 Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Mon, 9 Jan 2023 01:09:34 +0900 Subject: [PATCH] added some fcgi support code --- bin/webs.c | 38 ++++++++-- lib/fcgi-cli.c | 191 +++++++++++++++++++++++++++++++++++++++------- lib/hio-fcgi.h | 107 ++++++++++++++++++++++++-- lib/hio-htre.h | 2 + lib/htrd.c | 1 + lib/http-fcgi.c | 197 +++++++++++++++++++++--------------------------- lib/sck.c | 4 +- 7 files changed, 388 insertions(+), 152 deletions(-) diff --git a/bin/webs.c b/bin/webs.c index 9776b13..df38753 100644 --- a/bin/webs.c +++ b/bin/webs.c @@ -36,6 +36,21 @@ typedef struct buff_t buff_t; /* ------------------------------------------------------------------------- */ +static void untar_write_status_code (int fd, int code) +{ + switch (code) + { + case 200: + write (fd, "Status: 200\r\n\r\n", 15); + break; + + case 500: + default: + write (fd, "Status: 500\r\n\r\n", 15); + break; + } +} + static void untar (hio_t* hio, hio_dev_thr_iopair_t* iop, hio_svc_htts_thr_func_info_t* tfi, void* ctx) { FILE* wfp = HIO_NULL; @@ -50,14 +65,14 @@ static void untar (hio_t* hio, hio_dev_thr_iopair_t* iop, hio_svc_htts_thr_func_ wfp = fdopen(iop->wfd, "w"); if (!wfp) { - write (iop->wfd, "Status: 500\r\n\r\n", 15); /* internal server error */ + untar_write_status_code (iop->wfd, 500); goto done; } tar = hio_tar_open(hio, 0); if (!tar) { - write (iop->wfd, "Status: 500\r\n\r\n", 15); + untar_write_status_code (iop->wfd, 500); goto done; } @@ -70,13 +85,13 @@ static void untar (hio_t* hio, hio_dev_thr_iopair_t* iop, hio_svc_htts_thr_func_ if (hio_tar_xfeed(tar, buf, n) <= -1) { - write (iop->wfd, "Status: 500\r\n\r\n", 20); + untar_write_status_code (iop->wfd, 500); goto done; } } hio_tar_endxfeed (tar); - write (iop->wfd, "Status: 200\r\n\r\n", 15); + untar_write_status_code (iop->wfd, 200); done: if (tar) @@ -286,7 +301,7 @@ static int process_http_request (hio_svc_htts_t* htts, hio_dev_sck_t* csck, hio_ htts_ext_t* ext = hio_svc_htts_getxtn(htts); hio_t* hio = hio_svc_htts_gethio(htts); hio_http_method_t mth; - const hio_bch_t* qpath; + const hio_bch_t* qpath, * qpath_ext; static hio_svc_htts_file_cbs_t fcbs = { file_get_mime_type, file_open_dir_list, HIO_NULL }; @@ -294,11 +309,20 @@ static int process_http_request (hio_svc_htts_t* htts, hio_dev_sck_t* csck, hio_ mth = hio_htre_getqmethodtype(req); qpath = hio_htre_getqpath(req); + qpath_ext = hio_rfind_bchar_in_bcstr(qpath, '.'); + if (!qpath_ext) qpath_ext = ""; - if (mth == HIO_HTTP_OTHER && hio_comp_bcstr(hio_htre_getqmethodname(req), "UNTAR", 1) == 0) + if (mth == HIO_HTTP_OTHER && hio_comp_bcstr(hio_htre_getqmethodname(req), "UNTAR", 1) == 0 && hio_comp_bcstr(qpath_ext, ".tar", 0) == 0) { /* don't care about the path for now. TODO: make this secure and reasonable */ - hio_svc_htts_dothr(htts, csck, req, untar, HIO_NULL, 0); + if (hio_svc_htts_dothr(htts, csck, req, untar, HIO_NULL, 0) <= -1) goto oops; + } + else if (hio_comp_bcstr(qpath_ext, ".php", 0) == 0) + { + hio_skad_t skad; + hio_bcstrtoskad(hio, "10.30.0.133:9000", &skad); + if (hio_svc_htts_dofcgi(htts, csck, req, &skad, 0) <= -1) goto oops; + /*if (hio_svc_htts_dotxt(htts, csck, req, HIO_HTTP_STATUS_INTERNAL_SERVER_ERROR, "text/plain", "what the...", 0) <= -1) goto oops;*/ } else // if (mth == HIO_HTTP_GET || mth == HIO_HTTP_POST) { diff --git a/lib/fcgi-cli.c b/lib/fcgi-cli.c index 2015892..b889ff8 100644 --- a/lib/fcgi-cli.c +++ b/lib/fcgi-cli.c @@ -48,6 +48,7 @@ struct hio_svc_fcgic_sess_t { hio_oow_t sid; hio_svc_fcgic_conn_t* conn; + hio_svc_fcgic_on_read_t on_read; }; struct hio_svc_fcgic_conn_t @@ -115,23 +116,28 @@ static void sck_on_disconnect (hio_dev_sck_t* sck) { fcgic_sck_xtn_t* sck_xtn = hio_dev_sck_getxtn(sck); hio_svc_fcgic_conn_t* conn = sck_xtn->conn; - + +printf ("DISCONNECT SOCKET .................. sck->%p conn->%p\n", sck, conn); + if (conn) { /* TODO: arrange to create it again if the server is not closing... */ /* if (.... ) */ -printf ("DISCONNECT SOCKET .................. %p\n", sck); +#if 0 if (sck->hio->stopreq == HIO_STOPREQ_NONE) { /* this may create a busy loop if the connection attempt fails repeatedly */ make_connection_socket(conn); /* don't care about failure for now */ } +#else + conn->dev = HIO_NULL; +#endif } - } static void sck_on_connect (hio_dev_sck_t* sck) { + printf ("CONNECTED >>>>>>>>>>>>>>>>>>>>>>>>>>\n"); } static int sck_on_write (hio_dev_sck_t* sck, hio_iolen_t wrlen, void* wrctx, const hio_skad_t* dstaddr) @@ -141,6 +147,21 @@ static int sck_on_write (hio_dev_sck_t* sck, hio_iolen_t wrlen, void* wrctx, con static int sck_on_read (hio_dev_sck_t* sck, const void* buf, hio_iolen_t len, const hio_skad_t* srcaddr) { + fcgic_sck_xtn_t* sck_xtn = hio_dev_sck_getxtn(sck); + hio_svc_fcgic_conn_t* conn = sck_xtn->conn; + + if (len == 0) + { + hio_dev_sck_halt (sck); + } + else + { + /* TODO: parse the reply ..*/ + + /*sess = get_session(using the session id);*/ + /*sess->on_read (sess, ptr, len);*/ + } + return 0; } @@ -169,10 +190,6 @@ static int make_connection_socket (hio_svc_fcgic_conn_t* conn) break; #endif - case HIO_AF_QX: - mi.type = HIO_DEV_SCK_QX; - break; - default: hio_seterrnum (hio, HIO_EINVAL); return -1; @@ -202,21 +219,12 @@ static int make_connection_socket (hio_svc_fcgic_conn_t* conn) } printf ("MAKING CONNECTION %p %p\n", conn->dev, sck); - -if (conn->dev != HIO_NULL) -{ -/* TODO: is this necessary???? */ - sck_xtn = hio_dev_sck_getxtn(conn->dev); - sck_xtn->conn = HIO_NULL; - hio_dev_sck_halt (conn->dev); - conn->dev = HIO_NULL; -} + HIO_ASSERT (hio, conn->dev == HIO_NULL); conn->dev = sck; return 0; } - static hio_svc_fcgic_conn_t* get_connection (hio_svc_fcgic_t* fcgic, const hio_skad_t* fcgis_addr) { hio_t* hio = fcgic->hio; @@ -228,7 +236,11 @@ static hio_svc_fcgic_conn_t* get_connection (hio_svc_fcgic_t* fcgic, const hio_s if (hio_equal_skads(&conn->addr, fcgis_addr, 1)) { if (conn->sess.free != INVALID_SID || - conn->sess.capa <= (CONN_SESS_CAPA_MAX - CONN_SESS_INC)) return conn; + conn->sess.capa <= (CONN_SESS_CAPA_MAX - CONN_SESS_INC)) + { + if (!conn->dev) make_connection_socket(conn); /* conn->dev will still be null if connection fails*/ + return conn; + } } conn = conn->next; } @@ -275,7 +287,7 @@ static void free_connections (hio_svc_fcgic_t* fcgic) } } -static hio_svc_fcgic_sess_t* new_session (hio_svc_fcgic_t* fcgic, const hio_skad_t* fcgis_addr) +static hio_svc_fcgic_sess_t* new_session (hio_svc_fcgic_t* fcgic, const hio_skad_t* fcgis_addr, hio_svc_fcgic_on_read_t on_read) { hio_t* hio = fcgic->hio; hio_svc_fcgic_conn_t* conn; @@ -309,6 +321,7 @@ static hio_svc_fcgic_sess_t* new_session (hio_svc_fcgic_t* fcgic, const hio_skad conn->sess.free = sess->sid; sess->sid = conn->sess.free; + sess->on_read = on_read; HIO_ASSERT (hio, sess->conn == conn); HIO_ASSERT (hio, sess->conn->fcgic == fcgic); @@ -329,7 +342,7 @@ hio_svc_fcgic_t* hio_svc_fcgic_start (hio_t* hio, const hio_svc_fcgic_tmout_t* t if (HIO_UNLIKELY(!fcgic)) goto oops; fcgic->hio = hio; - fcgic->svc_stop = hio_svc_fcgic_stop; + fcgic->svc_stop = (hio_svc_stop_t)hio_svc_fcgic_stop; if (tmout) { @@ -359,10 +372,10 @@ void hio_svc_fcgic_stop (hio_svc_fcgic_t* fcgic) hio_freemem (hio, fcgic); } -hio_svc_fcgic_sess_t* hio_svc_fcgic_tie (hio_svc_fcgic_t* fcgic, const hio_skad_t* addr) +hio_svc_fcgic_sess_t* hio_svc_fcgic_tie (hio_svc_fcgic_t* fcgic, const hio_skad_t* addr, hio_svc_fcgic_on_read_t on_read) { /* TODO: reference counting for safety?? */ - return new_session(fcgic, addr); + return new_session(fcgic, addr, on_read); } void hio_svc_fcgic_untie (hio_svc_fcgic_sess_t* sess) @@ -371,13 +384,137 @@ void hio_svc_fcgic_untie (hio_svc_fcgic_sess_t* sess) release_session (sess); } -int hio_svc_fcgic_write (hio_svc_fcgic_sess_t* sess, const void* data, hio_iolen_t len) +int hio_svc_fcgic_beginrequest (hio_svc_fcgic_sess_t* sess) { - return 0; + hio_iovec_t iov[2]; + hio_fcgi_record_header_t h; + hio_fcgi_begin_request_body_t b; + + if (!sess->conn->dev) + { + /* TODO: set error **/ + return -1; + } + + HIO_MEMSET (&h, 0, HIO_SIZEOF(h)); + h.version = HIO_FCGI_VERSION; + h.type = HIO_FCGI_BEGIN_REQUEST; + h.id = h.id = hio_hton16(sess->sid); + h.content_len = hio_hton16(HIO_SIZEOF(b)); + h.padding_len = 0; + + HIO_MEMSET (&b, 0, HIO_SIZEOF(b)); + b.role = HIO_CONST_HTON16(HIO_FCGI_ROLE_RESPONDER); + b.flags = HIO_FCGI_KEEP_CONN; + + iov[0].iov_ptr = &h; + iov[0].iov_len = HIO_SIZEOF(h); + iov[1].iov_ptr = &b; + iov[1].iov_len = HIO_SIZEOF(b); + +/* TODO: check if sess->conn->dev is still valid */ + return hio_dev_sck_writev(sess->conn->dev, iov, 2, HIO_NULL, HIO_NULL); } - -int hio_svc_fcgic_beginreq (hio_svc_fcgic_sess_t* sess) +int hio_svc_fcgic_writeparam (hio_svc_fcgic_sess_t* sess, const void* key, hio_iolen_t ksz, const void* val, hio_iolen_t vsz) { + hio_iovec_t iov[4]; + hio_fcgi_record_header_t h; + hio_uint8_t sz[8]; + hio_oow_t szc = 0; -} \ No newline at end of file + if (!sess->conn->dev) + { + /* TODO: set error **/ + return -1; + } + + HIO_MEMSET (&h, 0, HIO_SIZEOF(h)); + h.version = HIO_FCGI_VERSION; + h.type = HIO_FCGI_PARAMS; + h.id = hio_hton16(sess->sid); + h.content_len = 0; + + /* TODO: check ksz and vsz can't exceed max 32bit value. */ + /* limit sizes to the max of the signed 32-bit interger + * the high-order bit is used as encoding marker (1-byte or 4-byte encoding). + * so a size can't hit the unsigned max. */ + ksz &= HIO_TYPE_MAX(hio_int32_t); + vsz &= HIO_TYPE_MAX(hio_int32_t); + if (ksz > 0) + { + if (ksz > 0xFF) + { + sz[szc++] = (ksz >> 24) | 0x80; + sz[szc++] = (ksz >> 16) & 0xFF; + sz[szc++] = (ksz >> 8) & 0xFF; + sz[szc++] = ksz & 0xFF; + } + else + { + sz[szc++] = ksz; + } + + if (vsz > 0xFF) + { + sz[szc++] = (vsz >> 24) | 0x80; + sz[szc++] = (vsz >> 16) & 0xFF; + sz[szc++] = (vsz >> 8) & 0xFF; + sz[szc++] = vsz & 0xFF; + } + else + { + sz[szc++] = vsz; + } + + h.content_len = szc + ksz + vsz; + /* TODO: check content_len overflows... */ + } + + h.content_len = hio_hton16(h.content_len); + h.padding_len = 0; + +/* TODO: some buffering of parameters??? if the key/value isn't long enough, it may trigger many system calls*/ + iov[0].iov_ptr = &h; + iov[0].iov_len = HIO_SIZEOF(h); + if (ksz > 0) + { + iov[1].iov_ptr = sz; + iov[1].iov_len = szc; + iov[2].iov_ptr = key; + iov[2].iov_len = ksz; + iov[3].iov_ptr = val; + iov[3].iov_len = vsz; + } + + return hio_dev_sck_writev(sess->conn->dev, iov, (ksz > 0? 4: 1), HIO_NULL, HIO_NULL); +} + +int hio_svc_fcgic_writestdin (hio_svc_fcgic_sess_t* sess, const void* data, hio_iolen_t size) +{ + hio_iovec_t iov[2]; + hio_fcgi_record_header_t h; + + if (!sess->conn->dev) + { + /* TODO: set error **/ + return -1; + } + + HIO_MEMSET (&h, 0, HIO_SIZEOF(h)); + h.version = HIO_FCGI_VERSION; + h.type = HIO_FCGI_STDIN; + h.id = hio_hton16(sess->sid); + h.content_len = hio_hton16(size); + + iov[0].iov_ptr = &h; + iov[0].iov_len = HIO_SIZEOF(h); + if (size > 0) + { + iov[1].iov_ptr = (void*)data; + iov[1].iov_len = size; + } + +/* TODO: check if sess->conn->dev is still valid */ + return hio_dev_sck_writev(sess->conn->dev, iov, (size > 0? 2: 1), HIO_NULL, HIO_NULL); +} diff --git a/lib/hio-fcgi.h b/lib/hio-fcgi.h index b72919d..72692fe 100644 --- a/lib/hio-fcgi.h +++ b/lib/hio-fcgi.h @@ -27,6 +27,81 @@ #include #include + +/* ---------------------------------------------------------------- */ + +#define HIO_FCGI_VERSION (1) + +#define HIO_FCGI_PADDING_SIZE 255 +#define HIO_FCGI_RECORD_SIZE HIO_SIZEOF(hio_fcgi_record_header_t) + FCGI_CONTENT_SIZE + FCGI_PADDING_SIZE) + +enum hio_fcgi_req_type_t +{ + HIO_FCGI_BEGIN_REQUEST = 1, + HIO_FCGI_ABORT_REQUEST = 2, + HIO_FCGI_END_REQUEST = 3, + HIO_FCGI_PARAMS = 4, + HIO_FCGI_STDIN = 5, + HIO_FCGI_STDOUT = 6, + HIO_FCGI_STDERR = 7, + HIO_FCGI_DATA = 8, + HIO_FCGI_GET_VALUES = 9, + HIO_FCGI_GET_VALUES_RESULT = 10, + HIO_FCGI_UNKNOWN_TYPE = 11, + HIO_FCGI_MAXTYPE = (HIO_FCGI_UNKNOWN_TYPE) +}; +typedef enum hio_fcgi_req_type_t hio_fcgi_req_type_t; + +/* role in fcgi_begin_request_body */ +enum hio_fcgi_role_t +{ + HIO_FCGI_ROLE_RESPONDER = 1, + HIO_FCGI_ROLE_AUTHORIZER = 2, + HIO_FCGI_ROLE_FILTER = 3, +}; +typedef enum hio_fcgi_role_t hio_fcgi_role_t; + + +/* flag in fcgi_begin_request_body */ +#define HIO_FCGI_KEEP_CONN 1 + +/* proto in fcgi_end_request_body */ +#define HIO_FCGI_REQUEST_COMPLETE 0 +#define HIO_FCGI_CANT_MPX_CONN 1 +#define HIO_FCGI_OVERLOADED 2 +#define HIO_FCGI_UNKNOWN_ROLE 3 + +#include "hio-pac1.h" +struct hio_fcgi_record_header_t +{ + hio_uint8_t version; + hio_uint8_t type; + hio_uint16_t id; + hio_uint16_t content_len; + hio_uint8_t padding_len; + hio_uint8_t reserved; + /* content data of the record 'type'*/ + /* padding data ... */ +}; +typedef struct hio_fcgi_record_header_t hio_fcgi_record_header_t; + +struct hio_fcgi_begin_request_body_t +{ + hio_uint16_t role; + hio_uint8_t flags; + hio_uint8_t reserved[5]; +}; +typedef struct hio_fcgi_begin_request_body_t hio_fcgi_begin_request_body_t; + +struct hio_fcgi_end_request_body_t +{ + hio_uint32_t app_status; + hio_uint8_t proto_status; + hio_uint8_t reserved[3]; +}; +typedef struct hio_fcgi_end_request_body_t hio_fcgi_end_request_body_t; +#include "hio-upac.h" + /* ---------------------------------------------------------------- */ typedef struct hio_svc_fcgis_t hio_svc_fcgis_t; /* server service */ @@ -46,6 +121,13 @@ typedef struct hio_svc_fcgic_sess_t hio_svc_fcgic_sess_t; /* ---------------------------------------------------------------- */ +typedef int (*hio_svc_fcgic_on_read_t) ( + hio_svc_fcgic_sess_t* sess, + const void* data, + hio_iolen_t dlen +); + +/* ---------------------------------------------------------------- */ #if defined(__cplusplus) extern "C" { #endif @@ -68,18 +150,31 @@ static HIO_INLINE hio_t* hio_svc_fcgic_gethio(hio_svc_fcgic_t* svc) { return hio #endif HIO_EXPORT hio_svc_fcgic_sess_t* hio_svc_fcgic_tie ( - hio_svc_fcgic_t* fcgic, - const hio_skad_t* fcgis_addr + hio_svc_fcgic_t* fcgic, + const hio_skad_t* fcgis_addr, + hio_svc_fcgic_on_read_t on_read ); HIO_EXPORT void hio_svc_fcgic_untie ( hio_svc_fcgic_sess_t* sess ); -HIO_EXPORT int hio_svc_fcgic_write ( - hio_svc_fcgic_sess_t* sess, - const void* data, - hio_iolen_t len +HIO_EXPORT int hio_svc_fcgic_beginrequest ( + hio_svc_fcgic_sess_t* sess +); + +HIO_EXPORT int hio_svc_fcgic_writeparam ( + hio_svc_fcgic_sess_t* sess, + const void* key, + hio_iolen_t ksz, + const void* val, + hio_iolen_t vsz +); + +HIO_EXPORT int hio_svc_fcgic_writestdin ( + hio_svc_fcgic_sess_t* sess, + const void* data, + hio_iolen_t size ); #if defined(__cplusplus) diff --git a/lib/hio-htre.h b/lib/hio-htre.h index 4242f61..f4145a8 100644 --- a/lib/hio-htre.h +++ b/lib/hio-htre.h @@ -175,6 +175,7 @@ struct hio_htre_t { hio_http_method_t type; const hio_bch_t* name; + hio_oow_t len; } method; hio_bcs_t path; hio_bcs_t param; @@ -240,6 +241,7 @@ struct hio_htre_t #define hio_htre_getqmethodtype(re) ((re)->u.q.method.type) #define hio_htre_getqmethodname(re) ((re)->u.q.method.name) +#define hio_htre_getqmethodlen(re) ((re)->u.q.method.len) #define hio_htre_getqpath(re) ((re)->u.q.path.ptr) #define hio_htre_getqpathlen(re) ((re)->u.q.path.len) diff --git a/lib/htrd.c b/lib/htrd.c index 67ce6e7..c4a152f 100644 --- a/lib/htrd.c +++ b/lib/htrd.c @@ -214,6 +214,7 @@ static hio_bch_t* parse_initial_line (hio_htrd_t* htrd, hio_bch_t* line) htrd->re.u.q.method.type = hio_bchars_to_http_method(tmp.ptr, tmp.len); htrd->re.u.q.method.name = tmp.ptr; + htrd->re.u.q.method.len = tmp.len; } else if ((htrd->option & HIO_HTRD_RESPONSE) && hio_comp_bchars_bcstr(tmp.ptr, tmp.len, "HTTP", 1) == 0) { diff --git a/lib/http-fcgi.c b/lib/http-fcgi.c index 958d135..a39442c 100644 --- a/lib/http-fcgi.c +++ b/lib/http-fcgi.c @@ -22,77 +22,6 @@ typedef enum fcgi_res_mode_t fcgi_res_mode_t; #define FCGI_OVER_WRITE_TO_PEER (1 << 3) #define FCGI_OVER_ALL (FCGI_OVER_READ_FROM_CLIENT | FCGI_OVER_READ_FROM_PEER | FCGI_OVER_WRITE_TO_CLIENT | FCGI_OVER_WRITE_TO_PEER) - -#define FCGI_VERSION (1) - -#define FCGI_PADDING_SIZE 255 -#define FCGI_RECORD_SIZE HIO_SIZEOF(struct fcgi_record_header_t) + FCGI_CONTENT_SIZE + FCGI_PADDING_SIZE) - -enum fcgi_req_type_t -{ - FCGI_BEGIN_REQUEST = 1, - FCGI_ABORT_REQUEST = 2, - FCGI_END_REQUEST = 3, - FCGI_PARAMS = 4, - FCGI_STDIN = 5, - FCGI_STDOUT = 6, - FCGI_STDERR = 7, - FCGI_DATA = 8, - FCGI_GET_VALUES = 9, - FCGI_GET_VALUES_RESULT = 10, - FCGI_UNKNOWN_TYPE = 11, - FCGI_MAXTYPE = (FCGI_UNKNOWN_TYPE) -}; -typedef enum fcgi_req_type_t fcgi_req_type_t; - -/* role in fcgi_begin_request_body */ -enum fcgi_role_t -{ - FCGI_ROLE_RESPONDER = 1, - FCGI_ROLE_AUTHORIZER = 2, - FCGI_ROLE_FILTER = 3, -}; -typedef enum fcgi_role_t fcgi_role_t; - - -/* flag in fcgi_begin_request_body */ -#define FCGI_KEEP_CONN 1 - -/* proto in fcgi_end_request_body */ -#define FCGI_REQUEST_COMPLETE 0 -#define FCGI_CANT_MPX_CONN 1 -#define FFCGI_OVERLOADED 2 -#define FCGI_UNKNOWN_ROLE 3 - -#include "hio-pac1.h" -struct fcgi_record_header_t -{ - hio_uint8_t version; - hio_uint8_t type; - hio_uint16_t id; - hio_uint16_t content_len; - hio_uint8_t padding_len; - hio_uint8_t reserved; - /* content data of the record 'type'*/ - /* padding data ... */ -}; - -struct fcgi_begin_request_body_t -{ - hio_uint16_t role; - hio_uint8_t flags; - hio_uint8_t reserved[5]; -}; - -struct fcgi_end_request_body_t -{ - hio_uint32_t app_status; - hio_uint8_t proto_status; - hio_uint8_t reserved[3]; -}; -#include "hio-upac.h" - - struct fcgi_t { HIO_SVC_HTTS_RSRC_HEADER; @@ -150,7 +79,6 @@ static int begin_request () #endif - static void fcgi_halt_participating_devices (fcgi_t* fcgi) { HIO_ASSERT (fcgi->client->htts->hio, fcgi->client != HIO_NULL); @@ -199,6 +127,7 @@ static HIO_INLINE void fcgi_mark_over (fcgi_t* fcgi, int over_bits) if (!(old_over & FCGI_OVER_READ_FROM_CLIENT) && (fcgi->over & FCGI_OVER_READ_FROM_CLIENT)) { +printf (">>>>>>>>>>>> disableing client read watching ...................\n"); if (hio_dev_sck_read(fcgi->client->sck, 0) <= -1) { HIO_DEBUG2 (fcgi->htts->hio, "HTTS(%p) - halting client(%p) for failure to disable input watching\n", fcgi->htts, fcgi->client->sck); @@ -267,7 +196,6 @@ static int fcgi_write_to_client (fcgi_t* fcgi, const void* data, hio_iolen_t dle return 0; } - static int fcgi_send_final_status_to_client (fcgi_t* fcgi, int status_code, int force_close) { hio_svc_htts_cli_t* cli = fcgi->client; @@ -288,19 +216,15 @@ static int fcgi_send_final_status_to_client (fcgi_t* fcgi, int status_code, int static int fcgi_client_htrd_poke (hio_htrd_t* htrd, hio_htre_t* req) { - /* client request got completed */ - + /* the client request got completed including body. + * this callback is set and called only if there is content in the request */ hio_svc_htts_cli_htrd_xtn_t* htrdxtn = (hio_svc_htts_cli_htrd_xtn_t*)hio_htrd_getxtn(htrd); hio_dev_sck_t* sck = htrdxtn->sck; hio_svc_htts_cli_t* cli = hio_dev_sck_getxtn(sck); fcgi_t* fcgi = (fcgi_t*)cli->rsrc; -/*printf (">> CLIENT REQUEST COMPLETED\n");*/ - -#if 0 // TODO: send abort??? - /* indicate EOF to the client peer */ - if (fcgi_write_to_peer(fcgi, HIO_NULL, 0) <= -1) return -1; -#endif + /* indicate end of STDIN */ + if (hio_svc_fcgic_writestdin(fcgi->peer, HIO_NULL, 0) <= -1) return -1; fcgi_mark_over (fcgi, FCGI_OVER_READ_FROM_CLIENT); return 0; @@ -313,9 +237,10 @@ static int fcgi_client_htrd_push_content (hio_htrd_t* htrd, hio_htre_t* req, con hio_svc_htts_cli_t* cli = hio_dev_sck_getxtn(sck); fcgi_t* fcgi = (fcgi_t*)cli->rsrc; -/* TODO: THIS must be written to the peer as FCGI_DATA */ HIO_ASSERT (sck->hio, cli->sck == sck); - return fcgi_write_to_peer(fcgi, data, dlen); + + /* write the contents to fcgi server as stdin*/ + return hio_svc_fcgic_writestdin(fcgi->peer, data, dlen); } static hio_htrd_recbs_t fcgi_client_htrd_recbs = @@ -330,6 +255,7 @@ static void fcgi_client_on_disconnect (hio_dev_sck_t* sck) hio_svc_htts_cli_t* cli = hio_dev_sck_getxtn(sck); fcgi_t* fcgi = (fcgi_t*)cli->rsrc; fcgi->client_disconnected = 1; +printf ("client disconnected ............................\n"); fcgi->client_org_on_disconnect (sck); } @@ -363,10 +289,8 @@ static int fcgi_client_on_read (hio_dev_sck_t* sck, const void* buf, hio_iolen_t if (!(fcgi->over & FCGI_OVER_READ_FROM_CLIENT)) /* if this is true, EOF is received without fcgi_client_htrd_poke() */ { -#if 0 /* indicate eof to the write side */ - if (fcgi_write_to_peer(fcgi, HIO_NULL, 0) <= -1) goto oops; -#endif + if (hio_svc_fcgic_writestdin(fcgi->peer, HIO_NULL, 0) <= -1) goto oops; fcgi_mark_over (fcgi, FCGI_OVER_READ_FROM_CLIENT); } } @@ -441,6 +365,12 @@ oops: return 0; } +static int fcgi_peer_on_read (hio_svc_fcgic_sess_t* peer, const void* buf, hio_iolen_t len) +{ +printf ("GOT FCGI DATA.............[%.*s]\n", (int)len, buf); + return 0; +} + static void fcgi_on_kill (fcgi_t* fcgi) { hio_t* hio = fcgi->htts->hio; @@ -456,6 +386,7 @@ static void fcgi_on_kill (fcgi_t* fcgi) hio_dev_pro_kill (fcgi->peer); fcgi->peer = HIO_NULL; } +#endif if (fcgi->client_org_on_read) { @@ -489,9 +420,65 @@ static void fcgi_on_kill (fcgi_t* fcgi) hio_dev_sck_halt (fcgi->client->sck); } } -#endif } +static int write_params (fcgi_t* fcgi, hio_dev_sck_t* csck, hio_htre_t* req) +{ + hio_t* hio = fcgi->htts->hio; + hio_bch_t tmp[256]; + hio_oow_t len; + const hio_bch_t* qparam; + hio_oow_t content_length; + + HIO_ASSERT (hio, fcgi->client->sck == csck); + + if (hio_svc_fcgic_writeparam(fcgi->peer, "GATEWAY_INTERFACE", 17, "CGI/1.1", 7) <= -1) goto oops; + + len = hio_fmttobcstr(hio, tmp, HIO_COUNTOF(tmp), "HTTP/%d.%d", (int)hio_htre_getmajorversion(req), (int)hio_htre_getminorversion(req)); + if (hio_svc_fcgic_writeparam(fcgi->peer, "SERVER_PROTOCOL", 15, tmp, len) <= -1) goto oops; + +// TODOs: +// DOCUMENT_ROOT +// SCRIPT_NAME +// PATH_INFO + + if (hio_svc_fcgic_writeparam(fcgi->peer, "REQUEST_METHOD", 14, hio_htre_getqmethodname(req), hio_htre_getqmethodlen(req)) <= -1) goto oops; + if (hio_svc_fcgic_writeparam(fcgi->peer, "REQUEST_URI", 11, hio_htre_getqpath(req), hio_htre_getqpathlen(req)) <= -1) goto oops; + + qparam = hio_htre_getqparam(req); + if (qparam && hio_svc_fcgic_writeparam(fcgi->peer, "QUERY_STRING", 12, qparam, hio_count_bcstr(qparam)) <= -1) goto oops; + + if (hio_htre_getreqcontentlen(req, &content_length) == 0) + { + /* content length is known and fixed */ + len = hio_fmt_uintmax_to_bcstr(tmp, HIO_COUNTOF(tmp), content_length, 10, 0, '\0', HIO_NULL); + if (hio_svc_fcgic_writeparam(fcgi->peer, "CONTENT_LENGTH", 14, tmp, len) <= -1) goto oops; + } + + if (hio_svc_fcgic_writeparam(fcgi->peer, "SERVER_SOFTWARE", 15, fcgi->htts->server_name, hio_count_bcstr(fcgi->htts->server_name)) <= -1) goto oops; + + len = hio_skadtobcstr (hio, &csck->localaddr, tmp, HIO_COUNTOF(tmp), HIO_SKAD_TO_BCSTR_ADDR); + if (hio_svc_fcgic_writeparam(fcgi->peer, "SERVER_ADDR", 11, tmp, len) <= -1) goto oops; + + gethostname (tmp, HIO_COUNTOF(tmp)); /* if this fails, i assume tmp contains the ip address set by hio_skadtobcstr() above */ + if (hio_svc_fcgic_writeparam(fcgi->peer, "SERVER_NAME", 11, tmp, hio_count_bcstr(tmp)) <= -1) goto oops; + + len = hio_skadtobcstr (hio, &csck->localaddr, tmp, HIO_COUNTOF(tmp), HIO_SKAD_TO_BCSTR_PORT); + if (hio_svc_fcgic_writeparam(fcgi->peer, "SERVER_PORT", 11, tmp, len) <= -1) goto oops; + + len = hio_skadtobcstr (hio, &csck->remoteaddr, tmp, HIO_COUNTOF(tmp), HIO_SKAD_TO_BCSTR_ADDR); + if (hio_svc_fcgic_writeparam(fcgi->peer, "REMOTE_ADDR", 11, tmp, len) <= -1) goto oops; + + len = hio_skadtobcstr (hio, &csck->remoteaddr, tmp, HIO_COUNTOF(tmp), HIO_SKAD_TO_BCSTR_PORT); + if (hio_svc_fcgic_writeparam(fcgi->peer, "REMOTE_PORT", 11, tmp, len) <= -1) goto oops; + + //hio_htre_walkheaders (req,) + + return 0; + +oops: + return -1; +} int hio_svc_htts_dofcgi (hio_svc_htts_t* htts, hio_dev_sck_t* csck, hio_htre_t* req, const hio_skad_t* fcgis_addr, int options) { hio_t* hio = htts->hio; @@ -502,7 +489,7 @@ int hio_svc_htts_dofcgi (hio_svc_htts_t* htts, hio_dev_sck_t* csck, hio_htre_t* /* ensure that you call this function before any contents is received */ HIO_ASSERT (hio, hio_htre_getcontentlen(req) == 0); - if (!htts->fcgic) + if (HIO_UNLIKELY(!htts->fcgic)) { hio_seterrbfmt (hio, HIO_ENOCAPA, "fcgi client service not enabled"); goto oops; @@ -529,27 +516,15 @@ int hio_svc_htts_dofcgi (hio_svc_htts_t* htts, hio_dev_sck_t* csck, hio_htre_t* HIO_ASSERT (hio, cli->rsrc == HIO_NULL); HIO_SVC_HTTS_RSRC_ATTACH ((hio_svc_htts_rsrc_t*)fcgi, cli->rsrc); /* cli->rsrc = fcgi */ -#if 0 // TODO - fcgi->peer = hio_dev_pro_make(hio, HIO_SIZEOF(*peer_xtn), &mi); - if (HIO_UNLIKELY(!fcgi->peer)) goto oops; - peer_xtn = hio_dev_pro_getxtn(fcgi->peer); - HIO_SVC_HTTS_RSRC_ATTACH ((hio_svc_htts_rsrc_t*)fcgi, peer_xtn->fcgi); /* peer->fcgi = fcgi */ -#else - fcgi->peer = hio_svc_fcgic_tie(htts->fcgic, fcgis_addr /* TODO: add a read callback */); + /* create a session in in the fcgi client service */ + fcgi->peer = hio_svc_fcgic_tie(htts->fcgic, fcgis_addr, fcgi_peer_on_read); if (HIO_UNLIKELY(!fcgi->peer)) goto oops; - hio_svc_fcgic_write (fcgi->peer, "hello", 5); -#endif - -#if 0 // TODO - fcgi->peer_htrd = hio_htrd_open(hio, HIO_SIZEOF(*peer)); - if (HIO_UNLIKELY(!fcgi->peer_htrd)) goto oops; - hio_htrd_setoption (fcgi->peer_htrd, HIO_HTRD_SKIP_INITIAL_LINE | HIO_HTRD_RESPONSE); - hio_htrd_setrecbs (fcgi->peer_htrd, &peer_htrd_recbs); - - peer = hio_htrd_getxtn(fcgi->peer_htrd); - HIO_SVC_HTTS_RSRC_ATTACH ((hio_svc_htts_rsrc_t*)fcgi, peer->fcgi); /* peer->fcgi = fcgi */ -#endif + /* send FCGI_BEGIN_REQUEST */ + if (hio_svc_fcgic_beginrequest(fcgi->peer) <= -1) goto oops; + /* write FCGI_PARAM */ + if (write_params(fcgi, csck, req) <= -1) goto oops; + if (hio_svc_fcgic_writeparam(fcgi->peer, HIO_NULL, 0, HIO_NULL, 0) <= -1) goto oops; /* end of params */ #if !defined(FCGI_ALLOW_UNLIMITED_REQ_CONTENT_LENGTH) if (fcgi->req_content_length_unlimited) @@ -566,7 +541,7 @@ int hio_svc_htts_dofcgi (hio_svc_htts_t* htts, hio_dev_sck_t* csck, hio_htre_t* if (req->flags & HIO_HTRE_ATTR_EXPECT100) { - /* TODO: Expect: 100-continue? who should handle this? cgi? or the http server? */ + /* TODO: Expect: 100-continue? who should handle this? fcgi? or the http server? */ /* CAN I LET the cgi SCRIPT handle this? */ if (!(options & HIO_SVC_HTTS_CGI_NO_100_CONTINUE) && hio_comp_http_version_numbers(&req->version, 1, 1) >= 0 && @@ -623,8 +598,8 @@ int hio_svc_htts_dofcgi (hio_svc_htts_t* htts, hio_dev_sck_t* csck, hio_htre_t* else { /* no content to be uploaded from the client */ - /* indicate EOF to the peer and disable input wathching from the client */ - if (fcgi_write_to_peer(fcgi, HIO_NULL, 0) <= -1) goto oops; + /* indicate end of stdin to the peer and disable input wathching from the client */ + if (hio_svc_fcgic_writestdin(fcgi->peer, HIO_NULL, 0) <= -1) goto oops; fcgi_mark_over (fcgi, FCGI_OVER_READ_FROM_CLIENT | FCGI_OVER_WRITE_TO_PEER); } #if defined(FCGI_ALLOW_UNLIMITED_REQ_CONTENT_LENGTH) @@ -652,4 +627,4 @@ oops: HIO_DEBUG2 (hio, "HTTS(%p) - FAILURE in dofcgi - socket(%p)\n", htts, csck); if (fcgi) fcgi_halt_participating_devices (fcgi); return -1; -} +} \ No newline at end of file diff --git a/lib/sck.c b/lib/sck.c index f9727d7..38c5e1f 100644 --- a/lib/sck.c +++ b/lib/sck.c @@ -2428,6 +2428,9 @@ int hio_dev_sck_bind (hio_dev_sck_t* dev, hio_dev_sck_bind_t* info) int hio_dev_sck_connect (hio_dev_sck_t* dev, hio_dev_sck_connect_t* info) { +/* TODO: if connecting to a hostname, do name resolutin first ... before calling ioctl(SCK_CONNECT). also some caching may be required.... +for this, hio_dev_sck_connect_t must be changed to accomodate a string as a host name. +*/ return hio_dev_ioctl((hio_dev_t*)dev, HIO_DEV_SCK_CONNECT, info); } @@ -2543,7 +2546,6 @@ static int update_mcast_group (hio_dev_sck_t* dev, int join, const hio_skad_t* m } } - hio_seterrbfmt (hio_dev_sck_gethio(dev), HIO_EINVAL, "invalid multicast address family"); return -1; }