added some code to support raw proxying
This commit is contained in:
parent
efc8d5ceb4
commit
a7ca23fa50
@ -356,9 +356,10 @@ static int make_resource (
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
rsrc->type = QSE_HTTPD_RSRC_PROXY;
|
rsrc->type = QSE_HTTPD_RSRC_PROXY;
|
||||||
|
rsrc->u.proxy.raw = 0;
|
||||||
rsrc->u.proxy.dst = client->orgdst_addr;
|
rsrc->u.proxy.dst = client->orgdst_addr;
|
||||||
rsrc->u.proxy.src = client->remote_addr;
|
rsrc->u.proxy.src = client->remote_addr;
|
||||||
|
|
||||||
if (rsrc->u.proxy.src.type == QSE_NWAD_IN4)
|
if (rsrc->u.proxy.src.type == QSE_NWAD_IN4)
|
||||||
rsrc->u.proxy.src.u.in4.port = 0; /* reset the port to 0. */
|
rsrc->u.proxy.src.u.in4.port = 0; /* reset the port to 0. */
|
||||||
else if (rsrc->u.proxy.src.type == QSE_NWAD_IN6)
|
else if (rsrc->u.proxy.src.type == QSE_NWAD_IN6)
|
||||||
@ -1658,7 +1659,7 @@ static void reconf_server (qse_httpd_t* httpd, qse_httpd_server_t* server)
|
|||||||
server_xtn_t* server_xtn;
|
server_xtn_t* server_xtn;
|
||||||
qse_xli_pair_t* pair;
|
qse_xli_pair_t* pair;
|
||||||
|
|
||||||
/* reconfigure the server when the server is impeded. */
|
/* reconfigure the server when the server is impeded in sig_reconf(). */
|
||||||
|
|
||||||
httpd_xtn = qse_httpd_getxtnstd (httpd);
|
httpd_xtn = qse_httpd_getxtnstd (httpd);
|
||||||
server_xtn = qse_httpd_getserverstdxtn (httpd, server);
|
server_xtn = qse_httpd_getserverstdxtn (httpd, server);
|
||||||
@ -1681,6 +1682,8 @@ static void impede_httpd (qse_httpd_t* httpd)
|
|||||||
{
|
{
|
||||||
httpd_xtn_t* httpd_xtn;
|
httpd_xtn_t* httpd_xtn;
|
||||||
|
|
||||||
|
/* reconfigure the server when the server is impeded in sig_reconf(). */
|
||||||
|
|
||||||
httpd_xtn = qse_httpd_getxtnstd (httpd);
|
httpd_xtn = qse_httpd_getxtnstd (httpd);
|
||||||
|
|
||||||
if (open_config_file (httpd) >= 0)
|
if (open_config_file (httpd) >= 0)
|
||||||
|
@ -56,7 +56,8 @@ enum qse_htrd_option_t
|
|||||||
QSE_HTRD_REQUEST = (1 << 4), /**< parse input as a request */
|
QSE_HTRD_REQUEST = (1 << 4), /**< parse input as a request */
|
||||||
QSE_HTRD_RESPONSE = (1 << 5), /**< parse input as a response */
|
QSE_HTRD_RESPONSE = (1 << 5), /**< parse input as a response */
|
||||||
QSE_HTRD_TRAILERS = (1 << 6), /**< store trailers in a separate table */
|
QSE_HTRD_TRAILERS = (1 << 6), /**< store trailers in a separate table */
|
||||||
QSE_HTRD_STRICT = (1 << 7) /**< be more picky */
|
QSE_HTRD_STRICT = (1 << 7), /**< be more picky */
|
||||||
|
QSE_HTRD_DUMMY = (1 << 8) /**< be dummy */
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef enum qse_htrd_option_t qse_htrd_option_t;
|
typedef enum qse_htrd_option_t qse_htrd_option_t;
|
||||||
|
@ -62,7 +62,7 @@ struct qse_htre_t
|
|||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
QSE_HTRE_Q,
|
QSE_HTRE_Q,
|
||||||
QSE_HTRE_S
|
QSE_HTRE_S
|
||||||
} type;
|
} type;
|
||||||
|
|
||||||
/* version */
|
/* version */
|
||||||
|
@ -477,6 +477,14 @@ struct qse_httpd_rsrc_cgi_t
|
|||||||
int nph;
|
int nph;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct qse_httpd_rsrc_proxy_t qse_httpd_rsrc_proxy_t;
|
||||||
|
struct qse_httpd_rsrc_proxy_t
|
||||||
|
{
|
||||||
|
qse_nwad_t dst;
|
||||||
|
qse_nwad_t src;
|
||||||
|
int raw;
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct qse_httpd_rsrc_dir_t qse_httpd_rsrc_dir_t;
|
typedef struct qse_httpd_rsrc_dir_t qse_httpd_rsrc_dir_t;
|
||||||
struct qse_httpd_rsrc_dir_t
|
struct qse_httpd_rsrc_dir_t
|
||||||
{
|
{
|
||||||
@ -511,21 +519,17 @@ struct qse_httpd_rsrc_t
|
|||||||
const qse_mchar_t* mime;
|
const qse_mchar_t* mime;
|
||||||
} file;
|
} file;
|
||||||
|
|
||||||
struct
|
qse_httpd_rsrc_proxy_t proxy;
|
||||||
{
|
|
||||||
qse_nwad_t dst;
|
|
||||||
qse_nwad_t src;
|
|
||||||
} proxy;
|
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
const qse_mchar_t* dst;
|
const qse_mchar_t* dst;
|
||||||
} reloc;
|
} reloc;
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
const qse_mchar_t* dst;
|
const qse_mchar_t* dst;
|
||||||
} redir;
|
} redir;
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
@ -758,15 +762,15 @@ QSE_EXPORT qse_httpd_task_t* qse_httpd_entasktext (
|
|||||||
);
|
);
|
||||||
|
|
||||||
QSE_EXPORT qse_httpd_task_t* qse_httpd_entaskerr (
|
QSE_EXPORT qse_httpd_task_t* qse_httpd_entaskerr (
|
||||||
qse_httpd_t* httpd,
|
qse_httpd_t* httpd,
|
||||||
qse_httpd_client_t* client,
|
qse_httpd_client_t* client,
|
||||||
qse_httpd_task_t* pred,
|
qse_httpd_task_t* pred,
|
||||||
int code,
|
int code,
|
||||||
qse_htre_t* req
|
qse_htre_t* req
|
||||||
);
|
);
|
||||||
|
|
||||||
QSE_EXPORT qse_httpd_task_t* qse_httpd_entaskcontinue (
|
QSE_EXPORT qse_httpd_task_t* qse_httpd_entaskcontinue (
|
||||||
qse_httpd_t* httpd,
|
qse_httpd_t* httpd,
|
||||||
qse_httpd_client_t* client,
|
qse_httpd_client_t* client,
|
||||||
qse_httpd_task_t* pred,
|
qse_httpd_task_t* pred,
|
||||||
qse_htre_t* req
|
qse_htre_t* req
|
||||||
@ -776,7 +780,7 @@ QSE_EXPORT qse_httpd_task_t* qse_httpd_entaskcontinue (
|
|||||||
* The qse_httpd_entaskauth() function adds a basic authorization task.
|
* The qse_httpd_entaskauth() function adds a basic authorization task.
|
||||||
*/
|
*/
|
||||||
QSE_EXPORT qse_httpd_task_t* qse_httpd_entaskauth (
|
QSE_EXPORT qse_httpd_task_t* qse_httpd_entaskauth (
|
||||||
qse_httpd_t* httpd,
|
qse_httpd_t* httpd,
|
||||||
qse_httpd_client_t* client,
|
qse_httpd_client_t* client,
|
||||||
qse_httpd_task_t* pred,
|
qse_httpd_task_t* pred,
|
||||||
const qse_mchar_t* realm,
|
const qse_mchar_t* realm,
|
||||||
@ -784,7 +788,7 @@ QSE_EXPORT qse_httpd_task_t* qse_httpd_entaskauth (
|
|||||||
);
|
);
|
||||||
|
|
||||||
QSE_EXPORT qse_httpd_task_t* qse_httpd_entaskreloc (
|
QSE_EXPORT qse_httpd_task_t* qse_httpd_entaskreloc (
|
||||||
qse_httpd_t* httpd,
|
qse_httpd_t* httpd,
|
||||||
qse_httpd_client_t* client,
|
qse_httpd_client_t* client,
|
||||||
qse_httpd_task_t* pred,
|
qse_httpd_task_t* pred,
|
||||||
const qse_mchar_t* dst,
|
const qse_mchar_t* dst,
|
||||||
@ -792,7 +796,7 @@ QSE_EXPORT qse_httpd_task_t* qse_httpd_entaskreloc (
|
|||||||
);
|
);
|
||||||
|
|
||||||
QSE_EXPORT qse_httpd_task_t* qse_httpd_entaskredir (
|
QSE_EXPORT qse_httpd_task_t* qse_httpd_entaskredir (
|
||||||
qse_httpd_t* httpd,
|
qse_httpd_t* httpd,
|
||||||
qse_httpd_client_t* client,
|
qse_httpd_client_t* client,
|
||||||
qse_httpd_task_t* pred,
|
qse_httpd_task_t* pred,
|
||||||
const qse_mchar_t* dst,
|
const qse_mchar_t* dst,
|
||||||
@ -801,7 +805,7 @@ QSE_EXPORT qse_httpd_task_t* qse_httpd_entaskredir (
|
|||||||
|
|
||||||
|
|
||||||
QSE_EXPORT qse_httpd_task_t* qse_httpd_entasknomod (
|
QSE_EXPORT qse_httpd_task_t* qse_httpd_entasknomod (
|
||||||
qse_httpd_t* httpd,
|
qse_httpd_t* httpd,
|
||||||
qse_httpd_client_t* client,
|
qse_httpd_client_t* client,
|
||||||
qse_httpd_task_t* pred,
|
qse_httpd_task_t* pred,
|
||||||
qse_htre_t* req
|
qse_htre_t* req
|
||||||
@ -833,20 +837,19 @@ QSE_EXPORT qse_httpd_task_t* qse_httpd_entaskfile (
|
|||||||
);
|
);
|
||||||
|
|
||||||
QSE_EXPORT qse_httpd_task_t* qse_httpd_entaskcgi (
|
QSE_EXPORT qse_httpd_task_t* qse_httpd_entaskcgi (
|
||||||
qse_httpd_t* httpd,
|
qse_httpd_t* httpd,
|
||||||
qse_httpd_client_t* client,
|
qse_httpd_client_t* client,
|
||||||
qse_httpd_task_t* pred,
|
qse_httpd_task_t* pred,
|
||||||
qse_httpd_rsrc_cgi_t* cgi,
|
const qse_httpd_rsrc_cgi_t* cgi,
|
||||||
qse_htre_t* req
|
qse_htre_t* req
|
||||||
);
|
);
|
||||||
|
|
||||||
QSE_EXPORT qse_httpd_task_t* qse_httpd_entaskproxy (
|
QSE_EXPORT qse_httpd_task_t* qse_httpd_entaskproxy (
|
||||||
qse_httpd_t* httpd,
|
qse_httpd_t* httpd,
|
||||||
qse_httpd_client_t* client,
|
qse_httpd_client_t* client,
|
||||||
qse_httpd_task_t* pred,
|
qse_httpd_task_t* pred,
|
||||||
const qse_nwad_t* dst,
|
const qse_httpd_rsrc_proxy_t* proxy,
|
||||||
const qse_nwad_t* src,
|
qse_htre_t* req
|
||||||
qse_htre_t* req
|
|
||||||
);
|
);
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
|
@ -169,9 +169,9 @@ QSE_EXPORT qse_httpd_server_t* qse_httpd_attachserverstd (
|
|||||||
QSE_EXPORT qse_httpd_server_t* qse_httpd_attachserverstdwithuri (
|
QSE_EXPORT qse_httpd_server_t* qse_httpd_attachserverstdwithuri (
|
||||||
qse_httpd_t* httpd,
|
qse_httpd_t* httpd,
|
||||||
const qse_char_t* uri,
|
const qse_char_t* uri,
|
||||||
qse_httpd_server_detach_t detach,
|
qse_httpd_server_detach_t detach,
|
||||||
qse_httpd_server_impede_t impede,
|
qse_httpd_server_impede_t impede,
|
||||||
qse_httpd_serverstd_query_t query,
|
qse_httpd_serverstd_query_t query,
|
||||||
qse_size_t xtnsize
|
qse_size_t xtnsize
|
||||||
);
|
);
|
||||||
#endif
|
#endif
|
||||||
|
@ -837,6 +837,10 @@ qse_mchar_t* parse_header_field (
|
|||||||
* the continuation */
|
* the continuation */
|
||||||
if (is_purespace_octet (*++p))
|
if (is_purespace_octet (*++p))
|
||||||
{
|
{
|
||||||
|
/* RFC: HTTP/1.0 headers may be folded onto multiple lines if
|
||||||
|
* each continuation line begins with a space or horizontal tab.
|
||||||
|
* All linear whitespace, including folding, has the same semantics
|
||||||
|
* as SP. */
|
||||||
qse_mchar_t* cpydst;
|
qse_mchar_t* cpydst;
|
||||||
|
|
||||||
cpydst = p - 1;
|
cpydst = p - 1;
|
||||||
@ -1091,6 +1095,13 @@ int qse_htrd_feed (qse_htrd_t* htrd, const qse_mchar_t* req, qse_size_t len)
|
|||||||
|
|
||||||
QSE_ASSERT (len > 0);
|
QSE_ASSERT (len > 0);
|
||||||
|
|
||||||
|
if (htrd->option & QSE_HTRD_DUMMY)
|
||||||
|
{
|
||||||
|
/* treat everything as contents.
|
||||||
|
* i don't care about headers or whatsoever. */
|
||||||
|
return push_content (htrd, req, len);
|
||||||
|
}
|
||||||
|
|
||||||
/* does this goto drop code maintainability? */
|
/* does this goto drop code maintainability? */
|
||||||
if (htrd->fed.s.need > 0)
|
if (htrd->fed.s.need > 0)
|
||||||
{
|
{
|
||||||
@ -1117,7 +1128,7 @@ int qse_htrd_feed (qse_htrd_t* htrd, const qse_mchar_t* req, qse_size_t len)
|
|||||||
goto dechunk_get_trailers;
|
goto dechunk_get_trailers;
|
||||||
}
|
}
|
||||||
|
|
||||||
htrd->clean = 0; /* mark that the htrd is in need of some data */
|
htrd->clean = 0; /* mark that htrd is in need of some data */
|
||||||
|
|
||||||
while (ptr < end)
|
while (ptr < end)
|
||||||
{
|
{
|
||||||
@ -1196,7 +1207,7 @@ int qse_htrd_feed (qse_htrd_t* htrd, const qse_mchar_t* req, qse_size_t len)
|
|||||||
*/
|
*/
|
||||||
if (ptr < end && push_content (htrd, ptr, end - ptr) <= -1) return -1;
|
if (ptr < end && push_content (htrd, ptr, end - ptr) <= -1) return -1;
|
||||||
|
|
||||||
/* i don't really know if it is really completed
|
/* i don't really know if it is really completed
|
||||||
* with content. QSE_HTRD_PEEKONLY is not compatible
|
* with content. QSE_HTRD_PEEKONLY is not compatible
|
||||||
* with the completed state. anyway, let me complete
|
* with the completed state. anyway, let me complete
|
||||||
* it. */
|
* it. */
|
||||||
@ -1213,12 +1224,12 @@ int qse_htrd_feed (qse_htrd_t* htrd, const qse_mchar_t* req, qse_size_t len)
|
|||||||
{
|
{
|
||||||
/* transfer-encoding: chunked */
|
/* transfer-encoding: chunked */
|
||||||
QSE_ASSERT (!(htrd->re.attr.flags & QSE_HTRE_ATTR_LENGTH));
|
QSE_ASSERT (!(htrd->re.attr.flags & QSE_HTRE_ATTR_LENGTH));
|
||||||
|
|
||||||
dechunk_start:
|
dechunk_start:
|
||||||
htrd->fed.s.chunk.phase = GET_CHUNK_LEN;
|
htrd->fed.s.chunk.phase = GET_CHUNK_LEN;
|
||||||
htrd->fed.s.chunk.len = 0;
|
htrd->fed.s.chunk.len = 0;
|
||||||
htrd->fed.s.chunk.count = 0;
|
htrd->fed.s.chunk.count = 0;
|
||||||
|
|
||||||
dechunk_resume:
|
dechunk_resume:
|
||||||
ptr = getchunklen (htrd, ptr, end - ptr);
|
ptr = getchunklen (htrd, ptr, end - ptr);
|
||||||
if (ptr == QSE_NULL) return -1;
|
if (ptr == QSE_NULL) return -1;
|
||||||
@ -1242,7 +1253,7 @@ int qse_htrd_feed (qse_htrd_t* htrd, const qse_mchar_t* req, qse_size_t len)
|
|||||||
dechunk_get_trailers:
|
dechunk_get_trailers:
|
||||||
ptr = get_trailing_headers (htrd, ptr, end);
|
ptr = get_trailing_headers (htrd, ptr, end);
|
||||||
if (ptr == QSE_NULL) return -1;
|
if (ptr == QSE_NULL) return -1;
|
||||||
|
|
||||||
if (htrd->fed.s.chunk.phase == GET_CHUNK_TRAILERS)
|
if (htrd->fed.s.chunk.phase == GET_CHUNK_TRAILERS)
|
||||||
{
|
{
|
||||||
/* still in the same state.
|
/* still in the same state.
|
||||||
@ -1330,7 +1341,7 @@ int qse_htrd_feed (qse_htrd_t* htrd, const qse_mchar_t* req, qse_size_t len)
|
|||||||
{
|
{
|
||||||
QSE_ASSERT (htrd->fed.s.need == 0);
|
QSE_ASSERT (htrd->fed.s.need == 0);
|
||||||
htrd->fed.s.chunk.phase = GET_CHUNK_CRLF;
|
htrd->fed.s.chunk.phase = GET_CHUNK_CRLF;
|
||||||
|
|
||||||
dechunk_crlf:
|
dechunk_crlf:
|
||||||
while (ptr < end && is_space_octet(*ptr)) ptr++;
|
while (ptr < end && is_space_octet(*ptr)) ptr++;
|
||||||
if (ptr < end)
|
if (ptr < end)
|
||||||
@ -1339,12 +1350,12 @@ int qse_htrd_feed (qse_htrd_t* htrd, const qse_mchar_t* req, qse_size_t len)
|
|||||||
{
|
{
|
||||||
/* end of chunk data. */
|
/* end of chunk data. */
|
||||||
ptr++;
|
ptr++;
|
||||||
|
|
||||||
/* more octets still available.
|
/* more octets still available.
|
||||||
* let it decode the next chunk
|
* let it decode the next chunk
|
||||||
*/
|
*/
|
||||||
if (ptr < end) goto dechunk_start;
|
if (ptr < end) goto dechunk_start;
|
||||||
|
|
||||||
/* no more octets available after
|
/* no more octets available after
|
||||||
* chunk data. the chunk state variables
|
* chunk data. the chunk state variables
|
||||||
* need to be reset when a jump is made
|
* need to be reset when a jump is made
|
||||||
@ -1419,6 +1430,17 @@ qse_printf (QSE_T("CONTENT_LENGTH %d, RAW HEADER LENGTH %d\n"),
|
|||||||
clear_feed (htrd);
|
clear_feed (htrd);
|
||||||
if (ptr >= end) return 0; /* no more feeds to handle */
|
if (ptr >= end) return 0; /* no more feeds to handle */
|
||||||
|
|
||||||
|
if (htrd->option & QSE_HTRD_DUMMY)
|
||||||
|
{
|
||||||
|
/* once the mode changes to RAW in a callback,
|
||||||
|
* left-over is pused as contents */
|
||||||
|
if (ptr < end)
|
||||||
|
return push_content (htrd, ptr, end - ptr);
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* let ptr point to the next character to LF or
|
/* let ptr point to the next character to LF or
|
||||||
* the optional contents */
|
* the optional contents */
|
||||||
req = ptr;
|
req = ptr;
|
||||||
|
@ -262,7 +262,7 @@ static int cgi_htrd_peek_script_output (qse_htrd_t* htrd, qse_htre_t* req)
|
|||||||
location = qse_htre_getheaderval (req, QSE_MT("Location"));
|
location = qse_htre_getheaderval (req, QSE_MT("Location"));
|
||||||
if (location)
|
if (location)
|
||||||
{
|
{
|
||||||
snprintf (buf, QSE_COUNTOF(buf),
|
snprintf (buf, QSE_COUNTOF(buf),
|
||||||
QSE_MT("HTTP/%d.%d 301 Moved Permanently\r\n"),
|
QSE_MT("HTTP/%d.%d 301 Moved Permanently\r\n"),
|
||||||
cgi->version.major, cgi->version.minor
|
cgi->version.major, cgi->version.minor
|
||||||
);
|
);
|
||||||
@ -277,7 +277,7 @@ static int cgi_htrd_peek_script_output (qse_htrd_t* htrd, qse_htre_t* req)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
snprintf (buf, QSE_COUNTOF(buf),
|
snprintf (buf, QSE_COUNTOF(buf),
|
||||||
QSE_MT("HTTP/%d.%d 200 OK\r\n"),
|
QSE_MT("HTTP/%d.%d 200 OK\r\n"),
|
||||||
cgi->version.major, cgi->version.minor
|
cgi->version.major, cgi->version.minor
|
||||||
);
|
);
|
||||||
@ -755,7 +755,7 @@ static int task_init_cgi (
|
|||||||
cgi->version = *qse_htre_getversion(arg->req);
|
cgi->version = *qse_htre_getversion(arg->req);
|
||||||
cgi->keepalive = (arg->req->attr.flags & QSE_HTRE_ATTR_KEEPALIVE);
|
cgi->keepalive = (arg->req->attr.flags & QSE_HTRE_ATTR_KEEPALIVE);
|
||||||
cgi->nph = arg->nph;
|
cgi->nph = arg->nph;
|
||||||
cgi->req = QSE_NULL;
|
cgi->req = QSE_NULL;
|
||||||
|
|
||||||
content_length = 0;
|
content_length = 0;
|
||||||
if (arg->req->state & QSE_HTRE_DISCARDED) goto done;
|
if (arg->req->state & QSE_HTRE_DISCARDED) goto done;
|
||||||
@ -1519,7 +1519,7 @@ qse_httpd_task_t* qse_httpd_entaskcgi (
|
|||||||
qse_httpd_t* httpd,
|
qse_httpd_t* httpd,
|
||||||
qse_httpd_client_t* client,
|
qse_httpd_client_t* client,
|
||||||
qse_httpd_task_t* pred,
|
qse_httpd_task_t* pred,
|
||||||
qse_httpd_rsrc_cgi_t* cgi,
|
const qse_httpd_rsrc_cgi_t* cgi,
|
||||||
qse_htre_t* req)
|
qse_htre_t* req)
|
||||||
{
|
{
|
||||||
qse_httpd_task_t task;
|
qse_httpd_task_t task;
|
||||||
|
@ -27,8 +27,7 @@
|
|||||||
typedef struct task_proxy_arg_t task_proxy_arg_t;
|
typedef struct task_proxy_arg_t task_proxy_arg_t;
|
||||||
struct task_proxy_arg_t
|
struct task_proxy_arg_t
|
||||||
{
|
{
|
||||||
const qse_nwad_t* peer_nwad;
|
const qse_httpd_rsrc_proxy_t* rsrc;
|
||||||
const qse_nwad_t* peer_local;
|
|
||||||
qse_htre_t* req;
|
qse_htre_t* req;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -43,6 +42,7 @@ struct task_proxy_t
|
|||||||
int method;
|
int method;
|
||||||
qse_http_version_t version;
|
qse_http_version_t version;
|
||||||
int keepalive; /* taken from the request */
|
int keepalive; /* taken from the request */
|
||||||
|
int raw;
|
||||||
|
|
||||||
qse_htrd_t* peer_htrd;
|
qse_htrd_t* peer_htrd;
|
||||||
|
|
||||||
@ -184,9 +184,40 @@ static int proxy_capture_client_trailer (qse_htre_t* req, const qse_mchar_t* key
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int proxy_snatch_client_input_raw (
|
||||||
|
qse_htre_t* req, const qse_mchar_t* ptr, qse_size_t len, void* ctx)
|
||||||
|
{
|
||||||
|
/* it is a callback function set to the client-side htrd reader
|
||||||
|
* when the raw proxying is enabled. raw proxying doesn't parse
|
||||||
|
* requests. */
|
||||||
|
|
||||||
|
qse_httpd_task_t* task;
|
||||||
|
task_proxy_t* proxy;
|
||||||
|
|
||||||
|
task = (qse_httpd_task_t*)ctx;
|
||||||
|
proxy = (task_proxy_t*)task->ctx;
|
||||||
|
|
||||||
|
if (ptr && !(proxy->reqflags & PROXY_REQ_FWDERR))
|
||||||
|
{
|
||||||
|
if (qse_mbs_ncat (proxy->reqfwdbuf, ptr, len) == (qse_size_t)-1)
|
||||||
|
{
|
||||||
|
proxy->httpd->errnum = QSE_HTTPD_ENOMEM;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
task->trigger[0].mask |= QSE_HTTPD_TASK_TRIGGER_WRITE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int proxy_snatch_client_input (
|
static int proxy_snatch_client_input (
|
||||||
qse_htre_t* req, const qse_mchar_t* ptr, qse_size_t len, void* ctx)
|
qse_htre_t* req, const qse_mchar_t* ptr, qse_size_t len, void* ctx)
|
||||||
{
|
{
|
||||||
|
/* it is a callback function set to the client-side htrd reader
|
||||||
|
* when the normal proxying is enabled. normal proxying requires
|
||||||
|
* request parsing. */
|
||||||
|
|
||||||
qse_httpd_task_t* task;
|
qse_httpd_task_t* task;
|
||||||
task_proxy_t* proxy;
|
task_proxy_t* proxy;
|
||||||
|
|
||||||
@ -708,7 +739,7 @@ static int task_init_proxy (
|
|||||||
task_proxy_arg_t* arg;
|
task_proxy_arg_t* arg;
|
||||||
qse_size_t len;
|
qse_size_t len;
|
||||||
const qse_mchar_t* ptr;
|
const qse_mchar_t* ptr;
|
||||||
int snatch_needed;
|
|
||||||
|
|
||||||
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;
|
||||||
@ -719,9 +750,11 @@ static int task_init_proxy (
|
|||||||
proxy->method = qse_htre_getqmethodtype(arg->req);
|
proxy->method = qse_htre_getqmethodtype(arg->req);
|
||||||
proxy->version = *qse_htre_getversion(arg->req);
|
proxy->version = *qse_htre_getversion(arg->req);
|
||||||
proxy->keepalive = (arg->req->attr.flags & QSE_HTRE_ATTR_KEEPALIVE);
|
proxy->keepalive = (arg->req->attr.flags & QSE_HTRE_ATTR_KEEPALIVE);
|
||||||
proxy->peer.nwad = *arg->peer_nwad;
|
proxy->peer.nwad = arg->rsrc->dst;
|
||||||
if (arg->peer_local) proxy->peer.local = *arg->peer_local;
|
proxy->peer.local = arg->rsrc->src;
|
||||||
else proxy->peer.local.type = arg->peer_nwad->type;
|
proxy->raw = arg->rsrc->raw;
|
||||||
|
/*if (arg->rsrc->src) proxy->peer.local = arg->rsrc->src;
|
||||||
|
else proxy->peer.local.type = arg->rsrc->dst.type;*/
|
||||||
|
|
||||||
proxy->req = QSE_NULL;
|
proxy->req = QSE_NULL;
|
||||||
|
|
||||||
@ -731,158 +764,175 @@ static int task_init_proxy (
|
|||||||
* -------------------------------------------------------------------- */
|
* -------------------------------------------------------------------- */
|
||||||
|
|
||||||
/* TODO: DETERMINE THIS SIZE */
|
/* TODO: DETERMINE THIS SIZE */
|
||||||
len = 2048;
|
len = 4096;
|
||||||
|
|
||||||
proxy->reqfwdbuf = qse_mbs_open (httpd->mmgr, 0, (len < 512? 512: len));
|
proxy->reqfwdbuf = qse_mbs_open (httpd->mmgr, 0, (len < 512? 512: len));
|
||||||
if (proxy->reqfwdbuf == QSE_NULL) goto oops;
|
if (proxy->reqfwdbuf == QSE_NULL) goto oops;
|
||||||
|
|
||||||
if (qse_mbs_cat (proxy->reqfwdbuf, qse_htre_getqmethodname(arg->req)) == (qse_size_t)-1 ||
|
if (proxy->raw)
|
||||||
qse_mbs_cat (proxy->reqfwdbuf, QSE_MT(" ")) == (qse_size_t)-1 ||
|
|
||||||
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 ||
|
/* TODO: when connect is attempted, no keep-alive must be hornored.
|
||||||
qse_mbs_cat (proxy->reqfwdbuf, qse_htre_getqparam(arg->req)) == (qse_size_t)-1) goto oops;
|
* when connection fails, it returns failure page followed by close.... */
|
||||||
}
|
|
||||||
if (qse_mbs_cat (proxy->reqfwdbuf, QSE_MT(" ")) == (qse_size_t)-1 ||
|
|
||||||
qse_mbs_cat (proxy->reqfwdbuf, qse_htre_getverstr(arg->req)) == (qse_size_t)-1 ||
|
|
||||||
qse_mbs_cat (proxy->reqfwdbuf, QSE_MT("\r\n")) == (qse_size_t)-1 ||
|
|
||||||
qse_htre_walkheaders (arg->req, proxy_capture_client_header, proxy) <= -1) goto oops;
|
|
||||||
|
|
||||||
proxy->resflags |= PROXY_RES_AWAIT_RESHDR;
|
/* the caller must make sure that the actual content is discarded or completed
|
||||||
if ((arg->req->attr.flags & QSE_HTRE_ATTR_EXPECT100) &&
|
* and the following data is treated as contents */
|
||||||
(arg->req->version.major > 1 ||
|
printf ("proxy req = %p %d %d\n", arg->req, (arg->req->state & QSE_HTRE_DISCARDED), (arg->req->state& QSE_HTRE_COMPLETED));
|
||||||
(arg->req->version.major == 1 && arg->req->version.minor >= 1)))
|
QSE_ASSERT (arg->req->state & (QSE_HTRE_DISCARDED | QSE_HTRE_COMPLETED));
|
||||||
{
|
QSE_ASSERT (qse_htrd_getoption(client->htrd) & QSE_HTRD_DUMMY);
|
||||||
proxy->resflags |= PROXY_RES_AWAIT_100;
|
|
||||||
}
|
|
||||||
|
|
||||||
snatch_needed = 0;
|
proxy->req = arg->req;
|
||||||
|
qse_htre_setconcb (proxy->req, proxy_snatch_client_input_raw, task);
|
||||||
if (!(httpd->opt.trait & QSE_HTTPD_PROXYNOVIA))
|
|
||||||
{
|
|
||||||
/* add the Via: header into the request */
|
|
||||||
if (qse_mbs_cat (proxy->reqfwdbuf, QSE_MT("Via: ")) == (qse_size_t)-1 ||
|
|
||||||
qse_mbs_cat (proxy->reqfwdbuf, qse_httpd_getname (httpd)) == (qse_size_t)-1 ||
|
|
||||||
qse_mbs_cat (proxy->reqfwdbuf, QSE_MT("\r\n")) == (qse_size_t)-1) goto oops;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (arg->req->state & QSE_HTRE_DISCARDED)
|
|
||||||
{
|
|
||||||
/* no content to add */
|
|
||||||
if ((arg->req->attr.flags & QSE_HTRE_ATTR_LENGTH) ||
|
|
||||||
(arg->req->attr.flags & QSE_HTRE_ATTR_CHUNKED))
|
|
||||||
{
|
|
||||||
/* i don't add chunk traiers if the
|
|
||||||
* request content has been discarded */
|
|
||||||
if (qse_mbs_cat (proxy->reqfwdbuf, QSE_MT("Content-Length: 0\r\n\r\n")) == (qse_size_t)-1) goto oops;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (qse_mbs_cat (proxy->reqfwdbuf, QSE_MT("\r\n")) == (qse_size_t)-1) goto oops;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (arg->req->state & QSE_HTRE_COMPLETED)
|
|
||||||
{
|
|
||||||
if (arg->req->attr.flags & QSE_HTRE_ATTR_CHUNKED)
|
|
||||||
{
|
|
||||||
/* add trailers if any */
|
|
||||||
if (qse_htre_walktrailers (
|
|
||||||
arg->req, proxy_capture_client_trailer, proxy) <= -1) goto oops;
|
|
||||||
}
|
|
||||||
|
|
||||||
len = qse_htre_getcontentlen(arg->req);
|
|
||||||
if (len > 0 || (arg->req->attr.flags & QSE_HTRE_ATTR_LENGTH) ||
|
|
||||||
(arg->req->attr.flags & QSE_HTRE_ATTR_CHUNKED))
|
|
||||||
{
|
|
||||||
qse_mchar_t buf[64];
|
|
||||||
|
|
||||||
qse_fmtuintmaxtombs (
|
|
||||||
buf, QSE_COUNTOF(buf), len,
|
|
||||||
10, -1, QSE_MT('\0'), QSE_NULL);
|
|
||||||
|
|
||||||
/* force-insert content-length. content-length is added
|
|
||||||
* even if the original request dones't contain it */
|
|
||||||
if (qse_mbs_cat (proxy->reqfwdbuf, QSE_MT("Content-Length: ")) == (qse_size_t)-1 ||
|
|
||||||
qse_mbs_cat (proxy->reqfwdbuf, buf) == (qse_size_t)-1 ||
|
|
||||||
qse_mbs_cat (proxy->reqfwdbuf, QSE_MT("\r\n\r\n")) == (qse_size_t)-1) goto oops;
|
|
||||||
|
|
||||||
if (len > 0)
|
|
||||||
{
|
|
||||||
/* content */
|
|
||||||
ptr = qse_htre_getcontentptr(arg->req);
|
|
||||||
if (qse_mbs_ncat (proxy->reqfwdbuf, ptr, len) == (qse_size_t)-1) goto oops;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (qse_mbs_cat (proxy->reqfwdbuf, QSE_MT("\r\n")) == (qse_size_t)-1) goto oops;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (arg->req->attr.flags & QSE_HTRE_ATTR_LENGTH)
|
|
||||||
{
|
|
||||||
/* the Content-Length header field is contained in the request. */
|
|
||||||
qse_mchar_t buf[64];
|
|
||||||
qse_fmtuintmaxtombs (
|
|
||||||
buf, QSE_COUNTOF(buf),
|
|
||||||
arg->req->attr.content_length,
|
|
||||||
10, -1, QSE_MT('\0'), QSE_NULL);
|
|
||||||
|
|
||||||
if (qse_mbs_cat (proxy->reqfwdbuf, QSE_MT("Content-Length: ")) == (qse_size_t)-1 ||
|
|
||||||
qse_mbs_cat (proxy->reqfwdbuf, buf) == (qse_size_t)-1 ||
|
|
||||||
qse_mbs_cat (proxy->reqfwdbuf, QSE_MT("\r\n\r\n")) == (qse_size_t)-1) goto oops;
|
|
||||||
|
|
||||||
len = qse_htre_getcontentlen(arg->req);
|
|
||||||
if (len > 0)
|
|
||||||
{
|
|
||||||
/* content received so far */
|
|
||||||
ptr = qse_htre_getcontentptr(arg->req);
|
|
||||||
if (qse_mbs_ncat (proxy->reqfwdbuf, ptr, len) == (qse_size_t)-1) goto oops;
|
|
||||||
}
|
|
||||||
|
|
||||||
snatch_needed = 1;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* if this request is not chunked nor not length based,
|
int snatch_needed = 0;
|
||||||
* the state should be QSE_HTRE_COMPLETED. so only a
|
|
||||||
* chunked request should reach here */
|
|
||||||
QSE_ASSERT (arg->req->attr.flags & QSE_HTRE_ATTR_CHUNKED);
|
|
||||||
|
|
||||||
proxy->reqflags |= PROXY_REQ_FWDCHUNKED;
|
if (qse_mbs_cat (proxy->reqfwdbuf, qse_htre_getqmethodname(arg->req)) == (qse_size_t)-1 ||
|
||||||
if (qse_mbs_cat (proxy->reqfwdbuf, QSE_MT("Transfer-Encoding: chunked\r\n")) == (qse_size_t)-1 ||
|
qse_mbs_cat (proxy->reqfwdbuf, QSE_MT(" ")) == (qse_size_t)-1 ||
|
||||||
qse_mbs_cat (proxy->reqfwdbuf, QSE_MT("\r\n")) == (qse_size_t)-1 /* end of header */) goto oops;
|
qse_mbs_cat (proxy->reqfwdbuf, qse_htre_getqpath(arg->req)) == (qse_size_t)-1) goto oops;
|
||||||
|
|
||||||
len = qse_htre_getcontentlen(arg->req);
|
if (qse_htre_getqparam(arg->req))
|
||||||
if (len > 0)
|
|
||||||
{
|
{
|
||||||
qse_mchar_t buf[64];
|
if (qse_mbs_cat (proxy->reqfwdbuf, QSE_MT("?")) == (qse_size_t)-1 ||
|
||||||
|
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 ||
|
||||||
|
qse_mbs_cat (proxy->reqfwdbuf, qse_htre_getverstr(arg->req)) == (qse_size_t)-1 ||
|
||||||
|
qse_mbs_cat (proxy->reqfwdbuf, QSE_MT("\r\n")) == (qse_size_t)-1 ||
|
||||||
|
qse_htre_walkheaders (arg->req, proxy_capture_client_header, proxy) <= -1) goto oops;
|
||||||
|
|
||||||
qse_fmtuintmaxtombs (
|
proxy->resflags |= PROXY_RES_AWAIT_RESHDR;
|
||||||
buf, QSE_COUNTOF(buf), len,
|
if ((arg->req->attr.flags & QSE_HTRE_ATTR_EXPECT100) &&
|
||||||
16 | QSE_FMTUINTMAXTOMBS_UPPERCASE,
|
(arg->req->version.major > 1 ||
|
||||||
-1, QSE_MT('\0'), QSE_NULL);
|
(arg->req->version.major == 1 && arg->req->version.minor >= 1)))
|
||||||
|
{
|
||||||
ptr = qse_htre_getcontentptr(arg->req);
|
proxy->resflags |= PROXY_RES_AWAIT_100;
|
||||||
|
|
||||||
/* chunk length and chunk content */
|
|
||||||
if (qse_mbs_cat (proxy->reqfwdbuf, buf) == (qse_size_t)-1 ||
|
|
||||||
qse_mbs_cat (proxy->reqfwdbuf, QSE_MT("\r\n")) == (qse_size_t)-1 ||
|
|
||||||
qse_mbs_ncat (proxy->reqfwdbuf, ptr, len) == (qse_size_t)-1 ||
|
|
||||||
qse_mbs_cat (proxy->reqfwdbuf, QSE_MT("\r\n")) == (qse_size_t)-1) goto oops;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
snatch_needed = 1;
|
if (!(httpd->opt.trait & QSE_HTTPD_PROXYNOVIA))
|
||||||
}
|
{
|
||||||
|
/* add the Via: header into the request */
|
||||||
|
if (qse_mbs_cat (proxy->reqfwdbuf, QSE_MT("Via: ")) == (qse_size_t)-1 ||
|
||||||
|
qse_mbs_cat (proxy->reqfwdbuf, qse_httpd_getname (httpd)) == (qse_size_t)-1 ||
|
||||||
|
qse_mbs_cat (proxy->reqfwdbuf, QSE_MT("\r\n")) == (qse_size_t)-1) goto oops;
|
||||||
|
}
|
||||||
|
|
||||||
if (snatch_needed)
|
if (arg->req->state & QSE_HTRE_DISCARDED)
|
||||||
{
|
{
|
||||||
/* set up a callback to be called when the request content
|
/* no content to add */
|
||||||
* is fed to the htrd reader. qse_htre_addcontent() that
|
if ((arg->req->attr.flags & QSE_HTRE_ATTR_LENGTH) ||
|
||||||
* htrd calls invokes this callback. */
|
(arg->req->attr.flags & QSE_HTRE_ATTR_CHUNKED))
|
||||||
proxy->req = arg->req;
|
{
|
||||||
qse_htre_setconcb (proxy->req, proxy_snatch_client_input, task);
|
/* i don't add chunk traiers if the
|
||||||
|
* request content has been discarded */
|
||||||
|
if (qse_mbs_cat (proxy->reqfwdbuf, QSE_MT("Content-Length: 0\r\n\r\n")) == (qse_size_t)-1) goto oops;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (qse_mbs_cat (proxy->reqfwdbuf, QSE_MT("\r\n")) == (qse_size_t)-1) goto oops;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (arg->req->state & QSE_HTRE_COMPLETED)
|
||||||
|
{
|
||||||
|
if (arg->req->attr.flags & QSE_HTRE_ATTR_CHUNKED)
|
||||||
|
{
|
||||||
|
/* add trailers if any */
|
||||||
|
if (qse_htre_walktrailers (
|
||||||
|
arg->req, proxy_capture_client_trailer, proxy) <= -1) goto oops;
|
||||||
|
}
|
||||||
|
|
||||||
|
len = qse_htre_getcontentlen(arg->req);
|
||||||
|
if (len > 0 || (arg->req->attr.flags & QSE_HTRE_ATTR_LENGTH) ||
|
||||||
|
(arg->req->attr.flags & QSE_HTRE_ATTR_CHUNKED))
|
||||||
|
{
|
||||||
|
qse_mchar_t buf[64];
|
||||||
|
|
||||||
|
qse_fmtuintmaxtombs (
|
||||||
|
buf, QSE_COUNTOF(buf), len,
|
||||||
|
10, -1, QSE_MT('\0'), QSE_NULL);
|
||||||
|
|
||||||
|
/* force-insert content-length. content-length is added
|
||||||
|
* even if the original request dones't contain it */
|
||||||
|
if (qse_mbs_cat (proxy->reqfwdbuf, QSE_MT("Content-Length: ")) == (qse_size_t)-1 ||
|
||||||
|
qse_mbs_cat (proxy->reqfwdbuf, buf) == (qse_size_t)-1 ||
|
||||||
|
qse_mbs_cat (proxy->reqfwdbuf, QSE_MT("\r\n\r\n")) == (qse_size_t)-1) goto oops;
|
||||||
|
|
||||||
|
if (len > 0)
|
||||||
|
{
|
||||||
|
/* content */
|
||||||
|
ptr = qse_htre_getcontentptr(arg->req);
|
||||||
|
if (qse_mbs_ncat (proxy->reqfwdbuf, ptr, len) == (qse_size_t)-1) goto oops;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (qse_mbs_cat (proxy->reqfwdbuf, QSE_MT("\r\n")) == (qse_size_t)-1) goto oops;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (arg->req->attr.flags & QSE_HTRE_ATTR_LENGTH)
|
||||||
|
{
|
||||||
|
/* the Content-Length header field is contained in the request. */
|
||||||
|
qse_mchar_t buf[64];
|
||||||
|
qse_fmtuintmaxtombs (
|
||||||
|
buf, QSE_COUNTOF(buf),
|
||||||
|
arg->req->attr.content_length,
|
||||||
|
10, -1, QSE_MT('\0'), QSE_NULL);
|
||||||
|
|
||||||
|
if (qse_mbs_cat (proxy->reqfwdbuf, QSE_MT("Content-Length: ")) == (qse_size_t)-1 ||
|
||||||
|
qse_mbs_cat (proxy->reqfwdbuf, buf) == (qse_size_t)-1 ||
|
||||||
|
qse_mbs_cat (proxy->reqfwdbuf, QSE_MT("\r\n\r\n")) == (qse_size_t)-1) goto oops;
|
||||||
|
|
||||||
|
len = qse_htre_getcontentlen(arg->req);
|
||||||
|
if (len > 0)
|
||||||
|
{
|
||||||
|
/* content received so far */
|
||||||
|
ptr = qse_htre_getcontentptr(arg->req);
|
||||||
|
if (qse_mbs_ncat (proxy->reqfwdbuf, ptr, len) == (qse_size_t)-1) goto oops;
|
||||||
|
}
|
||||||
|
|
||||||
|
snatch_needed = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* if this request is not chunked nor not length based,
|
||||||
|
* the state should be QSE_HTRE_COMPLETED. so only a
|
||||||
|
* chunked request should reach here */
|
||||||
|
QSE_ASSERT (arg->req->attr.flags & QSE_HTRE_ATTR_CHUNKED);
|
||||||
|
|
||||||
|
proxy->reqflags |= PROXY_REQ_FWDCHUNKED;
|
||||||
|
if (qse_mbs_cat (proxy->reqfwdbuf, QSE_MT("Transfer-Encoding: chunked\r\n")) == (qse_size_t)-1 ||
|
||||||
|
qse_mbs_cat (proxy->reqfwdbuf, QSE_MT("\r\n")) == (qse_size_t)-1 /* end of header */) goto oops;
|
||||||
|
|
||||||
|
len = qse_htre_getcontentlen(arg->req);
|
||||||
|
if (len > 0)
|
||||||
|
{
|
||||||
|
qse_mchar_t buf[64];
|
||||||
|
|
||||||
|
qse_fmtuintmaxtombs (
|
||||||
|
buf, QSE_COUNTOF(buf), len,
|
||||||
|
16 | QSE_FMTUINTMAXTOMBS_UPPERCASE,
|
||||||
|
-1, QSE_MT('\0'), QSE_NULL);
|
||||||
|
|
||||||
|
ptr = qse_htre_getcontentptr(arg->req);
|
||||||
|
|
||||||
|
/* chunk length and chunk content */
|
||||||
|
if (qse_mbs_cat (proxy->reqfwdbuf, buf) == (qse_size_t)-1 ||
|
||||||
|
qse_mbs_cat (proxy->reqfwdbuf, QSE_MT("\r\n")) == (qse_size_t)-1 ||
|
||||||
|
qse_mbs_ncat (proxy->reqfwdbuf, ptr, len) == (qse_size_t)-1 ||
|
||||||
|
qse_mbs_cat (proxy->reqfwdbuf, QSE_MT("\r\n")) == (qse_size_t)-1) goto oops;
|
||||||
|
}
|
||||||
|
|
||||||
|
snatch_needed = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (snatch_needed)
|
||||||
|
{
|
||||||
|
/* set up a callback to be called when the request content
|
||||||
|
* is fed to the htrd reader. qse_htre_addcontent() that
|
||||||
|
* htrd calls invokes this callback. */
|
||||||
|
proxy->req = arg->req;
|
||||||
|
qse_htre_setconcb (proxy->req, proxy_snatch_client_input, task);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* no triggers yet since the main loop doesn't allow me to set
|
/* no triggers yet since the main loop doesn't allow me to set
|
||||||
@ -1025,7 +1075,7 @@ qse_printf (QSE_T("task_main_proxy_4 trigger[0].mask=%d trigger[1].mask=%d trigg
|
|||||||
log_proxy_error (proxy, "proxy premature eof - ");
|
log_proxy_error (proxy, "proxy premature eof - ");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
task->main = task_main_proxy_5;
|
task->main = task_main_proxy_5;
|
||||||
task->trigger[0].mask = 0;
|
task->trigger[0].mask = 0;
|
||||||
@ -1135,19 +1185,12 @@ qse_printf (QSE_T("task_main_proxy_3 trigger[0].mask=%d trigger[1].mask=%d trigg
|
|||||||
if ((proxy->resflags & PROXY_RES_CLIENT_CHUNK) ||
|
if ((proxy->resflags & PROXY_RES_CLIENT_CHUNK) ||
|
||||||
((proxy->resflags & PROXY_RES_PEER_LENGTH) && proxy->peer_output_received >= proxy->peer_output_length))
|
((proxy->resflags & PROXY_RES_PEER_LENGTH) && proxy->peer_output_received >= proxy->peer_output_length))
|
||||||
{
|
{
|
||||||
#if 0
|
|
||||||
qse_printf (QSE_T("SWITINCG TO 55555555555555555555555555 %d %d %d %d\n"),
|
|
||||||
(proxy->resflags & PROXY_RES_CLIENT_CHUNK), (proxy->resflags & PROXY_RES_PEER_LENGTH),
|
|
||||||
(int)proxy->peer_output_received, (int)proxy->peer_output_length);
|
|
||||||
#endif
|
|
||||||
task->main = task_main_proxy_5;
|
task->main = task_main_proxy_5;
|
||||||
task->trigger[2].mask |= QSE_HTTPD_TASK_TRIGGER_WRITE;
|
task->trigger[2].mask |= QSE_HTTPD_TASK_TRIGGER_WRITE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
#if 0
|
/* arrange to read the remaining contents from the peer */
|
||||||
qse_printf (QSE_T("SWITICHING TO 4444444444444444444444444444\n"));
|
|
||||||
#endif
|
|
||||||
task->main = task_main_proxy_4;
|
task->main = task_main_proxy_4;
|
||||||
task->trigger[2].mask &= ~QSE_HTTPD_TASK_TRIGGER_WRITE;
|
task->trigger[2].mask &= ~QSE_HTTPD_TASK_TRIGGER_WRITE;
|
||||||
}
|
}
|
||||||
@ -1287,7 +1330,7 @@ qse_printf (QSE_T("]\n"));
|
|||||||
goto oops;
|
goto oops;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
proxy->buflen += n;
|
proxy->buflen += n;
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
@ -1299,6 +1342,7 @@ for (i = 0; i < proxy->buflen; i++) qse_printf (QSE_T("%hc"), proxy->buf[i]);
|
|||||||
qse_printf (QSE_T("]\n"));
|
qse_printf (QSE_T("]\n"));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
if (qse_htrd_feed (proxy->peer_htrd, proxy->buf, proxy->buflen) <= -1)
|
if (qse_htrd_feed (proxy->peer_htrd, proxy->buf, proxy->buflen) <= -1)
|
||||||
{
|
{
|
||||||
if (httpd->opt.trait & QSE_HTTPD_LOGACT)
|
if (httpd->opt.trait & QSE_HTTPD_LOGACT)
|
||||||
@ -1415,7 +1459,11 @@ static int task_main_proxy_1 (
|
|||||||
task->trigger[0].mask |= QSE_HTTPD_TASK_TRIGGER_WRITE;
|
task->trigger[0].mask |= QSE_HTTPD_TASK_TRIGGER_WRITE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
task->main = task_main_proxy_2;
|
|
||||||
|
if (proxy->raw)
|
||||||
|
task->main = task_main_proxy_4;
|
||||||
|
else
|
||||||
|
task->main = task_main_proxy_2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1435,16 +1483,19 @@ static int task_main_proxy (
|
|||||||
|
|
||||||
if (proxy->init_failed) goto oops;
|
if (proxy->init_failed) goto oops;
|
||||||
|
|
||||||
/* set up a http reader to read a response from the peer */
|
if (!proxy->raw)
|
||||||
proxy->peer_htrd = qse_htrd_open (
|
{
|
||||||
httpd->mmgr, QSE_SIZEOF(proxy_peer_htrd_xtn_t));
|
/* set up a http reader to read a response from the peer */
|
||||||
if (proxy->peer_htrd == QSE_NULL) goto oops;
|
proxy->peer_htrd = qse_htrd_open (
|
||||||
xtn = (proxy_peer_htrd_xtn_t*) qse_htrd_getxtn (proxy->peer_htrd);
|
httpd->mmgr, QSE_SIZEOF(proxy_peer_htrd_xtn_t));
|
||||||
xtn->proxy = proxy;
|
if (proxy->peer_htrd == QSE_NULL) goto oops;
|
||||||
xtn->client = client;
|
xtn = (proxy_peer_htrd_xtn_t*) qse_htrd_getxtn (proxy->peer_htrd);
|
||||||
xtn->task = task;
|
xtn->proxy = proxy;
|
||||||
qse_htrd_setrecbs (proxy->peer_htrd, &proxy_peer_htrd_cbs);
|
xtn->client = client;
|
||||||
qse_htrd_setoption (proxy->peer_htrd, QSE_HTRD_RESPONSE | QSE_HTRD_TRAILERS);
|
xtn->task = task;
|
||||||
|
qse_htrd_setrecbs (proxy->peer_htrd, &proxy_peer_htrd_cbs);
|
||||||
|
qse_htrd_setoption (proxy->peer_htrd, QSE_HTRD_RESPONSE | QSE_HTRD_TRAILERS);
|
||||||
|
}
|
||||||
|
|
||||||
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;
|
||||||
@ -1519,15 +1570,13 @@ qse_httpd_task_t* qse_httpd_entaskproxy (
|
|||||||
qse_httpd_t* httpd,
|
qse_httpd_t* httpd,
|
||||||
qse_httpd_client_t* client,
|
qse_httpd_client_t* client,
|
||||||
qse_httpd_task_t* pred,
|
qse_httpd_task_t* pred,
|
||||||
const qse_nwad_t* dst,
|
const qse_httpd_rsrc_proxy_t* proxy,
|
||||||
const qse_nwad_t* src,
|
|
||||||
qse_htre_t* req)
|
qse_htre_t* req)
|
||||||
{
|
{
|
||||||
qse_httpd_task_t task;
|
qse_httpd_task_t task;
|
||||||
task_proxy_arg_t arg;
|
task_proxy_arg_t arg;
|
||||||
|
|
||||||
arg.peer_nwad = dst;
|
arg.rsrc = proxy;
|
||||||
arg.peer_local = src;
|
|
||||||
arg.req = req;
|
arg.req = req;
|
||||||
|
|
||||||
QSE_MEMSET (&task, 0, QSE_SIZEOF(task));
|
QSE_MEMSET (&task, 0, QSE_SIZEOF(task));
|
||||||
|
@ -1977,6 +1977,8 @@ static int process_request (
|
|||||||
{
|
{
|
||||||
qse_httpd_task_t* task;
|
qse_httpd_task_t* task;
|
||||||
server_xtn_t* server_xtn;
|
server_xtn_t* server_xtn;
|
||||||
|
qse_http_method_t mth;
|
||||||
|
qse_httpd_rsrc_t rsrc;
|
||||||
|
|
||||||
server_xtn = (server_xtn_t*)qse_httpd_getserverxtn (httpd, client->server);
|
server_xtn = (server_xtn_t*)qse_httpd_getserverxtn (httpd, client->server);
|
||||||
|
|
||||||
@ -2008,31 +2010,40 @@ if (qse_htre_getcontentlen(req) > 0)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
mth = qse_htre_getqmethodtype(req);
|
||||||
|
|
||||||
if (peek)
|
if (peek)
|
||||||
{
|
{
|
||||||
qse_httpd_rsrc_t rsrc;
|
|
||||||
|
|
||||||
/* determine what to do once the header fields are all received.
|
/* determine what to do once the header fields are all received.
|
||||||
* i don't want to delay this until the contents are received.
|
* i don't want to delay this until the contents are received.
|
||||||
* if you don't like this behavior, you must implement your own
|
* if you don't like this behavior, you must implement your own
|
||||||
* callback function for request handling. */
|
* callback function for request handling. */
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
/* TODO support X-HTTP-Method-Override */
|
/* TODO support X-HTTP-Method-Override */
|
||||||
if (data.method == QSE_HTTP_POST)
|
if (data.method == QSE_HTTP_POST)
|
||||||
{
|
|
||||||
tmp = qse_htre_getheaderval(req, QSE_MT("X-HTTP-Method-Override"));
|
|
||||||
if (tmp)
|
|
||||||
{
|
{
|
||||||
/*while (tmp->next) tmp = tmp->next;*/ /* get the last value */
|
tmp = qse_htre_getheaderval(req, QSE_MT("X-HTTP-Method-Override"));
|
||||||
data.method = qse_mbstohttpmethod (tmp->ptr);
|
if (tmp)
|
||||||
|
{
|
||||||
|
/*while (tmp->next) tmp = tmp->next;*/ /* get the last value */
|
||||||
|
data.method = qse_mbstohttpmethod (tmp->ptr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (qse_htre_getqmethodtype(req) == QSE_HTTP_POST &&
|
if (mth == QSE_HTTP_CONNECT)
|
||||||
!(req->attr.flags & QSE_HTRE_ATTR_LENGTH) &&
|
{
|
||||||
!(req->attr.flags & QSE_HTRE_ATTR_CHUNKED))
|
/* CONNECT method must not have content set.
|
||||||
|
* however, arrange to discard it if so.
|
||||||
|
*
|
||||||
|
* NOTE: CONNECT is implemented to ignore many headers like
|
||||||
|
* 'Expect: 100-continue' and 'Connection: keep-alive'. */
|
||||||
|
qse_httpd_discardcontent (httpd, req);
|
||||||
|
}
|
||||||
|
else if (mth == QSE_HTTP_POST &&
|
||||||
|
!(req->attr.flags & QSE_HTRE_ATTR_LENGTH) &&
|
||||||
|
!(req->attr.flags & QSE_HTRE_ATTR_CHUNKED))
|
||||||
{
|
{
|
||||||
/* POST without Content-Length nor not chunked */
|
/* POST without Content-Length nor not chunked */
|
||||||
req->attr.flags &= ~QSE_HTRE_ATTR_KEEPALIVE;
|
req->attr.flags &= ~QSE_HTRE_ATTR_KEEPALIVE;
|
||||||
@ -2058,9 +2069,12 @@ if (qse_htre_getcontentlen(req) > 0)
|
|||||||
{
|
{
|
||||||
task = QSE_NULL;
|
task = QSE_NULL;
|
||||||
|
|
||||||
/* inject '100 continue' first if it is needed */
|
|
||||||
if ((rsrc.flags & QSE_HTTPD_RSRC_100_CONTINUE) &&
|
if ((rsrc.flags & QSE_HTTPD_RSRC_100_CONTINUE) &&
|
||||||
(task = qse_httpd_entaskcontinue (httpd, client, task, req)) == QSE_NULL) goto oops;
|
(task = qse_httpd_entaskcontinue (httpd, client, task, req)) == QSE_NULL)
|
||||||
|
{
|
||||||
|
/* inject '100 continue' first if it is needed */
|
||||||
|
goto oops;
|
||||||
|
}
|
||||||
|
|
||||||
/* arrange the actual resource to be returned */
|
/* arrange the actual resource to be returned */
|
||||||
task = qse_httpd_entaskrsrc (httpd, client, task, &rsrc, req);
|
task = qse_httpd_entaskrsrc (httpd, client, task, &rsrc, req);
|
||||||
@ -2079,7 +2093,32 @@ if (qse_htre_getcontentlen(req) > 0)
|
|||||||
{
|
{
|
||||||
/* contents are all received */
|
/* contents are all received */
|
||||||
|
|
||||||
if (req->attr.flags & QSE_HTRE_ATTR_PROXIED)
|
if (mth == QSE_HTTP_CONNECT)
|
||||||
|
{
|
||||||
|
printf ("SWITCHING HTRD TO DUMMY....\n");
|
||||||
|
/* Switch the http read to a dummy mode so that the subsqeuent
|
||||||
|
* input is just treaet as connects to the request just completed */
|
||||||
|
qse_htrd_setoption (client->htrd, qse_htrd_getoption(client->htrd) | QSE_HTRD_DUMMY);
|
||||||
|
|
||||||
|
if (server_xtn->makersrc (httpd, client, req, &rsrc) <= -1)
|
||||||
|
{
|
||||||
|
/* failed to make a resource. just send the internal server error.
|
||||||
|
* the makersrc handler can return a negative number to return
|
||||||
|
* '500 Internal Server Error'. If it wants to return a specific
|
||||||
|
* error code, it should return 0 with the QSE_HTTPD_RSRC_ERR
|
||||||
|
* resource. */
|
||||||
|
task = qse_httpd_entaskerr (httpd, client, QSE_NULL, 500, req);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* arrange the actual resource to be returned */
|
||||||
|
task = qse_httpd_entaskrsrc (httpd, client, QSE_NULL, &rsrc, req);
|
||||||
|
server_xtn->freersrc (httpd, client, req, &rsrc);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (task == QSE_NULL) goto oops;
|
||||||
|
}
|
||||||
|
else if (req->attr.flags & QSE_HTRE_ATTR_PROXIED)
|
||||||
{
|
{
|
||||||
/* the contents should be proxied.
|
/* the contents should be proxied.
|
||||||
* do nothing locally */
|
* do nothing locally */
|
||||||
@ -2087,11 +2126,11 @@ if (qse_htre_getcontentlen(req) > 0)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* when the request is handled locally,
|
/* when the request is handled locally,
|
||||||
* there's nothing special to do here */
|
* there's nothing special to do here */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(req->attr.flags & QSE_HTRE_ATTR_KEEPALIVE))
|
if (!(req->attr.flags & QSE_HTRE_ATTR_KEEPALIVE) || mth == QSE_HTTP_CONNECT)
|
||||||
{
|
{
|
||||||
if (!peek)
|
if (!peek)
|
||||||
{
|
{
|
||||||
@ -2286,7 +2325,7 @@ static qse_mchar_t* merge_paths (
|
|||||||
ta[idx++] = base;
|
ta[idx++] = base;
|
||||||
if (path[0] != QSE_MT('\0'))
|
if (path[0] != QSE_MT('\0'))
|
||||||
{
|
{
|
||||||
ta[idx++] = QSE_MT("/");
|
ta[idx++] = QSE_MT("/");
|
||||||
ta[idx++] = path;
|
ta[idx++] = path;
|
||||||
}
|
}
|
||||||
ta[idx++] = QSE_NULL;
|
ta[idx++] = QSE_NULL;
|
||||||
@ -2483,6 +2522,7 @@ static int make_resource (
|
|||||||
{
|
{
|
||||||
server_xtn_t* server_xtn;
|
server_xtn_t* server_xtn;
|
||||||
struct rsrc_tmp_t tmp;
|
struct rsrc_tmp_t tmp;
|
||||||
|
qse_http_method_t mth;
|
||||||
|
|
||||||
qse_httpd_stat_t st;
|
qse_httpd_stat_t st;
|
||||||
int n, stx, acc;
|
int n, stx, acc;
|
||||||
@ -2495,15 +2535,36 @@ static int make_resource (
|
|||||||
|
|
||||||
server_xtn = qse_httpd_getserverxtn (httpd, client->server);
|
server_xtn = qse_httpd_getserverxtn (httpd, client->server);
|
||||||
|
|
||||||
|
mth = qse_htre_getqmethodtype (req);
|
||||||
|
if (mth == QSE_HTTP_CONNECT)
|
||||||
|
{
|
||||||
|
/* TODO: query if CONNECT is allowed */
|
||||||
|
/* TODO: Proxy-Authorization???? */
|
||||||
|
target->type = QSE_HTTPD_RSRC_PROXY;
|
||||||
|
target->u.proxy.raw = 1;
|
||||||
|
|
||||||
|
if (qse_mbstonwad (qse_htre_getqpath(req), &target->u.proxy.dst) <= -1) return -1;
|
||||||
|
target->u.proxy.src.type = target->u.proxy.dst.type;
|
||||||
|
|
||||||
|
/* mark that this request is going to be proxied. */
|
||||||
|
/*req->attr.flags |= QSE_HTRE_ATTR_PROXIED;*/
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (server_xtn->query (httpd, client->server, req, QSE_NULL, QSE_HTTPD_SERVERSTD_ROOT, &tmp.root) <= -1) return -1;
|
if (server_xtn->query (httpd, client->server, req, QSE_NULL, QSE_HTTPD_SERVERSTD_ROOT, &tmp.root) <= -1) return -1;
|
||||||
switch (tmp.root.type)
|
switch (tmp.root.type)
|
||||||
{
|
{
|
||||||
case QSE_HTTPD_SERVERSTD_ROOT_NWAD:
|
case QSE_HTTPD_SERVERSTD_ROOT_NWAD:
|
||||||
/* proxy the request */
|
/* proxy the request */
|
||||||
target->type = QSE_HTTPD_RSRC_PROXY;
|
target->type = QSE_HTTPD_RSRC_PROXY;
|
||||||
/*target->u.proxy.dst = client->orgdst_addr;*/
|
target->u.proxy.raw = 0;
|
||||||
target->u.proxy.dst = tmp.root.u.nwad;
|
|
||||||
|
/* transparent proxy may do the following
|
||||||
|
target->u.proxy.dst = client->orgdst_addr;
|
||||||
target->u.proxy.src = client->remote_addr;
|
target->u.proxy.src = client->remote_addr;
|
||||||
|
*/
|
||||||
|
target->u.proxy.dst = tmp.root.u.nwad;
|
||||||
|
target->u.proxy.src.type = target->u.proxy.dst.type;
|
||||||
|
|
||||||
/* mark that this request is going to be proxied. */
|
/* mark that this request is going to be proxied. */
|
||||||
req->attr.flags |= QSE_HTRE_ATTR_PROXIED;
|
req->attr.flags |= QSE_HTRE_ATTR_PROXIED;
|
||||||
@ -2630,7 +2691,7 @@ auth_ok:
|
|||||||
tmp.final_match = 1;
|
tmp.final_match = 1;
|
||||||
|
|
||||||
if (st.isdir)
|
if (st.isdir)
|
||||||
{
|
{
|
||||||
/* it is a directory */
|
/* it is a directory */
|
||||||
if (tmp.index.count > 0)
|
if (tmp.index.count > 0)
|
||||||
{
|
{
|
||||||
@ -2869,7 +2930,7 @@ static int query_server (
|
|||||||
*(const qse_mchar_t**)result = mimetab[i].type;
|
*(const qse_mchar_t**)result = mimetab[i].type;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*(const qse_mchar_t**)result = QSE_NULL;
|
*(const qse_mchar_t**)result = QSE_NULL;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -398,7 +398,7 @@ qse_httpd_task_t* qse_httpd_entaskrsrc (
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case QSE_HTTPD_RSRC_PROXY:
|
case QSE_HTTPD_RSRC_PROXY:
|
||||||
task = qse_httpd_entaskproxy (httpd, client, pred, &rsrc->u.proxy.dst, &rsrc->u.proxy.src, req);
|
task = qse_httpd_entaskproxy (httpd, client, pred, &rsrc->u.proxy, req);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case QSE_HTTPD_RSRC_RELOC:
|
case QSE_HTTPD_RSRC_RELOC:
|
||||||
|
@ -319,7 +319,7 @@ static QSE_INLINE int dequeue_task (
|
|||||||
|
|
||||||
if (client->task.count <= 0) return -1;
|
if (client->task.count <= 0) return -1;
|
||||||
|
|
||||||
task = client->task.head;
|
task = (qse_httpd_real_task_t*)client->task.head;
|
||||||
|
|
||||||
/* clear task triggers from mux if they are registered */
|
/* clear task triggers from mux if they are registered */
|
||||||
for (i = 0; i < QSE_COUNTOF(task->core.trigger); i++)
|
for (i = 0; i < QSE_COUNTOF(task->core.trigger); i++)
|
||||||
@ -333,7 +333,7 @@ static QSE_INLINE int dequeue_task (
|
|||||||
|
|
||||||
/* --------------------------------------------------- */
|
/* --------------------------------------------------- */
|
||||||
|
|
||||||
if (task == client->task.tail)
|
if (task == (qse_httpd_real_task_t*)client->task.tail)
|
||||||
{
|
{
|
||||||
client->task.head = QSE_NULL;
|
client->task.head = QSE_NULL;
|
||||||
client->task.tail = QSE_NULL;
|
client->task.tail = QSE_NULL;
|
||||||
@ -345,7 +345,7 @@ static QSE_INLINE int dequeue_task (
|
|||||||
}
|
}
|
||||||
client->task.count--;
|
client->task.count--;
|
||||||
|
|
||||||
if (task->core.fini) task->core.fini (httpd, client, task);
|
if (task->core.fini) task->core.fini (httpd, client, (qse_httpd_task_t*)task);
|
||||||
qse_httpd_freemem (httpd, task);
|
qse_httpd_freemem (httpd, task);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -816,7 +816,7 @@ qse_printf (QSE_T("]\n"));
|
|||||||
if (httpd->errnum == QSE_HTTPD_ENOERR)
|
if (httpd->errnum == QSE_HTTPD_ENOERR)
|
||||||
{
|
{
|
||||||
if (client->htrd->errnum == QSE_HTRD_EBADRE ||
|
if (client->htrd->errnum == QSE_HTRD_EBADRE ||
|
||||||
client->htrd->errnum == QSE_HTRD_EBADHDR)
|
client->htrd->errnum == QSE_HTRD_EBADHDR)
|
||||||
httpd->errnum = QSE_HTTPD_EBADREQ;
|
httpd->errnum = QSE_HTTPD_EBADREQ;
|
||||||
else httpd->errnum = QSE_HTTPD_ENOMEM; /* TODO: better translate error code */
|
else httpd->errnum = QSE_HTTPD_ENOMEM; /* TODO: better translate error code */
|
||||||
}
|
}
|
||||||
@ -829,10 +829,10 @@ for (i = 0; i < m; i++) qse_printf (QSE_T("%hc"), buf[i]);
|
|||||||
}
|
}
|
||||||
qse_printf (QSE_T("]\n"));
|
qse_printf (QSE_T("]\n"));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
qse_printf (QSE_T("!!!!!FEEDING OK OK OK OK %d from %d\n"), (int)m, (int)client->handle.i);
|
qse_printf (QSE_T("!!!!!FEEDING OK OK OK OK %d from %d\n"), (int)m, (int)client->handle.i);
|
||||||
#endif
|
#endif
|
||||||
@ -1370,7 +1370,7 @@ qse_mchar_t* qse_httpd_escapehtml (qse_httpd_t* httpd, const qse_mchar_t* str)
|
|||||||
qse_mchar_t* ptr, * buf;
|
qse_mchar_t* ptr, * buf;
|
||||||
qse_size_t reqlen = 0;
|
qse_size_t reqlen = 0;
|
||||||
|
|
||||||
for (ptr = str; *ptr != QSE_MT('\0'); ptr++)
|
for (ptr = (qse_mchar_t*)str; *ptr != QSE_MT('\0'); ptr++)
|
||||||
{
|
{
|
||||||
switch (*ptr)
|
switch (*ptr)
|
||||||
{
|
{
|
||||||
@ -1389,7 +1389,7 @@ qse_mchar_t* qse_httpd_escapehtml (qse_httpd_t* httpd, const qse_mchar_t* str)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ptr - str == reqlen) return str; /* no escaping is needed */
|
if (ptr - str == reqlen) return (qse_mchar_t*)str; /* no escaping is needed */
|
||||||
|
|
||||||
buf = qse_httpd_allocmem (httpd, QSE_SIZEOF(*buf) * (reqlen + 1));
|
buf = qse_httpd_allocmem (httpd, QSE_SIZEOF(*buf) * (reqlen + 1));
|
||||||
if (buf == QSE_NULL) return QSE_NULL;
|
if (buf == QSE_NULL) return QSE_NULL;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user