simplified setup_for_content_len() in some files

This commit is contained in:
hyung-hwan 2023-03-27 01:42:39 +09:00
parent e5d0946c5f
commit bb99ebb83d
4 changed files with 123 additions and 177 deletions

View File

@ -898,7 +898,14 @@ static void unbind_task_from_peer (cgi_t* cgi, int rcdown)
static int setup_for_content_length(cgi_t* cgi, hio_htre_t* req) static int setup_for_content_length(cgi_t* cgi, hio_htre_t* req)
{ {
int have_content;
#if defined(CGI_ALLOW_UNLIMITED_REQ_CONTENT_LENGTH) #if defined(CGI_ALLOW_UNLIMITED_REQ_CONTENT_LENGTH)
have_content = cgi->task_req_conlen > 0 || cgi->task_req_conlen_unlimited;
#else
have_content = cgi->task_req_conlen > 0;
#endif
if (cgi->task_req_conlen_unlimited) if (cgi->task_req_conlen_unlimited)
{ {
/* change the callbacks to subscribe to contents to be uploaded */ /* change the callbacks to subscribe to contents to be uploaded */
@ -909,25 +916,11 @@ static int setup_for_content_length(cgi_t* cgi, hio_htre_t* req)
} }
else else
{ {
#endif /* no content to be uploaded from the client */
if (cgi->task_req_conlen > 0) /* indicate EOF to the peer and disable input wathching from the client */
{ if (cgi_write_to_peer(cgi, HIO_NULL, 0) <= -1) return -1;
/* change the callbacks to subscribe to contents to be uploaded */ cgi_mark_over (cgi, CGI_OVER_READ_FROM_CLIENT | CGI_OVER_WRITE_TO_PEER);
cgi->client_htrd_org_recbs = *hio_htrd_getrecbs(cgi->task_client->htrd);
cgi_client_htrd_recbs.peek = cgi->client_htrd_org_recbs.peek;
hio_htrd_setrecbs (cgi->task_client->htrd, &cgi_client_htrd_recbs);
cgi->client_htrd_recbs_changed = 1;
}
else
{
/* no content to be uploaded from the client */
/* indicate EOF to the peer and disable input wathching from the client */
if (cgi_write_to_peer(cgi, HIO_NULL, 0) <= -1) return -1;
cgi_mark_over (cgi, CGI_OVER_READ_FROM_CLIENT | CGI_OVER_WRITE_TO_PEER);
}
#if defined(CGI_ALLOW_UNLIMITED_REQ_CONTENT_LENGTH)
} }
#endif
return 0; return 0;
} }

View File

@ -718,8 +718,15 @@ static void unbind_task_from_peer (fcgi_t* fcgi, int rcdown)
static int setup_for_content_length(fcgi_t* fcgi, hio_htre_t* req) static int setup_for_content_length(fcgi_t* fcgi, hio_htre_t* req)
{ {
int have_content;
#if defined(FCGI_ALLOW_UNLIMITED_REQ_CONTENT_LENGTH) #if defined(FCGI_ALLOW_UNLIMITED_REQ_CONTENT_LENGTH)
if (fcgi->task_req_conlen_unlimited) have_content = fcgi->task_req_conlen > 0 || fcgi->task_req_conlen_unlimited;
#else
have_content = fcgi->task_req_conlen > 0;
#endif
if (have_content)
{ {
/* change the callbacks to subscribe to contents to be uploaded */ /* change the callbacks to subscribe to contents to be uploaded */
fcgi->client_htrd_org_recbs = *hio_htrd_getrecbs(fcgi->task_client->htrd); fcgi->client_htrd_org_recbs = *hio_htrd_getrecbs(fcgi->task_client->htrd);
@ -729,25 +736,11 @@ static int setup_for_content_length(fcgi_t* fcgi, hio_htre_t* req)
} }
else else
{ {
#endif /* no content to be uploaded from the client */
if (fcgi->task_req_conlen > 0) /* indicate end of stdin to the peer and disable input wathching from the client */
{ if (fcgi_write_stdin_to_peer(fcgi, HIO_NULL, 0) <= -1) return -1;
/* change the callbacks to subscribe to contents to be uploaded */ fcgi_mark_over (fcgi, FCGI_OVER_READ_FROM_CLIENT | FCGI_OVER_WRITE_TO_PEER);
fcgi->client_htrd_org_recbs = *hio_htrd_getrecbs(fcgi->task_client->htrd);
fcgi_client_htrd_recbs.peek = fcgi->client_htrd_org_recbs.peek;
hio_htrd_setrecbs (fcgi->task_client->htrd, &fcgi_client_htrd_recbs);
fcgi->client_htrd_recbs_changed = 1;
}
else
{
/* no content to be uploaded from the client */
/* indicate end of stdin to the peer and disable input wathching from the client */
if (fcgi_write_stdin_to_peer(fcgi, HIO_NULL, 0) <= -1) return -1;
fcgi_mark_over (fcgi, FCGI_OVER_READ_FROM_CLIENT | FCGI_OVER_WRITE_TO_PEER);
}
#if defined(FCGI_ALLOW_UNLIMITED_REQ_CONTENT_LENGTH)
} }
#endif
return 0; return 0;
} }

