fixed a bug of sending http/1.0 taken from the peer while chunking.
enhanced proxy handling in general
This commit is contained in:
parent
e360d3396c
commit
654003e06d
@ -74,6 +74,8 @@ struct qse_htrd_t
|
||||
{
|
||||
struct
|
||||
{
|
||||
int flags;
|
||||
|
||||
int crlf; /* crlf status */
|
||||
qse_size_t plen; /* raw request length excluding crlf */
|
||||
qse_size_t need; /* number of octets needed for contents */
|
||||
@ -86,8 +88,7 @@ struct qse_htrd_t
|
||||
} chunk;
|
||||
} s; /* state */
|
||||
|
||||
|
||||
/* buffers needed to for processing a request */
|
||||
/* buffers needed for processing a request */
|
||||
struct
|
||||
{
|
||||
qse_htob_t raw; /* buffer to hold raw octets */
|
||||
@ -163,8 +164,13 @@ int qse_htrd_feed (
|
||||
qse_size_t len /**< number of octets */
|
||||
);
|
||||
|
||||
int qse_htrd_read (
|
||||
qse_htrd_t* htrd /**< htrd */
|
||||
/**
|
||||
* The qse_htrd_halt() function indicates the end of feeeding
|
||||
* if the current response should be processed until the
|
||||
* connection is closed.
|
||||
*/
|
||||
int qse_htrd_halt (
|
||||
qse_htrd_t* htrd
|
||||
);
|
||||
|
||||
int qse_htrd_scanqparam (
|
||||
|
@ -81,10 +81,11 @@ struct qse_htre_t
|
||||
/* special attributes derived from the header */
|
||||
struct
|
||||
{
|
||||
int chunked;
|
||||
int content_length_set;
|
||||
#define QSE_HTRE_ATTR_CHUNKED (1 << 0)
|
||||
#define QSE_HTRE_ATTR_LENGTH (1 << 1)
|
||||
#define QSE_HTRE_ATTR_KEEPALIVE (1 << 2)
|
||||
int flags;
|
||||
qse_size_t content_length;
|
||||
int keepalive;
|
||||
const qse_mchar_t* expect;
|
||||
const qse_mchar_t* status;
|
||||
} attr;
|
||||
|
@ -26,6 +26,8 @@ QSE_IMPLEMENT_COMMON_FUNCTIONS (htrd)
|
||||
|
||||
static const qse_mchar_t NUL = QSE_MT('\0');
|
||||
|
||||
#define CONSUME_UNTIL_CLOSE (1 << 0)
|
||||
|
||||
static QSE_INLINE int is_whspace_octet (qse_mchar_t c)
|
||||
{
|
||||
return c == QSE_MT(' ') || c == QSE_MT('\t') || c == QSE_MT('\r') || c == QSE_MT('\n');
|
||||
@ -425,7 +427,7 @@ static qse_mchar_t* parse_initial_line (
|
||||
if (htrd->re.version.major > 1 ||
|
||||
(htrd->re.version.major == 1 && htrd->re.version.minor >= 1))
|
||||
{
|
||||
htrd->re.attr.keepalive = 1;
|
||||
htrd->re.attr.flags |= QSE_HTRE_ATTR_KEEPALIVE;
|
||||
}
|
||||
|
||||
return ++p;
|
||||
@ -469,7 +471,7 @@ static int capture_connection (qse_htrd_t* htrd, qse_htb_pair_t* pair)
|
||||
"close", 5);
|
||||
if (n == 0)
|
||||
{
|
||||
htrd->re.attr.keepalive = 0;
|
||||
htrd->re.attr.flags &= ~QSE_HTRE_ATTR_KEEPALIVE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -478,7 +480,7 @@ static int capture_connection (qse_htrd_t* htrd, qse_htb_pair_t* pair)
|
||||
"keep-alive", 10);
|
||||
if (n == 0)
|
||||
{
|
||||
htrd->re.attr.keepalive = 1;
|
||||
htrd->re.attr.flags |= QSE_HTRE_ATTR_KEEPALIVE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -494,7 +496,7 @@ static int capture_connection (qse_htrd_t* htrd, qse_htb_pair_t* pair)
|
||||
if (htrd->re.version.major < 1 ||
|
||||
(htrd->re.version.major == 1 && htrd->re.version.minor <= 0))
|
||||
{
|
||||
htrd->re.attr.keepalive = 0;
|
||||
htrd->re.attr.flags &= ~QSE_HTRE_ATTR_KEEPALIVE;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -533,7 +535,7 @@ static int capture_content_length (qse_htrd_t* htrd, qse_htb_pair_t* pair)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (htrd->re.attr.chunked && len > 0)
|
||||
if ((htrd->re.attr.flags & QSE_HTRE_ATTR_CHUNKED) && len > 0)
|
||||
{
|
||||
/* content-length is greater than 0
|
||||
* while transfer-encoding: chunked is specified. */
|
||||
@ -541,8 +543,8 @@ static int capture_content_length (qse_htrd_t* htrd, qse_htb_pair_t* pair)
|
||||
return -1;
|
||||
}
|
||||
|
||||
htrd->re.attr.flags |= QSE_HTRE_ATTR_LENGTH;
|
||||
htrd->re.attr.content_length = len;
|
||||
htrd->re.attr.content_length_set = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -567,13 +569,13 @@ static int capture_transfer_encoding (qse_htrd_t* htrd, qse_htb_pair_t* pair)
|
||||
if (n == 0)
|
||||
{
|
||||
/* if (htrd->re.attr.content_length > 0) */
|
||||
if (htrd->re.attr.content_length_set)
|
||||
if (htrd->re.attr.flags & QSE_HTRE_ATTR_LENGTH)
|
||||
{
|
||||
/* both content-length and 'transfer-encoding: chunked' are specified. */
|
||||
goto badre;
|
||||
}
|
||||
|
||||
htrd->re.attr.chunked = 1;
|
||||
htrd->re.attr.flags |= QSE_HTRE_ATTR_CHUNKED;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1111,8 +1113,7 @@ int qse_htrd_feed (qse_htrd_t* htrd, const qse_mchar_t* req, qse_size_t len)
|
||||
/* reset the raw request length */
|
||||
htrd->fed.s.plen = 0;
|
||||
|
||||
if (parse_initial_line_and_headers (htrd, req, ptr - req) <= -1)
|
||||
return -1;
|
||||
if (parse_initial_line_and_headers (htrd, req, ptr - req) <= -1) return -1;
|
||||
|
||||
/* compelete request header is received */
|
||||
header_completed_during_this_feed = 1;
|
||||
@ -1149,10 +1150,10 @@ int qse_htrd_feed (qse_htrd_t* htrd, const qse_mchar_t* req, qse_size_t len)
|
||||
}
|
||||
|
||||
/* carry on processing content body fed together with the header */
|
||||
if (htrd->re.attr.chunked)
|
||||
if (htrd->re.attr.flags & QSE_HTRE_ATTR_CHUNKED)
|
||||
{
|
||||
/* transfer-encoding: chunked */
|
||||
QSE_ASSERT (!htrd->re.attr.content_length_set);
|
||||
QSE_ASSERT (!(htrd->re.attr.flags & QSE_HTRE_ATTR_LENGTH));
|
||||
|
||||
dechunk_start:
|
||||
htrd->fed.s.chunk.phase = GET_CHUNK_LEN;
|
||||
@ -1195,7 +1196,31 @@ int qse_htrd_feed (qse_htrd_t* htrd, const qse_mchar_t* req, qse_size_t len)
|
||||
{
|
||||
/* we need to read as many octets as
|
||||
* Content-Length */
|
||||
htrd->fed.s.need = htrd->re.attr.content_length;
|
||||
if ((htrd->option & QSE_HTRD_RESPONSE) &&
|
||||
!(htrd->re.attr.flags & QSE_HTRE_ATTR_LENGTH) &&
|
||||
!(htrd->re.attr.flags & QSE_HTRE_ATTR_KEEPALIVE))
|
||||
{
|
||||
/* for a response, no content-length and
|
||||
* no chunk are specified and 'connection'
|
||||
* is to close. i must read until the
|
||||
* connection is closed. however, there isn't
|
||||
* any good way to know when to stop from
|
||||
* within this function. so the caller
|
||||
* can call qse_htrd_halt() for this. */
|
||||
|
||||
/* set this to the maximum in a type safe way
|
||||
* assuming it's unsigned. the problem of
|
||||
* the current implementation is that
|
||||
* it can't receive more than */
|
||||
htrd->fed.s.need = 0;
|
||||
htrd->fed.s.need = ~htrd->fed.s.need;
|
||||
htrd->fed.s.flags |= CONSUME_UNTIL_CLOSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
htrd->fed.s.need = htrd->re.attr.content_length;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (htrd->fed.s.need > 0)
|
||||
@ -1209,7 +1234,17 @@ int qse_htrd_feed (qse_htrd_t* htrd, const qse_mchar_t* req, qse_size_t len)
|
||||
{
|
||||
/* the data is not as large as needed */
|
||||
if (push_content (htrd, ptr, avail) <= -1) return -1;
|
||||
htrd->fed.s.need -= avail;
|
||||
|
||||
if (!(htrd->fed.s.flags & CONSUME_UNTIL_CLOSE))
|
||||
{
|
||||
/* i don't decrement htrd->fed.s.need
|
||||
* if i should read until connection is closed.
|
||||
* well, unless set your own callback,
|
||||
* push_content() above will fail
|
||||
* if too much has been received already */
|
||||
htrd->fed.s.need -= avail;
|
||||
}
|
||||
|
||||
/* we didn't get a complete content yet */
|
||||
goto feedme_more;
|
||||
}
|
||||
@ -1218,7 +1253,8 @@ int qse_htrd_feed (qse_htrd_t* htrd, const qse_mchar_t* req, qse_size_t len)
|
||||
/* we got all or more than needed */
|
||||
if (push_content (htrd, ptr, htrd->fed.s.need) <= -1) return -1;
|
||||
ptr += htrd->fed.s.need;
|
||||
htrd->fed.s.need = 0;
|
||||
if (!(htrd->fed.s.flags & CONSUME_UNTIL_CLOSE))
|
||||
htrd->fed.s.need = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1361,6 +1397,33 @@ feedme_more:
|
||||
return 0;
|
||||
}
|
||||
|
||||
int qse_htrd_halt (qse_htrd_t* htrd)
|
||||
{
|
||||
if (htrd->fed.s.flags & CONSUME_UNTIL_CLOSE)
|
||||
{
|
||||
qse_htre_completecontent (&htrd->re);
|
||||
|
||||
if (htrd->recbs->handle)
|
||||
{
|
||||
int n;
|
||||
htrd->errnum = QSE_HTRD_ENOERR;
|
||||
n = htrd->recbs->handle (htrd, &htrd->re);
|
||||
if (n <= -1)
|
||||
{
|
||||
if (htrd->errnum == QSE_HTRD_ENOERR)
|
||||
htrd->errnum = QSE_HTRD_ERECBS;
|
||||
/* need to clear request on error?
|
||||
clear_feed (htrd); */
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
clear_feed (htrd);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
int qse_htrd_scanqparam (qse_htrd_t* htrd, const qse_mcstr_t* cstr)
|
||||
{
|
||||
|
@ -36,6 +36,11 @@
|
||||
|
||||
#define MAX_SEND_SIZE 4096
|
||||
|
||||
/* TODO:
|
||||
* many functions in this file use qse_size_t.
|
||||
* so the size data transfers is limited by this type.
|
||||
* break this barrier... */
|
||||
|
||||
static qse_http_version_t http_v11 = { 1, 1 };
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
@ -400,7 +405,8 @@ qse_httpd_task_t* qse_httpd_entaskerror (
|
||||
{
|
||||
return entask_error (
|
||||
httpd, client, pred, code,
|
||||
qse_htre_getversion(req), req->attr.keepalive);
|
||||
qse_htre_getversion(req),
|
||||
(req->attr.flags & QSE_HTRE_ATTR_KEEPALIVE));
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
@ -431,7 +437,7 @@ qse_httpd_task_t* qse_httpd_entaskauth (
|
||||
httpd, client, pred,
|
||||
QSE_MT("HTTP/%d.%d 401 Unauthorized\r\nConnection: %s\r\nWWW-Authenticate: Basic realm=\"%s\"\r\nContent-Type: text/html\r\nContent-Length: %lu\r\n\r\n%s\r\n\r\n"),
|
||||
version->major, version->minor,
|
||||
(req->attr.keepalive? QSE_MT("keep-alive"): QSE_MT("close")),
|
||||
((req->attr.flags & QSE_HTRE_ATTR_KEEPALIVE)? QSE_MT("keep-alive"): QSE_MT("close")),
|
||||
realm, (unsigned long)qse_mbslen(lmsg) + 4, lmsg);
|
||||
}
|
||||
|
||||
@ -1196,7 +1202,7 @@ qse_httpd_task_t* qse_httpd_entaskfile (
|
||||
QSE_MEMSET (&data, 0, QSE_SIZEOF(data));
|
||||
data.path = path;
|
||||
data.version = *qse_htre_getversion(req);
|
||||
data.keepalive = req->attr.keepalive;
|
||||
data.keepalive = (req->attr.flags & QSE_HTRE_ATTR_KEEPALIVE);
|
||||
|
||||
tmp = qse_htre_getheaderval(req, QSE_MT("Range"));
|
||||
if (tmp)
|
||||
@ -1414,7 +1420,7 @@ static int cgi_htrd_peek_script_output (qse_htrd_t* htrd, qse_htre_t* req)
|
||||
}
|
||||
|
||||
keepalive = cgi->keepalive;
|
||||
if (req->attr.content_length_set)
|
||||
if (req->attr.flags & QSE_HTRE_ATTR_LENGTH)
|
||||
{
|
||||
cgi->resflags |= CGI_RES_SCRIPT_LENGTH;
|
||||
cgi->script_output_length = req->attr.content_length;
|
||||
@ -1805,7 +1811,7 @@ static int task_init_cgi (
|
||||
qse_mbscpy ((qse_mchar_t*)(cgi + 1), arg->path);
|
||||
cgi->path = (qse_mchar_t*)(cgi + 1);
|
||||
cgi->version = *qse_htre_getversion(arg->req);
|
||||
cgi->keepalive = arg->req->attr.keepalive;
|
||||
cgi->keepalive = (arg->req->attr.flags & QSE_HTRE_ATTR_KEEPALIVE);
|
||||
cgi->nph = arg->nph;
|
||||
cgi->req = QSE_NULL;
|
||||
|
||||
@ -1826,7 +1832,7 @@ static int task_init_cgi (
|
||||
}
|
||||
|
||||
if (!(arg->req->state & QSE_HTRE_COMPLETED) &&
|
||||
!arg->req->attr.content_length_set)
|
||||
!(arg->req->attr.flags & QSE_HTRE_ATTR_LENGTH))
|
||||
{
|
||||
/* if the request is not completed and doesn't have
|
||||
* content-length set, it's not really possible to
|
||||
@ -1859,8 +1865,9 @@ static int task_init_cgi (
|
||||
* should reach here. if content-length is set
|
||||
* the length should match len. */
|
||||
QSE_ASSERT (len > 0);
|
||||
QSE_ASSERT (!arg->req->attr.content_length_set ||
|
||||
(arg->req->attr.content_length_set && arg->req->attr.content_length == len));
|
||||
QSE_ASSERT (!(arg->req->attr.flags & QSE_HTRE_ATTR_LENGTH) ||
|
||||
((arg->req->attr.flags & QSE_HTRE_ATTR_LENGTH) &&
|
||||
arg->req->attr.content_length == len));
|
||||
cgi->reqflags |= CGI_REQ_GOTALL;
|
||||
content_length = len;
|
||||
}
|
||||
@ -1885,7 +1892,7 @@ static int task_init_cgi (
|
||||
cgi->req = arg->req;
|
||||
qse_htre_setconcb (cgi->req, cgi_snatch_client_input, task);
|
||||
|
||||
QSE_ASSERT (arg->req->attr.content_length_set);
|
||||
QSE_ASSERT (arg->req->attr.flags & QSE_HTRE_ATTR_LENGTH);
|
||||
content_length = arg->req->attr.content_length;
|
||||
}
|
||||
}
|
||||
@ -2663,7 +2670,6 @@ static int proxy_snatch_peer_output (
|
||||
* the client should be chunked */
|
||||
QSE_ASSERT (proxy->resflags & PROXY_RES_CLIENT_CHUNK);
|
||||
|
||||
|
||||
/* TODO: better condition for compaction??? */
|
||||
if (proxy->res_pending > 0 && proxy->res_consumed > 0)
|
||||
{
|
||||
@ -2740,6 +2746,7 @@ static int proxy_htrd_peek_peer_output (qse_htrd_t* htrd, qse_htre_t* res)
|
||||
/* this peek handler is being called again.
|
||||
* this can happen if qse_htrd_feed() is fed with
|
||||
* multiple responses in task_main_proxy_2 (). */
|
||||
qse_printf (QSE_T("XXXXXXXXXXXXXXXXXXXXXXxx\n"));
|
||||
proxy->httpd->errnum = QSE_HTTPD_EINVAL;
|
||||
return -1;
|
||||
}
|
||||
@ -2772,17 +2779,9 @@ qse_printf (QSE_T("10000000000000000000000000000 CONTINUE 1000000000000000000000
|
||||
proxy->resflags |= PROXY_RES_RECEIVED_RESHDR;
|
||||
|
||||
qse_printf (QSE_T("NORMAL REPLY 222222222222222222222 NORMAL REPLY\n"));
|
||||
/* begin initial line */
|
||||
if (qse_mbs_cat (proxy->res, qse_htre_getverstr(res)) == (qse_size_t)-1) return -1;
|
||||
if (qse_mbs_cat (proxy->res, QSE_MT(" ")) == (qse_size_t)-1) return -1;;
|
||||
if (qse_mbs_cat (proxy->res, qse_htre_getscodestr(res)) == (qse_size_t)-1) return -1;
|
||||
if (qse_mbs_cat (proxy->res, QSE_MT(" ")) == (qse_size_t)-1) return -1;
|
||||
if (qse_mbs_cat (proxy->res, qse_htre_getsmesg(res)) == (qse_size_t)-1) return -1;
|
||||
if (qse_mbs_cat (proxy->res, QSE_MT("\r\n")) == (qse_size_t)-1) return -1;
|
||||
/* end initial line */
|
||||
|
||||
keepalive = proxy->keepalive;
|
||||
if (res->attr.content_length_set)
|
||||
if (res->attr.flags & QSE_HTRE_ATTR_LENGTH)
|
||||
{
|
||||
/* the response from the peer is length based */
|
||||
proxy->resflags |= PROXY_RES_PEER_LENGTH;
|
||||
@ -2797,13 +2796,7 @@ qse_printf (QSE_T("NORMAL REPLY 222222222222222222222 NORMAL REPLY\n"));
|
||||
/* chunk response when writing back to client */
|
||||
proxy->resflags |= PROXY_RES_CLIENT_CHUNK;
|
||||
|
||||
if (qse_mbs_cat (proxy->res, QSE_MT("Transfer-Encoding: chunked\r\n")) == (qse_size_t)-1)
|
||||
{
|
||||
proxy->httpd->errnum = QSE_HTTPD_ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (res->attr.chunked)
|
||||
if (res->attr.flags & QSE_HTRE_ATTR_CHUNKED)
|
||||
{
|
||||
/* mark the peer output is chunked */
|
||||
proxy->resflags |= PROXY_RES_PEER_CHUNK;
|
||||
@ -2822,13 +2815,42 @@ qse_printf (QSE_T("NORMAL REPLY 222222222222222222222 NORMAL REPLY\n"));
|
||||
proxy->resflags |= PROXY_RES_CLIENT_DISCON;
|
||||
if (qse_httpd_entaskdisconnect (proxy->httpd, xtn->client, xtn->task) == QSE_NULL) return -1;
|
||||
|
||||
if (res->attr.chunked)
|
||||
if (res->attr.flags & QSE_HTRE_ATTR_CHUNKED)
|
||||
proxy->resflags |= PROXY_RES_PEER_CHUNK;
|
||||
else
|
||||
proxy->resflags |= PROXY_RES_PEER_CLOSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* begin initial line */
|
||||
if (proxy->resflags & PROXY_RES_CLIENT_CHUNK &&
|
||||
qse_comparehttpversions (&res->version, &http_v11) < 0)
|
||||
{
|
||||
qse_mchar_t vbuf[64];
|
||||
snprintf (vbuf, QSE_COUNTOF(vbuf), QSE_MT("HTTP/%d.%d"),
|
||||
(int)proxy->version.major, (int)proxy->version.minor);
|
||||
if (qse_mbs_cat (proxy->res, vbuf) == (qse_size_t)-1) return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (qse_mbs_cat (proxy->res, qse_htre_getverstr(res)) == (qse_size_t)-1) return -1;
|
||||
}
|
||||
if (qse_mbs_cat (proxy->res, QSE_MT(" ")) == (qse_size_t)-1) return -1;;
|
||||
if (qse_mbs_cat (proxy->res, qse_htre_getscodestr(res)) == (qse_size_t)-1) return -1;
|
||||
if (qse_mbs_cat (proxy->res, QSE_MT(" ")) == (qse_size_t)-1) return -1;
|
||||
if (qse_mbs_cat (proxy->res, qse_htre_getsmesg(res)) == (qse_size_t)-1) return -1;
|
||||
if (qse_mbs_cat (proxy->res, QSE_MT("\r\n")) == (qse_size_t)-1) return -1;
|
||||
/* end initial line */
|
||||
|
||||
if (proxy->resflags & PROXY_RES_CLIENT_CHUNK)
|
||||
{
|
||||
if (qse_mbs_cat (proxy->res, QSE_MT("Transfer-Encoding: chunked\r\n")) == (qse_size_t)-1)
|
||||
{
|
||||
proxy->httpd->errnum = QSE_HTTPD_ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (qse_mbs_cat (proxy->res, (keepalive? QSE_MT("Connection: keep-alive\r\n"): QSE_MT("Connection: close\r\n"))) == (qse_size_t)-1)
|
||||
{
|
||||
proxy->httpd->errnum = QSE_HTTPD_ENOMEM;
|
||||
@ -2883,6 +2905,7 @@ qse_printf (QSE_T("PROXY PEER FUCKED - RETURNING TOO MUCH...\n"));
|
||||
/* arrange to store further contents received to proxy->res */
|
||||
qse_htre_setconcb (res, proxy_snatch_peer_output, xtn->task);
|
||||
}
|
||||
qse_printf (QSE_T("NORMAL REPLY 222222222222222222222 NORMAL REPLY OK\n"));
|
||||
}
|
||||
|
||||
proxy->res_pending = QSE_MBS_LEN(proxy->res) - proxy->res_consumed;
|
||||
@ -3000,7 +3023,7 @@ static int task_init_proxy (
|
||||
proxy->httpd = httpd;
|
||||
|
||||
proxy->version = *qse_htre_getversion(arg->req);
|
||||
proxy->keepalive = arg->req->attr.keepalive;
|
||||
proxy->keepalive = (arg->req->attr.flags & QSE_HTRE_ATTR_KEEPALIVE);
|
||||
proxy->peer.nwad = arg->peer_nwad;
|
||||
proxy->req = QSE_NULL;
|
||||
|
||||
@ -3051,7 +3074,7 @@ len = 1024;
|
||||
}
|
||||
|
||||
if (!(arg->req->state & QSE_HTRE_COMPLETED) &&
|
||||
!arg->req->attr.content_length_set)
|
||||
!(arg->req->attr.flags & QSE_HTRE_ATTR_LENGTH))
|
||||
{
|
||||
/* if the request is not completed and doesn't have
|
||||
* content-length set, it's not really possible to
|
||||
@ -3074,8 +3097,9 @@ len = 1024;
|
||||
* should reach here. if content-length is set
|
||||
* the length should match len. */
|
||||
QSE_ASSERT (len > 0);
|
||||
QSE_ASSERT (!arg->req->attr.content_length_set ||
|
||||
(arg->req->attr.content_length_set && arg->req->attr.content_length == len));
|
||||
QSE_ASSERT (!(arg->req->attr.flags & QSE_HTRE_ATTR_LENGTH) ||
|
||||
((arg->req->attr.flags & QSE_HTRE_ATTR_LENGTH) &&
|
||||
arg->req->attr.content_length == len));
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -3093,7 +3117,7 @@ len = 1024;
|
||||
* htrd calls invokes this callback. */
|
||||
proxy->req = arg->req;
|
||||
qse_htre_setconcb (proxy->req, proxy_snatch_client_input, task);
|
||||
QSE_ASSERT (arg->req->attr.content_length_set);
|
||||
QSE_ASSERT (arg->req->attr.flags & QSE_HTRE_ATTR_LENGTH);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3449,20 +3473,20 @@ qse_printf (QSE_T("#####PREMATURE EOF FROM PEER\n"));
|
||||
}
|
||||
else
|
||||
{
|
||||
qse_printf (QSE_T("#####PREMATURE EOF FROM PEER CLIENT CHUNK\n"));
|
||||
QSE_ASSERT (proxy->resflags & PROXY_RES_CLIENT_CHUNK);
|
||||
|
||||
if (proxy->resflags & PROXY_RES_PEER_CLOSE)
|
||||
{
|
||||
/* i should compelte the content manually
|
||||
* since the end of content is indicated by
|
||||
* close in this case. */
|
||||
qse_htre_completecontent (&proxy->peer_htrd->re);
|
||||
/* i should stop the reader manually since the
|
||||
* end of content is indicated by close in this
|
||||
* case. call qse_htrd_halt() for this. */
|
||||
qse_htrd_halt (proxy->peer_htrd);
|
||||
task->main = task_main_proxy_3;
|
||||
task->trigger[2].mask |= QSE_HTTPD_TASK_TRIGGER_WRITE;
|
||||
return 1;
|
||||
}
|
||||
|
||||
qse_printf (QSE_T("#####PREMATURE EOF FROM PEER CLIENT CHUNK\n"));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@ -3550,6 +3574,7 @@ static int task_main_proxy_1 (
|
||||
/* improve error conversion */
|
||||
if (httpd->errnum == QSE_HTTPD_ENOENT) http_errnum = 404;
|
||||
else if (httpd->errnum == QSE_HTTPD_EACCES) http_errnum = 403;
|
||||
qse_printf (QSE_T("task_main_proxy_1.... ERROR \n"));
|
||||
goto oops;
|
||||
}
|
||||
|
||||
@ -3589,11 +3614,13 @@ static int task_main_proxy (
|
||||
proxy_peer_htrd_xtn_t* xtn;
|
||||
int http_errnum = 500;
|
||||
int n;
|
||||
qse_printf (QSE_T("task_main_proxy....\n"));
|
||||
|
||||
if (proxy->init_failed) goto oops;
|
||||
|
||||
/* set up a http reader to read a response from the peer */
|
||||
proxy->peer_htrd = qse_htrd_open (httpd->mmgr, QSE_SIZEOF(proxy_peer_htrd_xtn_t));
|
||||
proxy->peer_htrd = qse_htrd_open (
|
||||
httpd->mmgr, QSE_SIZEOF(proxy_peer_htrd_xtn_t));
|
||||
if (proxy->peer_htrd == QSE_NULL) goto oops;
|
||||
xtn = (proxy_peer_htrd_xtn_t*) qse_htrd_getxtn (proxy->peer_htrd);
|
||||
xtn->proxy = proxy;
|
||||
@ -3614,6 +3641,7 @@ static int task_main_proxy (
|
||||
/* TODO: translate error code to http error... */
|
||||
if (httpd->errnum == QSE_HTTPD_ENOENT) http_errnum = 404;
|
||||
else if (httpd->errnum == QSE_HTTPD_EACCES) http_errnum = 403;
|
||||
qse_printf (QSE_T("caanot open peer....\n"));
|
||||
goto oops;
|
||||
}
|
||||
|
||||
|
@ -302,8 +302,9 @@ static qse_httpd_client_t* new_client (
|
||||
client->status = tmpl->status;
|
||||
client->handle = tmpl->handle;
|
||||
client->handle2 = tmpl->handle2;
|
||||
client->local_addr = tmpl->local_addr;
|
||||
client->remote_addr = tmpl->remote_addr;
|
||||
client->local_addr = tmpl->local_addr;
|
||||
client->orgdst_addr = tmpl->orgdst_addr;
|
||||
|
||||
xtn = (htrd_xtn_t*)qse_htrd_getxtn (client->htrd);
|
||||
xtn->httpd = httpd;
|
||||
@ -458,10 +459,11 @@ qse_printf (QSE_T("MUX ADDHND CLIENT READ %d\n"), client->handle.i);
|
||||
|
||||
{
|
||||
/* TODO: proper logging */
|
||||
qse_char_t tmp[128], tmp2[128];
|
||||
qse_char_t tmp[128], tmp2[128], tmp3[128];
|
||||
qse_nwadtostr (&client->local_addr, tmp, QSE_COUNTOF(tmp), QSE_NWADTOSTR_ALL);
|
||||
qse_nwadtostr (&client->remote_addr, tmp2, QSE_COUNTOF(tmp2), QSE_NWADTOSTR_ALL);
|
||||
qse_printf (QSE_T("connection %d accepted %s from %s\n"), client->handle.i, tmp, tmp2);
|
||||
qse_nwadtostr (&client->orgdst_addr, tmp2, QSE_COUNTOF(tmp2), QSE_NWADTOSTR_ALL);
|
||||
qse_nwadtostr (&client->remote_addr, tmp3, QSE_COUNTOF(tmp3), QSE_NWADTOSTR_ALL);
|
||||
qse_printf (QSE_T("connection %d accepted %s(%s from %s\n"), client->handle.i, tmp, tmp2, tmp3);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
@ -141,6 +141,7 @@ static qse_httpd_errnum_t syserr_to_errnum (int e)
|
||||
return QSE_HTTPD_EINVAL;
|
||||
|
||||
case EACCES:
|
||||
case ECONNREFUSED:
|
||||
return QSE_HTTPD_EACCES;
|
||||
|
||||
case ENOENT:
|
||||
@ -414,12 +415,6 @@ qse_fprintf (QSE_STDERR, QSE_T("Error: too many client?\n"));
|
||||
}
|
||||
#endif
|
||||
|
||||
{
|
||||
qse_char_t buf[100];
|
||||
qse_nwadtostr (&client->orgdst_addr, buf, QSE_COUNTOF(buf), QSE_NWADTOSTR_ALL);
|
||||
qse_printf (QSE_T("ORGDST address : (%s)\n"), buf);
|
||||
}
|
||||
|
||||
client->handle.i = fd;
|
||||
return 0;
|
||||
}
|
||||
@ -487,7 +482,11 @@ static int peer_connected (qse_httpd_t* httpd, qse_httpd_peer_t* peer)
|
||||
if (getsockopt (peer->handle.i, SOL_SOCKET, SO_ERROR, &ret, &len) <= -1) return -1;
|
||||
|
||||
if (ret == EINPROGRESS) return 0;
|
||||
if (ret != 0) return -1;
|
||||
if (ret != 0)
|
||||
{
|
||||
qse_httpd_seterrnum (httpd, syserr_to_errnum (ret));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 1; /* connection completed */
|
||||
}
|
||||
@ -533,8 +532,8 @@ struct mux_t
|
||||
|
||||
struct
|
||||
{
|
||||
struct mux_ev_t* ptr;
|
||||
qse_size_t capa;
|
||||
struct mux_ev_t** ptr;
|
||||
qse_size_t capa;
|
||||
} mev;
|
||||
};
|
||||
|
||||
@ -564,7 +563,13 @@ static void mux_close (qse_httpd_t* httpd, void* vmux)
|
||||
{
|
||||
struct mux_t* mux = (struct mux_t*)vmux;
|
||||
if (mux->ee.ptr) qse_httpd_freemem (httpd, mux->ee.ptr);
|
||||
if (mux->mev.ptr) qse_httpd_freemem (httpd, mux->mev.ptr);
|
||||
if (mux->mev.ptr)
|
||||
{
|
||||
qse_size_t i;
|
||||
for (i = 0; i < mux->mev.capa; i++)
|
||||
if (mux->mev.ptr[i]) qse_httpd_freemem (httpd, mux->mev.ptr[i]);
|
||||
qse_httpd_freemem (httpd, mux->mev.ptr);
|
||||
}
|
||||
close (mux->fd);
|
||||
qse_httpd_freemem (httpd, mux);
|
||||
}
|
||||
@ -589,20 +594,33 @@ static int mux_addhnd (
|
||||
|
||||
if (handle.i >= mux->mev.capa)
|
||||
{
|
||||
struct mux_ev_t* tmp;
|
||||
qse_size_t tmpcapa;
|
||||
struct mux_ev_t** tmp;
|
||||
qse_size_t tmpcapa, i;
|
||||
|
||||
tmpcapa = (((handle.i + MUX_EV_ALIGN) / MUX_EV_ALIGN) * MUX_EV_ALIGN);
|
||||
|
||||
tmp = qse_httpd_reallocmem (
|
||||
tmp = (struct mux_ev_t**) qse_httpd_reallocmem (
|
||||
httpd, mux->mev.ptr,
|
||||
QSE_SIZEOF(*mux->mev.ptr) * tmpcapa);
|
||||
if (tmp == QSE_NULL) return -1;
|
||||
|
||||
for (i = mux->mev.capa; i < tmpcapa; i++) tmp[i] = QSE_NULL;
|
||||
mux->mev.ptr = tmp;
|
||||
mux->mev.capa = tmpcapa;
|
||||
}
|
||||
|
||||
if (mux->mev.ptr[handle.i] == QSE_NULL)
|
||||
{
|
||||
/* the location of the data passed to epoll_ctl()
|
||||
* must not change unless i update the info with epoll()
|
||||
* whenever there is reallocation. so i simply
|
||||
* make mux-mev.ptr reallocatable but auctual
|
||||
* data fixed once allocated. */
|
||||
mux->mev.ptr[handle.i] = qse_httpd_allocmem (
|
||||
httpd, QSE_SIZEOF(*mux->mev.ptr[handle.i]));
|
||||
if (mux->mev.ptr[handle.i] == QSE_NULL) return -1;
|
||||
}
|
||||
|
||||
if (mux->ee.len >= mux->ee.capa)
|
||||
{
|
||||
struct epoll_event* tmp;
|
||||
@ -616,8 +634,7 @@ static int mux_addhnd (
|
||||
mux->ee.capa = (mux->ee.capa + 1) * 2;
|
||||
}
|
||||
|
||||
mev = &mux->mev.ptr[handle.i];
|
||||
|
||||
mev = mux->mev.ptr[handle.i];
|
||||
mev->handle = handle;
|
||||
mev->reqmask = mask;
|
||||
mev->cbfun = cbfun;
|
||||
@ -1070,7 +1087,7 @@ if (qse_htre_getcontentlen(req) > 0)
|
||||
if (peek)
|
||||
{
|
||||
/* cgi */
|
||||
if (req->attr.chunked)
|
||||
if (req->attr.flags & QSE_HTRE_ATTR_CHUNKED)
|
||||
{
|
||||
qse_printf (QSE_T("chunked cgi... delaying until contents are received\n"));
|
||||
#if 0
|
||||
@ -1081,10 +1098,9 @@ qse_printf (QSE_T("chunked cgi... delaying until contents are received\n"));
|
||||
if (task) qse_httpd_entaskdisconnect (httpd, client, QSE_NULL);
|
||||
#endif
|
||||
}
|
||||
else if (method == QSE_HTTP_POST &&
|
||||
!req->attr.content_length_set)
|
||||
else if (method == QSE_HTTP_POST && !(req->attr.flags & QSE_HTRE_ATTR_LENGTH))
|
||||
{
|
||||
req->attr.keepalive = 0;
|
||||
req->attr.flags &= ~QSE_HTRE_ATTR_KEEPALIVE;
|
||||
task = qse_httpd_entaskerror (
|
||||
httpd, client, QSE_NULL, 411, req);
|
||||
/* 411 can't keep alive */
|
||||
@ -1101,7 +1117,7 @@ qse_printf (QSE_T("chunked cgi... delaying until contents are received\n"));
|
||||
{
|
||||
/* to support the chunked request,
|
||||
* i need to wait until it's completed and invoke cgi */
|
||||
if (req->attr.chunked)
|
||||
if (req->attr.flags & QSE_HTRE_ATTR_CHUNKED)
|
||||
{
|
||||
qse_printf (QSE_T("Entasking chunked CGI...\n"));
|
||||
task = qse_httpd_entaskcgi (
|
||||
@ -1161,7 +1177,7 @@ qse_printf (QSE_T("Entasking chunked CGI...\n"));
|
||||
}
|
||||
}
|
||||
|
||||
if (!req->attr.keepalive)
|
||||
if (!(req->attr.flags & QSE_HTRE_ATTR_KEEPALIVE))
|
||||
{
|
||||
if (!peek)
|
||||
{
|
||||
@ -1236,6 +1252,7 @@ qse_printf (QSE_T("Host not included....\n"));
|
||||
{
|
||||
qse_nwad_t nwad;
|
||||
|
||||
#if 0
|
||||
if (qse_nwadequal (&client->local_addr, &client->orgdst_addr))
|
||||
{
|
||||
//qse_strtonwad (QSE_T("192.168.1.55:9000"), &nwad);
|
||||
@ -1243,13 +1260,16 @@ qse_printf (QSE_T("Host not included....\n"));
|
||||
}
|
||||
else
|
||||
{
|
||||
#endif
|
||||
nwad = client->orgdst_addr;
|
||||
#if 0
|
||||
}
|
||||
#endif
|
||||
task = qse_httpd_entaskproxy (httpd, client, QSE_NULL, &nwad, req);
|
||||
if (task == QSE_NULL) goto oops;
|
||||
}
|
||||
|
||||
if (!req->attr.keepalive)
|
||||
if (!(req->attr.flags & QSE_HTRE_ATTR_KEEPALIVE))
|
||||
{
|
||||
if (!peek)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user