added more proxy handling code
This commit is contained in:
parent
3d07790370
commit
7d8a5ff433
@ -97,12 +97,6 @@ struct qse_htrd_t
|
|||||||
void* chl;
|
void* chl;
|
||||||
} fed;
|
} fed;
|
||||||
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
QSE_HTRD_RETYPE_Q,
|
|
||||||
QSE_HTRD_RETYPE_S
|
|
||||||
} retype;
|
|
||||||
|
|
||||||
qse_htre_t re;
|
qse_htre_t re;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -45,12 +45,38 @@ struct qse_htre_t
|
|||||||
{
|
{
|
||||||
qse_mmgr_t* mmgr;
|
qse_mmgr_t* mmgr;
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
QSE_HTRE_Q,
|
||||||
|
QSE_HTRE_S
|
||||||
|
} type;
|
||||||
|
|
||||||
/* version */
|
/* version */
|
||||||
qse_http_version_t version;
|
qse_http_version_t version;
|
||||||
|
const qse_mchar_t* verstr; /* version string include HTTP/ */
|
||||||
|
|
||||||
int qmethod_or_sstatus;
|
union
|
||||||
qse_mbs_t qpath_or_smesg;
|
{
|
||||||
qse_mbs_t qparam;
|
struct
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
qse_http_method_t type;
|
||||||
|
const qse_mchar_t* name;
|
||||||
|
} method;
|
||||||
|
const qse_mchar_t* path;
|
||||||
|
const qse_mchar_t* param;
|
||||||
|
} q;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
int val;
|
||||||
|
const qse_mchar_t* str;
|
||||||
|
} code;
|
||||||
|
const qse_mchar_t* mesg;
|
||||||
|
} s;
|
||||||
|
} u;
|
||||||
|
|
||||||
/* special attributes derived from the header */
|
/* special attributes derived from the header */
|
||||||
struct
|
struct
|
||||||
@ -79,31 +105,17 @@ struct qse_htre_t
|
|||||||
#define qse_htre_getversion(re) (&((re)->version))
|
#define qse_htre_getversion(re) (&((re)->version))
|
||||||
#define qse_htre_getmajorversion(re) ((re)->version.major)
|
#define qse_htre_getmajorversion(re) ((re)->version.major)
|
||||||
#define qse_htre_getminorversion(re) ((re)->version.minor)
|
#define qse_htre_getminorversion(re) ((re)->version.minor)
|
||||||
#define qse_htre_setversion(re,v) QSE_BLOCK((re)->version = *(v);)
|
#define qse_htre_getverstr(re) ((re)->verstr)
|
||||||
|
|
||||||
#define qse_htre_getqmethod(re) ((re)->qmethod_or_sstatus)
|
#define qse_htre_getqmethodtype(re) ((re)->u.q.method.type)
|
||||||
#define qse_htre_setqmethod(re,v) QSE_BLOCK((re)->qmethod_or_sstatus=(v);)
|
#define qse_htre_getqmethodname(re) ((re)->u.q.method.name)
|
||||||
|
|
||||||
#define qse_htre_getsstatus(re) ((re)->qmethod_or_sstatus)
|
#define qse_htre_getqpath(re) ((re)->u.q.path)
|
||||||
#define qse_htre_setsstatus(re,v) QSE_BLOCK((re)->qmethod_or_sstatus=(v);)
|
#define qse_htre_getqparam(re) ((re)->u.q.param)
|
||||||
|
|
||||||
#define qse_htre_getqpath(re) (&(re)->qpath_or_smesg)
|
#define qse_htre_getscodeval(re) ((re)->u.s.code.val)
|
||||||
#define qse_htre_getqpathxstr(re) QSE_MBS_XSTR(&(re)->qpath_or_smesg)
|
#define qse_htre_getscodestr(re) ((re)->u.s.code.str)
|
||||||
#define qse_htre_getqpathcstr(re) QSE_MBS_CSTR(&(re)->qpath_or_smesg)
|
#define qse_htre_getsmesg(re) ((re)->u.s.mesg)
|
||||||
#define qse_htre_getqpathptr(re) QSE_MBS_PTR(&(re)->qpath_or_smesg)
|
|
||||||
#define qse_htre_getqpathlen(re) QSE_MBS_LEN(&(re)->qpath_or_smesg)
|
|
||||||
|
|
||||||
#define qse_htre_getqparam(re) (&(re)->qparam)
|
|
||||||
#define qse_htre_getqparamxstr(re) QSE_MBS_XSTR(&(re)->qparam)
|
|
||||||
#define qse_htre_getqparamcstr(re) QSE_MBS_CSTR(&(re)->qparam)
|
|
||||||
#define qse_htre_getqparamptr(re) QSE_MBS_PTR(&(re)->qparam)
|
|
||||||
#define qse_htre_getqparamlen(re) QSE_MBS_LEN(&(re)->qparam)
|
|
||||||
|
|
||||||
#define qse_htre_getsmessage(re) (&(re)->qpath_or_smesg)
|
|
||||||
#define qse_htre_getsmessagexstr(re) QSE_MBS_XSTR(&(re)->qpath_or_smesg)
|
|
||||||
#define qse_htre_getsmessagecstr(re) QSE_MBS_CSTR(&(re)->qpath_or_smesg)
|
|
||||||
#define qse_htre_getsmessageptr(re) QSE_MBS_PTR(&(re)->qpath_or_smesg)
|
|
||||||
#define qse_htre_getsmessagelen(re) QSE_MBS_LEN(&(re)->qpath_or_smesg)
|
|
||||||
|
|
||||||
#define qse_htre_getcontent(re) (&(re)->content)
|
#define qse_htre_getcontent(re) (&(re)->content)
|
||||||
#define qse_htre_getcontentxstr(re) QSE_MBS_XSTR(&(re)->content)
|
#define qse_htre_getcontentxstr(re) QSE_MBS_XSTR(&(re)->content)
|
||||||
@ -111,21 +123,6 @@ struct qse_htre_t
|
|||||||
#define qse_htre_getcontentptr(re) QSE_MBS_PTR(&(re)->content)
|
#define qse_htre_getcontentptr(re) QSE_MBS_PTR(&(re)->content)
|
||||||
#define qse_htre_getcontentlen(re) QSE_MBS_LEN(&(re)->content)
|
#define qse_htre_getcontentlen(re) QSE_MBS_LEN(&(re)->content)
|
||||||
|
|
||||||
#define qse_htre_setqpathfromcstr(re,v) \
|
|
||||||
qse_htre_setstrfromcstr((re),qse_htre_getqpath(re),(v))
|
|
||||||
#define qse_htre_setqpathfromxstr(re,v) \
|
|
||||||
qse_htre_setstrfromxstr((re),qse_htre_getqpath(re),(v))
|
|
||||||
|
|
||||||
#define qse_htre_setqparamfromcstr(re,v) \
|
|
||||||
qse_htre_setstrfromcstr((re),qse_htre_getqparam(re),(v))
|
|
||||||
#define qse_htre_setqparamfromxstr(re,v) \
|
|
||||||
qse_htre_setstrfromxstr((re),qse_htre_getqparam(re),(v))
|
|
||||||
|
|
||||||
#define qse_htre_setsmessagefromcstr(re,v) \
|
|
||||||
qse_htre_setstrfromcstr((re),qse_htre_getsmessage(re),(v))
|
|
||||||
#define qse_htre_setsmessagefromxstr(re,v) \
|
|
||||||
qse_htre_setstrfromxstr((re),qse_htre_getsmessage(re),(v))
|
|
||||||
|
|
||||||
typedef int (*qse_htre_header_walker_t) (
|
typedef int (*qse_htre_header_walker_t) (
|
||||||
qse_htre_t* re,
|
qse_htre_t* re,
|
||||||
const qse_mchar_t* key,
|
const qse_mchar_t* key,
|
||||||
@ -204,10 +201,6 @@ void qse_htre_setconcb (
|
|||||||
void* ctx
|
void* ctx
|
||||||
);
|
);
|
||||||
|
|
||||||
const qse_mchar_t* qse_htre_getqmethodname (
|
|
||||||
const qse_htre_t* re
|
|
||||||
);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -223,21 +223,28 @@ static qse_mchar_t* parse_initial_line (
|
|||||||
do { p++; } while (is_upalpha_octet(*p));
|
do { p++; } while (is_upalpha_octet(*p));
|
||||||
tmp.len = p - tmp.ptr;
|
tmp.len = p - tmp.ptr;
|
||||||
|
|
||||||
htrd->retype = QSE_HTRD_RETYPE_Q;
|
htrd->re.type = QSE_HTRE_Q;
|
||||||
if (htrd->option & QSE_HTRD_REQUEST)
|
if (htrd->option & QSE_HTRD_REQUEST)
|
||||||
{
|
{
|
||||||
qse_htre_setqmethod (&htrd->re, qse_mcstrtohttpmethod (&tmp));
|
/* method name must be followed by space */
|
||||||
|
if (!is_space_octet(*p)) goto badre;
|
||||||
|
|
||||||
|
*p = QSE_MT('\0'); /* null-terminate the method name */
|
||||||
|
|
||||||
|
htrd->re.u.q.method.type = qse_mcstrtohttpmethod (&tmp);
|
||||||
|
htrd->re.u.q.method.name = tmp.ptr;
|
||||||
}
|
}
|
||||||
else if ((htrd->option & QSE_HTRD_RESPONSE) &&
|
else if ((htrd->option & QSE_HTRD_RESPONSE) &&
|
||||||
qse_mbsxcmp (tmp.ptr, tmp.len, QSE_MT("HTTP")) == 0)
|
qse_mbsxcmp (tmp.ptr, tmp.len, QSE_MT("HTTP")) == 0)
|
||||||
{
|
{
|
||||||
/* it begins with HTTP. it may be a response */
|
/* it begins with HTTP. it may be a response */
|
||||||
htrd->retype = QSE_HTRD_RETYPE_S;
|
htrd->re.type = QSE_HTRE_S;
|
||||||
}
|
}
|
||||||
else goto badre;
|
else goto badre;
|
||||||
|
|
||||||
if (htrd->retype == QSE_HTRD_RETYPE_S)
|
if (htrd->re.type == QSE_HTRE_S)
|
||||||
{
|
{
|
||||||
|
/* response */
|
||||||
int n, status;
|
int n, status;
|
||||||
|
|
||||||
if (*p == QSE_MT('/') && p[1] != QSE_MT('\0') && p[2] == QSE_MT('.'))
|
if (*p == QSE_MT('/') && p[1] != QSE_MT('\0') && p[2] == QSE_MT('.'))
|
||||||
@ -254,15 +261,19 @@ static qse_mchar_t* parse_initial_line (
|
|||||||
}
|
}
|
||||||
else goto badre;
|
else goto badre;
|
||||||
|
|
||||||
/* htrd version must be followed by space */
|
/* version must be followed by space */
|
||||||
if (!is_space_octet(*p)) goto badre;
|
if (!is_space_octet(*p)) goto badre;
|
||||||
|
|
||||||
|
*p = QSE_MT('\0'); /* null-terminate version string */
|
||||||
|
htrd->re.verstr = tmp.ptr;
|
||||||
|
|
||||||
/* skip spaces */
|
/* skip spaces */
|
||||||
do p++; while (is_space_octet(*p));
|
do p++; while (is_space_octet(*p));
|
||||||
|
|
||||||
n = digit_to_num(*p);
|
n = digit_to_num(*p);
|
||||||
if (n <= -1) goto badre;
|
if (n <= -1) goto badre;
|
||||||
|
|
||||||
|
tmp.ptr = p;
|
||||||
status = 0;
|
status = 0;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
@ -271,37 +282,39 @@ static qse_mchar_t* parse_initial_line (
|
|||||||
}
|
}
|
||||||
while ((n = digit_to_num(*p)) >= 0);
|
while ((n = digit_to_num(*p)) >= 0);
|
||||||
|
|
||||||
qse_htre_setsstatus (&htrd->re, status);
|
if (!is_space_octet(*p)) goto badre;
|
||||||
|
*p = QSE_MT('\0'); /* null-terminate the status code */
|
||||||
|
|
||||||
/* i don't treat the following weird messages as bad message
|
htrd->re.u.s.code.val = status;
|
||||||
|
htrd->re.u.s.code.str = tmp.ptr;
|
||||||
|
|
||||||
|
/* i don't treat the following weird messages as bad message:
|
||||||
* no status message follows the status code
|
* no status message follows the status code
|
||||||
* no space between the status code and the status message
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* skip spaces */
|
/* skip spaces */
|
||||||
while (is_space_octet(*p)) p++;
|
do p++; while (is_space_octet(*p));
|
||||||
|
|
||||||
tmp.ptr = p;
|
tmp.ptr = p;
|
||||||
while (*p != QSE_MT('\0') && *p != QSE_MT('\n')) p++;
|
tmp.len = 0;
|
||||||
tmp.len = p - tmp.ptr;
|
while (*p != QSE_MT('\0') && *p != QSE_MT('\n'))
|
||||||
|
|
||||||
if (qse_htre_setsmessagefromcstr (&htrd->re, &tmp) <= -1) goto outofmem;
|
|
||||||
|
|
||||||
/* adjust Connection: Keep-Alive for HTTP 1.1 or later */
|
|
||||||
if (htrd->re.version.major > 1 ||
|
|
||||||
(htrd->re.version.major == 1 && htrd->re.version.minor >= 1))
|
|
||||||
{
|
{
|
||||||
htrd->re.attr.keepalive = 1;
|
if (!is_space_octet(*p)) tmp.len = p - tmp.ptr + 1;
|
||||||
|
p++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* if the line does not end with a new line, it is a bad request */
|
||||||
|
if (*p != QSE_T('\n')) goto badre;
|
||||||
|
|
||||||
|
/* null-terminate the message */
|
||||||
|
((qse_mchar_t*)tmp.ptr)[tmp.len] = QSE_MT('\0');
|
||||||
|
htrd->re.u.s.mesg = tmp.ptr;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
qse_mchar_t* out;
|
qse_mchar_t* out;
|
||||||
qse_mcstr_t param;
|
qse_mcstr_t param;
|
||||||
|
|
||||||
/* method name must be followed by space */
|
|
||||||
if (!is_space_octet(*p)) goto badre;
|
|
||||||
|
|
||||||
/* skip spaces */
|
/* skip spaces */
|
||||||
do p++; while (is_space_octet(*p));
|
do p++; while (is_space_octet(*p));
|
||||||
|
|
||||||
@ -314,8 +327,8 @@ static qse_mchar_t* parse_initial_line (
|
|||||||
{
|
{
|
||||||
if (*p == QSE_MT('%') && param.ptr == QSE_NULL)
|
if (*p == QSE_MT('%') && param.ptr == QSE_NULL)
|
||||||
{
|
{
|
||||||
/* decode percence-encoded charaters in the
|
/* decode percent-encoded charaters in the
|
||||||
* path part. if we're in the parameter string
|
* path part. if we're in the parameter string
|
||||||
* part, we don't decode them. */
|
* part, we don't decode them. */
|
||||||
|
|
||||||
int q = xdigit_to_num(*(p+1));
|
int q = xdigit_to_num(*(p+1));
|
||||||
@ -339,7 +352,7 @@ static qse_mchar_t* parse_initial_line (
|
|||||||
{
|
{
|
||||||
if (!param.ptr)
|
if (!param.ptr)
|
||||||
{
|
{
|
||||||
/* ? must be explicit to be a argument instroducer.
|
/* ? must be explicit to be an argument instroducer.
|
||||||
* %3f is just a literal. */
|
* %3f is just a literal. */
|
||||||
tmp.len = out - tmp.ptr;
|
tmp.len = out - tmp.ptr;
|
||||||
*out++ = QSE_MT('\0'); /* null-terminate the path part */
|
*out++ = QSE_MT('\0'); /* null-terminate the path part */
|
||||||
@ -360,15 +373,20 @@ static qse_mchar_t* parse_initial_line (
|
|||||||
if (param.ptr)
|
if (param.ptr)
|
||||||
{
|
{
|
||||||
param.len = out - param.ptr;
|
param.len = out - param.ptr;
|
||||||
if (qse_htre_setqparamfromcstr (&htrd->re, ¶m) <= -1) goto outofmem;
|
htrd->re.u.q.path = tmp.ptr;
|
||||||
|
htrd->re.u.q.param = param.ptr;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tmp.len = out - tmp.ptr;
|
||||||
|
htrd->re.u.q.path = tmp.ptr;
|
||||||
|
htrd->re.u.q.param = QSE_NULL;
|
||||||
}
|
}
|
||||||
else tmp.len = out - tmp.ptr;
|
|
||||||
|
|
||||||
if (qse_htre_setqpathfromcstr (&htrd->re, &tmp) <= -1) goto outofmem;
|
|
||||||
|
|
||||||
/* skip spaces after the url part */
|
/* skip spaces after the url part */
|
||||||
do { p++; } while (is_space_octet(*p));
|
do { p++; } while (is_space_octet(*p));
|
||||||
|
|
||||||
|
tmp.ptr = p;
|
||||||
/* check protocol version */
|
/* check protocol version */
|
||||||
if ((p[0] == 'H' || p[0] == 'h') &&
|
if ((p[0] == 'H' || p[0] == 'h') &&
|
||||||
(p[1] == 'T' || p[1] == 't') &&
|
(p[1] == 'T' || p[1] == 't') &&
|
||||||
@ -388,30 +406,30 @@ static qse_mchar_t* parse_initial_line (
|
|||||||
}
|
}
|
||||||
else goto badre;
|
else goto badre;
|
||||||
|
|
||||||
|
tmp.len = p - tmp.ptr;
|
||||||
|
|
||||||
/* skip trailing spaces on the line */
|
/* skip trailing spaces on the line */
|
||||||
while (is_space_octet(*p)) p++;
|
while (is_space_octet(*p)) p++;
|
||||||
|
|
||||||
/* adjust Connection: Keep-Alive for HTTP 1.1 or later */
|
/* if the line does not end with a new line, it is a bad request */
|
||||||
if (htrd->re.version.major > 1 ||
|
if (*p != QSE_T('\n')) goto badre;
|
||||||
(htrd->re.version.major == 1 && htrd->re.version.minor >= 1))
|
|
||||||
{
|
((qse_mchar_t*)tmp.ptr)[tmp.len] = QSE_MT('\0');
|
||||||
htrd->re.attr.keepalive = 1;
|
htrd->re.verstr = tmp.ptr;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if the line does not end with a new line, it is a bad request */
|
/* adjust Connection: Keep-Alive for HTTP 1.1 or later */
|
||||||
if (*p != QSE_T('\n')) goto badre;
|
if (htrd->re.version.major > 1 ||
|
||||||
|
(htrd->re.version.major == 1 && htrd->re.version.minor >= 1))
|
||||||
|
{
|
||||||
|
htrd->re.attr.keepalive = 1;
|
||||||
|
}
|
||||||
|
|
||||||
return ++p;
|
return ++p;
|
||||||
|
|
||||||
badre:
|
badre:
|
||||||
htrd->errnum = QSE_HTRD_EBADRE;
|
htrd->errnum = QSE_HTRD_EBADRE;
|
||||||
return QSE_NULL;
|
return QSE_NULL;
|
||||||
|
|
||||||
outofmem:
|
|
||||||
htrd->errnum = QSE_HTRD_ENOMEM;
|
|
||||||
return QSE_NULL;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void qse_htrd_clear (qse_htrd_t* htrd)
|
void qse_htrd_clear (qse_htrd_t* htrd)
|
||||||
@ -1085,7 +1103,7 @@ int qse_htrd_feed (qse_htrd_t* htrd, const qse_mchar_t* req, qse_size_t len)
|
|||||||
header_completed_during_this_feed = 1;
|
header_completed_during_this_feed = 1;
|
||||||
if (htrd->option & QSE_HTRD_PEEKONLY)
|
if (htrd->option & QSE_HTRD_PEEKONLY)
|
||||||
{
|
{
|
||||||
/* when QSE_HTRD_PEEKONCE is set,
|
/* when QSE_HTRD_PEEKONLY is set,
|
||||||
* the peek callback is invoked once
|
* the peek callback is invoked once
|
||||||
* a complete header is seen. the caller
|
* a complete header is seen. the caller
|
||||||
* should not feed more data by calling
|
* should not feed more data by calling
|
||||||
|
@ -29,16 +29,18 @@ int qse_htre_init (qse_htre_t* re, qse_mmgr_t* mmgr)
|
|||||||
if (qse_htb_init (&re->hdrtab, mmgr, 60, 70, 1, 1) <= -1) return -1;
|
if (qse_htb_init (&re->hdrtab, mmgr, 60, 70, 1, 1) <= -1) return -1;
|
||||||
|
|
||||||
qse_mbs_init (&re->content, mmgr, 0);
|
qse_mbs_init (&re->content, mmgr, 0);
|
||||||
qse_mbs_init (&re->qpath_or_smesg, mmgr, 0);
|
#if 0
|
||||||
qse_mbs_init (&re->qparam, mmgr, 0);
|
qse_mbs_init (&re->iniline, mmgr, 0);
|
||||||
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void qse_htre_fini (qse_htre_t* re)
|
void qse_htre_fini (qse_htre_t* re)
|
||||||
{
|
{
|
||||||
qse_mbs_fini (&re->qparam);
|
#if 0
|
||||||
qse_mbs_fini (&re->qpath_or_smesg);
|
qse_mbs_fini (&re->iniline);
|
||||||
|
#endif
|
||||||
qse_mbs_fini (&re->content);
|
qse_mbs_fini (&re->content);
|
||||||
qse_htb_fini (&re->hdrtab);
|
qse_htb_fini (&re->hdrtab);
|
||||||
}
|
}
|
||||||
@ -55,14 +57,17 @@ void qse_htre_clear (qse_htre_t* re)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
re->state = 0;
|
||||||
|
|
||||||
QSE_MEMSET (&re->version, 0, QSE_SIZEOF(re->version));
|
QSE_MEMSET (&re->version, 0, QSE_SIZEOF(re->version));
|
||||||
QSE_MEMSET (&re->attr, 0, QSE_SIZEOF(re->attr));
|
QSE_MEMSET (&re->attr, 0, QSE_SIZEOF(re->attr));
|
||||||
|
|
||||||
qse_htb_clear (&re->hdrtab);
|
qse_htb_clear (&re->hdrtab);
|
||||||
|
|
||||||
qse_mbs_clear (&re->content);
|
qse_mbs_clear (&re->content);
|
||||||
qse_mbs_clear (&re->qpath_or_smesg);
|
#if 0
|
||||||
qse_mbs_clear (&re->qparam);
|
qse_mbs_clear (&re->iniline);
|
||||||
|
#endif
|
||||||
re->state = 0;
|
re->state = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -134,8 +139,7 @@ int qse_htre_addcontent (
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* if the callback is not set, the contents goes to the internal buffer */
|
/* if the callback is not set, the contents goes to the internal buffer */
|
||||||
if (qse_mbs_ncat (&re->content, ptr, len) == (qse_size_t)-1)
|
if (qse_mbs_ncat (&re->content, ptr, len) == (qse_size_t)-1) return -1;
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1; /* added successfully */
|
return 1; /* added successfully */
|
||||||
@ -203,7 +207,3 @@ void qse_htre_setconcb (qse_htre_t* re, qse_htre_concb_t concb, void* ctx)
|
|||||||
re->concb_ctx = ctx;
|
re->concb_ctx = ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
const qse_mchar_t* qse_htre_getqmethodname (const qse_htre_t* re)
|
|
||||||
{
|
|
||||||
return qse_httpmethodtombs (re->qmethod_or_sstatus);
|
|
||||||
}
|
|
||||||
|
@ -1469,20 +1469,18 @@ static qse_env_t* makecgienv (
|
|||||||
|
|
||||||
{
|
{
|
||||||
/* TODO: corrent all these name??? */
|
/* TODO: corrent all these name??? */
|
||||||
qse_mchar_t tmp[1024];
|
//qse_env_insertmbs (env, QSE_MT("SCRIPT_NAME"), qse_htre_getqpath(req));
|
||||||
qse_mbsxncpy (tmp, QSE_COUNTOF(tmp), qse_htre_getqpathptr(req), qse_htre_getqpathlen(req));
|
//qse_env_insertmbs (env, QSE_MT("PATH_INFO"), qse_htre_getqpath(req));
|
||||||
//qse_env_insertmbs (env, QSE_MT("SCRIPT_NAME"), tmp);
|
//qse_env_insertmbs (env, QSE_MT("PATH_TRANSLATED"), qse_htre_getqpath(req));
|
||||||
//qse_env_insertmbs (env, QSE_MT("PATH_INFO"), tmp);
|
|
||||||
//qse_env_insertmbs (env, QSE_MT("PATH_TRANSLATED"), tmp);
|
|
||||||
//qse_env_insertmbs (env, QSE_MT("DOCUMENT_ROOT"), QSE_MT("/"));
|
//qse_env_insertmbs (env, QSE_MT("DOCUMENT_ROOT"), QSE_MT("/"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//qse_env_insertmbs (env, QSE_MT("SCRIPT_FILENAME"), path);
|
//qse_env_insertmbs (env, QSE_MT("SCRIPT_FILENAME"), path);
|
||||||
qse_env_insertmbs (env, QSE_MT("REQUEST_URI"), qse_htre_getqpathptr(req));
|
qse_env_insertmbs (env, QSE_MT("REQUEST_URI"), qse_htre_getqpath(req));
|
||||||
|
|
||||||
{
|
{
|
||||||
qse_mchar_t* tmp = qse_htre_getqparamptr(req);
|
qse_mchar_t* tmp = qse_htre_getqparam(req);
|
||||||
if (tmp) qse_env_insertmbs (env, QSE_MT("QUERY_STRING"), tmp);
|
if (tmp) qse_env_insertmbs (env, QSE_MT("QUERY_STRING"), tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1855,21 +1853,24 @@ static int task_main_cgi_5 (
|
|||||||
cgi_forward_content (httpd, task, 1);
|
cgi_forward_content (httpd, task, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
qse_printf (QSE_T("task_main_cgi_5\n"));
|
if (task->trigger[2].mask & QSE_HTTPD_TASK_TRIGGER_WRITABLE)
|
||||||
if (cgi->buflen > 0)
|
|
||||||
{
|
{
|
||||||
/* TODO: check if cgi outputs more than content-length if it is set... */
|
qse_printf (QSE_T("task_main_cgi_5\n"));
|
||||||
httpd->errnum = QSE_HTTPD_ENOERR;
|
if (cgi->buflen > 0)
|
||||||
n = httpd->cbs->client.send (httpd, client, cgi->buf, cgi->buflen);
|
|
||||||
if (n <= -1)
|
|
||||||
{
|
{
|
||||||
|
/* TODO: check if cgi outputs more than content-length if it is set... */
|
||||||
|
httpd->errnum = QSE_HTTPD_ENOERR;
|
||||||
|
n = httpd->cbs->client.send (httpd, client, cgi->buf, cgi->buflen);
|
||||||
|
if (n <= -1)
|
||||||
|
{
|
||||||
/* can't return internal server error any more... */
|
/* can't return internal server error any more... */
|
||||||
/* TODO: logging ... */
|
/* TODO: logging ... */
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
QSE_MEMCPY (&cgi->buf[0], &cgi->buf[n], cgi->buflen - n);
|
QSE_MEMCPY (&cgi->buf[0], &cgi->buf[n], cgi->buflen - n);
|
||||||
cgi->buflen -= n;
|
cgi->buflen -= n;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if forwarding didn't finish, something is not really right...
|
/* if forwarding didn't finish, something is not really right...
|
||||||
@ -1901,26 +1902,22 @@ qse_printf (QSE_T("task_main_cgi_4 trigger[0].mask=%d trigger[1].mask=%d trigger
|
|||||||
|
|
||||||
if (task->trigger[0].mask & QSE_HTTPD_TASK_TRIGGER_READABLE)
|
if (task->trigger[0].mask & QSE_HTTPD_TASK_TRIGGER_READABLE)
|
||||||
{
|
{
|
||||||
/* this function assumes that the chunk length does not exceeded
|
|
||||||
* 4 hexadecimal digits. */
|
|
||||||
QSE_ASSERT (QSE_SIZEOF(cgi->buf) <= 0xFFFF);
|
|
||||||
|
|
||||||
qse_printf (QSE_T("task_main_cgi_4\n"));
|
|
||||||
|
|
||||||
|
qse_printf (QSE_T("TASK_MAIN_CGI_4\n"));
|
||||||
if (cgi->content_chunked)
|
if (cgi->content_chunked)
|
||||||
{
|
{
|
||||||
qse_size_t count, extra;
|
qse_size_t count, extra;
|
||||||
qse_mchar_t chunklen[7];
|
qse_mchar_t chunklen[7];
|
||||||
|
|
||||||
|
/* this function assumes that the chunk length does not
|
||||||
|
* exceed 4 hexadecimal digits. */
|
||||||
|
QSE_ASSERT (QSE_SIZEOF(cgi->buf) <= 0xFFFF);
|
||||||
|
|
||||||
qse_printf (QSE_T("READING CHUNKED MODE...\n"));
|
qse_printf (QSE_T("READING CHUNKED MODE...\n"));
|
||||||
extra = (QSE_SIZEOF(chunklen) - 1) + 2;
|
extra = (QSE_SIZEOF(chunklen) - 1) + 2;
|
||||||
count = QSE_SIZEOF(cgi->buf) - cgi->buflen;
|
count = QSE_SIZEOF(cgi->buf) - cgi->buflen;
|
||||||
if (count > extra)
|
if (count > extra)
|
||||||
{
|
{
|
||||||
|
|
||||||
/* TODO: check if cgi outputs more than content-length if it is set... */
|
|
||||||
/* <- can i make it non-block?? or use select??? pio_tryread()? */
|
|
||||||
|
|
||||||
n = qse_pio_read (
|
n = qse_pio_read (
|
||||||
&cgi->pio, QSE_PIO_OUT,
|
&cgi->pio, QSE_PIO_OUT,
|
||||||
&cgi->buf[cgi->buflen + QSE_SIZEOF(chunklen) - 1],
|
&cgi->buf[cgi->buflen + QSE_SIZEOF(chunklen) - 1],
|
||||||
@ -1935,7 +1932,6 @@ qse_printf (QSE_T("task_main_cgi_4 trigger[0].mask=%d trigger[1].mask=%d trigger
|
|||||||
if (n == 0)
|
if (n == 0)
|
||||||
{
|
{
|
||||||
/* the cgi script closed the output */
|
/* the cgi script closed the output */
|
||||||
task->trigger[0].mask = 0;
|
|
||||||
|
|
||||||
cgi->buf[cgi->buflen++] = QSE_MT('0');
|
cgi->buf[cgi->buflen++] = QSE_MT('0');
|
||||||
cgi->buf[cgi->buflen++] = QSE_MT('\r');
|
cgi->buf[cgi->buflen++] = QSE_MT('\r');
|
||||||
@ -1944,9 +1940,9 @@ qse_printf (QSE_T("task_main_cgi_4 trigger[0].mask=%d trigger[1].mask=%d trigger
|
|||||||
cgi->buf[cgi->buflen++] = QSE_MT('\n');
|
cgi->buf[cgi->buflen++] = QSE_MT('\n');
|
||||||
|
|
||||||
task->main = task_main_cgi_5;
|
task->main = task_main_cgi_5;
|
||||||
/* ok to chain-call since this task is called
|
task->trigger[0].mask = 0;
|
||||||
* if the client-side is writable */
|
task->trigger[2].mask |= QSE_HTTPD_TASK_TRIGGER_WRITE;
|
||||||
return task_main_cgi_5 (httpd, client, task);
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set the chunk length */
|
/* set the chunk length */
|
||||||
@ -1961,46 +1957,57 @@ qse_printf (QSE_T("task_main_cgi_4 trigger[0].mask=%d trigger[1].mask=%d trigger
|
|||||||
cgi->buf[cgi->buflen++] = QSE_MT('\n');
|
cgi->buf[cgi->buflen++] = QSE_MT('\n');
|
||||||
|
|
||||||
cgi->content_received += n;
|
cgi->content_received += n;
|
||||||
|
|
||||||
|
if (cgi->content_length_set &&
|
||||||
|
cgi->content_received > cgi->content_length)
|
||||||
|
{
|
||||||
|
/* TODO: cgi returning too much data... something is wrong in CGI */
|
||||||
|
qse_printf (QSE_T("CGI FUCKED UP...RETURNING TOO MUCH DATA\n"));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
qse_printf (QSE_T("READING IN NON-CHUNKED MODE...\n"));
|
qse_printf (QSE_T("READING IN NON-CHUNKED MODE...\n"));
|
||||||
n = qse_pio_read (
|
if (cgi->buflen < QSE_SIZEOF(cgi->buf))
|
||||||
&cgi->pio, QSE_PIO_OUT,
|
|
||||||
&cgi->buf[cgi->buflen],
|
|
||||||
QSE_SIZEOF(cgi->buf) - cgi->buflen
|
|
||||||
);
|
|
||||||
if (n <= -1)
|
|
||||||
{
|
{
|
||||||
/* can't return internal server error any more... */
|
n = qse_pio_read (
|
||||||
|
&cgi->pio, QSE_PIO_OUT,
|
||||||
|
&cgi->buf[cgi->buflen],
|
||||||
|
QSE_SIZEOF(cgi->buf) - cgi->buflen
|
||||||
|
);
|
||||||
|
if (n <= -1)
|
||||||
|
{
|
||||||
|
/* can't return internal server error any more... */
|
||||||
/* TODO: loggig ... */
|
/* TODO: loggig ... */
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (n == 0)
|
if (n == 0)
|
||||||
{
|
{
|
||||||
task->trigger[0].mask = 0;
|
task->main = task_main_cgi_5;
|
||||||
task->main = task_main_cgi_5;
|
task->trigger[0].mask = 0;
|
||||||
/* ok to chain-call since this task is called
|
task->trigger[2].mask |= QSE_HTTPD_TASK_TRIGGER_WRITE;
|
||||||
* if the client-side is writable */
|
return 1;
|
||||||
return task_main_cgi_5 (httpd, client, task);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
cgi->buflen += n;
|
cgi->buflen += n;
|
||||||
cgi->content_received += n;
|
cgi->content_received += n;
|
||||||
}
|
|
||||||
|
if (cgi->content_length_set &&
|
||||||
if (cgi->content_length_set &&
|
cgi->content_received > cgi->content_length)
|
||||||
cgi->content_received > cgi->content_length)
|
{
|
||||||
{
|
|
||||||
/* TODO: cgi returning too much data... something is wrong in CGI */
|
/* TODO: cgi returning too much data... something is wrong in CGI */
|
||||||
qse_printf (QSE_T("CGI FUCKED UP...RETURNING TOO MUCH DATA\n"));
|
qse_printf (QSE_T("CGI FUCKED UP...RETURNING TOO MUCH DATA\n"));
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
/* the main loop invokes the task function only if the client
|
||||||
qse_printf (QSE_T("CGI_4 SEND [%.*hs]\n"), (int)cgi->buflen, cgi->buf);
|
* side is writable. it should be safe to write whenever
|
||||||
#endif
|
* this task function is called. */
|
||||||
|
|
||||||
httpd->errnum = QSE_HTTPD_ENOERR;
|
httpd->errnum = QSE_HTTPD_ENOERR;
|
||||||
n = httpd->cbs->client.send (httpd, client, cgi->buf, cgi->buflen);
|
n = httpd->cbs->client.send (httpd, client, cgi->buf, cgi->buflen);
|
||||||
if (n <= -1)
|
if (n <= -1)
|
||||||
@ -2013,10 +2020,6 @@ qse_printf (QSE_T("CGI_4 SEND [%.*hs]\n"), (int)cgi->buflen, cgi->buf);
|
|||||||
|
|
||||||
QSE_MEMCPY (&cgi->buf[0], &cgi->buf[n], cgi->buflen - n);
|
QSE_MEMCPY (&cgi->buf[0], &cgi->buf[n], cgi->buflen - n);
|
||||||
cgi->buflen -= n;
|
cgi->buflen -= n;
|
||||||
|
|
||||||
#if 0
|
|
||||||
qse_printf (QSE_T("CGI SEND DONE\n"));
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
@ -2041,7 +2044,9 @@ static int task_main_cgi_3 (
|
|||||||
cgi_forward_content (httpd, task, 1);
|
cgi_forward_content (httpd, task, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (task->trigger[0].mask & QSE_HTTPD_TASK_TRIGGER_READABLE)
|
/* send the partial reponse received with the initial line and headers
|
||||||
|
* so long as the client-side handle is writable... */
|
||||||
|
if (task->trigger[2].mask & QSE_HTTPD_TASK_TRIGGER_WRITABLE)
|
||||||
{
|
{
|
||||||
count = MAX_SEND_SIZE;
|
count = MAX_SEND_SIZE;
|
||||||
if (count >= cgi->res_left) count = cgi->res_left;
|
if (count >= cgi->res_left) count = cgi->res_left;
|
||||||
@ -2061,10 +2066,7 @@ qse_printf (QSE_T("[cgi-3 send failure....\n"));
|
|||||||
{
|
{
|
||||||
qse_printf (QSE_T("[switching to cgi-4....\n"));
|
qse_printf (QSE_T("[switching to cgi-4....\n"));
|
||||||
task->main = task_main_cgi_4;
|
task->main = task_main_cgi_4;
|
||||||
/* don't chain-call task_main_cgi_4 since it has another send
|
task->trigger[2].mask &= ~QSE_HTTPD_TASK_TRIGGER_WRITE;
|
||||||
* and it has already been sent here. so the writability must
|
|
||||||
* be checked again in the main loop.
|
|
||||||
* => return task_main_cgi_4 (httpd, client, task);*/
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2161,9 +2163,8 @@ qse_printf (QSE_T("#####INVALID HEADER FROM FROM CHILD [%.*hs]\n"), (int)cgi->bu
|
|||||||
|
|
||||||
qse_printf (QSE_T("TRAILING DATA=[%.*hs]\n"), (int)QSE_MBS_LEN(cgi->res), QSE_MBS_PTR(cgi->res));
|
qse_printf (QSE_T("TRAILING DATA=[%.*hs]\n"), (int)QSE_MBS_LEN(cgi->res), QSE_MBS_PTR(cgi->res));
|
||||||
task->main = task_main_cgi_3;
|
task->main = task_main_cgi_3;
|
||||||
/* ok to chain-call since this task is called
|
task->trigger[2].mask |= QSE_HTTPD_TASK_TRIGGER_WRITE;
|
||||||
* only if the client-side is writable */
|
return 1;
|
||||||
return task_main_cgi_3 (httpd, client, task);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -2255,7 +2256,8 @@ static int task_main_cgi (
|
|||||||
task->trigger[2].mask = QSE_HTTPD_TASK_TRIGGER_READ;
|
task->trigger[2].mask = QSE_HTTPD_TASK_TRIGGER_READ;
|
||||||
task->trigger[2].handle = client->handle;
|
task->trigger[2].handle = client->handle;
|
||||||
}
|
}
|
||||||
else if (QSE_MBS_LEN(cgi->reqfwdbuf) > 0)
|
|
||||||
|
if (QSE_MBS_LEN(cgi->reqfwdbuf) > 0)
|
||||||
{
|
{
|
||||||
/* there's nothing more to read from the client side but
|
/* there's nothing more to read from the client side but
|
||||||
* some contents are already read into the forwarding buffer.
|
* some contents are already read into the forwarding buffer.
|
||||||
@ -2284,9 +2286,6 @@ qse_printf (QSE_T("FORWARDING INITIAL PART OF CONTENT...\n"));
|
|||||||
}
|
}
|
||||||
|
|
||||||
task->main = cgi->nph? task_main_cgi_4: task_main_cgi_2;
|
task->main = cgi->nph? task_main_cgi_4: task_main_cgi_2;
|
||||||
/* no chain call since readability and writability needs
|
|
||||||
* to be checked in the main loop
|
|
||||||
return task->main (httpd, client, task); */
|
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
oops:
|
oops:
|
||||||
@ -2379,13 +2378,13 @@ struct task_proxy_t
|
|||||||
int reqfwderr;
|
int reqfwderr;
|
||||||
|
|
||||||
qse_mbs_t* res;
|
qse_mbs_t* res;
|
||||||
qse_mchar_t* res_ptr;
|
qse_size_t res_consumed;
|
||||||
qse_size_t res_left;
|
qse_size_t res_pending;
|
||||||
|
|
||||||
|
int expect_100;
|
||||||
|
|
||||||
/* if true, close connection after response is sent out */
|
/* if true, close connection after response is sent out */
|
||||||
int disconnect;
|
int disconnect;
|
||||||
/* if true, the content of response is chunked */
|
|
||||||
int content_chunked;
|
|
||||||
/* if true, content_length is set. */
|
/* if true, content_length is set. */
|
||||||
int content_length_set;
|
int content_length_set;
|
||||||
/* content-length that CGI returned */
|
/* content-length that CGI returned */
|
||||||
@ -2460,16 +2459,77 @@ qse_printf (QSE_T("!!!PROXY SNATCHED [%.*hs]\n"), len, ptr);
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int add_header_to_proxy_resbuf (qse_htre_t* req, const qse_mchar_t* key, const qse_mchar_t* val, void* ctx)
|
||||||
|
{
|
||||||
|
task_proxy_t* proxy = (task_proxy_t*)ctx;
|
||||||
|
|
||||||
|
if (qse_mbs_cat (proxy->res, key) == (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, val) == (qse_size_t)-1) return -1;
|
||||||
|
if (qse_mbs_cat (proxy->res, QSE_MT("\r\n")) == (qse_size_t)-1) return -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int proxy_htrd_peek_request (qse_htrd_t* htrd, qse_htre_t* req)
|
static int proxy_htrd_peek_request (qse_htrd_t* htrd, qse_htre_t* req)
|
||||||
{
|
{
|
||||||
proxy_htrd_xtn_t* xtn = (proxy_htrd_xtn_t*) qse_htrd_getxtn (htrd);
|
proxy_htrd_xtn_t* xtn = (proxy_htrd_xtn_t*) qse_htrd_getxtn (htrd);
|
||||||
task_proxy_t* proxy = xtn->proxy;
|
task_proxy_t* proxy = xtn->proxy;
|
||||||
|
const qse_mchar_t* mbsptr;
|
||||||
|
|
||||||
/* add initial line and headers to proxy->res */
|
mbsptr = QSE_MBS_PTR(proxy->res);
|
||||||
if (qse_mbs_cat (proxy->res, QSE_MT("\r\n")) == (qse_size_t)-1) return -1;
|
|
||||||
|
|
||||||
/* add any contents received so far to cgi->res */
|
if (proxy->expect_100 > 0 && qse_htre_getscodeval(req) == 100)
|
||||||
if (qse_mbs_ncat (proxy->res, qse_htre_getcontentptr(req), qse_htre_getcontentlen(req)) == (qse_size_t)-1) return -1;
|
{
|
||||||
|
/* TODO: check if the request contained Expect... */
|
||||||
|
qse_printf (QSE_T("10000000000000000000000000000 CONTINUE 10000000000000000000000000000000\n"));
|
||||||
|
proxy->expect_100 = 0;
|
||||||
|
|
||||||
|
if (qse_mbs_cat (proxy->res, qse_htre_getverstr(req)) == (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(req)) == (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(req)) == (qse_size_t)-1) return -1;
|
||||||
|
if (qse_mbs_cat (proxy->res, QSE_MT("\r\n\r\n")) == (qse_size_t)-1) return -1;
|
||||||
|
|
||||||
|
/* '100 continue' should not include contents. drop them if any */
|
||||||
|
qse_htre_discardcontent (req);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* add initial line and headers to proxy->res */
|
||||||
|
proxy->expect_100 = -1;
|
||||||
|
|
||||||
|
qse_printf (QSE_T("NORMAL REPLY 222222222222222222222 NORMAL REPLY\n"));
|
||||||
|
if (qse_mbs_cat (proxy->res, qse_htre_getverstr(req)) == (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(req)) == (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(req)) == (qse_size_t)-1) return -1;
|
||||||
|
|
||||||
|
if (qse_mbs_cat (proxy->res, QSE_MT("\r\n")) == (qse_size_t)-1) return -1;
|
||||||
|
if (qse_htre_walkheaders (req, add_header_to_proxy_resbuf, proxy) <= -1) return -1;
|
||||||
|
if (qse_mbs_cat (proxy->res, QSE_MT("\r\n")) == (qse_size_t)-1) return -1;
|
||||||
|
|
||||||
|
/* add any contents received so far to cgi->res */
|
||||||
|
if (qse_mbs_ncat (proxy->res, qse_htre_getcontentptr(req), qse_htre_getcontentlen(req)) == (qse_size_t)-1) return -1;
|
||||||
|
qse_printf (QSE_T("NORMAL REPLY 222222222222222222222 NORMAL REPLY [%hs]\n"), QSE_MBS_PTR(proxy->res));
|
||||||
|
}
|
||||||
|
|
||||||
|
proxy->res_pending = QSE_MBS_LEN(proxy->res) - proxy->res_consumed;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int proxy_htrd_handle_request (qse_htrd_t* htrd, qse_htre_t* req)
|
||||||
|
{
|
||||||
|
proxy_htrd_xtn_t* xtn = (proxy_htrd_xtn_t*) qse_htrd_getxtn (htrd);
|
||||||
|
task_proxy_t* proxy = xtn->proxy;
|
||||||
|
|
||||||
|
if (proxy->expect_100 == 0 || proxy->expect_100 == -2)
|
||||||
|
{
|
||||||
|
qse_printf (QSE_T("SETTIG HTRD TO PEEK ONLY >>>>>>>>>>>>>>>>>>>>>>>>.\n"));
|
||||||
|
qse_htrd_setoption (htrd, qse_htrd_getoption(htrd) | QSE_HTRD_PEEKONLY);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -2477,7 +2537,7 @@ static int proxy_htrd_peek_request (qse_htrd_t* htrd, qse_htre_t* req)
|
|||||||
static qse_htrd_recbs_t proxy_htrd_cbs =
|
static qse_htrd_recbs_t proxy_htrd_cbs =
|
||||||
{
|
{
|
||||||
proxy_htrd_peek_request,
|
proxy_htrd_peek_request,
|
||||||
QSE_NULL /* not needed for proxy */
|
proxy_htrd_handle_request
|
||||||
};
|
};
|
||||||
|
|
||||||
static void proxy_forward_content (
|
static void proxy_forward_content (
|
||||||
@ -2552,6 +2612,17 @@ qse_printf (QSE_T("FORWARD: @@@@@@@@NOTHING MORE TO WRITE TO PROXY\n"));
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int add_header_to_proxy_fwdbuf (qse_htre_t* req, const qse_mchar_t* key, const qse_mchar_t* val, void* ctx)
|
||||||
|
{
|
||||||
|
task_proxy_t* proxy = (task_proxy_t*)ctx;
|
||||||
|
|
||||||
|
if (qse_mbs_cat (proxy->reqfwdbuf, key) == (qse_size_t)-1) return -1;
|
||||||
|
if (qse_mbs_cat (proxy->reqfwdbuf, QSE_MT(": ")) == (qse_size_t)-1) return -1;
|
||||||
|
if (qse_mbs_cat (proxy->reqfwdbuf, val) == (qse_size_t)-1) return -1;
|
||||||
|
if (qse_mbs_cat (proxy->reqfwdbuf, QSE_MT("\r\n")) == (qse_size_t)-1) return -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int task_init_proxy (
|
static int task_init_proxy (
|
||||||
qse_httpd_t* httpd, qse_httpd_client_t* client, qse_httpd_task_t* task)
|
qse_httpd_t* httpd, qse_httpd_client_t* client, qse_httpd_task_t* task)
|
||||||
@ -2565,11 +2636,6 @@ static int task_init_proxy (
|
|||||||
proxy = (task_proxy_t*)qse_httpd_gettaskxtn (httpd, task);
|
proxy = (task_proxy_t*)qse_httpd_gettaskxtn (httpd, task);
|
||||||
arg = (task_proxy_arg_t*)task->ctx;
|
arg = (task_proxy_arg_t*)task->ctx;
|
||||||
|
|
||||||
/* TODO: can content length be a different type???
|
|
||||||
* maybe qse_uintmax_t.... it thinks the data size can be larger than the max pointer size
|
|
||||||
* qse_htre_t and qse_htrd_t also needs changes to support it
|
|
||||||
*/
|
|
||||||
|
|
||||||
QSE_MEMSET (proxy, 0, QSE_SIZEOF(*proxy));
|
QSE_MEMSET (proxy, 0, QSE_SIZEOF(*proxy));
|
||||||
proxy->version = *qse_htre_getversion(arg->req);
|
proxy->version = *qse_htre_getversion(arg->req);
|
||||||
proxy->keepalive = arg->req->attr.keepalive;
|
proxy->keepalive = arg->req->attr.keepalive;
|
||||||
@ -2580,6 +2646,36 @@ static int task_init_proxy (
|
|||||||
* TODO: also change the content length check logic below...
|
* TODO: also change the content length check logic below...
|
||||||
* -------------------------------------------------------------------- */
|
* -------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* TODO: DETERMINE THIS SIZE */
|
||||||
|
len = 1024;
|
||||||
|
proxy->reqfwdbuf = qse_mbs_open (httpd->mmgr, 0, (len < 512? 512: len));
|
||||||
|
if (proxy->reqfwdbuf == QSE_NULL) goto oops;
|
||||||
|
|
||||||
|
if (qse_mbs_cat (proxy->reqfwdbuf, qse_htre_getqmethodname(arg->req)) == (qse_size_t)-1) goto oops;
|
||||||
|
if (qse_mbs_cat (proxy->reqfwdbuf, QSE_MT(" ")) == (qse_size_t)-1) goto oops;
|
||||||
|
if (qse_mbs_cat (proxy->reqfwdbuf, qse_htre_getqpath(arg->req)) == (qse_size_t)-1) goto oops;
|
||||||
|
if (qse_htre_getqparam(arg->req))
|
||||||
|
{
|
||||||
|
if (qse_mbs_cat (proxy->reqfwdbuf, QSE_MT("?")) == (qse_size_t)-1) goto oops;
|
||||||
|
if (qse_mbs_cat (proxy->reqfwdbuf, qse_htre_getqparam(arg->req)) == (qse_size_t)-1) goto oops;
|
||||||
|
}
|
||||||
|
if (qse_mbs_cat (proxy->reqfwdbuf, QSE_MT(" ")) == (qse_size_t)-1) goto oops;
|
||||||
|
if (qse_mbs_cat (proxy->reqfwdbuf, qse_htre_getverstr(arg->req)) == (qse_size_t)-1) goto oops;
|
||||||
|
|
||||||
|
if (qse_mbs_cat (proxy->reqfwdbuf, QSE_MT("\r\n")) == (qse_size_t)-1) goto oops;
|
||||||
|
if (qse_htre_walkheaders (arg->req, add_header_to_proxy_fwdbuf, proxy) <= -1) goto oops;
|
||||||
|
if (qse_mbs_cat (proxy->reqfwdbuf, QSE_MT("\r\n")) == (qse_size_t)-1) goto oops;
|
||||||
|
|
||||||
|
if (arg->req->attr.expect &&
|
||||||
|
(arg->req->version.major > 1 ||
|
||||||
|
(arg->req->version.major == 1 && arg->req->version.minor >= 1)))
|
||||||
|
{
|
||||||
|
if (qse_mbscasecmp(arg->req->attr.expect, QSE_MT("100-continue")) == 0)
|
||||||
|
{
|
||||||
|
proxy->expect_100 = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (arg->req->state & QSE_HTRE_DISCARDED)
|
if (arg->req->state & QSE_HTRE_DISCARDED)
|
||||||
{
|
{
|
||||||
content_length = 0;
|
content_length = 0;
|
||||||
@ -2610,17 +2706,8 @@ static int task_init_proxy (
|
|||||||
{
|
{
|
||||||
/* create a buffer to hold request content from the client
|
/* create a buffer to hold request content from the client
|
||||||
* and copy content received already */
|
* and copy content received already */
|
||||||
proxy->reqfwdbuf = qse_mbs_open (httpd->mmgr, 0, (len < 512? 512: len));
|
|
||||||
if (proxy->reqfwdbuf == QSE_NULL) goto oops;
|
|
||||||
|
|
||||||
ptr = qse_htre_getcontentptr(arg->req);
|
ptr = qse_htre_getcontentptr(arg->req);
|
||||||
if (qse_mbs_ncpy (proxy->reqfwdbuf, ptr, len) == (qse_size_t)-1)
|
if (qse_mbs_ncat (proxy->reqfwdbuf, ptr, len) == (qse_size_t)-1) goto oops;
|
||||||
{
|
|
||||||
qse_mbs_close (proxy->reqfwdbuf);
|
|
||||||
proxy->reqfwdbuf = QSE_NULL;
|
|
||||||
goto oops;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (arg->req->state & QSE_HTRE_COMPLETED)
|
if (arg->req->state & QSE_HTRE_COMPLETED)
|
||||||
{
|
{
|
||||||
@ -2635,7 +2722,7 @@ static int task_init_proxy (
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* CGI entasking is invoked probably from the peek handler
|
/* proxy entasking is invoked probably from the peek handler
|
||||||
* that was triggered after the request header is received.
|
* that was triggered after the request header is received.
|
||||||
* you can know this because the request is not completed.
|
* you can know this because the request is not completed.
|
||||||
* In this case, arrange to forward content
|
* In this case, arrange to forward content
|
||||||
@ -2661,6 +2748,7 @@ done:
|
|||||||
* will be invoked so long as the client handle is writable by
|
* will be invoked so long as the client handle is writable by
|
||||||
* the main loop. */
|
* the main loop. */
|
||||||
|
|
||||||
|
qse_printf (QSE_T("GOING TO PROXY [%hs]\n"), QSE_MBS_PTR(proxy->reqfwdbuf));
|
||||||
task->ctx = proxy;
|
task->ctx = proxy;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -2668,6 +2756,11 @@ oops:
|
|||||||
/* since a new task can't be added in the initializer,
|
/* since a new task can't be added in the initializer,
|
||||||
* i mark that initialization failed and let task_main_proxy()
|
* i mark that initialization failed and let task_main_proxy()
|
||||||
* add an error task */
|
* add an error task */
|
||||||
|
if (proxy->reqfwdbuf)
|
||||||
|
{
|
||||||
|
qse_mbs_close (proxy->reqfwdbuf);
|
||||||
|
proxy->reqfwdbuf = QSE_NULL;
|
||||||
|
}
|
||||||
proxy->init_failed = 1;
|
proxy->init_failed = 1;
|
||||||
task->ctx = proxy;
|
task->ctx = proxy;
|
||||||
return 0;
|
return 0;
|
||||||
@ -2704,20 +2797,23 @@ static int task_main_proxy_5 (
|
|||||||
}
|
}
|
||||||
|
|
||||||
qse_printf (QSE_T("task_main_proxy_5\n"));
|
qse_printf (QSE_T("task_main_proxy_5\n"));
|
||||||
if (proxy->buflen > 0)
|
if (task->trigger[2].mask & QSE_HTTPD_TASK_TRIGGER_WRITABLE)
|
||||||
{
|
{
|
||||||
/* TODO: check if proxy outputs more than content-length if it is set... */
|
if (proxy->buflen > 0)
|
||||||
httpd->errnum = QSE_HTTPD_ENOERR;
|
|
||||||
n = httpd->cbs->client.send (httpd, client, proxy->buf, proxy->buflen);
|
|
||||||
if (n <= -1)
|
|
||||||
{
|
{
|
||||||
/* can't return internal server error any more... */
|
/* TODO: check if proxy outputs more than content-length if it is set... */
|
||||||
|
httpd->errnum = QSE_HTTPD_ENOERR;
|
||||||
|
n = httpd->cbs->client.send (httpd, client, proxy->buf, proxy->buflen);
|
||||||
|
if (n <= -1)
|
||||||
|
{
|
||||||
|
/* can't return internal server error any more... */
|
||||||
/* TODO: logging ... */
|
/* TODO: logging ... */
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
QSE_MEMCPY (&proxy->buf[0], &proxy->buf[n], proxy->buflen - n);
|
QSE_MEMCPY (&proxy->buf[0], &proxy->buf[n], proxy->buflen - n);
|
||||||
proxy->buflen -= n;
|
proxy->buflen -= n;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if forwarding didn't finish, something is not really right...
|
/* if forwarding didn't finish, something is not really right...
|
||||||
@ -2747,48 +2843,58 @@ qse_printf (QSE_T("task_main_proxy_4 trigger[0].mask=%d trigger[1].mask=%d trigg
|
|||||||
proxy_forward_content (httpd, task, 1);
|
proxy_forward_content (httpd, task, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
qse_printf (QSE_T("task_main_proxy_4 about to read from PEER...\n"));
|
||||||
if (task->trigger[0].mask & QSE_HTTPD_TASK_TRIGGER_READABLE)
|
if (task->trigger[0].mask & QSE_HTTPD_TASK_TRIGGER_READABLE)
|
||||||
{
|
{
|
||||||
/* this function assumes that the chunk length does not exceeded
|
if (proxy->buflen < QSE_SIZEOF(proxy->buf))
|
||||||
* 4 hexadecimal digits. */
|
|
||||||
QSE_ASSERT (QSE_SIZEOF(proxy->buf) <= 0xFFFF);
|
|
||||||
|
|
||||||
qse_printf (QSE_T("task_main_proxy_4\n"));
|
|
||||||
|
|
||||||
n = httpd->cbs->peer.recv (
|
|
||||||
httpd, &proxy->peer,
|
|
||||||
&proxy->buf[proxy->buflen],
|
|
||||||
QSE_SIZEOF(proxy->buf) - proxy->buflen
|
|
||||||
);
|
|
||||||
if (n <= -1)
|
|
||||||
{
|
{
|
||||||
/* can't return internal server error any more... */
|
qse_printf (QSE_T("task_main_proxy_4 reading from PEER... %d %d\n"), (int)proxy->content_length, (int)proxy->content_received);
|
||||||
|
httpd->errnum = QSE_HTTPD_ENOERR;
|
||||||
|
n = httpd->cbs->peer.recv (
|
||||||
|
httpd, &proxy->peer,
|
||||||
|
&proxy->buf[proxy->buflen],
|
||||||
|
QSE_SIZEOF(proxy->buf) - proxy->buflen
|
||||||
|
);
|
||||||
|
qse_printf (QSE_T("task_main_proxy_4 read from PEER...%d\n"), (int)n);
|
||||||
|
if (n <= -1)
|
||||||
|
{
|
||||||
|
/* can't return internal server error any more... */
|
||||||
/* TODO: loggig ... */
|
/* TODO: loggig ... */
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (n == 0)
|
if (n == 0)
|
||||||
{
|
{
|
||||||
task->trigger[0].mask = 0;
|
task->main = task_main_proxy_5;
|
||||||
task->main = task_main_proxy_5;
|
task->trigger[0].mask = 0;
|
||||||
/* ok to chain-call since this task is called
|
task->trigger[2].mask |= QSE_HTTPD_TASK_TRIGGER_WRITE;
|
||||||
* if the client-side is writable */
|
return 1;
|
||||||
return task_main_proxy_5 (httpd, client, task);
|
}
|
||||||
|
|
||||||
|
proxy->buflen += n;
|
||||||
|
proxy->content_received += n;
|
||||||
|
|
||||||
|
if (proxy->content_length_set &&
|
||||||
|
proxy->content_received > proxy->content_length)
|
||||||
|
{
|
||||||
|
/* TODO: proxy returning too much data... something is wrong in PROXY */
|
||||||
|
qse_printf (QSE_T("PROXY FUCKED UP...RETURNING TOO MUCH DATA\n"));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (proxy->content_length_set &&
|
||||||
|
proxy->content_received == proxy->content_length)
|
||||||
|
{
|
||||||
|
qse_printf (QSE_T("PROXY DONE READING\n"));
|
||||||
|
task->main = task_main_proxy_5;
|
||||||
|
task->trigger[0].mask = 0;
|
||||||
|
task->trigger[2].mask |= QSE_HTTPD_TASK_TRIGGER_WRITE;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
proxy->buflen += n;
|
/* the main loop invokes the task function only if the client
|
||||||
proxy->content_received += n;
|
* side is writable. it should be safe to write whenever
|
||||||
|
* this task function is called. */
|
||||||
if (proxy->content_length_set &&
|
|
||||||
proxy->content_received > proxy->content_length)
|
|
||||||
{
|
|
||||||
/* TODO: proxy returning too much data... something is wrong in CGI */
|
|
||||||
qse_printf (QSE_T("CGI FUCKED UP...RETURNING TOO MUCH DATA\n"));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
qse_printf (QSE_T("CGI_4 SEND [%.*hs]\n"), (int)proxy->buflen, proxy->buf);
|
|
||||||
#endif
|
|
||||||
httpd->errnum = QSE_HTTPD_ENOERR;
|
httpd->errnum = QSE_HTTPD_ENOERR;
|
||||||
n = httpd->cbs->client.send (httpd, client, proxy->buf, proxy->buflen);
|
n = httpd->cbs->client.send (httpd, client, proxy->buf, proxy->buflen);
|
||||||
if (n <= -1)
|
if (n <= -1)
|
||||||
@ -2801,10 +2907,6 @@ qse_printf (QSE_T("CGI_4 SEND [%.*hs]\n"), (int)proxy->buflen, proxy->buf);
|
|||||||
|
|
||||||
QSE_MEMCPY (&proxy->buf[0], &proxy->buf[n], proxy->buflen - n);
|
QSE_MEMCPY (&proxy->buf[0], &proxy->buf[n], proxy->buflen - n);
|
||||||
proxy->buflen -= n;
|
proxy->buflen -= n;
|
||||||
|
|
||||||
#if 0
|
|
||||||
qse_printf (QSE_T("CGI SEND DONE\n"));
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
@ -2817,8 +2919,6 @@ static int task_main_proxy_3 (
|
|||||||
* returned by peer. it may include some contents as well */
|
* returned by peer. it may include some contents as well */
|
||||||
|
|
||||||
task_proxy_t* proxy = (task_proxy_t*)task->ctx;
|
task_proxy_t* proxy = (task_proxy_t*)task->ctx;
|
||||||
qse_ssize_t n;
|
|
||||||
qse_size_t count;
|
|
||||||
|
|
||||||
if (task->trigger[2].mask & QSE_HTTPD_TASK_TRIGGER_READABLE)
|
if (task->trigger[2].mask & QSE_HTTPD_TASK_TRIGGER_READABLE)
|
||||||
{
|
{
|
||||||
@ -2829,34 +2929,42 @@ static int task_main_proxy_3 (
|
|||||||
proxy_forward_content (httpd, task, 1);
|
proxy_forward_content (httpd, task, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (task->trigger[0].mask & QSE_HTTPD_TASK_TRIGGER_READABLE)
|
qse_printf (QSE_T("[PROXY-----3]\n"));
|
||||||
|
if (task->trigger[2].mask & QSE_HTTPD_TASK_TRIGGER_WRITABLE)
|
||||||
{
|
{
|
||||||
count = MAX_SEND_SIZE;
|
qse_ssize_t n;
|
||||||
if (count >= proxy->res_left) count = proxy->res_left;
|
qse_size_t count;
|
||||||
|
|
||||||
qse_printf (QSE_T("[proxy_3 sending %d bytes]\n"), (int)count);
|
qse_printf (QSE_T("[PROXY-----3 SENDING XXXXX]\n"));
|
||||||
httpd->errnum = QSE_HTTPD_ENOERR;
|
count = proxy->res_pending;
|
||||||
n = httpd->cbs->client.send (httpd, client, proxy->res_ptr, count);
|
if (count > MAX_SEND_SIZE) count = MAX_SEND_SIZE;
|
||||||
|
|
||||||
if (n <= -1)
|
if (count > 0)
|
||||||
{
|
{
|
||||||
|
qse_printf (QSE_T("[proxy_3 sending %d bytes]\n"), (int)count);
|
||||||
|
httpd->errnum = QSE_HTTPD_ENOERR;
|
||||||
|
n = httpd->cbs->client.send (
|
||||||
|
httpd, client,
|
||||||
|
&QSE_MBS_CHAR(proxy->res,proxy->res_consumed),
|
||||||
|
count
|
||||||
|
);
|
||||||
|
|
||||||
|
if (n <= -1)
|
||||||
|
{
|
||||||
qse_printf (QSE_T("[proxy-3 send failure....\n"));
|
qse_printf (QSE_T("[proxy-3 send failure....\n"));
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
proxy->res_consumed += n;
|
||||||
|
proxy->res_pending -= n;
|
||||||
}
|
}
|
||||||
|
|
||||||
proxy->res_left -= n;
|
if (proxy->res_pending <= 0)
|
||||||
if (proxy->res_left <= 0)
|
|
||||||
{
|
{
|
||||||
qse_printf (QSE_T("[switching to proxy-4....\n"));
|
|
||||||
task->main = task_main_proxy_4;
|
task->main = task_main_proxy_4;
|
||||||
/* don't chain-call task_main_proxy_4 since it has another send
|
task->trigger[2].mask &= ~QSE_HTTPD_TASK_TRIGGER_WRITE;
|
||||||
* and it has already been sent here. so the writability must
|
|
||||||
* be checked again in the main loop.
|
|
||||||
* => return task_main_proxy_4 (httpd, client, task);*/
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
proxy->res_ptr += n;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1; /* more work to do */
|
return 1; /* more work to do */
|
||||||
@ -2867,8 +2975,6 @@ static int task_main_proxy_2 (
|
|||||||
qse_httpd_t* httpd, qse_httpd_client_t* client, qse_httpd_task_t* task)
|
qse_httpd_t* httpd, qse_httpd_client_t* client, qse_httpd_task_t* task)
|
||||||
{
|
{
|
||||||
task_proxy_t* proxy = (task_proxy_t*)task->ctx;
|
task_proxy_t* proxy = (task_proxy_t*)task->ctx;
|
||||||
qse_ssize_t n;
|
|
||||||
qse_size_t count;
|
|
||||||
|
|
||||||
if (task->trigger[2].mask & QSE_HTTPD_TASK_TRIGGER_READABLE)
|
if (task->trigger[2].mask & QSE_HTTPD_TASK_TRIGGER_READABLE)
|
||||||
{
|
{
|
||||||
@ -2879,9 +2985,45 @@ static int task_main_proxy_2 (
|
|||||||
proxy_forward_content (httpd, task, 1);
|
proxy_forward_content (httpd, task, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (proxy->res_pending > 0)
|
||||||
|
{
|
||||||
|
/* the 'if' condition becomes true only if '100 Continue'
|
||||||
|
* is received without an actual reply in a previous call to
|
||||||
|
* qse_htrd_feed() below. Since the actual reply is not
|
||||||
|
* received yet, i just want to read more while realying
|
||||||
|
* '100 Continue' to the client. this task handler is called
|
||||||
|
* only if the client side handle is writable. i can safely
|
||||||
|
* write to the client without a check. */
|
||||||
|
|
||||||
|
qse_ssize_t n;
|
||||||
|
qse_size_t count;
|
||||||
|
|
||||||
|
count = proxy->res_pending;
|
||||||
|
if (count > MAX_SEND_SIZE) count = MAX_SEND_SIZE;
|
||||||
|
|
||||||
|
qse_printf (QSE_T("[proxy_2 sending %d bytes] [%.*hs]\n"), (int)count, (int)count, &QSE_MBS_CHAR(proxy->res,proxy->res_consumed));
|
||||||
|
httpd->errnum = QSE_HTTPD_ENOERR;
|
||||||
|
n = httpd->cbs->client.send (
|
||||||
|
httpd, client,
|
||||||
|
&QSE_MBS_CHAR(proxy->res,proxy->res_consumed),
|
||||||
|
count
|
||||||
|
);
|
||||||
|
if (n <= -1)
|
||||||
|
{
|
||||||
|
qse_printf (QSE_T("[proxy-2 send failure....\n"));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
proxy->res_consumed += n;
|
||||||
|
proxy->res_pending -= n;
|
||||||
|
}
|
||||||
|
|
||||||
if (task->trigger[0].mask & QSE_HTTPD_TASK_TRIGGER_READABLE)
|
if (task->trigger[0].mask & QSE_HTTPD_TASK_TRIGGER_READABLE)
|
||||||
{
|
{
|
||||||
|
qse_ssize_t n;
|
||||||
|
|
||||||
/* there is something to read from peer */
|
/* there is something to read from peer */
|
||||||
|
httpd->errnum = QSE_HTTPD_ENOERR;
|
||||||
n = httpd->cbs->peer.recv (
|
n = httpd->cbs->peer.recv (
|
||||||
httpd, &proxy->peer,
|
httpd, &proxy->peer,
|
||||||
&proxy->buf[proxy->buflen],
|
&proxy->buf[proxy->buflen],
|
||||||
@ -2904,32 +3046,55 @@ qse_printf (QSE_T("#####PREMATURE EOF FROM PEER\n"));
|
|||||||
|
|
||||||
proxy->buflen += n;
|
proxy->buflen += n;
|
||||||
|
|
||||||
|
qse_printf (QSE_T("#####PROXY FEEDING [%.*hs]\n"), (int)proxy->buflen, proxy->buf);
|
||||||
if (qse_htrd_feed (proxy->htrd, proxy->buf, proxy->buflen) <= -1)
|
if (qse_htrd_feed (proxy->htrd, proxy->buf, proxy->buflen) <= -1)
|
||||||
{
|
{
|
||||||
/* TODO: logging */
|
/* TODO: logging */
|
||||||
qse_printf (QSE_T("#####INVALID HEADER FROM FROM PEER [%.*hs]\n"), (int)proxy->buflen, proxy->buf);
|
qse_printf (QSE_T("#####INVALID HEADER FROM PEER [%.*hs]\n"), (int)proxy->buflen, proxy->buf);
|
||||||
goto oops;
|
goto oops;
|
||||||
}
|
}
|
||||||
|
|
||||||
proxy->buflen = 0;
|
proxy->buflen = 0;
|
||||||
|
|
||||||
|
|
||||||
if (QSE_MBS_LEN(proxy->res) > 0)
|
if (QSE_MBS_LEN(proxy->res) > 0)
|
||||||
{
|
{
|
||||||
if (proxy->disconnect &&
|
qse_printf (QSE_T("proxy->expect_100 %d\n"), proxy->expect_100);
|
||||||
qse_httpd_entaskdisconnect (httpd, client, task) == QSE_NULL)
|
if (proxy->expect_100 == -1)
|
||||||
{
|
{
|
||||||
goto oops;
|
/* the peek handler for proxy->htrd sets
|
||||||
|
* proxy->expect_100 to either -1 or 0.
|
||||||
|
* it's set to 0 if it's called with
|
||||||
|
* '100 Continue', -1 with other responses.
|
||||||
|
* But at this point, the handler could
|
||||||
|
* be called with both '100 Continue' and
|
||||||
|
* another response for a single feed.
|
||||||
|
* if it's already set to -1, proxy->res
|
||||||
|
* should contains at least the part of
|
||||||
|
* the actual reply. so i can switch to the
|
||||||
|
* next phase */
|
||||||
|
|
||||||
|
if (proxy->disconnect &&
|
||||||
|
qse_httpd_entaskdisconnect (httpd, client, task) == QSE_NULL)
|
||||||
|
{
|
||||||
|
goto oops;
|
||||||
|
}
|
||||||
|
|
||||||
|
qse_printf (QSE_T("TRAILING DATA=[%hs]\n"), &QSE_MBS_CHAR(proxy->res,proxy->res_consumed));
|
||||||
|
/* switch to the next phase */
|
||||||
|
task->main = task_main_proxy_3;
|
||||||
|
task->trigger[2].mask |= QSE_HTTPD_TASK_TRIGGER_WRITE;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (proxy->expect_100 == 0)
|
||||||
|
{
|
||||||
|
/* if it's set to 0, it's seen '100 Continue'
|
||||||
|
* without an actual response. so i need to
|
||||||
|
* arrange to relay '100 Continue' while
|
||||||
|
* waiting for at least the header of an
|
||||||
|
* actual reponse */
|
||||||
|
proxy->expect_100 = -2;
|
||||||
}
|
}
|
||||||
|
|
||||||
proxy->res_ptr = QSE_MBS_PTR(proxy->res);
|
|
||||||
proxy->res_left = QSE_MBS_LEN(proxy->res);
|
|
||||||
|
|
||||||
qse_printf (QSE_T("TRAILING DATA=[%.*hs]\n"), (int)QSE_MBS_LEN(proxy->res), QSE_MBS_PTR(proxy->res));
|
|
||||||
task->main = task_main_proxy_3;
|
|
||||||
/* ok to chain-call since this task is called
|
|
||||||
* only if the client-side is writable */
|
|
||||||
return task_main_proxy_3 (httpd, client, task);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2940,7 +3105,7 @@ oops:
|
|||||||
return (entask_error (httpd, client, task, 500, &proxy->version, proxy->keepalive) == QSE_NULL)? -1: 0;
|
return (entask_error (httpd, client, task, 500, &proxy->version, proxy->keepalive) == QSE_NULL)? -1: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int task_main_proxy_0 (
|
static int task_main_proxy_1 (
|
||||||
qse_httpd_t* httpd, qse_httpd_client_t* client, qse_httpd_task_t* task)
|
qse_httpd_t* httpd, qse_httpd_client_t* client, qse_httpd_task_t* task)
|
||||||
{
|
{
|
||||||
task_proxy_t* proxy = (task_proxy_t*)task->ctx;
|
task_proxy_t* proxy = (task_proxy_t*)task->ctx;
|
||||||
@ -2956,26 +3121,22 @@ static int task_main_proxy_0 (
|
|||||||
if (n >= 1)
|
if (n >= 1)
|
||||||
{
|
{
|
||||||
proxy->peer_status |= PEER_CONNECTED;
|
proxy->peer_status |= PEER_CONNECTED;
|
||||||
task->trigger[0].mask &= ~QSE_HTTPD_TASK_TRIGGER_WRITE;
|
|
||||||
if (proxy->reqfwdbuf)
|
if (proxy->req)
|
||||||
{
|
{
|
||||||
if (proxy->req)
|
task->trigger[2].mask = QSE_HTTPD_TASK_TRIGGER_READ;
|
||||||
|
task->trigger[2].handle = client->handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
task->trigger[0].mask &= ~QSE_HTTPD_TASK_TRIGGER_WRITE;
|
||||||
|
if (QSE_MBS_LEN(proxy->reqfwdbuf) > 0)
|
||||||
|
{
|
||||||
|
proxy_forward_content (httpd, task, 0);
|
||||||
|
if (QSE_MBS_LEN(proxy->reqfwdbuf) > 0)
|
||||||
{
|
{
|
||||||
task->trigger[2].mask = QSE_HTTPD_TASK_TRIGGER_READ;
|
task->trigger[0].mask |= QSE_HTTPD_TASK_TRIGGER_WRITE;
|
||||||
task->trigger[2].handle = client->handle;
|
|
||||||
}
|
|
||||||
else if (QSE_MBS_LEN(proxy->reqfwdbuf) > 0)
|
|
||||||
{
|
|
||||||
proxy_forward_content (httpd, task, 0);
|
|
||||||
if (QSE_MBS_LEN(proxy->reqfwdbuf) > 0)
|
|
||||||
{
|
|
||||||
task->trigger[0].mask |= QSE_HTTPD_TASK_TRIGGER_WRITE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
qse_printf (QSE_T("FINALLY connected to peer ...............................\n"));
|
|
||||||
qse_printf (QSE_T("FINALLY connected to peer ...............................\n"));
|
|
||||||
qse_printf (QSE_T("FINALLY connected to peer ...............................\n"));
|
|
||||||
qse_printf (QSE_T("FINALLY connected to peer ...............................\n"));
|
qse_printf (QSE_T("FINALLY connected to peer ...............................\n"));
|
||||||
task->main = task_main_proxy_2;
|
task->main = task_main_proxy_2;
|
||||||
}
|
}
|
||||||
@ -2999,14 +3160,16 @@ static int task_main_proxy (
|
|||||||
xtn = (proxy_htrd_xtn_t*) qse_htrd_getxtn (proxy->htrd);
|
xtn = (proxy_htrd_xtn_t*) qse_htrd_getxtn (proxy->htrd);
|
||||||
xtn->proxy = proxy;
|
xtn->proxy = proxy;
|
||||||
qse_htrd_setrecbs (proxy->htrd, &proxy_htrd_cbs);
|
qse_htrd_setrecbs (proxy->htrd, &proxy_htrd_cbs);
|
||||||
qse_htrd_setoption (
|
|
||||||
proxy->htrd,
|
if (proxy->expect_100 == 1)
|
||||||
QSE_HTRD_PEEKONLY |
|
qse_htrd_setoption (proxy->htrd, QSE_HTRD_RESPONSE);
|
||||||
QSE_HTRD_REQUEST
|
else
|
||||||
);
|
qse_htrd_setoption (proxy->htrd, QSE_HTRD_PEEKONLY | QSE_HTRD_RESPONSE);
|
||||||
|
|
||||||
proxy->res = qse_mbs_open (httpd->mmgr, 0, 256);
|
proxy->res = qse_mbs_open (httpd->mmgr, 0, 256);
|
||||||
if (proxy->res == QSE_NULL) goto oops;
|
if (proxy->res == QSE_NULL) goto oops;
|
||||||
|
proxy->res_consumed = 0;
|
||||||
|
proxy->res_pending = 0;
|
||||||
|
|
||||||
httpd->errnum = QSE_HTTPD_ENOERR;
|
httpd->errnum = QSE_HTTPD_ENOERR;
|
||||||
n = httpd->cbs->peer.open (httpd, &proxy->peer);
|
n = httpd->cbs->peer.open (httpd, &proxy->peer);
|
||||||
@ -3026,27 +3189,24 @@ static int task_main_proxy (
|
|||||||
{
|
{
|
||||||
/* peer not connected yet */
|
/* peer not connected yet */
|
||||||
task->trigger[0].mask |= QSE_HTTPD_TASK_TRIGGER_WRITE;
|
task->trigger[0].mask |= QSE_HTTPD_TASK_TRIGGER_WRITE;
|
||||||
task->main = task_main_proxy_0;
|
task->main = task_main_proxy_1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* peer connected already */
|
/* peer connected already */
|
||||||
proxy->peer_status |= PEER_CONNECTED;
|
proxy->peer_status |= PEER_CONNECTED;
|
||||||
if (proxy->reqfwdbuf)
|
if (proxy->req)
|
||||||
{
|
{
|
||||||
if (proxy->req)
|
task->trigger[2].mask = QSE_HTTPD_TASK_TRIGGER_READ;
|
||||||
|
task->trigger[2].handle = client->handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (QSE_MBS_LEN(proxy->reqfwdbuf) > 0)
|
||||||
|
{
|
||||||
|
proxy_forward_content (httpd, task, 0);
|
||||||
|
if (QSE_MBS_LEN(proxy->reqfwdbuf) > 0)
|
||||||
{
|
{
|
||||||
task->trigger[2].mask = QSE_HTTPD_TASK_TRIGGER_READ;
|
task->trigger[0].mask |= QSE_HTTPD_TASK_TRIGGER_WRITE;
|
||||||
task->trigger[2].handle = client->handle;
|
|
||||||
}
|
|
||||||
else if (QSE_MBS_LEN(proxy->reqfwdbuf) > 0)
|
|
||||||
{
|
|
||||||
proxy_forward_content (httpd, task, 0);
|
|
||||||
|
|
||||||
if (QSE_MBS_LEN(proxy->reqfwdbuf) > 0)
|
|
||||||
{
|
|
||||||
task->trigger[0].mask |= QSE_HTTPD_TASK_TRIGGER_WRITE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
task->main = task_main_proxy_2;
|
task->main = task_main_proxy_2;
|
||||||
|
@ -967,25 +967,29 @@ qse_printf (QSE_T("HEADER OK %d[%hs] %d[%hs]\n"), (int)QSE_HTB_KLEN(pair), QSE_
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int process_request (
|
static int process_request (
|
||||||
qse_httpd_t* httpd, qse_httpd_client_t* client, qse_htre_t* req, int peek)
|
qse_httpd_t* httpd, qse_httpd_client_t* client,
|
||||||
|
qse_htre_t* req, int peek)
|
||||||
{
|
{
|
||||||
int method;
|
int method;
|
||||||
qse_httpd_task_t* task;
|
qse_httpd_task_t* task;
|
||||||
int content_received;
|
int content_received;
|
||||||
|
|
||||||
method = qse_htre_getqmethod(req);
|
method = qse_htre_getqmethodtype(req);
|
||||||
content_received = (qse_htre_getcontentlen(req) > 0);
|
content_received = (qse_htre_getcontentlen(req) > 0);
|
||||||
|
|
||||||
qse_printf (QSE_T("================================\n"));
|
qse_printf (QSE_T("================================\n"));
|
||||||
qse_printf (QSE_T("[%lu] %hs REQUEST ==> [%hs] version[%d.%d] method[%hs]\n"),
|
qse_printf (QSE_T("[%lu] %hs REQUEST ==> [%hs] version[%d.%d %hs] method[%hs]\n"),
|
||||||
(unsigned long)time(NULL),
|
(unsigned long)time(NULL),
|
||||||
(peek? QSE_MT("PEEK"): QSE_MT("HANDLE")),
|
(peek? QSE_MT("PEEK"): QSE_MT("HANDLE")),
|
||||||
qse_htre_getqpathptr(req),
|
qse_htre_getqpath(req),
|
||||||
qse_htre_getmajorversion(req),
|
qse_htre_getmajorversion(req),
|
||||||
qse_htre_getminorversion(req),
|
qse_htre_getminorversion(req),
|
||||||
|
qse_htre_getverstr(req),
|
||||||
qse_htre_getqmethodname(req)
|
qse_htre_getqmethodname(req)
|
||||||
);
|
);
|
||||||
if (qse_htre_getqparamlen(req) > 0) qse_printf (QSE_T("PARAMS ==> [%hs]\n"), qse_htre_getqparamptr(req));
|
if (qse_htre_getqparam(req))
|
||||||
|
qse_printf (QSE_T("PARAMS ==> [%hs]\n"), qse_htre_getqparam(req));
|
||||||
|
|
||||||
qse_htb_walk (&req->hdrtab, walk, QSE_NULL);
|
qse_htb_walk (&req->hdrtab, walk, QSE_NULL);
|
||||||
if (qse_htre_getcontentlen(req) > 0)
|
if (qse_htre_getcontentlen(req) > 0)
|
||||||
{
|
{
|
||||||
@ -1038,7 +1042,7 @@ if (qse_htre_getcontentlen(req) > 0)
|
|||||||
|
|
||||||
if (method == QSE_HTTP_GET || method == QSE_HTTP_POST)
|
if (method == QSE_HTTP_GET || method == QSE_HTTP_POST)
|
||||||
{
|
{
|
||||||
const qse_mchar_t* qpath = qse_htre_getqpathptr(req);
|
const qse_mchar_t* qpath = qse_htre_getqpath(req);
|
||||||
const qse_mchar_t* dot = qse_mbsrchr (qpath, QSE_MT('.'));
|
const qse_mchar_t* dot = qse_mbsrchr (qpath, QSE_MT('.'));
|
||||||
|
|
||||||
if (dot && qse_mbscmp (dot, QSE_MT(".cgi")) == 0)
|
if (dot && qse_mbscmp (dot, QSE_MT(".cgi")) == 0)
|
||||||
@ -1211,6 +1215,7 @@ qse_printf (QSE_T("Host not included....\n"));
|
|||||||
if (peek)
|
if (peek)
|
||||||
{
|
{
|
||||||
qse_nwad_t nwad;
|
qse_nwad_t nwad;
|
||||||
|
//qse_strtonwad (QSE_T("192.168.1.55:9000"), &nwad);
|
||||||
qse_strtonwad (QSE_T("192.168.1.3:80"), &nwad);
|
qse_strtonwad (QSE_T("192.168.1.3:80"), &nwad);
|
||||||
task = qse_httpd_entaskproxy (httpd, client, QSE_NULL, &nwad, req);
|
task = qse_httpd_entaskproxy (httpd, client, QSE_NULL, &nwad, req);
|
||||||
if (task == QSE_NULL) goto oops;
|
if (task == QSE_NULL) goto oops;
|
||||||
|
Loading…
Reference in New Issue
Block a user