added some fcgi support code
This commit is contained in:
parent
d2efac3ce2
commit
529363913f
38
bin/webs.c
38
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)
|
||||
{
|
||||
|
191
lib/fcgi-cli.c
191
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;
|
||||
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
107
lib/hio-fcgi.h
107
lib/hio-fcgi.h
@ -27,6 +27,81 @@
|
||||
|
||||
#include <hio.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 */
|
||||
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
{
|
||||
|
197
lib/http-fcgi.c
197
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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user