diff --git a/qse/cmd/http/httpd.c b/qse/cmd/http/httpd.c index d1363a2a..dc9c739d 100644 --- a/qse/cmd/http/httpd.c +++ b/qse/cmd/http/httpd.c @@ -198,6 +198,7 @@ struct loccfg_t int dns_queries; int urs_timeout; int urs_retries; + qse_httpd_mod_t* dns_preresolve_mod; qse_httpd_mod_t* urs_prerewrite_mod; qse_mchar_t pseudonym[128]; /* TODO: good size? */ } proxy; @@ -574,6 +575,7 @@ proxy_ok: root->u.proxy.dns_server.tmout.sec = loccfg->proxy.dns_timeout; root->u.proxy.dns_server.retries = loccfg->proxy.dns_retries; root->u.proxy.dns_server.flags = loccfg->proxy.dns_queries; + root->u.proxy.dns_preresolve_mod = loccfg->proxy.dns_preresolve_mod; } if (loccfg->proxy.urs_enabled) @@ -1481,6 +1483,16 @@ static int load_loccfg_proxy (qse_httpd_t* httpd, qse_xli_t* xli, qse_xli_list_t } else cfg->proxy.dns_queries = QSE_HTTPD_DNS_SERVER_A | QSE_HTTPD_DNS_SERVER_AAAA; + pair = QSE_NULL; + if (proxy) pair = qse_xli_findpair (xli, proxy, QSE_T("dns-preresolve-hook")); + if (!pair && default_proxy) pair = qse_xli_findpair (xli, default_proxy, QSE_T("dns-preresolve-hook")); + if (pair) + { + cfg->proxy.dns_preresolve_mod = qse_httpd_findmod (httpd, ((qse_xli_str_t*)pair->val)->ptr); + if (!cfg->proxy.dns_preresolve_mod) + qse_printf (QSE_T("WARNING: dns-preresolve-hook not found - %s\n"), ((qse_xli_str_t*)pair->val)->ptr); + } + 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")); @@ -1895,6 +1907,7 @@ static int open_config_file (qse_httpd_t* httpd) { 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.dns-queries"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 0, 0xFFFF } }, + { QSE_T("server-default.proxy.dns-preresolve-hook"), { 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 } }, @@ -1943,13 +1956,14 @@ static int open_config_file (qse_httpd_t* httpd) { 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.intercept"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } }, + { QSE_T("server.host.location.proxy.intercept"), { 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.dns-queries"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 0, 0xFFFF } }, + { QSE_T("server.host.location.proxy.dns-preresolve-hook"), { 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 } }, diff --git a/qse/include/qse/http/httpd.h b/qse/include/qse/http/httpd.h index 0c70da42..b3d75fb1 100644 --- a/qse/include/qse/http/httpd.h +++ b/qse/include/qse/http/httpd.h @@ -99,6 +99,13 @@ typedef void (*qse_httpd_mod_unload_t) ( qse_httpd_mod_t* mod ); +typedef int (*qse_httpd_mod_dns_preresolve_t) ( + qse_httpd_mod_t* mod, + qse_httpd_client_t* client, + const qse_mchar_t* host, + qse_nwad_t* nwad +); + typedef int (*qse_httpd_mod_urs_prerewrite_t) ( qse_httpd_mod_t* mod, qse_httpd_client_t* client, @@ -121,6 +128,7 @@ struct qse_httpd_mod_t /* module's entry point may set these items */ void* ctx; qse_httpd_mod_unload_t unload; + qse_httpd_mod_dns_preresolve_t dns_preresolve; qse_httpd_mod_urs_prerewrite_t urs_prerewrite; /* more fields will get added here for expansion in the future. */ @@ -196,7 +204,7 @@ struct qse_httpd_urs_server_t /* -------------------------------------------------------------------------- */ -typedef void (*qse_httpd_resol_t) ( +typedef void (*qse_httpd_resolve_t) ( qse_httpd_t* httpd, const qse_mchar_t* name, const qse_nwad_t* nwad, @@ -215,6 +223,14 @@ typedef void (*qse_httpd_rewrite_t) ( ); +typedef int (*qse_httpd_dns_preresolve_t) ( + qse_httpd_t* httpd, + qse_httpd_client_t* client, + const qse_mchar_t* host, + qse_nwad_t* nwad +); + + typedef int (*qse_httpd_urs_open_t) ( qse_httpd_t* httpd, qse_httpd_urs_t* urs @@ -389,8 +405,10 @@ struct qse_httpd_scb_t void (*close) (qse_httpd_t* httpd, qse_httpd_dns_t* dns); 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_mchar_t* name, qse_httpd_resolve_t resol, const qse_httpd_dns_server_t* dns_server, void* ctx); + + qse_httpd_dns_preresolve_t preresolve; } dns; struct @@ -737,6 +755,7 @@ struct qse_httpd_rsrc_proxy_t qse_httpd_dns_server_t dns_server; qse_httpd_urs_server_t urs_server; + qse_httpd_mod_t* dns_preresolve_mod; qse_httpd_mod_t* urs_prerewrite_mod; /* optional pseudonym to use for Via: */ @@ -1165,10 +1184,10 @@ QSE_EXPORT qse_mchar_t* qse_httpd_escapehtml ( const qse_mchar_t* str ); -QSE_EXPORT int qse_httpd_resolname ( +QSE_EXPORT int qse_httpd_resolvename ( qse_httpd_t* httpd, const qse_mchar_t* name, - qse_httpd_resol_t resol, + qse_httpd_resolve_t resol, const qse_httpd_dns_server_t* dns_server, void* ctx ); diff --git a/qse/lib/http/httpd-proxy.c b/qse/lib/http/httpd-proxy.c index 430ff467..b5c974f8 100644 --- a/qse/lib/http/httpd-proxy.c +++ b/qse/lib/http/httpd-proxy.c @@ -72,6 +72,7 @@ struct task_proxy_t qse_mchar_t* pseudonym; qse_htrd_t* peer_htrd; + qse_httpd_mod_t* dns_preresolve_mod; qse_mchar_t* peer_name; qse_uint16_t peer_port; @@ -948,9 +949,9 @@ static int task_init_proxy ( if (arg->rsrc->flags & QSE_HTTPD_RSRC_PROXY_ENABLE_DNS) { proxy->peer_name = proxy->pseudonym + len + 1; - qse_mbscpy (proxy->peer_name, arg->rsrc->dst.str); adjust_peer_name_and_port (proxy); + proxy->dns_preresolve_mod = arg->rsrc->dns_preresolve_mod; proxy->flags |= PROXY_RESOLVE_PEER_NAME; if (arg->rsrc->flags & QSE_HTTPD_RSRC_PROXY_DNS_SERVER) @@ -989,7 +990,7 @@ printf (">>>>>>>>>>>>>>>>>>>>>>>> [%s] <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n", proxy if (x == 0) { /* prerewrite() indicates that proxy->url_to_rewrite is the final - * rewriting result and no futher rewriting is required */ + * rewriting result and no further rewriting is required */ proxy->flags |= PROXY_URL_PREREWRITTEN; } @@ -2129,7 +2130,7 @@ static int task_main_proxy ( { /* note that url_to_rewrite is URL + extra information. */ if (qse_httpd_rewriteurl (httpd, proxy->url_to_rewrite, on_url_rewritten, - ((proxy->flags & PROXY_URS_SERVER)? &proxy->urs_server: QSE_NULL), task) <= -1) goto oops; + ((proxy->flags & PROXY_URS_SERVER)? &proxy->urs_server: QSE_NULL), task) <= -1) goto oops; if (proxy->flags & PROXY_INIT_FAILED) goto oops; @@ -2143,14 +2144,31 @@ static int task_main_proxy ( if (proxy->flags & PROXY_RESOLVE_PEER_NAME) { /* arrange to resolve a host name and return */ - + int x; QSE_ASSERT (proxy->peer_name != QSE_NULL); - if (qse_httpd_resolname (httpd, proxy->peer_name, on_peer_name_resolved, - ((proxy->flags & PROXY_DNS_SERVER)? &proxy->dns_server: QSE_NULL), task) <= -1) goto oops; + if (proxy->dns_preresolve_mod && proxy->dns_preresolve_mod->dns_preresolve) + x = proxy->dns_preresolve_mod->dns_preresolve (proxy->dns_preresolve_mod, client, proxy->peer_name, &proxy->peer.nwad); + else + x = httpd->opt.scb.dns.preresolve (httpd, client, proxy->peer_name, &proxy->peer.nwad); + if (x <= -1) goto oops; + + if (x == 0) + { + /* preresolve() indicates that proxy->peer.nwad contains the + * final address. no actual dns resolution is required */ + proxy->flags |= PROXY_PEER_NAME_RESOLVED; + proxy->flags &= ~PROXY_RESOLVE_PEER_NAME; + qse_setnwadport (&proxy->peer.nwad, qse_hton16(proxy->peer_port)); + } + else + { + x = qse_httpd_resolvename (httpd, proxy->peer_name, on_peer_name_resolved, ((proxy->flags & PROXY_DNS_SERVER)? &proxy->dns_server: QSE_NULL), task); + if (x <= -1) goto oops; + } /* if the name could be resolved without sending a request - * in qse_httpd_resolname(), on_peer_name_resolve would be + * in qse_httpd_resolvename(), on_peer_name_resolve would be * called. */ if (proxy->flags & PROXY_INIT_FAILED) { diff --git a/qse/lib/http/httpd-std-dns.h b/qse/lib/http/httpd-std-dns.h index a945d9f7..80f009e5 100644 --- a/qse/lib/http/httpd-std-dns.h +++ b/qse/lib/http/httpd-std-dns.h @@ -153,7 +153,7 @@ struct dns_req_t qse_uint8_t* dn; qse_size_t dnlen; - qse_httpd_resol_t resol; + qse_httpd_resolve_t resol; void* ctx; qse_uint8_t qa[DNS_MAX_DN_LEN + QSE_SIZEOF(dns_hdr_t) + QSE_SIZEOF(dns_qdtrail_t)]; @@ -795,7 +795,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_httpd_dns_server_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_resolve_t resol, const qse_httpd_dns_server_t* dns_server, void* ctx) { dns_ctx_t* dc = (dns_ctx_t*)dns->ctx; httpd_xtn_t* httpd_xtn; @@ -942,3 +942,11 @@ oops: } return -1; } + + +static int dns_preresolve (qse_httpd_t* httpd, qse_httpd_client_t* client, const qse_mchar_t* host, qse_nwad_t* nwad) +{ + /* do nothing */ + return 1; /* unhandled */ +} + diff --git a/qse/lib/http/httpd-std-urs.h b/qse/lib/http/httpd-std-urs.h index 3a7e7b81..fa106f77 100644 --- a/qse/lib/http/httpd-std-urs.h +++ b/qse/lib/http/httpd-std-urs.h @@ -538,7 +538,6 @@ static int urs_prerewrite (qse_httpd_t* httpd, qse_httpd_client_t* client, qse_h url_to_rewrite = qse_httpd_allocmem (httpd, total_len); if (url_to_rewrite == QSE_NULL) return -1; - if (mtype == QSE_HTTP_CONNECT || !host_ptr) { host_ptr = QSE_MT(""); diff --git a/qse/lib/http/httpd-std.c b/qse/lib/http/httpd-std.c index d8d78976..1460b313 100644 --- a/qse/lib/http/httpd-std.c +++ b/qse/lib/http/httpd-std.c @@ -2389,7 +2389,8 @@ static qse_httpd_scb_t httpd_system_callbacks = dns_open, dns_close, dns_recv, - dns_send + dns_send, + dns_preresolve }, /* urs */ diff --git a/qse/lib/http/httpd.c b/qse/lib/http/httpd.c index 33c32d0f..fc699b1e 100644 --- a/qse/lib/http/httpd.c +++ b/qse/lib/http/httpd.c @@ -1853,7 +1853,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_httpd_dns_server_t* dns_server, void* ctx) +int qse_httpd_resolvename (qse_httpd_t* httpd, const qse_mchar_t* name, qse_httpd_resolve_t resol, const qse_httpd_dns_server_t* dns_server, void* ctx) { printf ("DNS_SEND.........................\n"); if (!httpd->dnsactive) @@ -1862,7 +1862,6 @@ printf ("DNS_SEND.........................\n"); return -1; } - return httpd->opt.scb.dns.send (httpd, &httpd->dns, name, resol, dns_server, ctx); }