diff --git a/lib/dhcp-svr.c b/lib/dhcp-svr.c index 4ae1352..8417e67 100644 --- a/lib/dhcp-svr.c +++ b/lib/dhcp-svr.c @@ -30,6 +30,7 @@ struct hio_svc_dhcs_t { HIO_SVC_HEADER; + int stopping; hio_dev_sck_t* sck; }; @@ -122,6 +123,7 @@ hio_svc_dhcs_t* hio_svc_dhcs_start (hio_t* hio, const hio_skad_t* local_binds, h if (HIO_UNLIKELY(!dhcs)) goto oops; dhcs->hio = hio; + dhcs->svc_stop = (hio_svc_stop_t)hio_svc_dhcs_stop; for (i = 0; i < local_nbinds; i++) { @@ -151,3 +153,16 @@ oops: } return HIO_NULL; } + +void hio_svc_dhcs_stop (hio_svc_dhcs_t* dhcs) +{ + hio_t* hio = dhcs->hio; + + HIO_DEBUG1 (hio, "FCGIC - STOPPING SERVICE %p\n", dhcs); + dhcs->stopping = 1; + + HIO_SVCL_UNLINK_SVC (dhcs); + hio_freemem (hio, dhcs); + + HIO_DEBUG1 (hio, "FCGIC - STOPPED SERVICE %p\n", dhcs); +} diff --git a/lib/hio-http.h b/lib/hio-http.h index 9572e06..92dffb0 100644 --- a/lib/hio-http.h +++ b/lib/hio-http.h @@ -498,6 +498,36 @@ HIO_EXPORT int hio_svc_htts_task_buildfinalres ( int force_close ); +HIO_EXPORT int hio_svc_htts_task_startreshdr ( + hio_svc_htts_task_t* task, + int status_code, + const hio_bch_t* status_desc, + int chunked +); + +HIO_EXPORT int hio_svc_htts_task_addreshdrs ( + hio_svc_htts_task_t* task, + const hio_bch_t* key, + const hio_htre_hdrval_t* value +); + +HIO_EXPORT int hio_svc_htts_task_addreshdr ( + hio_svc_htts_task_t* task, + const hio_bch_t* key, + const hio_bch_t* value +); + +HIO_EXPORT int hio_svc_htts_task_addreshdrfmt ( + hio_svc_htts_task_t* task, + const hio_bch_t* key, + const hio_bch_t* vfmt, + ... +); + +HIO_EXPORT int hio_svc_htts_task_endreshdr ( + hio_svc_htts_task_t* task +); + HIO_EXPORT void hio_svc_htts_fmtgmtime ( hio_svc_htts_t* htts, const hio_ntime_t* nt, diff --git a/lib/http-cgi.c b/lib/http-cgi.c index d1ae985..09b8645 100644 --- a/lib/http-cgi.c +++ b/lib/http-cgi.c @@ -474,31 +474,7 @@ oops: static int peer_capture_response_header (hio_htre_t* req, const hio_bch_t* key, const hio_htre_hdrval_t* val, void* ctx) { - hio_svc_htts_cli_t* cli = (hio_svc_htts_cli_t*)ctx; - - /* capture a header except Status, Connection, Transfer-Encoding, and Server */ - if (hio_comp_bcstr(key, "Status", 1) != 0 && - hio_comp_bcstr(key, "Connection", 1) != 0 && - hio_comp_bcstr(key, "Transfer-Encoding", 1) != 0 && - hio_comp_bcstr(key, "Server", 1) != 0 && - hio_comp_bcstr(key, "Date", 1) != 0) - { - do - { - if (hio_becs_cat(cli->sbuf, key) == (hio_oow_t)-1 || - hio_becs_cat(cli->sbuf, ": ") == (hio_oow_t)-1 || - hio_becs_cat(cli->sbuf, val->ptr) == (hio_oow_t)-1 || - hio_becs_cat(cli->sbuf, "\r\n") == (hio_oow_t)-1) - { - return -1; - } - - val = val->next; - } - while (val); - } - - return 0; + return hio_svc_htts_task_addreshdrs((cgi_t*)ctx, key, val); } static int peer_htrd_peek (hio_htrd_t* htrd, hio_htre_t* req) @@ -506,42 +482,24 @@ static int peer_htrd_peek (hio_htrd_t* htrd, hio_htre_t* req) cgi_peer_xtn_t* peer = hio_htrd_getxtn(htrd); cgi_t* cgi = peer->cgi; hio_svc_htts_cli_t* cli = cgi->task_client; - hio_bch_t dtbuf[64]; int status_code = HIO_HTTP_STATUS_OK; const hio_bch_t* status_desc = HIO_NULL; + int chunked; - if (req->attr.content_length) + if (HIO_UNLIKELY(!cli)) { -// TOOD: remove content_length if content_length is negative or not numeric. - cgi->res_mode_to_cli = CGI_RES_MODE_LENGTH; + /* client disconnected or not connectd */ + return 0; } + if (req->attr.content_length) cgi->res_mode_to_cli = CGI_RES_MODE_LENGTH; if (req->attr.status) hio_parse_http_status_header_value(req->attr.status, &status_code, &status_desc); - hio_svc_htts_fmtgmtime (cli->htts, HIO_NULL, dtbuf, HIO_COUNTOF(dtbuf)); + chunked = cgi->task_keep_client_alive && !req->attr.content_length; - if (hio_becs_fmt(cli->sbuf, "HTTP/%d.%d ", cgi->task_req_version.major, cgi->task_req_version.minor) == (hio_oow_t)-1) return -1; - if (hio_becs_fcat(cli->sbuf, "%d %hs\r\n", status_code, (status_desc? status_desc: hio_http_status_to_bcstr(status_code))) == (hio_oow_t)-1) return -1; - if (hio_becs_fcat(cli->sbuf, "Server: %hs\r\nDate: %hs\r\n", cli->htts->server_name, dtbuf) == (hio_oow_t)-1) return -1; - - if (hio_htre_walkheaders(req, peer_capture_response_header, cli) <= -1) return -1; - - switch (cgi->res_mode_to_cli) - { - case CGI_RES_MODE_CHUNKED: - if (hio_becs_cat(cli->sbuf, "Transfer-Encoding: chunked\r\n") == (hio_oow_t)-1) return -1; - /*if (hio_becs_cat(cli->sbuf, "Connection: keep-alive\r\n") == (hio_oow_t)-1) return -1;*/ - break; - - case CGI_RES_MODE_CLOSE: - if (hio_becs_cat(cli->sbuf, "Connection: close\r\n") == (hio_oow_t)-1) return -1; - break; - - case CGI_RES_MODE_LENGTH: - if (hio_becs_cat(cli->sbuf, (cgi->task_keep_client_alive? "Connection: keep-alive\r\n": "Connection: close\r\n")) == (hio_oow_t)-1) return -1; - } - - if (hio_becs_cat(cli->sbuf, "\r\n") == (hio_oow_t)-1) return -1; + if (hio_svc_htts_task_startreshdr(cgi, status_code, status_desc, chunked) <= -1 || + hio_htre_walkheaders(req, peer_capture_response_header, cgi) <= -1 || + hio_svc_htts_task_endreshdr(cgi) <= -1) return -1; cgi->task_status_code = status_code; return cgi_write_to_client(cgi, HIO_BECS_PTR(cli->sbuf), HIO_BECS_LEN(cli->sbuf)); diff --git a/lib/http-fcgi.c b/lib/http-fcgi.c index 44326ff..e32faa8 100644 --- a/lib/http-fcgi.c +++ b/lib/http-fcgi.c @@ -374,75 +374,33 @@ oops: static int peer_capture_response_header (hio_htre_t* req, const hio_bch_t* key, const hio_htre_hdrval_t* val, void* ctx) { - hio_svc_htts_cli_t* cli = (hio_svc_htts_cli_t*)ctx; - - /* capture a header except Status, Connection, Transfer-Encoding, and Server */ - if (hio_comp_bcstr(key, "Status", 1) != 0 && - hio_comp_bcstr(key, "Connection", 1) != 0 && - hio_comp_bcstr(key, "Transfer-Encoding", 1) != 0 && - hio_comp_bcstr(key, "Server", 1) != 0 && - hio_comp_bcstr(key, "Date", 1) != 0) - { - do - { - if (hio_becs_cat(cli->sbuf, key) == (hio_oow_t)-1 || - hio_becs_cat(cli->sbuf, ": ") == (hio_oow_t)-1 || - hio_becs_cat(cli->sbuf, val->ptr) == (hio_oow_t)-1 || - hio_becs_cat(cli->sbuf, "\r\n") == (hio_oow_t)-1) - { - return -1; - } - - val = val->next; - } - while (val); - } - - return 0; + return hio_svc_htts_task_addreshdrs((fcgi_t*)ctx, key, val); } - static int peer_htrd_peek (hio_htrd_t* htrd, hio_htre_t* req) { fcgi_peer_xtn_t* peer = hio_htrd_getxtn(htrd); fcgi_t* fcgi = peer->fcgi; hio_svc_htts_cli_t* cli = fcgi->task_client; - hio_bch_t dtbuf[64]; int status_code = HIO_HTTP_STATUS_OK; const hio_bch_t* status_desc = HIO_NULL; + int chunked; - if (req->attr.content_length) + if (HIO_UNLIKELY(!cli)) { -// TOOD: remove content_length if content_length is negative or not numeric. - fcgi->res_mode_to_cli = FCGI_RES_MODE_LENGTH; + /* client disconnected or not connectd */ + return 0; } + // TOOD: remove content_length if content_length is negative or not numeric. + if (req->attr.content_length) fcgi->res_mode_to_cli = FCGI_RES_MODE_LENGTH; if (req->attr.status) hio_parse_http_status_header_value(req->attr.status, &status_code, &status_desc); - hio_svc_htts_fmtgmtime (cli->htts, HIO_NULL, dtbuf, HIO_COUNTOF(dtbuf)); + chunked = fcgi->task_keep_client_alive && !req->attr.content_length; - if (hio_becs_fmt(cli->sbuf, "HTTP/%d.%d ", fcgi->task_req_version.major, fcgi->task_req_version.minor) == (hio_oow_t)-1) return -1; - if (hio_becs_fcat(cli->sbuf, "%d %hs\r\n", status_code, (status_desc? status_desc: hio_http_status_to_bcstr(status_code))) == (hio_oow_t)-1) return -1; - if (hio_becs_fcat(cli->sbuf, "Server: %hs\r\nDate: %hs\r\n", cli->htts->server_name, dtbuf) == (hio_oow_t)-1) return -1; - - if (hio_htre_walkheaders(req, peer_capture_response_header, cli) <= -1) return -1; - - switch (fcgi->res_mode_to_cli) - { - case FCGI_RES_MODE_CHUNKED: - if (hio_becs_cat(cli->sbuf, "Transfer-Encoding: chunked\r\n") == (hio_oow_t)-1) return -1; - /*if (hio_becs_cat(cli->sbuf, "Connection: keep-alive\r\n") == (hio_oow_t)-1) return -1;*/ - break; - - case FCGI_RES_MODE_CLOSE: - if (hio_becs_cat(cli->sbuf, "Connection: close\r\n") == (hio_oow_t)-1) return -1; - break; - - case FCGI_RES_MODE_LENGTH: - if (hio_becs_cat(cli->sbuf, (fcgi->task_keep_client_alive? "Connection: keep-alive\r\n": "Connection: close\r\n")) == (hio_oow_t)-1) return -1; - } - - if (hio_becs_cat(cli->sbuf, "\r\n") == (hio_oow_t)-1) return -1; + if (hio_svc_htts_task_startreshdr(fcgi, status_code, status_desc, chunked) <= -1 || + hio_htre_walkheaders(req, peer_capture_response_header, fcgi) <= -1 || + hio_svc_htts_task_endreshdr(fcgi) <= -1) return -1; fcgi->task_status_code = status_code; return fcgi_write_to_client(fcgi, HIO_BECS_PTR(cli->sbuf), HIO_BECS_LEN(cli->sbuf)); diff --git a/lib/http-file.c b/lib/http-file.c index d949c87..026a8db 100644 --- a/lib/http-file.c +++ b/lib/http-file.c @@ -457,6 +457,7 @@ static hio_htrd_recbs_t file_client_htrd_recbs = static int file_send_header_to_client (file_t* file, int status_code, int force_close, const hio_bch_t* mime_type) { +#if 0 hio_svc_htts_cli_t* cli = file->task_client; hio_bch_t dtbuf[64]; hio_foff_t content_length; @@ -494,6 +495,43 @@ static int file_send_header_to_client (file_t* file, int status_code, int force_ file->task_status_code = status_code; return file_write_to_client(file, HIO_BECS_PTR(cli->sbuf), HIO_BECS_LEN(cli->sbuf)); +#else + hio_svc_htts_cli_t* cli = file->task_client; + hio_foff_t content_length; + + if (HIO_UNLIKELY(!cli)) + { + /* client disconnected or not connectd */ + return 0; + } + + content_length = file->end_offset - file->start_offset + 1; + if (status_code == HIO_HTTP_STATUS_OK && file->total_size != content_length) status_code = HIO_HTTP_STATUS_PARTIAL_CONTENT; + + if (hio_svc_htts_task_startreshdr(file, status_code, HIO_NULL, 0) <= -1) return -1; + + + if (mime_type && mime_type[0] != '\0' && hio_svc_htts_task_addreshdr(file, "Content-Type", mime_type) <= -1) return -1; + + if ((file->task_req_method == HIO_HTTP_GET || file->task_req_method == HIO_HTTP_HEAD) && + hio_svc_htts_task_addreshdr(file, "ETag", file->peer_etag) <= -1) return -1; + + if (status_code == HIO_HTTP_STATUS_PARTIAL_CONTENT && + hio_svc_htts_task_addreshdrfmt(file, "Content-Ranges", "bytes %ju-%ju/%ju", (hio_uintmax_t)file->start_offset, (hio_uintmax_t)file->end_offset, (hio_uintmax_t)file->total_size) <= -1) return -1; + +/* ----- */ +// TODO: Allow-Contents +// Allow-Headers... support custom headers... + if (hio_svc_htts_task_addreshdr(file, "Access-Control-Allow-Origin", "*") <= -1) return -1; +/* ----- */ + + if (hio_svc_htts_task_addreshdrfmt(file, "Content-Length", "%ju", (hio_uintmax_t)content_length) <= -1) return -1; + + if (hio_svc_htts_task_endreshdr(file) <= -1) return -1; + + file->task_status_code = status_code; + return file_write_to_client(file, HIO_BECS_PTR(cli->sbuf), HIO_BECS_LEN(cli->sbuf)); +#endif } static void send_contents_to_client_later (hio_t* hio, const hio_ntime_t* now, hio_tmrjob_t* tmrjob) diff --git a/lib/http-svr.c b/lib/http-svr.c index 5c9dc9c..cd6896d 100644 --- a/lib/http-svr.c +++ b/lib/http-svr.c @@ -25,6 +25,7 @@ #include "http-prv.h" #include #include +#include #define INVALID_LIDX HIO_TYPE_MAX(hio_oow_t) @@ -713,13 +714,12 @@ int hio_svc_htts_task_buildfinalres (hio_svc_htts_task_t* task, int status_code, hio_bch_t dtbuf[64]; hio_oow_t content_len; const hio_bch_t* status_msg; - int redir = 0; - if (!cli) + if (HIO_UNLIKELY(!cli)) { /* the client has probably been disconnected */ HIO_ASSERT (hio, task->task_csck == HIO_NULL); - return 0; + return 0; /* no data */ } status_msg = hio_http_status_to_bcstr(status_code); @@ -761,6 +761,87 @@ int hio_svc_htts_task_buildfinalres (hio_svc_htts_task_t* task, int status_code, // if (hio_dev_sck_write(task->task_csck, HIO_BECS_PTR(cli->sbuf), HIO_BECS_LEN(cli->sbuf), HIO_NULL, HIO_NULL) <= -1) return -1; // if (force_close && hio_dev_sck_write(task->task_csck, HIO_NULL, 0, HIO_NULL, HIO_NULL) <= -1) return -1; + return 1; +} + +int hio_svc_htts_task_startreshdr (hio_svc_htts_task_t* task, int status_code, const hio_bch_t* status_desc, int chunked) +{ + hio_svc_htts_cli_t* cli = task->task_client; + hio_bch_t dtbuf[64]; + + HIO_ASSERT (task->htts->hio, cli != HIO_NULL); + + hio_svc_htts_fmtgmtime (cli->htts, HIO_NULL, dtbuf, HIO_COUNTOF(dtbuf)); + + if (hio_becs_fmt(cli->sbuf, "HTTP/%d.%d ", task->task_req_version.major, task->task_req_version.minor) == (hio_oow_t)-1) return -1; + if (hio_becs_fcat(cli->sbuf, "%d %hs\r\n", status_code, (status_desc? status_desc: hio_http_status_to_bcstr(status_code))) == (hio_oow_t)-1) return -1; + if (hio_becs_fcat(cli->sbuf, "Server: %hs\r\nDate: %hs\r\n", cli->htts->server_name, dtbuf) == (hio_oow_t)-1) return -1; + + if (chunked && hio_becs_cat(cli->sbuf, "Transfer-Encoding: chunked\r\n") == (hio_oow_t)-1) return -1; + if (hio_becs_cat(cli->sbuf, (task->task_keep_client_alive? "Connection: keep-alive\r\n": "Connection: close\r\n")) == (hio_oow_t)-1) return -1; + + return 0; +} + +static int is_res_header_acceptable (const hio_bch_t* key) +{ + return hio_comp_bcstr(key, "Status", 1) != 0 && + hio_comp_bcstr(key, "Connection", 1) != 0 && + hio_comp_bcstr(key, "Transfer-Encoding", 1) != 0 && + hio_comp_bcstr(key, "Server", 1) != 0 && + hio_comp_bcstr(key, "Date", 1) != 0; +} + +int hio_svc_htts_task_addreshdrs (hio_svc_htts_task_t* task, const hio_bch_t* key, const hio_htre_hdrval_t* value) +{ + hio_svc_htts_cli_t* cli = task->task_client; + HIO_ASSERT (task->htts->hio, cli != HIO_NULL); + + if (!is_res_header_acceptable(key)) return 0; /* ignore it*/ + while (value) + { + if (hio_becs_fcat(cli->sbuf, "%hs: %hs\r\n", key, value->ptr) == (hio_oow_t)-1) return -1; + value = value->next; + } + + return 0; +} + +int hio_svc_htts_task_addreshdr (hio_svc_htts_task_t* task, const hio_bch_t* key, const hio_bch_t* value) +{ + hio_svc_htts_cli_t* cli = task->task_client; + HIO_ASSERT (task->htts->hio, cli != HIO_NULL); + + if (!is_res_header_acceptable(key)) return 0; /* just ignore it*/ + if (hio_becs_fcat(cli->sbuf, "%hs: %hs\r\n", key, value) == (hio_oow_t)-1) return -1; + return 0; +} + +int hio_svc_htts_task_addreshdrfmt (hio_svc_htts_task_t* task, const hio_bch_t* key, const hio_bch_t* vfmt, ...) +{ + hio_svc_htts_cli_t* cli = task->task_client; + va_list ap; + HIO_ASSERT (task->htts->hio, cli != HIO_NULL); + + if (!is_res_header_acceptable(key)) return 0; /* just ignore it*/ + if (hio_becs_fcat(cli->sbuf, "%hs: ", key) == (hio_oow_t)-1) return -1; + va_start (ap, vfmt); + if (hio_becs_vfcat(cli->sbuf, vfmt, ap) == (hio_oow_t)-1) + { + va_end (ap); + return -1; + } + va_end (ap); + if (hio_becs_cat(cli->sbuf, "\r\n") == (hio_oow_t)-1) return -1; + return 0; +} + +int hio_svc_htts_task_endreshdr (hio_svc_htts_task_t* task) +{ + hio_svc_htts_cli_t* cli = task->task_client; + + HIO_ASSERT (task->htts->hio, cli != HIO_NULL); + if (hio_becs_cat(cli->sbuf, "\r\n") == (hio_oow_t)-1) return -1; return 0; } diff --git a/lib/http-thr.c b/lib/http-thr.c index 0c2e631..0804739 100644 --- a/lib/http-thr.c +++ b/lib/http-thr.c @@ -421,37 +421,14 @@ oops: return 0; } -static int thr_peer_capture_response_header (hio_htre_t* req, const hio_bch_t* key, const hio_htre_hdrval_t* val, void* ctx) +static int peer_capture_response_header (hio_htre_t* req, const hio_bch_t* key, const hio_htre_hdrval_t* val, void* ctx) { - hio_svc_htts_cli_t* cli = (hio_svc_htts_cli_t*)ctx; - - /* capture a header except Status, Connection, Transfer-Encoding, and Server */ - if (hio_comp_bcstr(key, "Status", 1) != 0 && - hio_comp_bcstr(key, "Connection", 1) != 0 && - hio_comp_bcstr(key, "Transfer-Encoding", 1) != 0 && - hio_comp_bcstr(key, "Server", 1) != 0 && - hio_comp_bcstr(key, "Date", 1) != 0) - { - do - { - if (hio_becs_cat(cli->sbuf, key) == (hio_oow_t)-1 || - hio_becs_cat(cli->sbuf, ": ") == (hio_oow_t)-1 || - hio_becs_cat(cli->sbuf, val->ptr) == (hio_oow_t)-1 || - hio_becs_cat(cli->sbuf, "\r\n") == (hio_oow_t)-1) - { - return -1; - } - - val = val->next; - } - while (val); - } - - return 0; + return hio_svc_htts_task_addreshdrs((thr_task_t*)ctx, key, val); } static int thr_peer_htrd_peek (hio_htrd_t* htrd, hio_htre_t* req) { +#if 0 thr_peer_xtn_t* peer_xtn = hio_htrd_getxtn(htrd); thr_task_t* thr = peer_xtn->task; hio_svc_htts_cli_t* cli = thr->task_client; @@ -495,6 +472,33 @@ static int thr_peer_htrd_peek (hio_htrd_t* htrd, hio_htre_t* req) thr->task_status_code = status_code; return thr_write_to_client(thr, HIO_BECS_PTR(cli->sbuf), HIO_BECS_LEN(cli->sbuf)); +#else + thr_peer_xtn_t* peer = hio_htrd_getxtn(htrd); + thr_task_t* thr = peer->task; + hio_svc_htts_cli_t* cli = thr->task_client; + int status_code = HIO_HTTP_STATUS_OK; + const hio_bch_t* status_desc = HIO_NULL; + int chunked; + + if (HIO_UNLIKELY(!cli)) + { + /* client disconnected or not connectd */ + return 0; + } + + // TOOD: remove content_length if content_length is negative or not numeric. + if (req->attr.content_length) thr->res_mode_to_cli = THR_RES_MODE_LENGTH; + if (req->attr.status) hio_parse_http_status_header_value(req->attr.status, &status_code, &status_desc); + + chunked = thr->task_keep_client_alive && !req->attr.content_length; + + if (hio_svc_htts_task_startreshdr(thr, status_code, status_desc, chunked) <= -1 || + hio_htre_walkheaders(req, peer_capture_response_header, thr) <= -1 || + hio_svc_htts_task_endreshdr(thr) <= -1) return -1; + + thr->task_status_code = status_code; + return thr_write_to_client(thr, HIO_BECS_PTR(cli->sbuf), HIO_BECS_LEN(cli->sbuf)); +#endif } static int thr_peer_htrd_poke (hio_htrd_t* htrd, hio_htre_t* req)