From eb1511b817f41310a11f1d07565dd92733b82a17 Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Wed, 13 Aug 2014 14:35:43 +0000 Subject: [PATCH] added more configuration items to httpd --- qse/cmd/http/httpd.c | 284 +++++++++++++++++++++----------- qse/cmd/http/httpd.conf | 13 ++ qse/include/qse/http/httpd.h | 70 +++++--- qse/include/qse/http/stdhttpd.h | 14 +- qse/lib/http/httpd-proxy.c | 105 ++++++------ qse/lib/http/httpd-std-dns.h | 66 ++++---- qse/lib/http/httpd-std-urs.h | 87 +++++----- qse/lib/http/httpd-std.c | 151 +++-------------- qse/lib/http/httpd.c | 95 +++++------ qse/lib/http/httpd.h | 15 -- 10 files changed, 469 insertions(+), 431 deletions(-) diff --git a/qse/cmd/http/httpd.c b/qse/cmd/http/httpd.c index 46efe65a..1f9f3033 100644 --- a/qse/cmd/http/httpd.c +++ b/qse/cmd/http/httpd.c @@ -73,7 +73,6 @@ enum XCFG_DIRFOOT, XCFG_ERRHEAD, XCFG_ERRFOOT, - XCFG_PSEUDONYM, XCFG_MAX }; @@ -186,10 +185,17 @@ struct loccfg_t struct { - int allow_http: 1; - int allow_connect: 1; + unsigned int allow_http: 1; + unsigned int allow_connect: 1; + unsigned int dns_enabled: 1; + unsigned int urs_enabled: 1; qse_nwad_t dns_nwad; /* TODO: multiple dns */ qse_nwad_t urs_nwad; /* TODO: multiple urs */ + int dns_timeout; + int dns_retries; + int urs_timeout; + int urs_retries; + const qse_mchar_t pseudonym[128]; /* TODO: good size? */ } proxy; loccfg_t* next; @@ -354,9 +360,19 @@ static int make_resource ( server_xtn = qse_httpd_getserverstdxtn (httpd, client->server); +#if 0 if (server_xtn->tproxy) { - if (qse_nwadequal(&client->orgdst_addr, &client->local_addr)) /* both equal and error */ + if (client->status & QSE_HTTPD_CLIENT_INTERCEPTED) + { + rsrc->type = QSE_HTTPD_RSRC_PROXY; + rsrc->u.proxy.flags = 0; + rsrc->u.proxy.dst.nwad = client->orgdst_addr; + rsrc->u.proxy.src.nwad = client->remote_addr; + + qse_setnwadport (&rsrc->u.proxy.src.nwad, 0); + } + else { /* TODO: implement a better check that the * destination is not one of the local addresses */ @@ -364,23 +380,12 @@ static int make_resource ( rsrc->type = QSE_HTTPD_RSRC_ERROR; rsrc->u.error.code = 500; } - else - { - rsrc->type = QSE_HTTPD_RSRC_PROXY; - rsrc->u.proxy.flags = 0; - rsrc->u.proxy.dst.nwad = client->orgdst_addr; - rsrc->u.proxy.src.nwad = client->remote_addr; - - if (rsrc->u.proxy.src.nwad.type == QSE_NWAD_IN4) - rsrc->u.proxy.src.nwad.u.in4.port = 0; /* reset the port to 0. */ - else if (rsrc->u.proxy.src.nwad.type == QSE_NWAD_IN6) - rsrc->u.proxy.src.nwad.u.in6.port = 0; /* reset the port to 0. */ - } return 0; } else { +#endif if (server_xtn->orgmakersrc (httpd, client, req, rsrc) <= -1) return -1; if (server_xtn->nodir && rsrc->type == QSE_HTTPD_RSRC_DIR) { @@ -390,7 +395,9 @@ static int make_resource ( rsrc->u.error.code = 403; } return 0; +#if 0 } +#endif } static void free_resource ( @@ -401,14 +408,18 @@ static void free_resource ( server_xtn = qse_httpd_getserverstdxtn (httpd, client->server); +#if 0 if (server_xtn->tproxy) { /* nothing to do */ } else { +#endif server_xtn->orgfreersrc (httpd, client, req, rsrc); +#if 0 } +#endif } /* --------------------------------------------------------------------- */ @@ -460,28 +471,33 @@ static int get_server_root ( qse_memset (root, 0, QSE_SIZEOF(*root)); - if (loccfg->proxy.dns_nwad.type != QSE_NWAD_NX) + if ((qinfo->client->status & QSE_HTTPD_CLIENT_INTERCEPTED) /*&& + loccfg->proxy.allow_intercept */) { - root->u.proxy.dns_server = loccfg->proxy.dns_nwad; - root->u.proxy.flags |= QSE_HTTPD_RSRC_PROXY_DNS_SERVER; - } + root->type = QSE_HTTPD_SERVERSTD_ROOT_PROXY; + root->u.proxy.dst.nwad = qinfo->client->orgdst_addr; + /* if TPROXY is used, set the source to the original source. + root->u.proxy.src.nwad = qinfo->client->remote_addr; + qse_setnwadport (&root->u.proxy.src.nwad, 0);*/ - if (loccfg->proxy.urs_nwad.type != QSE_NWAD_NX) - { - root->u.proxy.urs_server = loccfg->proxy.urs_nwad; - root->u.proxy.flags |= QSE_HTTPD_RSRC_PROXY_URS_SERVER; + if (mth == QSE_HTTP_CONNECT) + root->u.proxy.flags |= QSE_HTTPD_RSRC_PROXY_RAW; + else if (loccfg->proxy.pseudonym[0]) + root->u.proxy.pseudonym = loccfg->proxy.pseudonym; + + goto proxy_ok; } if (mth == QSE_HTTP_CONNECT) { if (loccfg->proxy.allow_connect) { - /* TODO: check on what conditions CONNECT is allowed. */ /* TODO: disallow connecting back to self */ /* TODO: Proxy-Authorization???? */ root->type = QSE_HTTPD_SERVERSTD_ROOT_PROXY; root->u.proxy.flags |= QSE_HTTPD_RSRC_PROXY_RAW; + /* no pseudonym for RAW proxying */ if (qse_mbstonwad(qpath, &root->u.proxy.dst.nwad) <= -1) { @@ -494,7 +510,8 @@ static int get_server_root ( /* no default port for raw proxying */ root->u.proxy.src.nwad.type = root->u.proxy.dst.nwad.type; } - return 0; + + goto proxy_ok; } else { @@ -504,44 +521,45 @@ static int get_server_root ( } } - if (loccfg->proxy.allow_http) + if (loccfg->proxy.allow_http && + qse_mbszcasecmp (qpath, QSE_MT("http://"), 7) == 0) { - if (qse_mbszcasecmp (qpath, QSE_MT("http://"), 7) == 0) + qse_mchar_t* host, * slash; + + host = qpath + 7; + slash = qse_mbschr (host, QSE_MT('/')); + + if (slash && slash - host > 0) { - qse_mchar_t* host, * slash; +/* TODO: refrain from manipulating the request like this */ - host = qpath + 7; - slash = qse_mbschr (host, QSE_MT('/')); + root->type = QSE_HTTPD_SERVERSTD_ROOT_PROXY; - if (slash && slash - host > 0) + if (loccfg->proxy.pseudonym[0]) + root->u.proxy.pseudonym = loccfg->proxy.pseudonym; + + qse_memmove (host - 1, host, slash - host); + slash[-1] = QSE_MT('\0'); + host = host - 1; + root->u.proxy.host = host; + + if (qse_mbstonwad (host, &root->u.proxy.dst.nwad) <= -1) { - /* TODO: refrain from manipulating the request like this */ - - root->type = QSE_HTTPD_SERVERSTD_ROOT_PROXY; - - qse_memmove (host - 1, host, slash - host); - slash[-1] = QSE_MT('\0'); - host = host - 1; - root->u.proxy.host = host; - - if (qse_mbstonwad (host, &root->u.proxy.dst.nwad) <= -1) - { - root->u.proxy.flags |= QSE_HTTPD_RSRC_PROXY_DST_STR; - root->u.proxy.dst.str = host; - } - else - { - /* make the source binding type the same as destination */ - if (qse_getnwadport(&root->u.proxy.dst.nwad) == 0) - qse_setnwadport (&root->u.proxy.dst.nwad, qse_hton16(80)); - root->u.proxy.src.nwad.type = root->u.proxy.dst.nwad.type; - } - - /* TODO: refrain from manipulating the request like this */ - qinfo->req->u.q.path = slash; /* TODO: use setqpath or something... */ - - return 0; + root->u.proxy.flags |= QSE_HTTPD_RSRC_PROXY_DST_STR; + root->u.proxy.dst.str = host; } + else + { + /* make the source binding type the same as destination */ + if (qse_getnwadport(&root->u.proxy.dst.nwad) == 0) + qse_setnwadport (&root->u.proxy.dst.nwad, qse_hton16(80)); + root->u.proxy.src.nwad.type = root->u.proxy.dst.nwad.type; + } + +/* TODO: refrain from manipulating the request like this */ + qinfo->req->u.q.path = slash; /* TODO: use setqpath or something... */ + + goto proxy_ok; } else { @@ -551,18 +569,42 @@ static int get_server_root ( } } - - if (loccfg->root_is_nwad) { - root->type = QSE_HTTPD_SERVERSTD_ROOT_NWAD; - root->u.nwad = loccfg->root_nwad; + /* simple forwarding. it's not controlled by proxy.http or proxy.connect */ + root->type = QSE_HTTPD_SERVERSTD_ROOT_PROXY; + + root->u.proxy.dst.nwad = loccfg->root_nwad; + root->u.proxy.src.nwad.type = root->u.proxy.dst.nwad.type; + + if (loccfg->proxy.pseudonym[0]) + root->u.proxy.pseudonym = loccfg->proxy.pseudonym; + + goto proxy_ok; } - else + + /* local file system */ + root->type = QSE_HTTPD_SERVERSTD_ROOT_PATH; + root->u.path.val = loccfg->xcfg[XCFG_ROOT]; + root->u.path.rpl = loccfg->locname.len; + return 0; + + +proxy_ok: + if (loccfg->proxy.dns_enabled) { - root->type = QSE_HTTPD_SERVERSTD_ROOT_PATH; - root->u.path.val = loccfg->xcfg[XCFG_ROOT]; - root->u.path.rpl = loccfg->locname.len; + root->u.proxy.flags |= QSE_HTTPD_RSRC_PROXY_ENABLE_DNS | QSE_HTTPD_RSRC_PROXY_DNS_SERVER; + root->u.proxy.dns_server.nwad = loccfg->proxy.dns_nwad; + root->u.proxy.dns_server.tmout.sec = loccfg->proxy.dns_timeout; + root->u.proxy.dns_server.retries = loccfg->proxy.dns_retries; + } + + if (loccfg->proxy.urs_enabled) + { + root->u.proxy.flags |= QSE_HTTPD_RSRC_PROXY_ENABLE_URS | QSE_HTTPD_RSRC_PROXY_URS_SERVER; + root->u.proxy.urs_server.nwad = loccfg->proxy.urs_nwad; + root->u.proxy.urs_server.tmout.sec = loccfg->proxy.urs_timeout; + root->u.proxy.urs_server.retries = loccfg->proxy.urs_retries; } return 0; @@ -598,20 +640,30 @@ static int query_server ( const qse_mchar_t* host = QSE_NULL; const qse_mchar_t* qpath; qse_http_method_t mth; + const qse_htre_hdrval_t* hosthdr; mth = qse_htre_getqmethodtype (qinfo->req); qpath = qse_htre_getqpath (qinfo->req); if (mth == QSE_HTTP_CONNECT) { + qse_nwad_t nwad; + /* the query path for CONNECT is not a path name, but * a host name. the path is adjusted to the root directory. */ host = qpath; qpath = QSE_MT("/"); + + if (qse_mbstonwad (host, &nwad) >= 0) + { + /* the host is a numeric. try he Host: header. + * i expect the values of the host and qpath variables + * are maintained if Host: is not found after goto. */ + goto try_host; + } } else { - const qse_htre_hdrval_t* hosthdr; - + try_host: hosthdr = qse_htre_getheaderval (qinfo->req, QSE_MT("Host")); if (hosthdr) { @@ -684,19 +736,6 @@ found: #endif return get_server_root (httpd, server, loccfg, qinfo, result); -/* - if (loccfg->root_is_nwad) - { - ((qse_httpd_serverstd_root_t*)result)->type = QSE_HTTPD_SERVERSTD_ROOT_NWAD; - ((qse_httpd_serverstd_root_t*)result)->u.nwad = loccfg->root_nwad; - } - else - { - ((qse_httpd_serverstd_root_t*)result)->type = QSE_HTTPD_SERVERSTD_ROOT_PATH; - ((qse_httpd_serverstd_root_t*)result)->u.path.val = loccfg->xcfg[XCFG_ROOT]; - ((qse_httpd_serverstd_root_t*)result)->u.path.rpl = loccfg->locname.len; - } - return 0;*/ case QSE_HTTPD_SERVERSTD_REALM: { @@ -774,10 +813,6 @@ found: *(const qse_mchar_t**)result = loccfg->xcfg[XCFG_ERRFOOT]; return 0; - case QSE_HTTPD_SERVERSTD_PSEUDONYM: - *(const qse_mchar_t**)result = loccfg->xcfg[XCFG_PSEUDONYM]; - return 0; - case QSE_HTTPD_SERVERSTD_INDEX: ((qse_httpd_serverstd_index_t*)result)->count = loccfg->index.count; ((qse_httpd_serverstd_index_t*)result)->files = loccfg->index.files; @@ -991,6 +1026,12 @@ static int get_boolean (const qse_xli_str_t* v) qse_strxcasecmp (v->ptr, v->len, QSE_T("on")) == 0); } +static int get_integer (const qse_xli_str_t* v) +{ +/* TODO: be more strict */ + return qse_strxtoi (v->ptr, v->len); +} + static int load_loccfg_basic (qse_httpd_t* httpd, qse_xli_t* xli, qse_xli_list_t* list, loccfg_t* cfg) { static struct @@ -1005,8 +1046,7 @@ static int load_loccfg_basic (qse_httpd_t* httpd, qse_xli_t* xli, qse_xli_list_t { QSE_T("dir-head"), QSE_T("server-default.dir-head") }, { QSE_T("dir-foot"), QSE_T("server-default.dir-foot") }, { QSE_T("error-head"), QSE_T("server-default.error-head") }, - { QSE_T("error-foot"), QSE_T("server-default.error-foot") }, - { QSE_T("pseudonym"), QSE_T("server-default.pseudonym") } + { QSE_T("error-foot"), QSE_T("server-default.error-foot") } }; int i; @@ -1378,6 +1418,30 @@ static int load_loccfg_proxy (qse_httpd_t* httpd, qse_xli_t* xli, qse_xli_list_t if (!pair && default_proxy) pair = qse_xli_findpair (xli, default_proxy, QSE_T("connect")); if (pair) cfg->proxy.allow_connect = get_boolean ((qse_xli_str_t*)pair->val); + pair = QSE_NULL; + if (proxy) pair = qse_xli_findpair (xli, proxy, QSE_T("pseudonym")); + if (!pair && default_proxy) pair = qse_xli_findpair (xli, default_proxy, QSE_T("pseudonym")); + if (pair) + { + qse_xli_str_t* str = (qse_xli_str_t*)pair->val; + + #if defined(QSE_CHAR_IS_MCHAR) + qse_mbsxcpy (cfg->proxy.pseudonym, QSE_COUNTOF(cfg->proxy.pseudonym), str->ptr); + #else + qse_size_t wcslen, mbslen = QSE_COUNTOF(cfg->proxy.pseudonym); + if (qse_wcstombs (str->ptr, &wcslen, cfg->proxy.pseudonym, &mbslen) <= -1) + { + qse_printf (QSE_T("ERROR: invalid pseudonym for proxy - %s"), str->ptr); + return -1; + } + #endif + } + + pair = QSE_NULL; + if (proxy) pair = qse_xli_findpair (xli, proxy, QSE_T("dns-enabled")); + if (!pair && default_proxy) pair = qse_xli_findpair (xli, default_proxy, QSE_T("dns-enabled")); + if (pair) cfg->proxy.dns_enabled = get_boolean ((qse_xli_str_t*)pair->val); + pair = QSE_NULL; if (proxy) pair = qse_xli_findpair (xli, proxy, QSE_T("dns-server")); if (!pair && default_proxy) pair = qse_xli_findpair (xli, default_proxy, QSE_T("dns-server")); @@ -1391,6 +1455,25 @@ static int load_loccfg_proxy (qse_httpd_t* httpd, qse_xli_t* xli, qse_xli_list_t } } + pair = QSE_NULL; + if (proxy) pair = qse_xli_findpair (xli, proxy, QSE_T("dns-timeout")); + if (!pair && default_proxy) pair = qse_xli_findpair (xli, default_proxy, QSE_T("dns-timeout")); + if (pair) cfg->proxy.dns_timeout = get_integer ((qse_xli_str_t*)pair->val); + else cfg->proxy.dns_timeout = -1; + + pair = QSE_NULL; + if (proxy) pair = qse_xli_findpair (xli, proxy, QSE_T("dns-retries")); + if (!pair && default_proxy) pair = qse_xli_findpair (xli, default_proxy, QSE_T("dns-retries")); + if (pair) cfg->proxy.dns_retries = get_integer ((qse_xli_str_t*)pair->val); + else cfg->proxy.dns_retries = -1; + + + + pair = QSE_NULL; + if (proxy) pair = qse_xli_findpair (xli, proxy, QSE_T("urs-enabled")); + if (!pair && default_proxy) pair = qse_xli_findpair (xli, default_proxy, QSE_T("urs-enabled")); + if (pair) cfg->proxy.urs_enabled = get_boolean ((qse_xli_str_t*)pair->val); + pair = QSE_NULL; if (proxy) pair = qse_xli_findpair (xli, proxy, QSE_T("urs-server")); if (!pair && default_proxy) pair = qse_xli_findpair (xli, default_proxy, QSE_T("urs-server")); @@ -1404,6 +1487,18 @@ static int load_loccfg_proxy (qse_httpd_t* httpd, qse_xli_t* xli, qse_xli_list_t } } + pair = QSE_NULL; + if (proxy) pair = qse_xli_findpair (xli, proxy, QSE_T("urs-timeout")); + if (!pair && default_proxy) pair = qse_xli_findpair (xli, default_proxy, QSE_T("urs-timeout")); + if (pair) cfg->proxy.urs_timeout = get_integer ((qse_xli_str_t*)pair->val); + else cfg->proxy.urs_timeout = -1; + + pair = QSE_NULL; + if (proxy) pair = qse_xli_findpair (xli, proxy, QSE_T("urs-retries")); + if (!pair && default_proxy) pair = qse_xli_findpair (xli, default_proxy, QSE_T("urs-retries")); + if (pair) cfg->proxy.urs_retries = get_integer ((qse_xli_str_t*)pair->val); + else cfg->proxy.urs_retries = -1; + return 0; } @@ -1731,14 +1826,15 @@ static int open_config_file (qse_httpd_t* httpd) { QSE_T("server-default.dir-foot"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } }, { QSE_T("server-default.error-head"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } }, { QSE_T("server-default.error-foot"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } }, - { QSE_T("server-default.pseudonym"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } }, { QSE_T("server-default.proxy"), { QSE_XLI_SCM_VALLIST | QSE_XLI_SCM_KEYNODUP, 0, 0 } }, { QSE_T("server-default.proxy.http"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } }, { QSE_T("server-default.proxy.connect"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } }, { QSE_T("server-default.proxy.pseudonym"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } }, + { QSE_T("server-default.proxy.dns-enabled"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } }, { QSE_T("server-default.proxy.dns-server"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } }, { QSE_T("server-default.proxy.dns-timeout"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } }, { QSE_T("server-default.proxy.dns-retries"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } }, + { QSE_T("server-default.proxy.urs-enabled"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } }, { QSE_T("server-default.proxy.urs-server"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } }, { QSE_T("server-default.proxy.urs-timeout"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } }, { QSE_T("server-default.proxy.urs-retries"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } }, @@ -1782,15 +1878,15 @@ static int open_config_file (qse_httpd_t* httpd) { QSE_T("server.host.location.dir-foot"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } }, { QSE_T("server.host.location.error-head"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } }, { QSE_T("server.host.location.error-foot"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } }, - { QSE_T("server.host.location.pseudonym"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } }, - { QSE_T("server.host.location.proxy"), { QSE_XLI_SCM_VALLIST | QSE_XLI_SCM_KEYNODUP, 0, 0 } }, { QSE_T("server.host.location.proxy.http"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } }, { QSE_T("server.host.location.proxy.connect"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } }, { QSE_T("server.host.location.proxy.pseudonym"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } }, + { QSE_T("server.host.location.proxy.dns-enabled"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } }, { QSE_T("server.host.location.proxy.dns-server"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } }, { QSE_T("server.host.location.proxy.dns-timeout"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } }, { QSE_T("server.host.location.proxy.dns-retries"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } }, + { QSE_T("server.host.location.proxy.urs-enabled"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } }, { QSE_T("server.host.location.proxy.urs-server"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } }, { QSE_T("server.host.location.proxy.urs-timeout"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } }, { QSE_T("server.host.location.proxy.urs-retries"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } }, @@ -2258,13 +2354,7 @@ static int httpd_main (int argc, qse_char_t* argv[]) if (g_debug) rcb.logact = logact_httpd; /* i don't remember old logging handler */ qse_httpd_setopt (httpd, QSE_HTTPD_RCB, &rcb); -/* TODO: read from configuration... */ -{ -qse_httpd_ursstd_t urs; -qse_memset (&urs, 0, QSE_SIZEOF(urs)); -qse_mbstonwad ("[::1]:97", &urs.nwad); - ret = qse_httpd_loopstd (httpd, QSE_NULL, &urs); -} + ret = qse_httpd_loopstd (httpd, QSE_NULL, QSE_NULL); restore_signal_handlers (); g_httpd = QSE_NULL; diff --git a/qse/cmd/http/httpd.conf b/qse/cmd/http/httpd.conf index de65a21b..ced293aa 100644 --- a/qse/cmd/http/httpd.conf +++ b/qse/cmd/http/httpd.conf @@ -129,6 +129,19 @@ server-default { proxy { http = yes; connect = yes; + + #pseudonym = "nice-host"; + + dns-enabled = yes; + dns-server = "192.168.1.1:53"; + #dns-server = "[::1]:53"; + #dns-timeout = 3 + #dns-retries = 2 + + #urs-enabled = yes; + #urs-server = "127.0.0.1:97"; + #urs-timeout = 1; + #urs-retries = 4; } } diff --git a/qse/include/qse/http/httpd.h b/qse/include/qse/http/httpd.h index cb29e697..fa7067e4 100644 --- a/qse/include/qse/http/httpd.h +++ b/qse/include/qse/http/httpd.h @@ -58,8 +58,8 @@ enum qse_httpd_errnum_t QSE_HTTPD_ENOBUF, /* no buffer available */ QSE_HTTPD_EDISCON, /* client disconnnected */ QSE_HTTPD_EBADREQ, /* bad request */ - QSE_HTTPD_ENODNS, /* dns service not activated */ - QSE_HTTPD_ENOURS, /* urs service not activated */ + QSE_HTTPD_ENODNS, /* dns service not activated/enabled or no valid dns server specified */ + QSE_HTTPD_ENOURS, /* urs service not activated/enabled or no valid urs server specified */ QSE_HTTPD_ETASK }; typedef enum qse_httpd_errnum_t qse_httpd_errnum_t; @@ -127,6 +127,15 @@ struct qse_httpd_dirent_t qse_httpd_stat_t stat; }; +typedef struct qse_httpd_natr_t qse_httpd_natr_t; + +struct qse_httpd_natr_t +{ + qse_nwad_t nwad; + qse_ntime_t tmout; + int retries; +}; + typedef void (*qse_httpd_resol_t) ( qse_httpd_t* httpd, const qse_mchar_t* name, @@ -264,7 +273,7 @@ struct qse_httpd_scb_t int (*recv) (qse_httpd_t* httpd, qse_httpd_dns_t* dns, qse_ubi_t handle); int (*send) (qse_httpd_t* httpd, qse_httpd_dns_t* dns, const qse_mchar_t* name, qse_httpd_resol_t resol, - const qse_nwad_t* dns_server, void* ctx); + const qse_httpd_natr_t* dns_server, void* ctx); } dns; struct @@ -274,7 +283,7 @@ struct qse_httpd_scb_t int (*recv) (qse_httpd_t* httpd, qse_httpd_urs_t* urs, qse_ubi_t handle); int (*send) (qse_httpd_t* httpd, qse_httpd_urs_t* urs, const qse_mchar_t* url, qse_httpd_rewrite_t rewrite, - const qse_nwad_t* urs_server, void* ctx); + const qse_httpd_natr_t* urs_server, void* ctx); } urs; }; @@ -459,6 +468,22 @@ struct qse_httpd_client_t } task; }; +/* client->status */ +#define QSE_HTTPD_CLIENT_BAD (1 << 0) +#define QSE_HTTPD_CLIENT_READY (1 << 1) +#define QSE_HTTPD_CLIENT_INTERCEPTED (1 << 2) +#define QSE_HTTPD_CLIENT_SECURE (1 << 3) +#define QSE_HTTPD_CLIENT_PENDING (1 << 4) +#define QSE_HTTPD_CLIENT_MUTE (1 << 5) +#define QSE_HTTPD_CLIENT_MUTE_DELETED (1 << 6) +#define QSE_HTTPD_CLIENT_HANDLE_READ_IN_MUX (1 << 7) +#define QSE_HTTPD_CLIENT_HANDLE_WRITE_IN_MUX (1 << 8) +#define QSE_HTTPD_CLIENT_HANDLE_RW_IN_MUX (QSE_HTTPD_CLIENT_HANDLE_READ_IN_MUX | QSE_HTTPD_CLIENT_HANDLE_WRITE_IN_MUX) + +#define QSE_HTTPD_CLIENT_TASK_TRIGGER_READ_IN_MUX(i) (1 << ((i) + 9)) +#define QSE_HTTPD_CLIENT_TASK_TRIGGER_WRITE_IN_MUX(i) (1 << ((i) + 9 + QSE_HTTPD_TASK_TRIGGER_MAX)) +#define QSE_HTTPD_CLIENT_TASK_TRIGGER_RW_IN_MUX(i) (QSE_HTTPD_CLIENT_TASK_TRIGGER_READ_IN_MUX(i) | QSE_HTTPD_CLIENT_TASK_TRIGGER_WRITE_IN_MUX(i)) + enum qse_httpd_server_flag_t { QSE_HTTPD_SERVER_ACTIVE = (1 << 0), @@ -559,12 +584,13 @@ struct qse_httpd_rsrc_cgi_t enum qse_httpd_rsrc_proxy_flag_t { - QSE_HTTPD_RSRC_PROXY_RAW = (1 << 0), - QSE_HTTPD_RSRC_PROXY_DST_STR = (1 << 1), - QSE_HTTPD_RSRC_PROXY_TRANSPARENT = (1 << 2), - QSE_HTTPD_RSRC_PROXY_ENABLE_URS = (1 << 3), /* url rewriting enabled */ - QSE_HTTPD_RSRC_PROXY_DNS_SERVER = (1 << 4), - QSE_HTTPD_RSRC_PROXY_URS_SERVER = (1 << 5) + QSE_HTTPD_RSRC_PROXY_RAW = (1 << 0), /* raw proxying. set this for CONNECT */ + QSE_HTTPD_RSRC_PROXY_TRANSPARENT = (1 << 1), + QSE_HTTPD_RSRC_PROXY_DST_STR = (1 << 2), /* destination is an unresovled string pointed to by dst.str */ + QSE_HTTPD_RSRC_PROXY_ENABLE_DNS = (1 << 3), /* dns service enabled */ + QSE_HTTPD_RSRC_PROXY_ENABLE_URS = (1 << 4), /* url rewriting enabled */ + QSE_HTTPD_RSRC_PROXY_DNS_SERVER = (1 << 5), /* dns address specified */ + QSE_HTTPD_RSRC_PROXY_URS_SERVER = (1 << 6) /* urs address specified */ }; typedef struct qse_httpd_rsrc_proxy_t qse_httpd_rsrc_proxy_t; @@ -583,8 +609,8 @@ struct qse_httpd_rsrc_proxy_t const qse_mchar_t* str; } dst; /* remote destination address to connect to */ - qse_nwad_t dns_server; - qse_nwad_t urs_server; + qse_httpd_natr_t dns_server; + qse_httpd_natr_t urs_server; const qse_mchar_t* pseudonym; /* pseudonym to use in Via: */ }; @@ -1007,19 +1033,19 @@ QSE_EXPORT qse_mchar_t* qse_httpd_escapehtml ( ); QSE_EXPORT int qse_httpd_resolname ( - qse_httpd_t* httpd, - const qse_mchar_t* name, - qse_httpd_resol_t resol, - const qse_nwad_t* dns_server, - void* ctx + qse_httpd_t* httpd, + const qse_mchar_t* name, + qse_httpd_resol_t resol, + const qse_httpd_natr_t* dns_server, + void* ctx ); QSE_EXPORT int qse_httpd_rewriteurl ( - qse_httpd_t* ttpd, - const qse_mchar_t* url, - qse_httpd_rewrite_t rewrite, - const qse_nwad_t* urs_server, - void* ctx + qse_httpd_t* httpd, + const qse_mchar_t* url, + qse_httpd_rewrite_t rewrite, + const qse_httpd_natr_t* urs_server, + void* ctx ); diff --git a/qse/include/qse/http/stdhttpd.h b/qse/include/qse/http/stdhttpd.h index 0e217580..590287ed 100644 --- a/qse/include/qse/http/stdhttpd.h +++ b/qse/include/qse/http/stdhttpd.h @@ -40,7 +40,6 @@ typedef void (*qse_httpd_serverstd_freersrc_t) ( enum qse_httpd_serverstd_root_type_t { QSE_HTTPD_SERVERSTD_ROOT_PATH, - QSE_HTTPD_SERVERSTD_ROOT_NWAD, QSE_HTTPD_SERVERSTD_ROOT_TEXT, QSE_HTTPD_SERVERSTD_ROOT_PROXY, QSE_HTTPD_SERVERSTD_ROOT_ERROR @@ -59,8 +58,6 @@ struct qse_httpd_serverstd_root_t qse_size_t rpl; /* replacement length */ } path; - qse_nwad_t nwad; - struct { const qse_mchar_t* ptr; @@ -125,8 +122,6 @@ enum qse_httpd_serverstd_query_code_t QSE_HTTPD_SERVERSTD_DIRHEAD, /* const qse_mchar_t* */ QSE_HTTPD_SERVERSTD_DIRFOOT, /* const qse_mchar_t* */ - QSE_HTTPD_SERVERSTD_PSEUDONYM, /* const qse_mchar_t*, pseudonym to use in Via: */ - QSE_HTTPD_SERVERSTD_INDEX, /* qse_httpd_serverstd_index_t */ QSE_HTTPD_SERVERSTD_CGI, /* qse_httpd_serverstd_cgi_t */ QSE_HTTPD_SERVERSTD_MIME, /* const qse_mchar_t* */ @@ -138,6 +133,7 @@ typedef enum qse_httpd_serverstd_query_code_t qse_httpd_serverstd_query_code_t; struct qse_httpd_serverstd_query_info_t { + qse_httpd_client_t* client; qse_htre_t* req; qse_mchar_t* xpath; /* query path combined with document root */ }; @@ -162,7 +158,7 @@ typedef enum qse_httpd_serverstd_opt_t qse_httpd_serverstd_opt_t; #define QSE_HTTPD_DNSSTD_DEFAULT_PORT 53 #define QSE_HTTPD_DNSSTD_DEFAULT_TMOUT 3 -#define QSE_HTTPD_DNSSTD_DEFAULT_RESENDS 2 +#define QSE_HTTPD_DNSSTD_DEFAULT_RETRIES 2 #define QSE_HTTPD_DNSSTD_DEFAULT_CACHE_TTL 120 #define QSE_HTTPD_DNSSTD_DEFAULT_CACHE_NEGTTL 10 #define QSE_HTTPD_DNSSTD_DEFAULT_CACHE_MINTTL 2 @@ -171,7 +167,7 @@ struct qse_httpd_dnsstd_t { qse_nwad_t nwad; qse_ntime_t tmout; - qse_uint32_t resends; + qse_uint32_t retries; qse_uint32_t cache_ttl; qse_uint32_t cache_minttl; /* minimum ttl */ qse_uint32_t cache_negttl; /* negative ttl */ @@ -181,13 +177,13 @@ typedef struct qse_httpd_dnsstd_t qse_httpd_dnsstd_t; #define QSE_HTTPD_URSSTD_DEFAULT_PORT 94 #define QSE_HTTPD_URSSTD_DEFAULT_TMOUT 10 -#define QSE_HTTPD_URSSTD_DEFAULT_RESENDS 0 +#define QSE_HTTPD_URSSTD_DEFAULT_RETRIES 0 struct qse_httpd_ursstd_t { qse_nwad_t nwad; qse_ntime_t tmout; - qse_uint32_t resends; + qse_uint32_t retries; }; typedef struct qse_httpd_ursstd_t qse_httpd_ursstd_t; diff --git a/qse/lib/http/httpd-proxy.c b/qse/lib/http/httpd-proxy.c index 4ec5151d..090e1f7c 100644 --- a/qse/lib/http/httpd-proxy.c +++ b/qse/lib/http/httpd-proxy.c @@ -66,8 +66,8 @@ struct task_proxy_t qse_size_t qpath_pos_in_reqfwdbuf; qse_size_t qpath_len_in_reqfwdbuf; - qse_nwad_t dns_server; - qse_nwad_t urs_server; + qse_httpd_natr_t dns_server; + qse_httpd_natr_t urs_server; qse_mchar_t* pseudonym; qse_htrd_t* peer_htrd; @@ -943,15 +943,36 @@ static int task_init_proxy ( if (arg->rsrc->flags & QSE_HTTPD_RSRC_PROXY_RAW) proxy->flags |= PROXY_RAW; if (arg->rsrc->flags & QSE_HTTPD_RSRC_PROXY_TRANSPARENT) proxy->flags |= PROXY_TRANSPARENT; - if (arg->rsrc->flags & QSE_HTTPD_RSRC_PROXY_DNS_SERVER) + proxy->peer.local = arg->rsrc->src.nwad; + if (arg->rsrc->flags & QSE_HTTPD_RSRC_PROXY_DST_STR) { - proxy->flags |= PROXY_DNS_SERVER; - proxy->dns_server = arg->rsrc->dns_server; + if (arg->rsrc->flags & QSE_HTTPD_RSRC_PROXY_ENABLE_DNS) + { +/* TODO: get pseudonym from parameter... */ + proxy->peer_name = proxy->pseudonym + len + 1; + + qse_mbscpy (proxy->peer_name, arg->rsrc->dst.str); + adjust_peer_name_and_port (proxy); + + proxy->flags |= PROXY_RESOLVE_PEER_NAME; + if (arg->rsrc->flags & QSE_HTTPD_RSRC_PROXY_DNS_SERVER) + { + /* dns server specified */ + proxy->flags |= PROXY_DNS_SERVER; + proxy->dns_server = arg->rsrc->dns_server; + } + } + else + { + /* dns service is requried to resolve the destination. + * but it's not enabled */ + httpd->errnum = QSE_HTTPD_ENODNS; + goto oops; + } } - if (arg->rsrc->flags & QSE_HTTPD_RSRC_PROXY_URS_SERVER) + else { - proxy->flags |= PROXY_URS_SERVER; - proxy->urs_server = arg->rsrc->urs_server; + proxy->peer.nwad = arg->rsrc->dst.nwad; } if (arg->rsrc->flags & QSE_HTTPD_RSRC_PROXY_ENABLE_URS) @@ -1000,23 +1021,14 @@ static int task_init_proxy ( printf (">>>>>>>>>>>>>>>>>>>>>>>> [%s] <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n", proxy->url_to_rewrite); /* enable url rewriting */ proxy->flags |= PROXY_REWRITE_URL; - } - proxy->peer.local = arg->rsrc->src.nwad; - if (arg->rsrc->flags & QSE_HTTPD_RSRC_PROXY_DST_STR) - { - proxy->flags |= PROXY_RESOLVE_PEER_NAME; - proxy->peer_name = proxy->pseudonym + len + 1; - qse_mbscpy (proxy->peer_name, arg->rsrc->dst.str); - adjust_peer_name_and_port (proxy); + if (arg->rsrc->flags & QSE_HTTPD_RSRC_PROXY_URS_SERVER) + { + /* urs server address specified */ + proxy->flags |= PROXY_URS_SERVER; + proxy->urs_server = arg->rsrc->urs_server; + } } - else - { - proxy->peer.nwad = arg->rsrc->dst.nwad; - } - - /*if (arg->rsrc->src) proxy->peer.local = arg->rsrc->src; - else proxy->peer.local.type = arg->rsrc->dst.type;*/ proxy->req = QSE_NULL; /* -------------------------------------------------------------------- @@ -1028,7 +1040,7 @@ printf (">>>>>>>>>>>>>>>>>>>>>>>> [%s] <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n", proxy len = MAX_SEND_SIZE; 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 nomem_oops; proxy->host = arg->rsrc->host; if (proxy->flags & PROXY_RAW) @@ -1052,22 +1064,22 @@ printf (">>>>>>>>>>>>>>>>>>>>>>>> [%s] <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n", proxy * received from the client */ if (qse_mbs_cat (proxy->reqfwdbuf, qse_htre_getqmethodname(arg->req)) == (qse_size_t)-1 || - qse_mbs_cat (proxy->reqfwdbuf, QSE_MT(" ")) == (qse_size_t)-1) goto oops; - + qse_mbs_cat (proxy->reqfwdbuf, QSE_MT(" ")) == (qse_size_t)-1) goto nomem_oops; + proxy->qpath_pos_in_reqfwdbuf = QSE_STR_LEN(proxy->reqfwdbuf); - if (qse_mbs_cat (proxy->reqfwdbuf, qse_htre_getqpath(arg->req)) == (qse_size_t)-1) goto oops; + if (qse_mbs_cat (proxy->reqfwdbuf, qse_htre_getqpath(arg->req)) == (qse_size_t)-1) goto nomem_oops; proxy->qpath_len_in_reqfwdbuf = QSE_STR_LEN(proxy->reqfwdbuf) - proxy->qpath_pos_in_reqfwdbuf; if (qse_htre_getqparam(arg->req)) { 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; + qse_mbs_cat (proxy->reqfwdbuf, qse_htre_getqparam(arg->req)) == (qse_size_t)-1) goto nomem_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_htre_walkheaders (arg->req, proxy_capture_client_header, proxy) <= -1) goto nomem_oops; if (!(proxy->flags & (PROXY_TRANSPARENT | PROXY_X_FORWARDED_FOR))) { @@ -1081,7 +1093,7 @@ printf (">>>>>>>>>>>>>>>>>>>>>>>> [%s] <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n", proxy if (qse_mbs_cat (proxy->reqfwdbuf, QSE_MT("X-Forwarded-For: ")) == (qse_size_t)-1 || qse_mbs_cat (proxy->reqfwdbuf, extra) == (qse_size_t)-1 || - qse_mbs_cat (proxy->reqfwdbuf, QSE_MT("\r\n")) == (qse_size_t)-1) goto oops; + qse_mbs_cat (proxy->reqfwdbuf, QSE_MT("\r\n")) == (qse_size_t)-1) goto nomem_oops; } proxy->resflags |= PROXY_RES_AWAIT_RESHDR; @@ -1113,7 +1125,7 @@ printf (">>>>>>>>>>>>>>>>>>>>>>>> [%s] <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n", proxy proxy->reqfwdbuf, QSE_MT("Via: %d.%d %hs (%hs)\r\n"), (int)proxy->version.major, (int)proxy->version.minor, pseudonym, qse_httpd_getname(httpd)); - if (tmp == (qse_size_t)-1) goto oops; + if (tmp == (qse_size_t)-1) goto nomem_oops; } if (arg->req->state & QSE_HTRE_DISCARDED) @@ -1124,11 +1136,11 @@ printf (">>>>>>>>>>>>>>>>>>>>>>>> [%s] <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n", proxy { /* 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; + if (qse_mbs_cat (proxy->reqfwdbuf, QSE_MT("Content-Length: 0\r\n\r\n")) == (qse_size_t)-1) goto nomem_oops; } else { - if (qse_mbs_cat (proxy->reqfwdbuf, QSE_MT("\r\n")) == (qse_size_t)-1) goto oops; + if (qse_mbs_cat (proxy->reqfwdbuf, QSE_MT("\r\n")) == (qse_size_t)-1) goto nomem_oops; } } else if (arg->req->state & QSE_HTRE_COMPLETED) @@ -1136,7 +1148,7 @@ printf (">>>>>>>>>>>>>>>>>>>>>>>> [%s] <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n", proxy 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; + if (qse_htre_walktrailers (arg->req, proxy_capture_client_trailer, proxy) <= -1) goto nomem_oops; } len = qse_htre_getcontentlen(arg->req); @@ -1153,18 +1165,18 @@ printf (">>>>>>>>>>>>>>>>>>>>>>>> [%s] <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n", proxy * 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; + qse_mbs_cat (proxy->reqfwdbuf, QSE_MT("\r\n\r\n")) == (qse_size_t)-1) goto nomem_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; + if (qse_mbs_ncat (proxy->reqfwdbuf, ptr, len) == (qse_size_t)-1) goto nomem_oops; } } else { - if (qse_mbs_cat (proxy->reqfwdbuf, QSE_MT("\r\n")) == (qse_size_t)-1) goto oops; + if (qse_mbs_cat (proxy->reqfwdbuf, QSE_MT("\r\n")) == (qse_size_t)-1) goto nomem_oops; } } else if (arg->req->attr.flags & QSE_HTRE_ATTR_LENGTH) @@ -1178,14 +1190,14 @@ printf (">>>>>>>>>>>>>>>>>>>>>>>> [%s] <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n", proxy 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; + qse_mbs_cat (proxy->reqfwdbuf, QSE_MT("\r\n\r\n")) == (qse_size_t)-1) goto nomem_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; + if (qse_mbs_ncat (proxy->reqfwdbuf, ptr, len) == (qse_size_t)-1) goto nomem_oops; } snatch_needed = 1; @@ -1199,7 +1211,7 @@ printf (">>>>>>>>>>>>>>>>>>>>>>>> [%s] <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n", proxy 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; + qse_mbs_cat (proxy->reqfwdbuf, QSE_MT("\r\n")) == (qse_size_t)-1 /* end of header */) goto nomem_oops; len = qse_htre_getcontentlen(arg->req); if (len > 0) @@ -1217,7 +1229,7 @@ printf (">>>>>>>>>>>>>>>>>>>>>>>> [%s] <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n", proxy 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; + qse_mbs_cat (proxy->reqfwdbuf, QSE_MT("\r\n")) == (qse_size_t)-1) goto nomem_oops; } snatch_needed = 1; @@ -1243,6 +1255,10 @@ qse_printf (QSE_T("GOING TO PROXY [%hs]\n"), QSE_MBS_PTR(proxy->reqfwdbuf)); task->ctx = proxy; return 0; +nomem_oops: + httpd->errnum = QSE_HTTPD_ENOMEM; + /* goto oops */ + oops: printf ("init_proxy failed...........................................\n"); @@ -1267,7 +1283,7 @@ printf ("init_proxy failed...........................................\n"); proxy->flags |= PROXY_INIT_FAILED; task->ctx = proxy; - httpd->errnum = QSE_HTTPD_ENOMEM; + return 0; } @@ -1924,9 +1940,6 @@ static void on_url_rewritten (qse_httpd_t* httpd, const qse_mchar_t* url, const qse_httpd_task_t* task = (qse_httpd_task_t*)ctx; task_proxy_t* proxy = (task_proxy_t*)task->ctx; -//new_url = "302:http://www.google.com/login.html"; -//new_url = "127.0.0.1:443"; -new_url = "http://www.google.com/a/b/c"; if (new_url) { qse_nwad_t nwad; @@ -1997,7 +2010,7 @@ new_url = "http://www.google.com/a/b/c"; QSE_ASSERT (QSE_STR_LEN(proxy->reqfwdbuf) > 0); /* TODO: Host rewriting?? */ -/* TODO: Host rewriting - to support it, headers must be made available thru request cloning. + /* TODO: Host rewriting - to support it, headers must be made available thru request cloning. * the request may not be valid after task_init_proxy */ if (qse_mbszcasecmp (new_url, QSE_MT("http://"), 7) == 0) diff --git a/qse/lib/http/httpd-std-dns.h b/qse/lib/http/httpd-std-dns.h index a1f41a97..eeff1fef 100644 --- a/qse/lib/http/httpd-std-dns.h +++ b/qse/lib/http/httpd-std-dns.h @@ -165,9 +165,10 @@ struct dns_req_t qse_skad_t dns_skad; int dns_skadlen; int dns_socket; + int dns_retries; + qse_ntime_t dns_tmout; qse_tmr_index_t tmr_tmout; - int resends; dns_req_t* next; dns_req_t* prev; @@ -343,22 +344,15 @@ static int dns_open (qse_httpd_t* httpd, qse_httpd_dns_t* dns) } } - if (qse_getnwadport(&nwad) == 0) + if (nwad.type != QSE_NWAD_NX && qse_getnwadport(&nwad) == 0) qse_setnwadport (&nwad, qse_hton16(QSE_HTTPD_DNSSTD_DEFAULT_PORT)); - dc->skadlen = qse_nwadtoskad (&nwad, &dc->skad); - if (dc->skadlen <= -1) - { - qse_httpd_seterrnum (httpd, QSE_HTTPD_EINVAL); - goto oops; - } - if (httpd->opt.trait & QSE_HTTPD_LOGACT) { qse_httpd_act_t msg; qse_size_t pos; msg.code = QSE_HTTPD_CATCH_MDBGMSG; - pos = qse_mbsxcpy (msg.u.mdbgmsg, QSE_COUNTOF(msg.u.mdbgmsg), "global nameserver set to "); + pos = qse_mbsxcpy (msg.u.mdbgmsg, QSE_COUNTOF(msg.u.mdbgmsg), "default nameserver set to "); qse_nwadtombs (&nwad, &msg.u.mdbgmsg[pos], QSE_COUNTOF(msg.u.mdbgmsg) - pos, QSE_NWADTOMBS_ALL); httpd->opt.rcb.logact (httpd, &msg); } @@ -373,10 +367,21 @@ static int dns_open (qse_httpd_t* httpd, qse_httpd_dns_t* dns) goto oops; } - if (nwad.type == QSE_NWAD_IN4) - dc->dns_socket = dns->handle[0].i; + /* carry on regardless of success or failure */ + dc->skadlen = qse_nwadtoskad (&nwad, &dc->skad); + + /* determine which socket to use when sending a request to the server */ + if (dc->skadlen >= 0) + { + if (nwad.type == QSE_NWAD_IN4) + dc->dns_socket = dns->handle[0].i; + else + dc->dns_socket = dns->handle[1].i; + } else - dc->dns_socket = dns->handle[1].i; + { + dc->dns_socket = SOCK_INVALID; + } dns->handle_count = 2; dns->ctx = dc; @@ -736,7 +741,7 @@ printf (">>tmr_dns_tmout_handle req->>%p\n", req); /* --------------------------------------------------------------- * resend *---------------------------------------------------------------- */ - if (req->resends > 0) + if (req->dns_retries > 0) { httpd_xtn_t* httpd_xtn; qse_tmr_event_t tmout_event; @@ -744,7 +749,7 @@ printf (">>tmr_dns_tmout_handle req->>%p\n", req); httpd_xtn = qse_httpd_getxtn (dc->httpd); qse_gettime (&tmout_event.when); - qse_addtime (&tmout_event.when, &httpd_xtn->dns.tmout, &tmout_event.when); + qse_addtime (&tmout_event.when, &req->dns_tmout, &tmout_event.when); tmout_event.ctx = req; tmout_event.handler = tmr_dns_tmout_handle; tmout_event.updater = tmr_dns_tmout_update; @@ -759,7 +764,7 @@ printf (">>tmr_dns_tmout_handle req->>%p\n", req); QSE_ASSERT (tmr == dc->httpd->tmr); if (qse_httpd_inserttimerevent (dc->httpd, &tmout_event, &req->tmr_tmout) >= 0) { - req->resends--; + req->dns_retries--; return; /* resend ok */ } } @@ -788,7 +793,7 @@ printf (">>tmr_dns_tmout_handle req->>%p\n", req); dc->req_count--; } -static int dns_send (qse_httpd_t* httpd, qse_httpd_dns_t* dns, const qse_mchar_t* name, qse_httpd_resol_t resol, const qse_nwad_t* dns_server, void* ctx) +static int dns_send (qse_httpd_t* httpd, qse_httpd_dns_t* dns, const qse_mchar_t* name, qse_httpd_resol_t resol, const qse_httpd_natr_t* dns_server, void* ctx) { dns_ctx_t* dc = (dns_ctx_t*)dns->ctx; httpd_xtn_t* httpd_xtn; @@ -866,33 +871,32 @@ printf ("DNS REALLY SENING>>>>>>>>>>>>>>>>>>>>>>>\n"); goto oops; } - if (dns_server) - { -printf ("GETTING DNS_SERVER XXXXXXXXXXXXXXXXXXXXXXX\n"); - req->dns_skadlen = qse_nwadtoskad (dns_server, &req->dns_skad); - if (req->dns_skadlen <= -1) - { - qse_httpd_seterrnum (httpd, QSE_HTTPD_EINVAL); - goto oops; - } + req->dns_retries = httpd_xtn->dns.retries; + req->dns_tmout = httpd_xtn->dns.tmout; - if (dns_server->type == QSE_NWAD_IN4) + if (dns_server) + { + if (dns_server->retries >= 0) req->dns_retries = dns_server->retries; + if (dns_server->tmout.sec >= 0) req->dns_tmout = dns_server->tmout; + + req->dns_skadlen = qse_nwadtoskad (&dns_server->nwad, &req->dns_skad); + if (req->dns_skadlen <= -1) goto default_dns_server; + + if (dns_server->nwad.type == QSE_NWAD_IN4) req->dns_socket = dns->handle[0].i; else req->dns_socket = dns->handle[1].i; } else { -printf ("GETTING DNS_SERVER XXXXXXXXXXXXXXXXXXXXXXX GLOBAL XXXXXXXXXXXXXXXXXXXXXX\n"); + default_dns_server: req->dns_skad = dc->skad; req->dns_skadlen = dc->skadlen; req->dns_socket = dc->dns_socket; } - req->resends = httpd_xtn->dns.resends; - qse_gettime (&tmout_event.when); - qse_addtime (&tmout_event.when, &httpd_xtn->dns.tmout, &tmout_event.when); + qse_addtime (&tmout_event.when, &req->dns_tmout, &tmout_event.when); tmout_event.ctx = req; tmout_event.handler = tmr_dns_tmout_handle; tmout_event.updater = tmr_dns_tmout_update; diff --git a/qse/lib/http/httpd-std-urs.h b/qse/lib/http/httpd-std-urs.h index feff95ba..8a0cc851 100644 --- a/qse/lib/http/httpd-std-urs.h +++ b/qse/lib/http/httpd-std-urs.h @@ -76,9 +76,10 @@ struct urs_req_t qse_skad_t urs_skad; int urs_skadlen; int urs_socket; + int urs_retries; + qse_ntime_t urs_tmout; qse_tmr_index_t tmr_tmout; - int resends; urs_req_t* prev; urs_req_t* next; @@ -104,28 +105,15 @@ static int urs_open (qse_httpd_t* httpd, qse_httpd_urs_t* urs) dc->urs = urs; nwad = httpd_xtn->urs.nwad; - if (nwad.type == QSE_NWAD_NX) - { - qse_httpd_seterrnum (httpd, QSE_HTTPD_EINVAL); - goto oops; - } - - if (qse_getnwadport(&nwad) == 0) + if (nwad.type != QSE_NWAD_NX && qse_getnwadport(&nwad) == 0) qse_setnwadport (&nwad, qse_hton16(QSE_HTTPD_URSSTD_DEFAULT_PORT)); - dc->skadlen = qse_nwadtoskad (&nwad, &dc->skad); - if (dc->skadlen <= -1) - { - qse_httpd_seterrnum (httpd, QSE_HTTPD_EINVAL); - goto oops; - } - if (httpd->opt.trait & QSE_HTTPD_LOGACT) { qse_httpd_act_t msg; qse_size_t pos; msg.code = QSE_HTTPD_CATCH_MDBGMSG; - pos = qse_mbsxcpy (msg.u.mdbgmsg, QSE_COUNTOF(msg.u.mdbgmsg), "ursserver set to "); + pos = qse_mbsxcpy (msg.u.mdbgmsg, QSE_COUNTOF(msg.u.mdbgmsg), "default ursserver set to "); qse_nwadtombs (&nwad, &msg.u.mdbgmsg[pos], QSE_COUNTOF(msg.u.mdbgmsg) - pos, QSE_NWADTOMBS_ALL); httpd->opt.rcb.logact (httpd, &msg); } @@ -140,10 +128,21 @@ static int urs_open (qse_httpd_t* httpd, qse_httpd_urs_t* urs) goto oops; } - if (nwad.type == QSE_NWAD_IN4) - dc->urs_socket = urs->handle[0].i; + /* carry on regardless of success or failure */ + dc->skadlen = qse_nwadtoskad (&nwad, &dc->skad); + + /* determine which socket to use when sending a request to the server */ + if (dc->skadlen >= 0) + { + if (nwad.type == QSE_NWAD_IN4) + dc->urs_socket = urs->handle[0].i; + else + dc->urs_socket = urs->handle[1].i; + } else - dc->urs_socket = urs->handle[1].i; + { + dc->urs_socket = SOCK_INVALID; + } urs->handle_count = 2; @@ -273,7 +272,7 @@ static void tmr_urs_tmout_handle (qse_tmr_t* tmr, const qse_ntime_t* now, void* /* --------------------------------------------------------------- * resend *---------------------------------------------------------------- */ - if (req->resends > 0) + if (req->urs_retries > 0) { httpd_xtn_t* httpd_xtn; qse_tmr_event_t tmout_event; @@ -281,12 +280,12 @@ static void tmr_urs_tmout_handle (qse_tmr_t* tmr, const qse_ntime_t* now, void* httpd_xtn = qse_httpd_getxtn (dc->httpd); qse_gettime (&tmout_event.when); - qse_addtime (&tmout_event.when, &httpd_xtn->urs.tmout, &tmout_event.when); + qse_addtime (&tmout_event.when, &req->urs_tmout, &tmout_event.when); tmout_event.ctx = req; tmout_event.handler = tmr_urs_tmout_handle; tmout_event.updater = tmr_urs_tmout_update; - if (sendto (req->urs_socket, req->pkt, req->pktlen, 0, (struct sockaddr*)&dc->skad, dc->skadlen) != req->pktlen) + if (sendto (req->urs_socket, req->pkt, req->pktlen, 0, (struct sockaddr*)&req->urs_skad, req->urs_skadlen) != req->pktlen) { /* error. fall thru */ } @@ -295,7 +294,7 @@ static void tmr_urs_tmout_handle (qse_tmr_t* tmr, const qse_ntime_t* now, void* QSE_ASSERT (tmr == dc->httpd->tmr); if (qse_httpd_inserttimerevent (dc->httpd, &tmout_event, &req->tmr_tmout) >= 0) { - req->resends--; + req->urs_retries--; return; /* resend ok */ } } @@ -320,7 +319,7 @@ printf ("urs timed out....\n"); dc->req_count--; } -static int urs_send (qse_httpd_t* httpd, qse_httpd_urs_t* urs, const qse_mchar_t* url, qse_httpd_rewrite_t rewrite, const qse_nwad_t* urs_server, void* ctx) +static int urs_send (qse_httpd_t* httpd, qse_httpd_urs_t* urs, const qse_mchar_t* url, qse_httpd_rewrite_t rewrite, const qse_httpd_natr_t* urs_server, void* ctx) { urs_ctx_t* dc = (urs_ctx_t*)urs->ctx; httpd_xtn_t* httpd_xtn; @@ -371,37 +370,49 @@ printf ("URS REALLY SENING>>>>>>>>>>>>>>>>>>>>>>>\n"); req->rewrite = rewrite; req->ctx = ctx; - req->resends = httpd_xtn->urs.resends; - if (urs_server) + req->urs_retries = httpd_xtn->urs.retries; + req->urs_tmout = httpd_xtn->urs.tmout; + + if (urs_server) { - req->urs_skadlen = qse_nwadtoskad (urs_server, &req->urs_skad); - if (req->urs_skadlen <= -1) - { - qse_httpd_seterrnum (httpd, QSE_HTTPD_EINVAL); - goto oops; - } + if (urs_server->retries >= 0) req->urs_retries = urs_server->retries; + if (urs_server->tmout.sec >= 0) req->urs_tmout = urs_server->tmout; - if (urs_server->type == QSE_NWAD_IN4) + req->urs_skadlen = qse_nwadtoskad (&urs_server->nwad, &req->urs_skad); + if (req->urs_skadlen <= -1) goto default_urs_server; + + if (urs_server->nwad.type == QSE_NWAD_IN4) req->urs_socket = urs->handle[0].i; else req->urs_socket = urs->handle[1].i; } else { - req->urs_skad = dc->skad; - req->urs_skadlen = dc->skadlen; - req->urs_socket = dc->urs_socket; + default_urs_server: + if (dc->skadlen >= 0) + { + /* the default url rewrite server address set in urs_open + * is valid. */ + req->urs_skad = dc->skad; + req->urs_skadlen = dc->skadlen; + req->urs_socket = dc->urs_socket; + } + else + { + qse_httpd_seterrnum (httpd, QSE_HTTPD_ENOURS); + goto oops; + } } qse_gettime (&tmout_event.when); - qse_addtime (&tmout_event.when, &httpd_xtn->urs.tmout, &tmout_event.when); + qse_addtime (&tmout_event.when, &req->urs_tmout, &tmout_event.when); tmout_event.ctx = req; tmout_event.handler = tmr_urs_tmout_handle; tmout_event.updater = tmr_urs_tmout_update; if (qse_httpd_inserttimerevent (httpd, &tmout_event, &req->tmr_tmout) <= -1) goto oops; - if (sendto (req->urs_socket, req->pkt, req->pktlen, 0, (struct sockaddr*)&dc->skad, dc->skadlen) != req->pktlen) + if (sendto (req->urs_socket, req->pkt, req->pktlen, 0, (struct sockaddr*)&req->urs_skad, req->urs_skadlen) != req->pktlen) { qse_httpd_seterrnum (httpd, SKERR_TO_ERRNUM()); goto oops; diff --git a/qse/lib/http/httpd-std.c b/qse/lib/http/httpd-std.c index 439d279e..1465c71f 100644 --- a/qse/lib/http/httpd-std.c +++ b/qse/lib/http/httpd-std.c @@ -80,6 +80,9 @@ # if defined(HAVE_LINUX_NETFILTER_IPV4_H) # include /* SO_ORIGINAL_DST */ # endif +# if !defined(SO_ORIGINAL_DST) +# define SO_ORIGINAL_DST 80 +# endif # if !defined(IP_TRANSPARENT) # define IP_TRANSPARENT 19 # endif @@ -965,6 +968,9 @@ qse_fprintf (QSE_STDERR, QSE_T("Error: too many client?\n")); client->orgdst_addr = client->local_addr; #endif +/* TODO: how to set intercepted when TPROXY is used? */ + if (!qse_nwadequal(&client->orgdst_addr, &client->local_addr)) + client->status |= QSE_HTTPD_CLIENT_INTERCEPTED; #if 0 client->initial_ifindex = resolve_ifindex (fd, client->local_addr); @@ -1011,13 +1017,14 @@ static int peer_open (qse_httpd_t* httpd, qse_httpd_peer_t* peer) #endif connaddrsize = qse_nwadtoskad (&peer->nwad, &connaddr); - bindaddrsize = qse_nwadtoskad (&peer->local, &bindaddr); - if (connaddrsize <= -1 || bindaddrsize <= -1) + if (connaddrsize <= -1) { qse_httpd_seterrnum (httpd, QSE_HTTPD_ENOIMPL); return -1; } + bindaddrsize = qse_nwadtoskad (&peer->local, &bindaddr); + fd = socket (qse_skadfamily(&connaddr), SOCK_STREAM, IPPROTO_TCP); if (!is_valid_socket(fd)) { @@ -1025,12 +1032,14 @@ static int peer_open (qse_httpd_t* httpd, qse_httpd_peer_t* peer) goto oops; } +/* TODO: set transparent and bind only if the server is transparent */ #if defined(IP_TRANSPARENT) flag = 1; setsockopt (fd, SOL_IP, IP_TRANSPARENT, &flag, QSE_SIZEOF(flag)); #endif - if (bind (fd, (struct sockaddr*)&bindaddr, bindaddrsize) <= -1) + if (bindaddrsize >= 0 && + bind (fd, (struct sockaddr*)&bindaddr, bindaddrsize) <= -1) { /* i won't care about binding faiulre */ /* TODO: some logging for this failure though */ @@ -1868,7 +1877,7 @@ static qse_ssize_t client_recv ( qse_httpd_t* httpd, qse_httpd_client_t* client, qse_mchar_t* buf, qse_size_t bufsize) { - if (client->status & CLIENT_SECURE) + if (client->status & QSE_HTTPD_CLIENT_SECURE) { #if defined(HAVE_SSL) int ret = SSL_read (client->handle2.ptr, buf, bufsize); @@ -1882,9 +1891,9 @@ static qse_ssize_t client_recv ( } if (SSL_pending (client->handle2.ptr) > 0) - client->status |= CLIENT_PENDING; + client->status |= QSE_HTTPD_CLIENT_PENDING; else - client->status &= ~CLIENT_PENDING; + client->status &= ~QSE_HTTPD_CLIENT_PENDING; return ret; #else @@ -1910,7 +1919,7 @@ static qse_ssize_t client_send ( qse_httpd_t* httpd, qse_httpd_client_t* client, const qse_mchar_t* buf, qse_size_t bufsize) { - if (client->status & CLIENT_SECURE) + if (client->status & QSE_HTTPD_CLIENT_SECURE) { #if defined(HAVE_SSL) int ret = SSL_write (client->handle2.ptr, buf, bufsize); @@ -1945,7 +1954,7 @@ static qse_ssize_t client_sendfile ( qse_httpd_t* httpd, qse_httpd_client_t* client, qse_ubi_t handle, qse_foff_t* offset, qse_size_t count) { - if (client->status & CLIENT_SECURE) + if (client->status & QSE_HTTPD_CLIENT_SECURE) { return __send_file_ssl (httpd, client->handle2.ptr, handle, offset, count); } @@ -1958,7 +1967,7 @@ static qse_ssize_t client_sendfile ( static int client_accepted (qse_httpd_t* httpd, qse_httpd_client_t* client) { - if (client->status & CLIENT_SECURE) + if (client->status & QSE_HTTPD_CLIENT_SECURE) { #if defined(HAVE_SSL) int ret; @@ -2031,7 +2040,7 @@ static int client_accepted (qse_httpd_t* httpd, qse_httpd_client_t* client) static void client_closed (qse_httpd_t* httpd, qse_httpd_client_t* client) { - if (client->status & CLIENT_SECURE) + if (client->status & QSE_HTTPD_CLIENT_SECURE) { #if defined(HAVE_SSL) if (client->handle2.ptr) @@ -2664,7 +2673,6 @@ static int make_resource ( { server_xtn_t* server_xtn; struct rsrc_tmp_t tmp; - qse_http_method_t mth; qse_httpd_stat_t st; int n, stx, acc; @@ -2681,119 +2689,11 @@ static int make_resource ( QSE_MEMSET (&qinfo, 0, QSE_SIZEOF(qinfo)); qinfo.req = req; - -#if 0 - mth = qse_htre_getqmethodtype (req); - if (mth == QSE_HTTP_CONNECT) - { - /* TODO: query if CONNECT is allowed */ - /* TODO: check on what conditions CONNECT is allowed. */ - /* TODO: disallow connecting back to self */ - /* TODO: Proxy-Authorization???? */ - - target->type = QSE_HTTPD_RSRC_PROXY; - target->u.proxy.flags |= QSE_HTTPD_RSRC_PROXY_RAW; - target->u.proxy.host = QSE_NULL; - - if (qse_mbstonwad (qse_htre_getqpath(req), &target->u.proxy.dst.nwad) <= -1) - { - target->u.proxy.flags |= QSE_HTTPD_RSRC_PROXY_DST_STR; - target->u.proxy.dst.str = qse_htre_getqpath(req); - } - else - { - /* make the source binding type the same as destination */ - /* no default port for raw proxying */ - target->u.proxy.src.nwad.type = target->u.proxy.dst.nwad.type; - } - - /* pseudonym for raw proxying should not be useful. but set it for consistency */ - if (server_xtn->query (httpd, client->server, QSE_HTTPD_SERVERSTD_PSEUDONYM, &qinfo, &target->u.proxy.pseudonym) <= -1) - target->u.proxy.pseudonym = QSE_NULL; - -/******************************************************************/ -/*TODO: load this from configuration. reamove this after debugging */ -//target->u.proxy.flags |= QSE_HTTPD_RSRC_PROXY_URS; -/******************************************************************/ - /* mark that this request is going to be proxied. */ - req->attr.flags |= QSE_HTRE_ATTR_PROXIED; - return 0; - } - - if (qse_mbszcasecmp (tmp.qpath, QSE_MT("http://"), 7) == 0) - { -/* TODO: check if proxying is allowed.... */ - qse_mchar_t* host, * slash; - - host = tmp.qpath + 7; - slash = qse_mbschr (host, QSE_MT('/')); - - if (slash && slash - host > 0) - { - target->type = QSE_HTTPD_RSRC_PROXY; - target->u.proxy.flags = 0; - -/* TODO: refrain from manipulating the request like this */ - QSE_MEMMOVE (host - 1, host, slash - host); - slash[-1] = QSE_MT('\0'); - host = host - 1; - target->u.proxy.host = host; - - if (qse_mbstonwad (host, &target->u.proxy.dst.nwad) <= -1) - { - target->u.proxy.flags |= QSE_HTTPD_RSRC_PROXY_DST_STR; - target->u.proxy.dst.str = host; - } - else - { - /* make the source binding type the same as destination */ - if (qse_getnwadport(&target->u.proxy.dst.nwad) == 0) - qse_setnwadport (&target->u.proxy.dst.nwad, qse_hton16(QSE_HTTPD_DEFAULT_PORT)); - target->u.proxy.src.nwad.type = target->u.proxy.dst.nwad.type; - } - - if (server_xtn->query (httpd, client->server, QSE_HTTPD_SERVERSTD_PSEUDONYM, &qinfo, &target->u.proxy.pseudonym) <= -1) - target->u.proxy.pseudonym = QSE_NULL; - -/* TODO: refrain from manipulating the request like this */ - req->u.q.path = slash; /* TODO: use setqpath or something... */ - -/******************************************************************/ -/*TODO: load this from configuration. reamove this after debugging */ -//target->u.proxy.flags |= QSE_HTTPD_RSRC_PROXY_URS; -/******************************************************************/ - - /* mark that this request is going to be proxied. */ - req->attr.flags |= QSE_HTRE_ATTR_PROXIED; - return 0; - } - } - -#endif + qinfo.client = client; if (server_xtn->query (httpd, client->server, QSE_HTTPD_SERVERSTD_ROOT, &qinfo, &tmp.root) <= -1) return -1; switch (tmp.root.type) { - case QSE_HTTPD_SERVERSTD_ROOT_NWAD: - /* proxy the request */ - target->type = QSE_HTTPD_RSRC_PROXY; - target->u.proxy.flags = 0; - target->u.proxy.host = QSE_NULL; - - /* transparent proxy may do the following - target->u.proxy.dst = client->orgdst_addr; - target->u.proxy.src = client->remote_addr; - */ - target->u.proxy.dst.nwad = tmp.root.u.nwad; - target->u.proxy.src.nwad.type = target->u.proxy.dst.nwad.type; - - if (server_xtn->query (httpd, client->server, QSE_HTTPD_SERVERSTD_PSEUDONYM, &qinfo, &target->u.proxy.pseudonym) <= -1) - target->u.proxy.pseudonym = QSE_NULL; - - /* mark that this request is going to be proxied. */ - req->attr.flags |= QSE_HTRE_ATTR_PROXIED; - return 0; - case QSE_HTTPD_SERVERSTD_ROOT_TEXT: target->type = QSE_HTTPD_RSRC_TEXT; target->u.text.ptr = tmp.root.u.text.ptr; @@ -3196,10 +3096,6 @@ static int query_server ( } return 0; } - - case QSE_HTTPD_SERVERSTD_PSEUDONYM: - *(const qse_mchar_t**)result = QSE_NULL; - return 0; } qse_httpd_seterrnum (httpd, QSE_HTTPD_EINVAL); @@ -3361,6 +3257,7 @@ int qse_httpd_loopstd (qse_httpd_t* httpd, const qse_httpd_dnsstd_t* dns, const { httpd_xtn_t* httpd_xtn = qse_httpd_getxtn (httpd); + /* default dns server info */ if (dns) { httpd_xtn->dns = *dns; @@ -3370,12 +3267,13 @@ int qse_httpd_loopstd (qse_httpd_t* httpd, const qse_httpd_dnsstd_t* dns, const httpd_xtn->dns.nwad.type = QSE_NWAD_NX; httpd_xtn->dns.tmout.sec = QSE_HTTPD_DNSSTD_DEFAULT_TMOUT; httpd_xtn->dns.tmout.nsec = 0; - httpd_xtn->dns.resends = QSE_HTTPD_DNSSTD_DEFAULT_RESENDS; + httpd_xtn->dns.retries = QSE_HTTPD_DNSSTD_DEFAULT_RETRIES; httpd_xtn->dns.cache_ttl = QSE_HTTPD_DNSSTD_DEFAULT_CACHE_TTL; httpd_xtn->dns.cache_minttl = QSE_HTTPD_DNSSTD_DEFAULT_CACHE_MINTTL; httpd_xtn->dns.cache_negttl = QSE_HTTPD_DNSSTD_DEFAULT_CACHE_NEGTTL; } + /* default urs server info */ if (urs) { httpd_xtn->urs = *urs; @@ -3385,8 +3283,9 @@ int qse_httpd_loopstd (qse_httpd_t* httpd, const qse_httpd_dnsstd_t* dns, const httpd_xtn->urs.nwad.type = QSE_NWAD_NX; httpd_xtn->urs.tmout.sec = QSE_HTTPD_URSSTD_DEFAULT_TMOUT; httpd_xtn->urs.tmout.nsec = 0; - httpd_xtn->urs.resends = QSE_HTTPD_URSSTD_DEFAULT_RESENDS; + httpd_xtn->urs.retries = QSE_HTTPD_URSSTD_DEFAULT_RETRIES; } + /* main loop */ return qse_httpd_loop (httpd); } diff --git a/qse/lib/http/httpd.c b/qse/lib/http/httpd.c index 04febe53..9231cae4 100644 --- a/qse/lib/http/httpd.c +++ b/qse/lib/http/httpd.c @@ -327,11 +327,11 @@ static QSE_INLINE int dequeue_task ( /* clear task triggers from mux if they are registered */ for (i = 0; i < QSE_COUNTOF(task->core.trigger.v); i++) { - if (client->status & CLIENT_TASK_TRIGGER_RW_IN_MUX(i)) + if (client->status & QSE_HTTPD_CLIENT_TASK_TRIGGER_RW_IN_MUX(i)) { QSE_ASSERT (task->core.trigger.v[i].handle.i != client->handle.i); httpd->opt.scb.mux.delhnd (httpd, httpd->mux, task->core.trigger.v[i].handle); - client->status &= ~CLIENT_TASK_TRIGGER_RW_IN_MUX(i); + client->status &= ~QSE_HTTPD_CLIENT_TASK_TRIGGER_RW_IN_MUX(i); } } @@ -388,9 +388,9 @@ static void tmr_idle_handle (qse_tmr_t* tmr, const qse_ntime_t* now, void* ctx); static void mark_bad_client (qse_httpd_client_t* client) { /* you can call this function multiple times */ - if (!(client->status & CLIENT_BAD)) + if (!(client->status & QSE_HTTPD_CLIENT_BAD)) { - client->status |= CLIENT_BAD; + client->status |= QSE_HTTPD_CLIENT_BAD; client->bad_next = client->server->httpd->client.bad; client->server->httpd->client.bad = client; } @@ -429,7 +429,7 @@ static qse_httpd_client_t* new_client (qse_httpd_t* httpd, qse_httpd_client_t* t /* copy the public fields, * keep the private fields initialized at 0 */ client->status = tmpl->status; - if (httpd->opt.scb.client.accepted == QSE_NULL) client->status |= CLIENT_READY; + if (httpd->opt.scb.client.accepted == QSE_NULL) client->status |= QSE_HTTPD_CLIENT_READY; client->handle = tmpl->handle; client->handle2 = tmpl->handle2; client->remote_addr = tmpl->remote_addr; @@ -474,10 +474,10 @@ static void free_client ( qse_printf (QSE_T("Debug: CLOSING SOCKET %d\n"), client->handle.i); #endif - if (client->status & CLIENT_HANDLE_RW_IN_MUX) + if (client->status & QSE_HTTPD_CLIENT_HANDLE_RW_IN_MUX) { httpd->opt.scb.mux.delhnd (httpd, httpd->mux, client->handle); - client->status &= ~CLIENT_HANDLE_RW_IN_MUX; + client->status &= ~QSE_HTTPD_CLIENT_HANDLE_RW_IN_MUX; } if (client->tmr_idle != QSE_TMR_INVALID_INDEX) @@ -577,7 +577,7 @@ qse_printf (QSE_T("failed to accept from server [%s] [%d]\n"), tmp, server->hand /* TODO: check maximum number of client. if exceed call client.close */ - if (server->dope.flags & QSE_HTTPD_SERVER_SECURE) clibuf.status |= CLIENT_SECURE; + if (server->dope.flags & QSE_HTTPD_SERVER_SECURE) clibuf.status |= QSE_HTTPD_CLIENT_SECURE; clibuf.server = server; client = new_client (httpd, &clibuf); @@ -595,7 +595,7 @@ printf ("MUX ADDHND CLIENT READ %d\n", client->handle.i); free_client (httpd, client); return -1; } - client->status |= CLIENT_HANDLE_READ_IN_MUX; + client->status |= QSE_HTTPD_CLIENT_HANDLE_READ_IN_MUX; qse_gettime (&client->last_active); /* TODO: error check */ /* link the new client to the tail of the client list. */ @@ -963,7 +963,7 @@ qse_printf (QSE_T("Debug: connection closed %d\n"), client->handle.i); { /* there is still more tasks to finish and * http reader is not waiting for any more feeds. */ - client->status |= CLIENT_MUTE; + client->status |= QSE_HTTPD_CLIENT_MUTE; #if 0 qse_printf (QSE_T(">>>>> Marking client %d as MUTE\n"), client->handle.i); #endif @@ -1020,9 +1020,9 @@ qse_printf (QSE_T("]\n")); qse_printf (QSE_T("!!!!!FEEDING OK OK OK OK %d from %d\n"), (int)m, (int)client->handle.i); #endif - if (client->status & CLIENT_PENDING) + if (client->status & QSE_HTTPD_CLIENT_PENDING) { - /* this CLIENT_PENDING thing is a dirty hack for SSL. + /* this QSE_HTTPD_CLIENT_PENDING thing is a dirty hack for SSL. * In SSL, data is transmitted in a record. a record can be * as large as 16K bytes since its length field is 2 bytes. * If SSL_read() has record a record but it's given a @@ -1030,7 +1030,7 @@ qse_printf (QSE_T("!!!!!FEEDING OK OK OK OK %d from %d\n"), (int)m, (int)client- * to select() won't return. there is no data to read * at the socket layer. SSL_pending() can tell you the * amount of data in the SSL buffer. I try to consume - * the pending data if the client.recv handler set CLIENT_PENDING. + * the pending data if the client.recv handler set QSE_HTTPD_CLIENT_PENDING. * * TODO: Investigate if there is any starvation issues. * What if a single client never stops sending? @@ -1067,7 +1067,7 @@ static int update_mux_for_current_task (qse_httpd_t* httpd, qse_httpd_client_t* /*printf ("update_mux_for_current_task..............\n");*/ if (QSE_MEMCMP (&client->trigger, &task->trigger, QSE_SIZEOF(client->trigger)) != 0 || - ((client->status & CLIENT_MUTE) && !(client->status & CLIENT_MUTE_DELETED))) + ((client->status & QSE_HTTPD_CLIENT_MUTE) && !(client->status & QSE_HTTPD_CLIENT_MUTE_DELETED))) { /* manipulate muxtiplexer settings if there are trigger changes */ @@ -1085,17 +1085,17 @@ static int update_mux_for_current_task (qse_httpd_t* httpd, qse_httpd_client_t* /*printf ("ACTIVE TO INACTIVE....\n");*/ for (i = 0; i < QSE_COUNTOF(task->trigger.v); i++) { - if (client->status & CLIENT_TASK_TRIGGER_RW_IN_MUX(i)) + if (client->status & QSE_HTTPD_CLIENT_TASK_TRIGGER_RW_IN_MUX(i)) { httpd->opt.scb.mux.delhnd (httpd, httpd->mux, client->trigger.v[i].handle); - client->status &= ~CLIENT_TASK_TRIGGER_RW_IN_MUX(i); + client->status &= ~QSE_HTTPD_CLIENT_TASK_TRIGGER_RW_IN_MUX(i); } } - if (client->status & CLIENT_HANDLE_RW_IN_MUX) + if (client->status & QSE_HTTPD_CLIENT_HANDLE_RW_IN_MUX) { httpd->opt.scb.mux.delhnd (httpd, httpd->mux, client->handle); - client->status &= ~CLIENT_HANDLE_RW_IN_MUX; + client->status &= ~QSE_HTTPD_CLIENT_HANDLE_RW_IN_MUX; } /* save the task trigger information */ @@ -1124,10 +1124,10 @@ static int update_mux_for_current_task (qse_httpd_t* httpd, qse_httpd_client_t* /* delete previous trigger handles */ for (i = 0; i < QSE_COUNTOF(task->trigger.v); i++) { - if (client->status & CLIENT_TASK_TRIGGER_RW_IN_MUX(i)) + if (client->status & QSE_HTTPD_CLIENT_TASK_TRIGGER_RW_IN_MUX(i)) { httpd->opt.scb.mux.delhnd (httpd, httpd->mux, client->trigger.v[i].handle); - client->status &= ~CLIENT_TASK_TRIGGER_RW_IN_MUX(i); + client->status &= ~QSE_HTTPD_CLIENT_TASK_TRIGGER_RW_IN_MUX(i); } } @@ -1142,12 +1142,12 @@ static int update_mux_for_current_task (qse_httpd_t* httpd, qse_httpd_client_t* if (task->trigger.v[i].mask & QSE_HTTPD_TASK_TRIGGER_READ) { expected_trigger_mux_mask |= QSE_HTTPD_MUX_READ; - expected_trigger_mux_status |= CLIENT_TASK_TRIGGER_READ_IN_MUX(i); + expected_trigger_mux_status |= QSE_HTTPD_CLIENT_TASK_TRIGGER_READ_IN_MUX(i); } if (task->trigger.v[i].mask & QSE_HTTPD_TASK_TRIGGER_WRITE) { expected_trigger_mux_mask |= QSE_HTTPD_MUX_WRITE; - expected_trigger_mux_status |= CLIENT_TASK_TRIGGER_WRITE_IN_MUX(i); + expected_trigger_mux_status |= QSE_HTTPD_CLIENT_TASK_TRIGGER_WRITE_IN_MUX(i); } if (expected_trigger_mux_mask) @@ -1164,7 +1164,7 @@ static int update_mux_for_current_task (qse_httpd_t* httpd, qse_httpd_client_t* * * starting from the second call, the client-side handle * is registered for writing if it's explicitly requested. - * it's always registered for reading if not for CLIENT_MUTE. + * it's always registered for reading if not for QSE_HTTPD_CLIENT_MUTE. * * this means that QSE_HTTP_TASK_TRIGGER_READ set or clear * in task->trigger.cmask is not honored. @@ -1175,21 +1175,21 @@ static int update_mux_for_current_task (qse_httpd_t* httpd, qse_httpd_client_t* if (task->trigger.cmask & QSE_HTTPD_TASK_TRIGGER_WRITE) { expected_client_handle_mux_mask |= QSE_HTTPD_MUX_WRITE; - expected_client_handle_mux_status |= CLIENT_HANDLE_WRITE_IN_MUX; + expected_client_handle_mux_status |= QSE_HTTPD_CLIENT_HANDLE_WRITE_IN_MUX; } - if (client->status & CLIENT_MUTE) + if (client->status & QSE_HTTPD_CLIENT_MUTE) { /* reading should be excluded from mux if the client-side has * been closed */ - client->status |= CLIENT_MUTE_DELETED; + client->status |= QSE_HTTPD_CLIENT_MUTE_DELETED; } else { if (task->trigger.cmask & QSE_HTTPD_TASK_TRIGGER_READ) { expected_client_handle_mux_mask |= QSE_HTTPD_MUX_READ; - expected_client_handle_mux_status |= CLIENT_HANDLE_READ_IN_MUX; + expected_client_handle_mux_status |= QSE_HTTPD_CLIENT_HANDLE_READ_IN_MUX; } } @@ -1198,13 +1198,13 @@ static int update_mux_for_current_task (qse_httpd_t* httpd, qse_httpd_client_t* /* if there is no trigger and the client handle is to be excluded * from reading and writing, writing should be enabled. */ expected_client_handle_mux_mask |= QSE_HTTPD_MUX_WRITE; - expected_client_handle_mux_status |= CLIENT_HANDLE_WRITE_IN_MUX; + expected_client_handle_mux_status |= QSE_HTTPD_CLIENT_HANDLE_WRITE_IN_MUX; } - if ((client->status & CLIENT_HANDLE_RW_IN_MUX) != expected_client_handle_mux_status) + if ((client->status & QSE_HTTPD_CLIENT_HANDLE_RW_IN_MUX) != expected_client_handle_mux_status) { httpd->opt.scb.mux.delhnd (httpd, httpd->mux, client->handle); - client->status &= ~CLIENT_HANDLE_RW_IN_MUX; + client->status &= ~QSE_HTTPD_CLIENT_HANDLE_RW_IN_MUX; if (expected_client_handle_mux_mask) { @@ -1233,7 +1233,7 @@ static int update_mux_for_next_task (qse_httpd_t* httpd, qse_httpd_client_t* cli /*printf ("update_mux_for_next_task\n");*/ expected_mux_mask = QSE_HTTPD_MUX_READ; - expected_mux_status = CLIENT_HANDLE_READ_IN_MUX; + expected_mux_status = QSE_HTTPD_CLIENT_HANDLE_READ_IN_MUX; expected_trigger_cmask = QSE_HTTPD_TASK_TRIGGER_READ; task = client->task.head; @@ -1242,15 +1242,15 @@ static int update_mux_for_next_task (qse_httpd_t* httpd, qse_httpd_client_t* cli /* there is a pending task. arrange to trigger it as if it is * just entasked. */ expected_mux_mask |= QSE_HTTPD_MUX_WRITE; - expected_mux_status |= CLIENT_HANDLE_WRITE_IN_MUX; + expected_mux_status |= QSE_HTTPD_CLIENT_HANDLE_WRITE_IN_MUX; expected_trigger_cmask |= QSE_HTTPD_TASK_TRIGGER_WRITE; - if (client->status & CLIENT_MUTE) + if (client->status & QSE_HTTPD_CLIENT_MUTE) { /* when client-side has been disconnected, it can't read * from the side any more. so exclude reading */ expected_mux_mask &= ~QSE_HTTPD_MUX_READ; - expected_mux_status &= ~CLIENT_HANDLE_READ_IN_MUX; + expected_mux_status &= ~QSE_HTTPD_CLIENT_HANDLE_READ_IN_MUX; expected_trigger_cmask &= ~QSE_HTTPD_TASK_TRIGGER_READ; } } @@ -1258,7 +1258,7 @@ static int update_mux_for_next_task (qse_httpd_t* httpd, qse_httpd_client_t* cli { /* there is no pending task to invoke. */ - if (client->status & CLIENT_MUTE) + if (client->status & QSE_HTTPD_CLIENT_MUTE) { /* and this client has closed connection previously. * if not, reading would be the only clue to mux for @@ -1268,12 +1268,12 @@ static int update_mux_for_next_task (qse_httpd_t* httpd, qse_httpd_client_t* cli } } - if ((client->status & CLIENT_HANDLE_RW_IN_MUX) != expected_mux_status) + if ((client->status & QSE_HTTPD_CLIENT_HANDLE_RW_IN_MUX) != expected_mux_status) { httpd->opt.scb.mux.delhnd (httpd, httpd->mux, client->handle); - client->status &= ~CLIENT_HANDLE_RW_IN_MUX; + client->status &= ~QSE_HTTPD_CLIENT_HANDLE_RW_IN_MUX; - QSE_ASSERT (expected_mux_status & CLIENT_HANDLE_RW_IN_MUX); + QSE_ASSERT (expected_mux_status & QSE_HTTPD_CLIENT_HANDLE_RW_IN_MUX); if (httpd->opt.scb.mux.addhnd (httpd, httpd->mux, client->handle, expected_mux_mask, client) <= -1) return -1; client->status |= expected_mux_status; } @@ -1295,7 +1295,7 @@ static int invoke_client_task ( { /* keep reading from the client-side as long as * it's readable. */ - if (!(client->status & CLIENT_MUTE) && + if (!(client->status & QSE_HTTPD_CLIENT_MUTE) && read_from_client (httpd, client) <= -1) { /* return failure on disconnection also in order to @@ -1310,7 +1310,7 @@ static int invoke_client_task ( if (task == QSE_NULL) { /* this client doesn't have any task */ - if (client->status & CLIENT_MUTE) + if (client->status & QSE_HTTPD_CLIENT_MUTE) { /* handle the delayed client disconnection */ return -1; @@ -1416,16 +1416,16 @@ static int perform_client_task ( client = (qse_httpd_client_t*)cbarg; - if (client->status & CLIENT_BAD) return 0; + if (client->status & QSE_HTTPD_CLIENT_BAD) return 0; - if (!(client->status & CLIENT_READY)) + if (!(client->status & QSE_HTTPD_CLIENT_READY)) { int x; x = httpd->opt.scb.client.accepted (httpd, client); if (x <= -1) goto oops; if (x >= 1) { - client->status |= CLIENT_READY; + client->status |= QSE_HTTPD_CLIENT_READY; qse_gettime (&client->last_active); move_client_to_tail (httpd, client); @@ -1493,7 +1493,7 @@ qse_httpd_task_t* qse_httpd_entask ( { qse_httpd_real_task_t* new_task; - if (client->status & CLIENT_BAD) return QSE_NULL; + if (client->status & QSE_HTTPD_CLIENT_BAD) return QSE_NULL; new_task = enqueue_task (httpd, client, pred, task, xtnsize); if (new_task == QSE_NULL) @@ -1767,7 +1767,7 @@ qse_mchar_t* qse_httpd_escapehtml (qse_httpd_t* httpd, const qse_mchar_t* str) /* ----------------------------------------------------------------------- */ -int qse_httpd_resolname (qse_httpd_t* httpd, const qse_mchar_t* name, qse_httpd_resol_t resol, const qse_nwad_t* dns_server, void* ctx) +int qse_httpd_resolname (qse_httpd_t* httpd, const qse_mchar_t* name, qse_httpd_resol_t resol, const qse_httpd_natr_t* dns_server, void* ctx) { /* TODO: find the name in cache */ @@ -1779,10 +1779,11 @@ printf ("DNS_SEND.........................\n"); return -1; } + return httpd->opt.scb.dns.send (httpd, &httpd->dns, name, resol, dns_server, ctx); } -int qse_httpd_rewriteurl (qse_httpd_t* httpd, const qse_mchar_t* url, qse_httpd_rewrite_t rewrite, const qse_nwad_t* urs_server, void* ctx) +int qse_httpd_rewriteurl (qse_httpd_t* httpd, const qse_mchar_t* url, qse_httpd_rewrite_t rewrite, const qse_httpd_natr_t* urs_server, void* ctx) { if (!httpd->ursactive) { @@ -1806,7 +1807,7 @@ int qse_httpd_activatetasktrigger (qse_httpd_t* httpd, qse_httpd_client_t* clien * if no data is available for reading, the task can never be * called after activation. so let's request writing here. */ - QSE_ASSERT (!(client->status & CLIENT_HANDLE_RW_IN_MUX)); + QSE_ASSERT (!(client->status & QSE_HTTPD_CLIENT_HANDLE_RW_IN_MUX)); org_cmask = task->trigger.cmask; task->trigger.cmask |= QSE_HTTPD_TASK_TRIGGER_WRITE; diff --git a/qse/lib/http/httpd.h b/qse/lib/http/httpd.h index 92a3c156..3038d428 100644 --- a/qse/lib/http/httpd.h +++ b/qse/lib/http/httpd.h @@ -107,21 +107,6 @@ struct qse_httpd_status_reloc_t #define MAX_SEND_SIZE 4096 #define MAX_RECV_SIZE 4096 -/* client->status */ -#define CLIENT_BAD (1 << 0) -#define CLIENT_READY (1 << 1) -#define CLIENT_SECURE (1 << 2) -#define CLIENT_PENDING (1 << 3) -#define CLIENT_MUTE (1 << 4) -#define CLIENT_MUTE_DELETED (1 << 5) -#define CLIENT_HANDLE_READ_IN_MUX (1 << 6) -#define CLIENT_HANDLE_WRITE_IN_MUX (1 << 7) -#define CLIENT_HANDLE_RW_IN_MUX (CLIENT_HANDLE_READ_IN_MUX | CLIENT_HANDLE_WRITE_IN_MUX) - -#define CLIENT_TASK_TRIGGER_READ_IN_MUX(i) (1 << ((i) + 8)) -#define CLIENT_TASK_TRIGGER_WRITE_IN_MUX(i) (1 << ((i) + 8 + QSE_HTTPD_TASK_TRIGGER_MAX)) -#define CLIENT_TASK_TRIGGER_RW_IN_MUX(i) (CLIENT_TASK_TRIGGER_READ_IN_MUX(i) | CLIENT_TASK_TRIGGER_WRITE_IN_MUX(i)) - #ifdef __cplusplus extern "C" { #endif