View File

@ -830,8 +830,15 @@ static void unbind_task_from_peer (file_t* file, int rcdown)
static int setup_for_content_length(file_t* file, hio_htre_t* req) static int setup_for_content_length(file_t* file, hio_htre_t* req)
{ {
int have_content;
#if defined(FILE_ALLOW_UNLIMITED_REQ_CONTENT_LENGTH) #if defined(FILE_ALLOW_UNLIMITED_REQ_CONTENT_LENGTH)
if (file->task_req_conlen_unlimited) have_content = file->task_req_conlen > 0 || file->task_req_conlen_unlimited;
#else
have_content = file->task_req_conlen > 0;
#endif
if (have_content)
{ {
/* change the callbacks to subscribe to contents to be uploaded */ /* change the callbacks to subscribe to contents to be uploaded */
file->client_htrd_org_recbs = *hio_htrd_getrecbs(file->task_client->htrd); file->client_htrd_org_recbs = *hio_htrd_getrecbs(file->task_client->htrd);
@ -841,31 +848,17 @@ static int setup_for_content_length(file_t* file, hio_htre_t* req)
} }
else else
{ {
#endif /* no content to be uploaded from the client */
if (file->task_req_conlen > 0) #if 0
{ /* indicate EOF to the peer and disable input wathching from the client */
/* change the callbacks to subscribe to contents to be uploaded */ if (file_write_to_peer(file, HIO_NULL, 0) <= -1) goto oops;
file->client_htrd_org_recbs = *hio_htrd_getrecbs(file->task_client->htrd); HIO_ASSERT (hio, file->over | FILE_OVER_WRITE_TO_PEER); /* must be set by the call to file_write_to_peer() above */
file_client_htrd_recbs.peek = file->client_htrd_org_recbs.peek; file_mark_over (file, FILE_OVER_READ_FROM_CLIENT);
hio_htrd_setrecbs (file->task_client->htrd, &file_client_htrd_recbs); #else
file->client_htrd_recbs_changed = 1; /* no peer is open yet. so simply set the mars forcibly instead of calling file_write_to_peer() with null data */
} file_mark_over (file, FILE_OVER_READ_FROM_CLIENT | FILE_OVER_WRITE_TO_PEER);
else #endif
{
/* no content to be uploaded from the client */
#if 0
/* indicate EOF to the peer and disable input wathching from the client */
if (file_write_to_peer(file, HIO_NULL, 0) <= -1) goto oops;
HIO_ASSERT (hio, file->over | FILE_OVER_WRITE_TO_PEER); /* must be set by the call to file_write_to_peer() above */
file_mark_over (file, FILE_OVER_READ_FROM_CLIENT);
#else
/* no peer is open yet. so simply set the mars forcibly instead of calling file_write_to_peer() with null data */
file_mark_over (file, FILE_OVER_READ_FROM_CLIENT | FILE_OVER_WRITE_TO_PEER);
#endif
}
#if defined(FILE_ALLOW_UNLIMITED_REQ_CONTENT_LENGTH)
} }
#endif
return 0; return 0;
} }

View File

