added some fcgi support code

This commit is contained in:
hyung-hwan 2023-01-09 01:09:34 +09:00
parent d2efac3ce2
commit 529363913f
7 changed files with 388 additions and 152 deletions

View File

@ -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) 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; 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"); wfp = fdopen(iop->wfd, "w");
if (!wfp) if (!wfp)
{ {
write (iop->wfd, "Status: 500\r\n\r\n", 15); /* internal server error */ untar_write_status_code (iop->wfd, 500);
goto done; goto done;
} }
tar = hio_tar_open(hio, 0); tar = hio_tar_open(hio, 0);
if (!tar) if (!tar)
{ {
write (iop->wfd, "Status: 500\r\n\r\n", 15); untar_write_status_code (iop->wfd, 500);
goto done; 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) 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; goto done;
} }
} }
hio_tar_endxfeed (tar); hio_tar_endxfeed (tar);
write (iop->wfd, "Status: 200\r\n\r\n", 15); untar_write_status_code (iop->wfd, 200);
done: done:
if (tar) 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); htts_ext_t* ext = hio_svc_htts_getxtn(htts);
hio_t* hio = hio_svc_htts_gethio(htts); hio_t* hio = hio_svc_htts_gethio(htts);
hio_http_method_t mth; 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 }; 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); mth = hio_htre_getqmethodtype(req);
qpath = hio_htre_getqpath(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 */ /* 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) else // if (mth == HIO_HTTP_GET || mth == HIO_HTTP_POST)
{ {

View File

@ -48,6 +48,7 @@ struct hio_svc_fcgic_sess_t
{ {
hio_oow_t sid; hio_oow_t sid;
hio_svc_fcgic_conn_t* conn; hio_svc_fcgic_conn_t* conn;
hio_svc_fcgic_on_read_t on_read;
}; };
struct hio_svc_fcgic_conn_t 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); fcgic_sck_xtn_t* sck_xtn = hio_dev_sck_getxtn(sck);
hio_svc_fcgic_conn_t* conn = sck_xtn->conn; hio_svc_fcgic_conn_t* conn = sck_xtn->conn;
printf ("DISCONNECT SOCKET .................. sck->%p conn->%p\n", sck, conn);
if (conn) if (conn)
{ {
/* TODO: arrange to create it again if the server is not closing... */ /* TODO: arrange to create it again if the server is not closing... */
/* if (.... ) */ /* if (.... ) */
printf ("DISCONNECT SOCKET .................. %p\n", sck); #if 0
if (sck->hio->stopreq == HIO_STOPREQ_NONE) if (sck->hio->stopreq == HIO_STOPREQ_NONE)
{ {
/* this may create a busy loop if the connection attempt fails repeatedly */ /* this may create a busy loop if the connection attempt fails repeatedly */
make_connection_socket(conn); /* don't care about failure for now */ 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) 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) 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) 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; return 0;
} }
@ -169,10 +190,6 @@ static int make_connection_socket (hio_svc_fcgic_conn_t* conn)
break; break;
#endif #endif
case HIO_AF_QX:
mi.type = HIO_DEV_SCK_QX;
break;
default: default:
hio_seterrnum (hio, HIO_EINVAL); hio_seterrnum (hio, HIO_EINVAL);
return -1; 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); printf ("MAKING CONNECTION %p %p\n", conn->dev, sck);
HIO_ASSERT (hio, conn->dev == HIO_NULL);
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;
}
conn->dev = sck; conn->dev = sck;
return 0; return 0;
} }
static hio_svc_fcgic_conn_t* get_connection (hio_svc_fcgic_t* fcgic, const hio_skad_t* fcgis_addr) static hio_svc_fcgic_conn_t* get_connection (hio_svc_fcgic_t* fcgic, const hio_skad_t* fcgis_addr)
{ {
hio_t* hio = fcgic->hio; 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 (hio_equal_skads(&conn->addr, fcgis_addr, 1))
{ {
if (conn->sess.free != INVALID_SID || 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; 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_t* hio = fcgic->hio;
hio_svc_fcgic_conn_t* conn; 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; conn->sess.free = sess->sid;
sess->sid = conn->sess.free; sess->sid = conn->sess.free;
sess->on_read = on_read;
HIO_ASSERT (hio, sess->conn == conn); HIO_ASSERT (hio, sess->conn == conn);
HIO_ASSERT (hio, sess->conn->fcgic == fcgic); 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; if (HIO_UNLIKELY(!fcgic)) goto oops;
fcgic->hio = hio; fcgic->hio = hio;
fcgic->svc_stop = hio_svc_fcgic_stop; fcgic->svc_stop = (hio_svc_stop_t)hio_svc_fcgic_stop;
if (tmout) if (tmout)
{ {
@ -359,10 +372,10 @@ void hio_svc_fcgic_stop (hio_svc_fcgic_t* fcgic)
hio_freemem (hio, 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?? */ /* 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) 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); 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_writeparam (hio_svc_fcgic_sess_t* sess, const void* key, hio_iolen_t ksz, const void* val, hio_iolen_t vsz)
int hio_svc_fcgic_beginreq (hio_svc_fcgic_sess_t* sess)
{ {
hio_iovec_t iov[4];
hio_fcgi_record_header_t h;
hio_uint8_t sz[8];
hio_oow_t szc = 0;
} 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);
}

View File

@ -27,6 +27,81 @@
#include <hio.h> #include <hio.h>
#include <hio-skad.h> #include <hio-skad.h>
/* ---------------------------------------------------------------- */
#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 */ 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) #if defined(__cplusplus)
extern "C" { extern "C" {
#endif #endif
@ -68,18 +150,31 @@ static HIO_INLINE hio_t* hio_svc_fcgic_gethio(hio_svc_fcgic_t* svc) { return hio
#endif #endif
HIO_EXPORT hio_svc_fcgic_sess_t* hio_svc_fcgic_tie ( HIO_EXPORT hio_svc_fcgic_sess_t* hio_svc_fcgic_tie (
hio_svc_fcgic_t* fcgic, hio_svc_fcgic_t* fcgic,
const hio_skad_t* fcgis_addr const hio_skad_t* fcgis_addr,
hio_svc_fcgic_on_read_t on_read
); );
HIO_EXPORT void hio_svc_fcgic_untie ( HIO_EXPORT void hio_svc_fcgic_untie (
hio_svc_fcgic_sess_t* sess hio_svc_fcgic_sess_t* sess
); );
HIO_EXPORT int hio_svc_fcgic_write ( HIO_EXPORT int hio_svc_fcgic_beginrequest (
hio_svc_fcgic_sess_t* sess, hio_svc_fcgic_sess_t* sess
const void* data, );
hio_iolen_t len
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) #if defined(__cplusplus)

View File

@ -175,6 +175,7 @@ struct hio_htre_t
{ {
hio_http_method_t type; hio_http_method_t type;
const hio_bch_t* name; const hio_bch_t* name;
hio_oow_t len;
} method; } method;
hio_bcs_t path; hio_bcs_t path;
hio_bcs_t param; 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_getqmethodtype(re) ((re)->u.q.method.type)
#define hio_htre_getqmethodname(re) ((re)->u.q.method.name) #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_getqpath(re) ((re)->u.q.path.ptr)
#define hio_htre_getqpathlen(re) ((re)->u.q.path.len) #define hio_htre_getqpathlen(re) ((re)->u.q.path.len)

View File

@ -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.type = hio_bchars_to_http_method(tmp.ptr, tmp.len);
htrd->re.u.q.method.name = tmp.ptr; 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) else if ((htrd->option & HIO_HTRD_RESPONSE) && hio_comp_bchars_bcstr(tmp.ptr, tmp.len, "HTTP", 1) == 0)
{ {

View File

@ -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_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_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 struct fcgi_t
{ {
HIO_SVC_HTTS_RSRC_HEADER; HIO_SVC_HTTS_RSRC_HEADER;
@ -150,7 +79,6 @@ static int begin_request ()
#endif #endif
static void fcgi_halt_participating_devices (fcgi_t* fcgi) static void fcgi_halt_participating_devices (fcgi_t* fcgi)
{ {
HIO_ASSERT (fcgi->client->htts->hio, fcgi->client != HIO_NULL); 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)) 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) 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); 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; return 0;
} }
static int fcgi_send_final_status_to_client (fcgi_t* fcgi, int status_code, int force_close) 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; 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) 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_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_dev_sck_t* sck = htrdxtn->sck;
hio_svc_htts_cli_t* cli = hio_dev_sck_getxtn(sck); hio_svc_htts_cli_t* cli = hio_dev_sck_getxtn(sck);
fcgi_t* fcgi = (fcgi_t*)cli->rsrc; fcgi_t* fcgi = (fcgi_t*)cli->rsrc;
/*printf (">> CLIENT REQUEST COMPLETED\n");*/ /* indicate end of STDIN */
if (hio_svc_fcgic_writestdin(fcgi->peer, HIO_NULL, 0) <= -1) return -1;
#if 0 // TODO: send abort???
/* indicate EOF to the client peer */
if (fcgi_write_to_peer(fcgi, HIO_NULL, 0) <= -1) return -1;
#endif
fcgi_mark_over (fcgi, FCGI_OVER_READ_FROM_CLIENT); fcgi_mark_over (fcgi, FCGI_OVER_READ_FROM_CLIENT);
return 0; 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); hio_svc_htts_cli_t* cli = hio_dev_sck_getxtn(sck);
fcgi_t* fcgi = (fcgi_t*)cli->rsrc; 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); 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 = 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); hio_svc_htts_cli_t* cli = hio_dev_sck_getxtn(sck);
fcgi_t* fcgi = (fcgi_t*)cli->rsrc; fcgi_t* fcgi = (fcgi_t*)cli->rsrc;
fcgi->client_disconnected = 1; fcgi->client_disconnected = 1;
printf ("client disconnected ............................\n");
fcgi->client_org_on_disconnect (sck); 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 (!(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 */ /* indicate eof to the write side */
if (fcgi_write_to_peer(fcgi, HIO_NULL, 0) <= -1) goto oops; if (hio_svc_fcgic_writestdin(fcgi->peer, HIO_NULL, 0) <= -1) goto oops;
#endif
fcgi_mark_over (fcgi, FCGI_OVER_READ_FROM_CLIENT); fcgi_mark_over (fcgi, FCGI_OVER_READ_FROM_CLIENT);
} }
} }
@ -441,6 +365,12 @@ oops:
return 0; 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) static void fcgi_on_kill (fcgi_t* fcgi)
{ {
hio_t* hio = fcgi->htts->hio; hio_t* hio = fcgi->htts->hio;
@ -456,6 +386,7 @@ static void fcgi_on_kill (fcgi_t* fcgi)
hio_dev_pro_kill (fcgi->peer); hio_dev_pro_kill (fcgi->peer);
fcgi->peer = HIO_NULL; fcgi->peer = HIO_NULL;
} }
#endif
if (fcgi->client_org_on_read) 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); 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) 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; 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 */ /* ensure that you call this function before any contents is received */
HIO_ASSERT (hio, hio_htre_getcontentlen(req) == 0); 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"); hio_seterrbfmt (hio, HIO_ENOCAPA, "fcgi client service not enabled");
goto oops; 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_ASSERT (hio, cli->rsrc == HIO_NULL);
HIO_SVC_HTTS_RSRC_ATTACH ((hio_svc_htts_rsrc_t*)fcgi, cli->rsrc); /* cli->rsrc = fcgi */ HIO_SVC_HTTS_RSRC_ATTACH ((hio_svc_htts_rsrc_t*)fcgi, cli->rsrc); /* cli->rsrc = fcgi */
#if 0 // TODO /* create a session in in the fcgi client service */
fcgi->peer = hio_dev_pro_make(hio, HIO_SIZEOF(*peer_xtn), &mi); fcgi->peer = hio_svc_fcgic_tie(htts->fcgic, fcgis_addr, fcgi_peer_on_read);
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 */);
if (HIO_UNLIKELY(!fcgi->peer)) goto oops; if (HIO_UNLIKELY(!fcgi->peer)) goto oops;
hio_svc_fcgic_write (fcgi->peer, "hello", 5); /* send FCGI_BEGIN_REQUEST */
#endif if (hio_svc_fcgic_beginrequest(fcgi->peer) <= -1) goto oops;
/* write FCGI_PARAM */
#if 0 // TODO if (write_params(fcgi, csck, req) <= -1) goto oops;
fcgi->peer_htrd = hio_htrd_open(hio, HIO_SIZEOF(*peer)); if (hio_svc_fcgic_writeparam(fcgi->peer, HIO_NULL, 0, HIO_NULL, 0) <= -1) goto oops; /* end of params */
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
#if !defined(FCGI_ALLOW_UNLIMITED_REQ_CONTENT_LENGTH) #if !defined(FCGI_ALLOW_UNLIMITED_REQ_CONTENT_LENGTH)
if (fcgi->req_content_length_unlimited) 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) 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? */ /* CAN I LET the cgi SCRIPT handle this? */
if (!(options & HIO_SVC_HTTS_CGI_NO_100_CONTINUE) && if (!(options & HIO_SVC_HTTS_CGI_NO_100_CONTINUE) &&
hio_comp_http_version_numbers(&req->version, 1, 1) >= 0 && 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 else
{ {
/* no content to be uploaded from the client */ /* no content to be uploaded from the client */
/* indicate EOF to the peer and disable input wathching from the client */ /* indicate end of stdin to the peer and disable input wathching from the client */
if (fcgi_write_to_peer(fcgi, HIO_NULL, 0) <= -1) goto oops; 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); fcgi_mark_over (fcgi, FCGI_OVER_READ_FROM_CLIENT | FCGI_OVER_WRITE_TO_PEER);
} }
#if defined(FCGI_ALLOW_UNLIMITED_REQ_CONTENT_LENGTH) #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); HIO_DEBUG2 (hio, "HTTS(%p) - FAILURE in dofcgi - socket(%p)\n", htts, csck);
if (fcgi) fcgi_halt_participating_devices (fcgi); if (fcgi) fcgi_halt_participating_devices (fcgi);
return -1; return -1;
} }

View File

@ -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) 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); 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"); hio_seterrbfmt (hio_dev_sck_gethio(dev), HIO_EINVAL, "invalid multicast address family");
return -1; return -1;
} }