diff --git a/qse/include/qse/http/stdhttpd.h b/qse/include/qse/http/stdhttpd.h index 9ca640d2..906bc1b6 100644 --- a/qse/include/qse/http/stdhttpd.h +++ b/qse/include/qse/http/stdhttpd.h @@ -142,12 +142,20 @@ enum qse_httpd_serverstd_opt_t }; typedef enum qse_httpd_serverstd_opt_t qse_httpd_serverstd_opt_t; -#define QSE_HTTPD_DNSSTD_DEFAULT_TMOUT 10 +#define QSE_HTTPD_DNSSTD_DEFAULT_TMOUT 3 +#define QSE_HTTPD_DNSSTD_DEFAULT_RESENDS 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 struct qse_httpd_dnsstd_t { qse_nwad_t nwad; qse_ntime_t tmout; + qse_uint32_t resends; + qse_uint32_t cache_ttl; + qse_uint32_t cache_minttl; /* minimum ttl */ + qse_uint32_t cache_negttl; /* negative ttl */ }; typedef struct qse_httpd_dnsstd_t qse_httpd_dnsstd_t; diff --git a/qse/lib/cmn/tmr.c b/qse/lib/cmn/tmr.c index d38511da..9c265164 100644 --- a/qse/lib/cmn/tmr.c +++ b/qse/lib/cmn/tmr.c @@ -170,7 +170,6 @@ void qse_tmr_remove (qse_tmr_t* tmr, qse_size_t index) QSE_ASSERT (index < tmr->size); -printf ("tmr_remove.....>>>>>>>>>>>>size=>%d index=>%d\n", (int)tmr->size, (int)index); item = tmr->event[index]; tmr->event[index].updater (tmr, index, QSE_TMR_INVALID, tmr->event[index].ctx); @@ -187,7 +186,6 @@ qse_size_t qse_tmr_insert (qse_tmr_t* tmr, const qse_tmr_event_t* event) { qse_size_t index = tmr->size; -printf ("tmr_insert ......size => %d\n", (int)tmr->size); if (index >= tmr->capa) { qse_tmr_event_t* tmp; diff --git a/qse/lib/http/httpd-proxy.c b/qse/lib/http/httpd-proxy.c index b7a5fc32..be615266 100644 --- a/qse/lib/http/httpd-proxy.c +++ b/qse/lib/http/httpd-proxy.c @@ -35,13 +35,14 @@ struct task_proxy_arg_t typedef struct task_proxy_t task_proxy_t; struct task_proxy_t { -#define PROXY_INIT_FAILED (1 << 0) -#define PROXY_RAW (1 << 1) -#define PROXY_RESOL_PEER_NAME (1 << 2) -#define PROXY_UNKNOWN_PEER_NWAD (1 << 3) -#define PROXY_X_FORWARDED_FOR (1 << 4) -#define PROXY_VIA (1 << 5) -#define PROXY_VIA_RETURNING (1 << 6) +#define PROXY_INIT_FAILED (1 << 0) +#define PROXY_RAW (1 << 1) +#define PROXY_RESOLVE_PEER_NAME (1 << 2) +#define PROXY_PEER_NAME_RESOLVED (1 << 3) +#define PROXY_PEER_NAME_UNRESOLVED (1 << 4) +#define PROXY_X_FORWARDED_FOR (1 << 5) +#define PROXY_VIA (1 << 6) +#define PROXY_VIA_RETURNING (1 << 7) int flags; qse_httpd_t* httpd; qse_httpd_client_t* client; @@ -907,7 +908,7 @@ static int task_init_proxy ( { qse_mchar_t* colon; - proxy->flags |= PROXY_RESOL_PEER_NAME; + proxy->flags |= PROXY_RESOLVE_PEER_NAME; proxy->peer_name = proxy->pseudonym + len + 1; qse_mbscpy (proxy->peer_name, arg->rsrc->dst.str); @@ -1794,9 +1795,10 @@ static void on_peer_name_resolved (qse_httpd_t* httpd, const qse_mchar_t* name, qse_httpd_task_t* task = (qse_httpd_task_t*)ctx; task_proxy_t* proxy = (task_proxy_t*)task->ctx; - QSE_ASSERT (proxy->flags & PROXY_RESOL_PEER_NAME); + QSE_ASSERT (proxy->flags & PROXY_RESOLVE_PEER_NAME); + QSE_ASSERT (!(proxy->flags & (PROXY_PEER_NAME_RESOLVED | PROXY_PEER_NAME_UNRESOLVED))); - proxy->flags &= ~PROXY_RESOL_PEER_NAME; + proxy->flags &= ~PROXY_RESOLVE_PEER_NAME; if (nwad) { @@ -1807,11 +1809,13 @@ static void on_peer_name_resolved (qse_httpd_t* httpd, const qse_mchar_t* name, if (proxy->peer.local.type == QSE_NWAD_NX) proxy->peer.local.type = proxy->peer.nwad.type; + + proxy->flags |= PROXY_PEER_NAME_RESOLVED; } else { /* resolution failure. */ - proxy->flags |= PROXY_INIT_FAILED | PROXY_UNKNOWN_PEER_NWAD; + proxy->flags |= PROXY_INIT_FAILED | PROXY_PEER_NAME_UNRESOLVED; } if (qse_httpd_activatetasktrigger (httpd, proxy->client, task) <= -1) @@ -1832,13 +1836,28 @@ static int task_main_proxy ( if (proxy->flags & PROXY_INIT_FAILED) { - if (proxy->flags & PROXY_UNKNOWN_PEER_NWAD) http_errnum = 404; /* 404 Not Found */ + if (proxy->flags & PROXY_PEER_NAME_UNRESOLVED) http_errnum = 404; /* 404 Not Found */ goto oops; } - if (proxy->flags & PROXY_RESOL_PEER_NAME) +#if 0 + if (proxy->flags & PROXY_REWRITE_URL) + { + if (qse_httpd_rewriteurl (httpd, proxy->url, on_url_rewritten, task) <= -1) goto oops; + + if (proxy->flags & PROXY_INIT_FAILED) goto oops; + + if ((proxy->flags & PROXY_RESOL_REWRITE_URL) && + qse_httpd_inactivatetasktrigger (httpd, client, task) <= -1) goto oops; + + return 1; + } +#endif + + if (proxy->flags & PROXY_RESOLVE_PEER_NAME) { /* arrange to resolve a host name and return */ + QSE_ASSERT (proxy->peer_name != QSE_NULL); if (qse_httpd_resolname (httpd, proxy->peer_name, on_peer_name_resolved, task) <= -1) goto oops; @@ -1848,11 +1867,12 @@ static int task_main_proxy ( * called. */ if (proxy->flags & PROXY_INIT_FAILED) { - if (proxy->flags & PROXY_UNKNOWN_PEER_NWAD) http_errnum = 404; /* 404 Not Found */ + if (proxy->flags & PROXY_PEER_NAME_UNRESOLVED) http_errnum = 404; /* 404 Not Found */ goto oops; } - if ((proxy->flags & PROXY_RESOL_PEER_NAME) && + /* peer name is not resolved yet. */ + if (!(proxy->flags & PROXY_PEER_NAME_RESOLVED) && qse_httpd_inactivatetasktrigger (httpd, client, task) <= -1) goto oops; return 1; diff --git a/qse/lib/http/httpd-std.c b/qse/lib/http/httpd-std.c index 8741ef25..58582e9a 100644 --- a/qse/lib/http/httpd-std.c +++ b/qse/lib/http/httpd-std.c @@ -2113,6 +2113,7 @@ struct dns_antrail_t struct dns_ctx_t { qse_httpd_t* httpd; + qse_httpd_dns_t* dns; qse_skad_t skad; int skadlen; @@ -2144,6 +2145,7 @@ struct dns_req_t dns_ctx_t* dc; qse_size_t tmr_tmout; + int resends; dns_req_t* next; }; @@ -2267,6 +2269,7 @@ static int dns_open (qse_httpd_t* httpd, qse_httpd_dns_t* dns) if (dc == NULL) goto oops; dc->httpd = httpd; + dc->dns = dns; /* TODO: add static cache entries from /etc/hosts */ @@ -2506,6 +2509,7 @@ static dns_ans_t* dns_get_answer_from_cache (dns_ctx_t* dc, const qse_mchar_t* n static int dns_recv (qse_httpd_t* httpd, qse_httpd_dns_t* dns) { dns_ctx_t* dc = (dns_ctx_t*)dns->ctx; + httpd_xtn_t* httpd_xtn; qse_skad_t fromaddr; socklen_t fromlen; @@ -2516,7 +2520,7 @@ static int dns_recv (qse_httpd_t* httpd, qse_httpd_dns_t* dns) printf ("DNS_RECV....\n"); -/* TODO: delete requests that're not replied at all for long time */ + httpd_xtn = qse_httpd_getxtn (httpd); fromlen = QSE_SIZEOF(fromaddr); len = recvfrom (dns->handle.i, buf, QSE_SIZEOF(buf), 0, (struct sockaddr*)&fromaddr, &fromlen); @@ -2534,7 +2538,6 @@ printf ("DNS_RECV....\n"); xid = (id >= QSE_COUNTOF(dc->reqs))? (id - QSE_COUNTOF(dc->reqs)): id; -printf ("%d qdcount %d ancount %d\n", id, qdcount, ancount); if (xid >= 0 && xid < QSE_COUNTOF(dc->reqs) && hdr->qr && hdr->opcode == DNS_OPCODE_QUERY && qdcount >= 1) { qse_uint8_t* plptr = (qse_uint8_t*)(hdr + 1); @@ -2622,6 +2625,8 @@ printf ("invoking resoll with ipv6 \n"); if (nwad.type != QSE_NWAD_NX) { + int ttl; + dns_remove_tmr_tmout (req); req->resol (httpd, req->name, &nwad, req->ctx); @@ -2630,7 +2635,10 @@ printf ("invoking resoll with ipv6 \n"); else dc->reqs[xid] = req->next; /*qse_httpd_freemem (httpd, req);*/ - dns_cache_answer (dc, req, &nwad, qse_ntoh32(antrail->ttl)); + ttl = httpd_xtn->dns.cache_ttl; + if (ttl > qse_ntoh32(antrail->ttl)) ttl = qse_ntoh32(antrail->ttl); + if (ttl < httpd_xtn->dns.cache_minttl) ttl = httpd_xtn->dns.cache_minttl; + dns_cache_answer (dc, req, &nwad, ttl); goto done; } @@ -2656,7 +2664,7 @@ printf ("invoking resoll with ipv6 \n"); else dc->reqs[xid] = req->next; /*qse_httpd_freemem (httpd, req);*/ - dns_cache_answer (dc, req, QSE_NULL, DNS_MIN_TTL); + dns_cache_answer (dc, req, QSE_NULL, httpd_xtn->dns.cache_negttl); } } } @@ -2677,10 +2685,44 @@ printf (">>tmr_dns_tmout_updated %d %d\n", (int)req->tmr_tmout, (int)old_index); static void tmr_dns_tmout_handle (qse_tmr_t* tmr, const qse_ntime_t* now, void* ctx) { /* destory the unanswered request if timed out */ + dns_req_t* req = (dns_req_t*)ctx; dns_req_t* preq, * xreq; qse_uint16_t xid; + /* when this handler is called, the event should be removed from the timer */ + QSE_ASSERT (req->tmr_tmout == QSE_TMR_INVALID); + +/* TODO: resend?? + reschedule?? */ + if (req->resends > 0) + { + httpd_xtn_t* httpd_xtn; + qse_tmr_event_t tmout_event; + + httpd_xtn = qse_httpd_getxtn (req->dc->httpd); + + qse_gettime (&tmout_event.when); + qse_addtime (&tmout_event.when, &httpd_xtn->dns.tmout, &tmout_event.when); + tmout_event.ctx = req; + tmout_event.handler = tmr_dns_tmout_handle; + tmout_event.updater = tmr_dns_tmout_updated; + + if ((!(req->flags & DNS_REQ_A_NX) && req->qalen > 0 && sendto (req->dc->dns->handle.i, req->qa, req->qalen, 0, (struct sockaddr*)&req->dc->skad, req->dc->skadlen) != req->qalen) || + (!(req->flags & DNS_REQ_AAAA_NX) && req->qaaaalen > 0 && sendto (req->dc->dns->handle.i, req->qaaaa, req->qaaaalen, 0, (struct sockaddr*)&req->dc->skad, req->dc->skadlen) != req->qaaaalen)) + { + /* error. fall thru */ + } + else + { + req->tmr_tmout = qse_tmr_insert (req->dc->httpd->tmr, &tmout_event); + if (req->tmr_tmout != QSE_TMR_INVALID) + { + req->resends--; + return; /* resend ok */ + } + } + } + printf ("dns timed out....\n"); xid = req->seqa; QSE_ASSERT (xid >= 0 && QSE_COUNTOF(req->dc->reqs)); @@ -2690,32 +2732,32 @@ printf ("dns timed out....\n"); if (req == xreq) break; } + /* this request that timed out must be inside the request list */ QSE_ASSERT (req == xreq); + /* detach the request off dc->reqs */ if (preq) preq->next = req->next; else req->dc->reqs[xid] = req->next; - QSE_ASSERT (req->tmr_tmout == QSE_TMR_INVALID); - /* dns timed out. report that name resolution failed */ req->resol (req->dc->httpd, req->name, QSE_NULL, req->ctx); /* i don't cache the items that have timed out */ qse_httpd_freemem (req->dc->httpd, req); - } static int dns_send (qse_httpd_t* httpd, qse_httpd_dns_t* dns, const qse_mchar_t* name, qse_httpd_resol_t resol, void* ctx) { dns_ctx_t* dc = (dns_ctx_t*)dns->ctx; - httpd_xtn_t* httpd_xtn = qse_httpd_getxtn (httpd); + httpd_xtn_t* httpd_xtn; qse_uint32_t seq; dns_req_t* req; qse_size_t name_len; dns_ans_t* ans; qse_tmr_event_t tmout_event; - + + httpd_xtn = qse_httpd_getxtn (httpd); printf ("DNS REALLY SENING>>>>>>>>>>>>>>>>>>>>>>>\n"); ans = dns_get_answer_from_cache (dc, name); @@ -2775,8 +2817,7 @@ printf ("DNS REALLY SENING>>>>>>>>>>>>>>>>>>>>>>>\n"); tmout_event.ctx = req; tmout_event.handler = tmr_dns_tmout_handle; tmout_event.updater = tmr_dns_tmout_updated; - -printf ("ABOUT TO REGISTER TMR_TMOUT...\n"); + req->tmr_tmout = qse_tmr_insert (httpd->tmr, &tmout_event); if (req->tmr_tmout == QSE_TMR_INVALID) { @@ -2784,7 +2825,7 @@ printf ("ABOUT TO REGISTER TMR_TMOUT...\n"); qse_httpd_freemem (httpd, req); return -1; } -printf ("???? initial tmr_tmout => %d\n", (int)req->tmr_tmout); + req->resends = httpd_xtn->dns.resends; if ((req->qalen > 0 && sendto (dns->handle.i, req->qa, req->qalen, 0, (struct sockaddr*)&dc->skad, dc->skadlen) != req->qalen) || (req->qaaaalen > 0 && sendto (dns->handle.i, req->qaaaa, req->qaaaalen, 0, (struct sockaddr*)&dc->skad, dc->skadlen) != req->qaaaalen)) @@ -2837,7 +2878,6 @@ static int process_request ( * non-peek mode as well */ if (peek) qse_perdechttpstr (qse_htre_getqpath(req), qse_htre_getqpath(req)); - if (peek && (httpd->opt.trait & QSE_HTTPD_LOGACT)) { /* TODO: improve logging */ @@ -4070,6 +4110,11 @@ int qse_httpd_loopstd (qse_httpd_t* httpd, const qse_httpd_dnsstd_t* dns) { 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.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; } return qse_httpd_loop (httpd); diff --git a/qse/lib/http/httpd-task.c b/qse/lib/http/httpd-task.c index 520ac06f..c6b62e99 100644 --- a/qse/lib/http/httpd-task.c +++ b/qse/lib/http/httpd-task.c @@ -185,6 +185,7 @@ static qse_httpd_task_t* entask_status ( switch (code) { case 301: + case 302: case 307: { status_reloc_t* reloc; diff --git a/qse/lib/http/httpd.c b/qse/lib/http/httpd.c index 383e3a05..de86a0b4 100644 --- a/qse/lib/http/httpd.c +++ b/qse/lib/http/httpd.c @@ -1681,6 +1681,13 @@ printf ("DNS_SEND.........................\n"); return httpd->opt.scb.dns.send (httpd, &httpd->dns, name, resol, ctx); } +#if 0 +int qse_httpd_rewriteurl (qse_httpd_t* httpd, const qse_mchar_t* url, qse_httpd_rewrite_t rewrite, void* ctx) +{ + return httpd->opt.scb.url.send (httpd, &httpd->dns, name, resol, ctx); +} +#endif + int qse_httpd_activatetasktrigger (qse_httpd_t* httpd, qse_httpd_client_t* client, qse_httpd_task_t* task) { int x, org_cmask;