@ -57,7 +57,7 @@ struct thr_func_start_t
}; };
typedef struct thr_func_start_t thr_func_start_t; typedef struct thr_func_start_t thr_func_start_t;
struct thr_task_t struct thr_t
{ {
HIO_SVC_HTTS_TASK_HEADER; HIO_SVC_HTTS_TASK_HEADER;
@ -82,15 +82,15 @@ struct thr_task_t
hio_htrd_recbs_t client_htrd_org_recbs; hio_htrd_recbs_t client_htrd_org_recbs;
}; };
typedef struct thr_task_t thr_task_t; typedef struct thr_t thr_t;
struct thr_peer_xtn_t struct thr_peer_xtn_t
{ {
thr_task_t* task; thr_t* task;
}; };
typedef struct thr_peer_xtn_t thr_peer_xtn_t; typedef struct thr_peer_xtn_t thr_peer_xtn_t;
static void thr_task_halt_participating_devices (thr_task_t* thr) static void thr_halt_participating_devices (thr_t* thr)
{ {
HIO_DEBUG4 (thr->htts->hio, "HTTS(%p) - Halting participating devices in thr task %p(csck=%p,peer=%p)\n", thr->htts, thr, thr->task_csck, thr->peer); HIO_DEBUG4 (thr->htts->hio, "HTTS(%p) - Halting participating devices in thr task %p(csck=%p,peer=%p)\n", thr->htts, thr, thr->task_csck, thr->peer);
@ -99,7 +99,7 @@ static void thr_task_halt_participating_devices (thr_task_t* thr)
if (thr->peer) hio_dev_thr_halt (thr->peer); if (thr->peer) hio_dev_thr_halt (thr->peer);
} }
static int thr_write_to_client (thr_task_t* thr, const void* data, hio_iolen_t dlen) static int thr_write_to_client (thr_t* thr, const void* data, hio_iolen_t dlen)
{ {
if (thr->task_csck) if (thr->task_csck)
{ {
@ -120,7 +120,7 @@ static int thr_write_to_client (thr_task_t* thr, const void* data, hio_iolen_t d
return 0; return 0;
} }
static int thr_writev_to_client (thr_task_t* thr, hio_iovec_t* iov, hio_iolen_t iovcnt) static int thr_writev_to_client (thr_t* thr, hio_iovec_t* iov, hio_iolen_t iovcnt)
{ {
if (thr->task_csck) if (thr->task_csck)
{ {
@ -141,12 +141,12 @@ static int thr_writev_to_client (thr_task_t* thr, hio_iovec_t* iov, hio_iolen_t
return 0; return 0;
} }
static HIO_INLINE int thr_send_final_status_to_client (thr_task_t* thr, int status_code, int force_close) static HIO_INLINE int thr_send_final_status_to_client (thr_t* thr, int status_code, int force_close)
{ {
return hio_svc_htts_task_sendfinalres(thr, status_code, HIO_NULL, HIO_NULL, force_close); return hio_svc_htts_task_sendfinalres(thr, status_code, HIO_NULL, HIO_NULL, force_close);
} }
static int thr_write_last_chunk_to_client (thr_task_t* thr) static int thr_write_last_chunk_to_client (thr_t* thr)
{ {
if (!thr->ever_attempted_to_write_to_client) if (!thr->ever_attempted_to_write_to_client)
{ {
@ -162,7 +162,7 @@ static int thr_write_last_chunk_to_client (thr_task_t* thr)
return 0; return 0;
} }
static int thr_write_to_peer (thr_task_t* thr, const void* data, hio_iolen_t dlen) static int thr_write_to_peer (thr_t* thr, const void* data, hio_iolen_t dlen)
{ {
if (thr->peer) if (thr->peer)
{ {
@ -182,7 +182,7 @@ static int thr_write_to_peer (thr_task_t* thr, const void* data, hio_iolen_t dle
return 0; return 0;
} }
static HIO_INLINE void thr_task_mark_over (thr_task_t* thr, int over_bits) static HIO_INLINE void thr_mark_over (thr_t* thr, int over_bits)
{ {
hio_svc_htts_t* htts = thr->htts; hio_svc_htts_t* htts = thr->htts;
hio_t* hio = htts->hio; hio_t* hio = htts->hio;
@ -226,10 +226,10 @@ static HIO_INLINE void thr_task_mark_over (thr_task_t* thr, int over_bits)
if (thr->task_keep_client_alive && !thr->client_eof_detected) if (thr->task_keep_client_alive && !thr->client_eof_detected)
{ {
/* how to arrange to delete this thr_task object and put the socket back to the normal waiting state??? */ /* how to arrange to delete this thr object and put the socket back to the normal waiting state??? */
HIO_ASSERT (thr->htts->hio, thr->task_client->task == (hio_svc_htts_task_t*)thr); HIO_ASSERT (thr->htts->hio, thr->task_client->task == (hio_svc_htts_task_t*)thr);
HIO_SVC_HTTS_TASK_UNREF (thr->task_client->task); HIO_SVC_HTTS_TASK_UNREF (thr->task_client->task);
/* IMPORTANT: thr_task must not be accessed from here down as it could have been destroyed */ /* IMPORTANT: thr must not be accessed from here down as it could have been destroyed */
} }
else else
{ {
@ -241,9 +241,9 @@ static HIO_INLINE void thr_task_mark_over (thr_task_t* thr, int over_bits)
} }
} }
static void thr_task_on_kill (hio_svc_htts_task_t* task) static void thr_on_kill (hio_svc_htts_task_t* task)
{ {
thr_task_t* thr = (thr_task_t*)task; thr_t* thr = (thr_t*)task;
hio_t* hio = thr->htts->hio; hio_t* hio = thr->htts->hio;
HIO_DEBUG5 (hio, "HTTS(%p) - thr(t=%p,c=%p[%d],p=%p) - killing the task\n", thr->htts, thr, thr->task_client, (thr->task_csck? thr->task_csck->hnd: -1), thr->peer); HIO_DEBUG5 (hio, "HTTS(%p) - thr(t=%p,c=%p[%d],p=%p) - killing the task\n", thr->htts, thr, thr->task_client, (thr->task_csck? thr->task_csck->hnd: -1), thr->peer);
@ -304,7 +304,7 @@ static void thr_peer_on_close (hio_dev_thr_t* peer, hio_dev_thr_sid_t sid)
{ {
hio_t* hio = peer->hio; hio_t* hio = peer->hio;
thr_peer_xtn_t* peer_xtn = (thr_peer_xtn_t*)hio_dev_thr_getxtn(peer); thr_peer_xtn_t* peer_xtn = (thr_peer_xtn_t*)hio_dev_thr_getxtn(peer);
thr_task_t* thr = peer_xtn->task; thr_t* thr = peer_xtn->task;
if (!thr) return; /* thr task already gone */ if (!thr) return; /* thr task already gone */
@ -335,14 +335,14 @@ static void thr_peer_on_close (hio_dev_thr_t* peer, hio_dev_thr_sid_t sid)
if (!(thr->over & THR_OVER_READ_FROM_PEER)) if (!(thr->over & THR_OVER_READ_FROM_PEER))
{ {
if (thr_write_last_chunk_to_client(thr) <= -1) if (thr_write_last_chunk_to_client(thr) <= -1)
thr_task_halt_participating_devices (thr); thr_halt_participating_devices (thr);
else else
thr_task_mark_over (thr, THR_OVER_READ_FROM_PEER); thr_mark_over (thr, THR_OVER_READ_FROM_PEER);
} }
break; break;
case HIO_DEV_THR_IN: case HIO_DEV_THR_IN:
thr_task_mark_over (thr, THR_OVER_WRITE_TO_PEER); thr_mark_over (thr, THR_OVER_WRITE_TO_PEER);
break; break;
default: default:
@ -356,7 +356,7 @@ static int thr_peer_on_read (hio_dev_thr_t* peer, const void* data, hio_iolen_t
{ {
hio_t* hio = peer->hio; hio_t* hio = peer->hio;
thr_peer_xtn_t* peer_xtn = (thr_peer_xtn_t*)hio_dev_thr_getxtn(peer); thr_peer_xtn_t* peer_xtn = (thr_peer_xtn_t*)hio_dev_thr_getxtn(peer);
thr_task_t* thr = peer_xtn->task; thr_t* thr = peer_xtn->task;
HIO_ASSERT (hio, thr != HIO_NULL); HIO_ASSERT (hio, thr != HIO_NULL);
@ -377,7 +377,7 @@ static int thr_peer_on_read (hio_dev_thr_t* peer, const void* data, hio_iolen_t
* it still has to read more but EOF is read. * it still has to read more but EOF is read.
* otherwise client_peer_htrd_poke() should have been called */ * otherwise client_peer_htrd_poke() should have been called */
n = thr_write_last_chunk_to_client(thr); n = thr_write_last_chunk_to_client(thr);
thr_task_mark_over (thr, THR_OVER_READ_FROM_PEER); thr_mark_over (thr, THR_OVER_READ_FROM_PEER);
if (n <= -1) goto oops; if (n <= -1) goto oops;
} }
} }
@ -411,19 +411,19 @@ static int thr_peer_on_read (hio_dev_thr_t* peer, const void* data, hio_iolen_t
return 0; return 0;
oops: oops:
thr_task_halt_participating_devices (thr); thr_halt_participating_devices (thr);
return 0; return 0;
} }
static int 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)
{ {
return hio_svc_htts_task_addreshdrs((thr_task_t*)ctx, key, val); return hio_svc_htts_task_addreshdrs((thr_t*)ctx, key, val);
} }
static int thr_peer_htrd_peek (hio_htrd_t* htrd, hio_htre_t* req) static int thr_peer_htrd_peek (hio_htrd_t* htrd, hio_htre_t* req)
{ {
thr_peer_xtn_t* peer = hio_htrd_getxtn(htrd); thr_peer_xtn_t* peer = hio_htrd_getxtn(htrd);
thr_task_t* thr = peer->task; thr_t* thr = peer->task;
hio_svc_htts_cli_t* cli = thr->task_client; hio_svc_htts_cli_t* cli = thr->task_client;
int status_code = HIO_HTTP_STATUS_OK; int status_code = HIO_HTTP_STATUS_OK;
const hio_bch_t* status_desc = HIO_NULL; const hio_bch_t* status_desc = HIO_NULL;
@ -452,18 +452,18 @@ static int thr_peer_htrd_poke (hio_htrd_t* htrd, hio_htre_t* req)
{ {
/* client request got completed */ /* client request got completed */
thr_peer_xtn_t* peer_xtn = hio_htrd_getxtn(htrd); thr_peer_xtn_t* peer_xtn = hio_htrd_getxtn(htrd);
thr_task_t* thr = peer_xtn->task; thr_t* thr = peer_xtn->task;
if (thr_write_last_chunk_to_client(thr) <= -1) return -1; if (thr_write_last_chunk_to_client(thr) <= -1) return -1;
thr_task_mark_over (thr, THR_OVER_READ_FROM_PEER); thr_mark_over (thr, THR_OVER_READ_FROM_PEER);
return 0; return 0;
} }
static int thr_peer_htrd_push_content (hio_htrd_t* htrd, hio_htre_t* req, const hio_bch_t* data, hio_oow_t dlen) static int thr_peer_htrd_push_content (hio_htrd_t* htrd, hio_htre_t* req, const hio_bch_t* data, hio_oow_t dlen)
{ {
thr_peer_xtn_t* peer_xtn = hio_htrd_getxtn(htrd); thr_peer_xtn_t* peer_xtn = hio_htrd_getxtn(htrd);
thr_task_t* thr = peer_xtn->task; thr_t* thr = peer_xtn->task;
HIO_ASSERT (thr->htts->hio, htrd == thr->peer_htrd); HIO_ASSERT (thr->htts->hio, htrd == thr->peer_htrd);
@ -522,12 +522,12 @@ static int thr_client_htrd_poke (hio_htrd_t* htrd, hio_htre_t* req)
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);
thr_task_t* thr = (thr_task_t*)cli->task; thr_t* thr = (thr_t*)cli->task;
/* indicate EOF to the client peer */ /* indicate EOF to the client peer */
if (thr_write_to_peer(thr, HIO_NULL, 0) <= -1) return -1; if (thr_write_to_peer(thr, HIO_NULL, 0) <= -1) return -1;
thr_task_mark_over (thr, THR_OVER_READ_FROM_CLIENT); thr_mark_over (thr, THR_OVER_READ_FROM_CLIENT);
return 0; return 0;
} }
@ -536,7 +536,7 @@ static int thr_client_htrd_push_content (hio_htrd_t* htrd, hio_htre_t* req, cons
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);
thr_task_t* thr = (thr_task_t*)cli->task; thr_t* thr = (thr_t*)cli->task;
HIO_ASSERT (sck->hio, cli->sck == sck); HIO_ASSERT (sck->hio, cli->sck == sck);
return thr_write_to_peer(thr, data, dlen); return thr_write_to_peer(thr, data, dlen);
@ -553,9 +553,9 @@ static int thr_peer_on_write (hio_dev_thr_t* peer, hio_iolen_t wrlen, void* wrct
{ {
hio_t* hio = peer->hio; hio_t* hio = peer->hio;
thr_peer_xtn_t* peer_xtn = (thr_peer_xtn_t*)hio_dev_thr_getxtn(peer); thr_peer_xtn_t* peer_xtn = (thr_peer_xtn_t*)hio_dev_thr_getxtn(peer);
thr_task_t* thr = peer_xtn->task; thr_t* thr = peer_xtn->task;
if (!thr) return 0; /* there is nothing i can do. the thr_task is being cleared or has been cleared already. */ if (!thr) return 0; /* there is nothing i can do. the thr is being cleared or has been cleared already. */
HIO_ASSERT (hio, thr->peer == peer); HIO_ASSERT (hio, thr->peer == peer);
@ -574,7 +574,7 @@ static int thr_peer_on_write (hio_dev_thr_t* peer, hio_iolen_t wrlen, void* wrct
HIO_DEBUG2 (hio, "HTTS(%p) - indicated EOF to peer %p\n", thr->htts, peer); HIO_DEBUG2 (hio, "HTTS(%p) - indicated EOF to peer %p\n", thr->htts, peer);
/* indicated EOF to the peer side. i need no more data from the client side. /* indicated EOF to the peer side. i need no more data from the client side.
* i don't need to enable input watching in the client side either */ * i don't need to enable input watching in the client side either */
thr_task_mark_over (thr, THR_OVER_WRITE_TO_PEER); thr_mark_over (thr, THR_OVER_WRITE_TO_PEER);
} }
else else
{ {
@ -589,21 +589,21 @@ static int thr_peer_on_write (hio_dev_thr_t* peer, hio_iolen_t wrlen, void* wrct
if ((thr->over & THR_OVER_READ_FROM_CLIENT) && thr->num_pending_writes_to_peer <= 0) if ((thr->over & THR_OVER_READ_FROM_CLIENT) && thr->num_pending_writes_to_peer <= 0)
{ {
thr_task_mark_over (thr, THR_OVER_WRITE_TO_PEER); thr_mark_over (thr, THR_OVER_WRITE_TO_PEER);
} }
} }
return 0; return 0;
oops: oops:
thr_task_halt_participating_devices (thr); thr_halt_participating_devices (thr);
return 0; return 0;
} }
static void thr_client_on_disconnect (hio_dev_sck_t* sck) static void thr_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);
thr_task_t* thr = (thr_task_t*)cli->task; thr_t* thr = (thr_t*)cli->task;
hio_svc_htts_t* htts = thr->htts; hio_svc_htts_t* htts = thr->htts;
hio_t* hio = sck->hio; hio_t* hio = sck->hio;
@ -617,7 +617,7 @@ static void thr_client_on_disconnect (hio_dev_sck_t* sck)
{ {
thr->client_org_on_disconnect (sck); thr->client_org_on_disconnect (sck);
/* this original callback destroys the associated resource. /* this original callback destroys the associated resource.
* thr_task must not be accessed from here down */ * thr must not be accessed from here down */
} }
HIO_DEBUG4 (hio, "HTTS(%p) - thr(t=%p,c=%p,csck=%p) - client socket disconnect handled\n", htts, thr, cli, sck); HIO_DEBUG4 (hio, "HTTS(%p) - thr(t=%p,c=%p,csck=%p) - client socket disconnect handled\n", htts, thr, cli, sck);
@ -628,7 +628,7 @@ static int thr_client_on_read (hio_dev_sck_t* sck, const void* buf, hio_iolen_t
{ {
hio_t* hio = sck->hio; hio_t* hio = sck->hio;
hio_svc_htts_cli_t* cli = hio_dev_sck_getxtn(sck); hio_svc_htts_cli_t* cli = hio_dev_sck_getxtn(sck);
thr_task_t* thr = (thr_task_t*)cli->task; thr_t* thr = (thr_t*)cli->task;
HIO_ASSERT (hio, sck == cli->sck); HIO_ASSERT (hio, sck == cli->sck);
@ -655,7 +655,7 @@ static int thr_client_on_read (hio_dev_sck_t* sck, const void* buf, hio_iolen_t
{ {
int n; int n;
n = thr_write_to_peer(thr, HIO_NULL, 0); n = thr_write_to_peer(thr, HIO_NULL, 0);
thr_task_mark_over (thr, THR_OVER_READ_FROM_CLIENT); thr_mark_over (thr, THR_OVER_READ_FROM_CLIENT);
if (n <= -1) goto oops; if (n <= -1) goto oops;
} }
} }
@ -677,7 +677,7 @@ static int thr_client_on_read (hio_dev_sck_t* sck, const void* buf, hio_iolen_t
return 0; return 0;
oops: oops:
thr_task_halt_participating_devices (thr); thr_halt_participating_devices (thr);
return 0; return 0;
} }
@ -685,7 +685,7 @@ static int thr_client_on_write (hio_dev_sck_t* sck, hio_iolen_t wrlen, void* wrc
{ {
hio_t* hio = sck->hio; hio_t* hio = sck->hio;
hio_svc_htts_cli_t* cli = hio_dev_sck_getxtn(sck); hio_svc_htts_cli_t* cli = hio_dev_sck_getxtn(sck);
thr_task_t* thr = (thr_task_t*)cli->task; thr_t* thr = (thr_t*)cli->task;
if (wrlen <= -1) if (wrlen <= -1)
{ {
@ -702,7 +702,7 @@ static int thr_client_on_write (hio_dev_sck_t* sck, hio_iolen_t wrlen, void* wrc
/* since EOF has been indicated to the client, it must not write to the client any further. /* since EOF has been indicated to the client, it must not write to the client any further.
* this also means that i don't need any data from the peer side either. * this also means that i don't need any data from the peer side either.
* i don't need to enable input watching on the peer side */ * i don't need to enable input watching on the peer side */
thr_task_mark_over (thr, THR_OVER_WRITE_TO_CLIENT); thr_mark_over (thr, THR_OVER_WRITE_TO_CLIENT);
} }
else else
{ {
@ -717,14 +717,14 @@ static int thr_client_on_write (hio_dev_sck_t* sck, hio_iolen_t wrlen, void* wrc
if ((thr->over & THR_OVER_READ_FROM_PEER) && thr->num_pending_writes_to_client <= 0) if ((thr->over & THR_OVER_READ_FROM_PEER) && thr->num_pending_writes_to_client <= 0)
{ {
thr_task_mark_over (thr, THR_OVER_WRITE_TO_CLIENT); thr_mark_over (thr, THR_OVER_WRITE_TO_CLIENT);
} }
} }
return 0; return 0;
oops: oops:
thr_task_halt_participating_devices (thr); thr_halt_participating_devices (thr);
return 0; return 0;
} }
@ -796,11 +796,44 @@ static int thr_capture_request_header (hio_htre_t* req, const hio_bch_t* key, co
return 0; return 0;
} }
/* ----------------------------------------------------------------------- */
static int setup_for_content_length(thr_t* thr, hio_htre_t* req)
{
int have_content;
#if defined(THR_ALLOW_UNLIMITED_REQ_CONTENT_LENGTH)
have_content = thr->task_req_conlen > 0 || thr->task_req_conlen_unlimited;
#else
have_content = thr->task_req_conlen > 0;
#endif
if (have_content)
{
/* change the callbacks to subscribe to contents to be uploaded */
thr->client_htrd_org_recbs = *hio_htrd_getrecbs(thr->task_client->htrd);
thr_client_htrd_recbs.peek = thr->client_htrd_org_recbs.peek;
hio_htrd_setrecbs (thr->task_client->htrd, &thr_client_htrd_recbs);
thr->client_htrd_recbs_changed = 1;
}
else
{
/* no content to be uploaded from the client */
/* indicate EOF to the peer and disable input wathching from the client */
if (thr_write_to_peer(thr, HIO_NULL, 0) <= -1) return -1;
thr_mark_over (thr, THR_OVER_READ_FROM_CLIENT | THR_OVER_WRITE_TO_PEER);
}
return 0;
}
/* ----------------------------------------------------------------------- */
int hio_svc_htts_dothr (hio_svc_htts_t* htts, hio_dev_sck_t* csck, hio_htre_t* req, hio_svc_htts_thr_func_t func, void* ctx, int options, hio_svc_htts_task_on_kill_t on_kill) int hio_svc_htts_dothr (hio_svc_htts_t* htts, hio_dev_sck_t* csck, hio_htre_t* req, hio_svc_htts_thr_func_t func, void* ctx, int options, hio_svc_htts_task_on_kill_t on_kill)
{ {
hio_t* hio = htts->hio; hio_t* hio = htts->hio;
hio_svc_htts_cli_t* cli = hio_dev_sck_getxtn(csck); hio_svc_htts_cli_t* cli = hio_dev_sck_getxtn(csck);
thr_task_t* thr = HIO_NULL; thr_t* thr = HIO_NULL;
thr_peer_xtn_t* peer_xtn; thr_peer_xtn_t* peer_xtn;
hio_dev_thr_make_t mi; hio_dev_thr_make_t mi;
thr_func_start_t* tfs; thr_func_start_t* tfs;
@ -840,7 +873,7 @@ int hio_svc_htts_dothr (hio_svc_htts_t* htts, hio_dev_sck_t* csck, hio_htre_t* r
mi.on_write = thr_peer_on_write; mi.on_write = thr_peer_on_write;
mi.on_close = thr_peer_on_close; mi.on_close = thr_peer_on_close;
thr = (thr_task_t*)hio_svc_htts_task_make(htts, HIO_SIZEOF(*thr), thr_task_on_kill, req, csck); thr = (thr_t*)hio_svc_htts_task_make(htts, HIO_SIZEOF(*thr), thr_on_kill, req, csck);
if (HIO_UNLIKELY(!thr)) goto oops; if (HIO_UNLIKELY(!thr)) goto oops;
thr->on_kill = on_kill; thr->on_kill = on_kill;
@ -881,80 +914,14 @@ int hio_svc_htts_dothr (hio_svc_htts_t* htts, hio_dev_sck_t* csck, hio_htre_t* r
peer_xtn = hio_htrd_getxtn(thr->peer_htrd); peer_xtn = hio_htrd_getxtn(thr->peer_htrd);
HIO_SVC_HTTS_TASK_REF (thr, peer_xtn->task); HIO_SVC_HTTS_TASK_REF (thr, peer_xtn->task);
#if !defined(THR_ALLOW_UNLIMITED_REQ_CONTENT_LENGTH) if (hio_svc_htts_task_handleexpect100(thr, options) <= -1) goto oops;
if (thr->task_req_conlen_unlimited) if (setup_for_content_length(thr, req) <= -1) goto oops;
{
/* Transfer-Encoding is chunked. no content-length is known in advance. */
/* option 1. buffer contents. if it gets too large, send 413 Request Entity Too Large.
* option 2. send 411 Length Required immediately
* option 3. set Content-Length to -1 and use EOF to indicate the end of content [Non-Standard] */
if (thr_send_final_status_to_client(thr, HIO_HTTP_STATUS_LENGTH_REQUIRED, 1) <= -1) goto oops;
}
#endif
if (req->flags & HIO_HTRE_ATTR_EXPECT100)
{
/* TODO: Expect: 100-continue? who should handle this? thr? or the http server? */
/* CAN I LET the thr SCRIPT handle this? */
if (hio_comp_http_version_numbers(&req->version, 1, 1) >= 0 &&
(thr->task_req_conlen_unlimited || thr->task_req_conlen > 0))
{
/*
* Don't send 100 Continue if http verions is lower than 1.1
* [RFC7231]
* A server that receives a 100-continue expectation in an HTTP/1.0
* request MUST ignore that expectation.
*
* Don't send 100 Continue if expected content lenth is 0.
* [RFC7231]
* A server MAY omit sending a 100 (Continue) response if it has
* already received some or all of the message body for the
* corresponding request, or if the framing indicates that there is
* no message body.
*/
hio_bch_t msgbuf[64];
hio_oow_t msglen;
msglen = hio_fmttobcstr(hio, msgbuf, HIO_COUNTOF(msgbuf), "HTTP/%d.%d %d %hs\r\n\r\n", thr->task_req_version.major, thr->task_req_version.minor, HIO_HTTP_STATUS_CONTINUE, hio_http_status_to_bcstr(HIO_HTTP_STATUS_CONTINUE));
if (thr_write_to_client(thr, msgbuf, msglen) <= -1) goto oops;
thr->ever_attempted_to_write_to_client = 0; /* reset this as it's polluted for 100 continue */
}
}
else if (req->flags & HIO_HTRE_ATTR_EXPECT)
{
/* 417 Expectation Failed */
thr_send_final_status_to_client(thr, HIO_HTTP_STATUS_EXPECTATION_FAILED, 1);
goto oops;
}
#if defined(THR_ALLOW_UNLIMITED_REQ_CONTENT_LENGTH)
have_content = thr->task_req_conlen > 0 || thr->task_req_conlen_unlimited;
#else
have_content = thr->task_req_conlen > 0;
#endif
if (have_content)
{
/* change the callbacks to subscribe to contents to be uploaded */
thr->client_htrd_org_recbs = *hio_htrd_getrecbs(thr->task_client->htrd);
thr_client_htrd_recbs.peek = thr->client_htrd_org_recbs.peek;
hio_htrd_setrecbs (thr->task_client->htrd, &thr_client_htrd_recbs);
thr->client_htrd_recbs_changed = 1;
}
else
{
/* no content to be uploaded from the client */
/* indicate EOF to the peer and disable input wathching from the client */
if (thr_write_to_peer(thr, HIO_NULL, 0) <= -1) goto oops;
thr_task_mark_over (thr, THR_OVER_READ_FROM_CLIENT | THR_OVER_WRITE_TO_PEER);
}
thr->res_mode_to_cli = thr->task_keep_client_alive? THR_RES_MODE_CHUNKED: THR_RES_MODE_CLOSE; thr->res_mode_to_cli = thr->task_keep_client_alive? THR_RES_MODE_CHUNKED: THR_RES_MODE_CLOSE;
/* the mode still can get switched from THR_RES_MODE_CHUNKED to THR_RES_MODE_LENGTH /* the mode still can get switched from THR_RES_MODE_CHUNKED to THR_RES_MODE_LENGTH
if the thread function emits Content-Length */ if the thread function emits Content-Length */
/* TODO: store current input watching state and use it when destroying the thr_task data */ /* TODO: store current input watching state and use it when destroying the thr data */
if (hio_dev_sck_read(csck, !(thr->over & THR_OVER_READ_FROM_CLIENT)) <= -1) goto oops; if (hio_dev_sck_read(csck, !(thr->over & THR_OVER_READ_FROM_CLIENT)) <= -1) goto oops;
HIO_SVC_HTTS_TASKL_APPEND_TASK (&htts->task, (hio_svc_htts_task_t*)thr); HIO_SVC_HTTS_TASKL_APPEND_TASK (&htts->task, (hio_svc_htts_task_t*)thr);
@ -963,6 +930,6 @@ int hio_svc_htts_dothr (hio_svc_htts_t* htts, hio_dev_sck_t* csck, hio_htre_t* r
oops: oops:
HIO_DEBUG2 (hio, "HTTS(%p) - FAILURE in dothr - socket(%p)\n", htts, csck); HIO_DEBUG2 (hio, "HTTS(%p) - FAILURE in dothr - socket(%p)\n", htts, csck);
if (tfs) free_thr_start_info (tfs); if (tfs) free_thr_start_info (tfs);
if (thr) thr_task_halt_participating_devices (thr); if (thr) thr_halt_participating_devices (thr);
return -1; return -1;
} }