improved dns handling and added some code for url rewriting

This commit is contained in:
hyung-hwan 2014-08-06 16:44:06 +00:00
parent 4f4f42ae4f
commit ae45071b5e
6 changed files with 773 additions and 194 deletions

View File

@ -1920,7 +1920,7 @@ static int httpd_main (int argc, qse_char_t* argv[])
setup_signal_handlers ();
qse_httpd_getopt (httpd, QSE_HTTPD_TRAIT, &trait);
trait |= QSE_HTTPD_CGIERRTONUL | QSE_HTTPD_LOGACT | QSE_HTTPD_DNSNOAAAA;
trait |= QSE_HTTPD_CGIERRTONUL | QSE_HTTPD_LOGACT | QSE_HTTPD_DNSNOAAAA; /* TODO: make NOAAAA configurable */
qse_httpd_setopt (httpd, QSE_HTTPD_TRAIT, &trait);
tmout.sec = 10;

View File

@ -34,6 +34,7 @@ typedef struct qse_httpd_mate_t qse_httpd_mate_t;
typedef struct qse_httpd_server_t qse_httpd_server_t;
typedef struct qse_httpd_client_t qse_httpd_client_t;
typedef struct qse_httpd_dns_t qse_httpd_dns_t;
typedef struct qse_httpd_urs_t qse_httpd_urs_t;
enum qse_httpd_errnum_t
{
@ -132,6 +133,13 @@ typedef void (*qse_httpd_resol_t) (
void* ctx
);
typedef void (*qse_httpd_rewrite_t) (
qse_httpd_t* httpd,
const qse_mchar_t* url,
const qse_mchar_t* new_url,
void* ctx
);
typedef struct qse_httpd_scb_t qse_httpd_scb_t;
struct qse_httpd_scb_t
{
@ -255,6 +263,14 @@ struct qse_httpd_scb_t
int (*recv) (qse_httpd_t* httpd, qse_httpd_dns_t* dns);
int (*send) (qse_httpd_t* httpd, qse_httpd_dns_t* dns, const qse_mchar_t* name, qse_httpd_resol_t resol, void* ctx);
} dns;
struct
{
int (*open) (qse_httpd_t* httpd, qse_httpd_urs_t* urs);
void (*close) (qse_httpd_t* httpd, qse_httpd_urs_t* urs);
int (*recv) (qse_httpd_t* httpd, qse_httpd_urs_t* urs);
int (*send) (qse_httpd_t* httpd, qse_httpd_urs_t* urs, const qse_mchar_t* url, qse_httpd_rewrite_t rewrite, void* ctx);
} urs;
};
/* -------------------------------------------------------------------------- */
@ -387,7 +403,8 @@ enum qse_httpd_mate_type_t
{
QSE_HTTPD_SERVER,
QSE_HTTPD_CLIENT,
QSE_HTTPD_DNS
QSE_HTTPD_DNS,
QSE_HTTPD_URS
};
typedef enum qse_httpd_mate_type_t qse_httpd_mate_type_t;
@ -486,6 +503,17 @@ struct qse_httpd_dns_t
qse_ubi_t handle;
void* ctx;
};
struct qse_httpd_urs_t
{
/* PRIVATE == */
QSE_HTTPD_MATE_HDR;
/* == PUBLIC == */
qse_ubi_t handle;
void* ctx;
};
/* -------------------------------------------------------------------------- */
/**

View File

@ -142,6 +142,7 @@ enum qse_httpd_serverstd_opt_t
};
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_CACHE_TTL 120
@ -160,6 +161,18 @@ struct qse_httpd_dnsstd_t
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
struct qse_httpd_ursstd_t
{
qse_nwad_t nwad;
qse_ntime_t tmout;
qse_uint32_t resends;
};
typedef struct qse_httpd_ursstd_t qse_httpd_ursstd_t;
#if defined(__cplusplus)
extern "C" {
#endif

View File

@ -543,6 +543,7 @@ struct httpd_xtn_t
#endif
qse_httpd_ecb_t ecb;
qse_httpd_dnsstd_t dns;
qse_httpd_ursstd_t urs;
};
#if defined(HAVE_SSL)
@ -2009,6 +2010,14 @@ static void client_closed (qse_httpd_t* httpd, qse_httpd_client_t* client)
}
}
/* ------------------------------------------------------------------- */
static qse_size_t hash_string (const qse_mchar_t *str)
{
qse_size_t h = 0;
while (*str) h = ((h << 5) + h) ^ *str++;
return h;
}
/* ------------------------------------------------------------------- */
#define DNS_MAX_DN_LEN 255 /* full domain name length in binary form (i.e. 3xyz2eu0) */
@ -2017,6 +2026,8 @@ static void client_closed (qse_httpd_t* httpd, qse_httpd_client_t* client)
#define DNS_MIN_TTL 10
#define DNS_MAX_TTL 120 /* TODO: make these configurable... */
#define DNS_SEQ_RANGE_SIZE ((QSE_TYPE_MAX(qse_uint16_t) / 2) - 2)
typedef struct dns_ctx_t dns_ctx_t;
typedef struct dns_req_t dns_req_t;
typedef struct dns_ans_t dns_ans_t;
@ -2109,7 +2120,6 @@ struct dns_antrail_t
};
#include <qse/unpack.h>
struct dns_ctx_t
{
qse_httpd_t* httpd;
@ -2119,8 +2129,13 @@ struct dns_ctx_t
int skadlen;
qse_uint16_t seq;
dns_req_t* reqs[1024]; /* TOOD: choose the right size */
dns_ans_t* anss[1024];
dns_req_t* reqs[2048]; /* TOOD: choose the right size or make it configurable. must be < DNS_SEQ_RANGE_SIZE */
dns_ans_t* anss[2048];
qse_uint16_t req_count; /* the number of pending requests */
qse_uint16_t n_qcin; /* DNS_QCLASS_IN in network byte order */
qse_uint16_t n_qta; /* DNS_QTYPE_A in network byte order */
qse_uint16_t n_qtaaaa; /* DNS_QTYPE_AAAA in network byte order */
};
struct dns_req_t
@ -2148,11 +2163,18 @@ struct dns_req_t
int resends;
dns_req_t* next;
dns_req_t* prev;
};
struct dns_ans_t
{
/* the name part must be the same as dns_req_t */
qse_mchar_t* name;
/* the total size of data fields below must not be greater than
* the total size of data fields of dns_req_t excluding name.
* this condition is required for reusing the dns_req_t chunk
* when caching an answer without allocating another chunk. */
qse_nwad_t nwad;
qse_int64_t age;
qse_uint32_t ttl;
@ -2270,6 +2292,9 @@ static int dns_open (qse_httpd_t* httpd, qse_httpd_dns_t* dns)
dc->httpd = httpd;
dc->dns = dns;
dc->n_qcin = qse_hton16(DNS_QCLASS_IN);
dc->n_qta = qse_hton16(DNS_QTYPE_A);
dc->n_qtaaaa = qse_hton16(DNS_QTYPE_AAAA);
/* TODO: add static cache entries from /etc/hosts */
@ -2314,7 +2339,7 @@ static int dns_open (qse_httpd_t* httpd, qse_httpd_dns_t* dns)
}
if (qse_getnwadport(&nwad) == 0)
qse_setnwadport (&nwad, qse_hton16(QSE_HTTPD_DEFAULT_DNS_PORT));
qse_setnwadport (&nwad, qse_hton16(QSE_HTTPD_DNSSTD_DEFAULT_PORT));
dc->skadlen = qse_nwadtoskad (&nwad, &dc->skad);
if (dc->skadlen <= -1)
@ -2359,6 +2384,7 @@ static int dns_open (qse_httpd_t* httpd, qse_httpd_dns_t* dns)
dns->handle.i = fd;
dns->ctx = dc;
return 0;
oops:
@ -2392,9 +2418,12 @@ static void dns_close (qse_httpd_t* httpd, qse_httpd_dns_t* dns)
dns_remove_tmr_tmout (dc->reqs[i]);
qse_httpd_freemem (httpd, dc->reqs[i]);
dc->reqs[i] = next_req;
dc->req_count--;
}
}
QSE_ASSERT (dc->req_count == 0);
for (i = 0; i < QSE_COUNTOF(dc->anss); i++)
{
dns_ans_t* next_ans;
@ -2406,25 +2435,11 @@ static void dns_close (qse_httpd_t* httpd, qse_httpd_dns_t* dns)
}
}
#if defined(_WIN32)
closesocket (dns->handle.i);
#elif defined(__OS2__)
soclose (dns->handle.i);
#elif defined(__DOS__)
/* TODO: */
#else
QSE_CLOSE (dns->handle.i);
#endif
close_socket (dns->handle.i);
qse_httpd_freemem (httpd, dns->ctx);
}
static unsigned long dns_hash_name (const qse_mchar_t *str)
{
qse_size_t h = 0;
while (*str) h = ((h << 5) + h) ^ *str++;
return h;
}
static void dns_cache_answer (dns_ctx_t* dc, dns_req_t* req, const qse_nwad_t* nwad, qse_uint32_t ttl)
{
@ -2441,6 +2456,10 @@ static void dns_cache_answer (dns_ctx_t* dc, dns_req_t* req, const qse_nwad_t* n
qse_gettime (&now);
ans = (dns_ans_t*)req; /* shadow the request with an answer */
/* reuse the data fields of the request except the name field.
* from here downwards, the data fields of the request are invalid. */
if (nwad) ans->nwad = *nwad; /* positive */
else ans->nwad.type = QSE_NWAD_NX; /* negative */
ans->age = now.sec; /* the granularity of a second should be good enough */
@ -2449,7 +2468,7 @@ static void dns_cache_answer (dns_ctx_t* dc, dns_req_t* req, const qse_nwad_t* n
else if (ttl > DNS_MAX_TTL) ttl = DNS_MAX_TTL;
ans->ttl = ttl;
hid = dns_hash_name (req->name) % QSE_COUNTOF(dc->anss);
hid = hash_string (req->name) % QSE_COUNTOF(dc->anss);
prv = QSE_NULL;
cur = dc->anss[hid];
@ -2477,7 +2496,7 @@ static dns_ans_t* dns_get_answer_from_cache (dns_ctx_t* dc, const qse_mchar_t* n
qse_size_t hid;
qse_ntime_t now;
hid = dns_hash_name (name) % QSE_COUNTOF(dc->anss);
hid = hash_string(name) % QSE_COUNTOF(dc->anss);
qse_gettime (&now);
@ -2518,6 +2537,19 @@ static int dns_recv (qse_httpd_t* httpd, qse_httpd_dns_t* dns)
qse_ssize_t len;
dns_hdr_t* hdr;
qse_uint16_t id, qdcount, ancount, i;
qse_uint8_t* plptr;
qse_size_t pllen;
dns_qdtrail_t* qdtrail;
dns_antrail_t* antrail;
qse_uint16_t anlen;
dns_req_t* req = QSE_NULL;
qse_uint16_t xid = QSE_COUNTOF(dc->reqs);
qse_nwad_t nwad;
qse_nwad_t* resolved_nwad = QSE_NULL;
int cache_ttl = 0;
printf ("DNS_RECV....\n");
httpd_xtn = qse_httpd_getxtn (httpd);
@ -2527,69 +2559,80 @@ printf ("DNS_RECV....\n");
/* TODO: check if fromaddr matches the dc->skad... */
if (len >= QSE_SIZEOF(*hdr))
{
qse_uint16_t id, qdcount, ancount, xid;
if (len < QSE_SIZEOF(*hdr)) goto done; /* packet too small */
hdr = (dns_hdr_t*)buf;
id = qse_ntoh16(hdr->id);
qdcount = qse_ntoh16(hdr->qdcount);
ancount = qse_ntoh16(hdr->ancount);
xid = (id >= QSE_COUNTOF(dc->reqs))? (id - QSE_COUNTOF(dc->reqs)): id;
if (xid >= 0 && xid < QSE_COUNTOF(dc->reqs) && hdr->qr && hdr->opcode == DNS_OPCODE_QUERY && qdcount >= 1)
if (!hdr->qr || hdr->opcode != DNS_OPCODE_QUERY || qdcount <= 0)
{
qse_uint8_t* plptr = (qse_uint8_t*)(hdr + 1);
qse_size_t pllen = len - QSE_SIZEOF(*hdr);
qse_uint8_t i, dnlen;
dns_req_t* req = QSE_NULL, * preq = QSE_NULL;
qse_size_t reclen;
/* not a response to a query */
goto done;
}
ancount = qse_ntoh16(hdr->ancount);
id = qse_ntoh16(hdr->id);
xid = (id >= DNS_SEQ_RANGE_SIZE)? (id - DNS_SEQ_RANGE_SIZE): id;
xid = xid % QSE_COUNTOF(dc->reqs);
plptr = (qse_uint8_t*)(hdr + 1);
pllen = len - QSE_SIZEOF(*hdr);
/* inspect the question section */
for (i = 0; i < qdcount; i++)
{
qse_size_t reclen;
qse_uint8_t dnlen;
dnlen = dn_length (plptr, pllen);
if (dnlen <= 0) goto done; /* invalid dn name */
reclen = dnlen + QSE_SIZEOF(dns_qdtrail_t);
if (pllen < reclen) goto done;
if (pllen < reclen) goto done; /* weird packet */
if (!req)
{
dns_qdtrail_t* qdtrail = (dns_qdtrail_t*)(plptr + dnlen);
for (preq = QSE_NULL, req = dc->reqs[xid]; req; preq = req, req = req->next)
qdtrail = (dns_qdtrail_t*)(plptr + dnlen);
if (qdtrail->qclass == dc->n_qcin &&
(qdtrail->qtype == dc->n_qta || qdtrail->qtype == dc->n_qtaaaa))
{
if (req->dnlen == dnlen &&
QSE_MEMCMP (req->dn, plptr, req->dnlen) == 0 &&
qdtrail->qclass == qse_hton16(DNS_QCLASS_IN) &&
(qdtrail->qtype == qse_hton16(DNS_QTYPE_A) || qdtrail->qtype == qse_hton16(DNS_QTYPE_AAAA)))
for (req = dc->reqs[xid]; req; req = req->next)
{
/* found a matching request */
if ((id == req->seqa || id == req->seqaaaa) &&
req->dnlen == dnlen && QSE_MEMCMP (req->dn, plptr, req->dnlen) == 0)
{
/* found a match. note that the test here is a bit loose
* in that it doesn't really check if the original question
* was A or AAAA. it is possible that it can process an AAAA answer
* for an A question and vice versa. i don't care if someone
* exploits this and sends a fake response*/
break;
}
}
}
}
plptr += reclen;
pllen -= reclen;
}
if (!req) goto done; /* no matching request for the question */
if (hdr->rcode == DNS_RCODE_NOERROR && ancount > 0)
{
dns_antrail_t* antrail;
qse_uint16_t qtype, anlen;
if (hdr->rcode != DNS_RCODE_NOERROR || ancount <= 0) goto done; /* no good answers */
/* inspect the answer section */
for (i = 0; i < ancount; i++)
{
if (pllen < 1) goto done;
qse_size_t reclen;
qse_uint8_t dnlen;
if (pllen < 1) goto done; /* weird length */
if (*plptr > 63) dnlen = 2;
else
{
dnlen = dn_length (plptr, pllen);
if (dnlen <= 0) goto done; /* invalid dn name */
if (dnlen <= 0) return 0; /* invalid dn name */
}
reclen = dnlen + QSE_SIZEOF(dns_antrail_t);
@ -2599,55 +2642,39 @@ printf ("DNS_RECV....\n");
reclen += qse_ntoh16(antrail->dlen);
if (pllen < reclen) goto done;
qtype = qse_ntoh16(antrail->qtype);
anlen = qse_ntoh16(antrail->dlen);
if (qse_ntoh16(antrail->qclass) == DNS_QCLASS_IN)
if (antrail->qclass == dc->n_qcin)
{
qse_nwad_t nwad;
nwad.type = QSE_NWAD_NX;
if (qtype == DNS_QTYPE_A && anlen == 4)
if (antrail->qtype == dc->n_qta && anlen == 4)
{
QSE_MEMSET (&nwad, 0, QSE_SIZEOF(nwad));
nwad.type = QSE_NWAD_IN4;
QSE_MEMCPY (&nwad.u.in4.addr, antrail + 1, 4);
printf ("invoking resoll with ipv4 \n");
}
else if (qtype == DNS_QTYPE_AAAA && anlen == 16)
else if (antrail->qtype == dc->n_qtaaaa && anlen == 16)
{
QSE_MEMSET (&nwad, 0, QSE_SIZEOF(nwad));
nwad.type = QSE_NWAD_IN6;
QSE_MEMCPY (&nwad.u.in6.addr, antrail + 1, 16);
printf ("invoking resoll with ipv6 \n");
}
if (nwad.type != QSE_NWAD_NX)
{
int ttl;
cache_ttl = httpd_xtn->dns.cache_ttl;
if (cache_ttl > qse_ntoh32(antrail->ttl)) cache_ttl = qse_ntoh32(antrail->ttl);
if (cache_ttl < httpd_xtn->dns.cache_minttl) cache_ttl = httpd_xtn->dns.cache_minttl;
dns_remove_tmr_tmout (req);
req->resol (httpd, req->name, &nwad, req->ctx);
/* detach the request off dc->reqs */
if (preq) preq->next = req->next;
else dc->reqs[xid] = req->next;
/*qse_httpd_freemem (httpd, req);*/
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;
resolved_nwad = &nwad;
goto resolved;
}
}
plptr += reclen;
pllen -= reclen;
}
}
/* no good answer have been found */
if (id == req->seqa) req->flags |= DNS_REQ_A_NX;
@ -2656,24 +2683,35 @@ printf ("invoking resoll with ipv6 \n");
if ((req->flags & (DNS_REQ_A_NX | DNS_REQ_AAAA_NX)) == (DNS_REQ_A_NX | DNS_REQ_AAAA_NX))
{
/* both ipv4 and ipv6 address are unresolvable */
dns_remove_tmr_tmout (req);
req->resol (httpd, req->name, QSE_NULL, req->ctx);
/* detach the request off dc->reqs */
if (preq) preq->next = req->next;
else dc->reqs[xid] = req->next;
/*qse_httpd_freemem (httpd, req);*/
dns_cache_answer (dc, req, QSE_NULL, httpd_xtn->dns.cache_negttl);
}
}
cache_ttl = httpd_xtn->dns.cache_negttl;
resolved_nwad = QSE_NULL;
goto resolved;
}
done:
/* is there anything to do here? */
return 0;
resolved:
QSE_ASSERT (req != QSE_NULL);
QSE_ASSERT (xid >= 0 && xid < QSE_COUNTOF(dc->reqs));
dns_remove_tmr_tmout (req);
req->resol (httpd, req->name, resolved_nwad, req->ctx);
/* detach the request off dc->reqs */
if (req == dc->reqs[xid]) dc->reqs[xid] = req->next;
else req->prev->next = req->next;
if (req->next) req->next->prev = req->prev;
/* cache the negative answer instead of destroying it */
dns_cache_answer (dc, req, resolved_nwad, cache_ttl);
dc->req_count--;
return 0;
}
static void tmr_dns_tmout_updated (qse_tmr_t* tmr, qse_size_t old_index, qse_size_t new_index, void* ctx)
static void tmr_dns_tmout_update (qse_tmr_t* tmr, qse_size_t old_index, qse_size_t new_index, void* ctx)
{
dns_req_t* req = (dns_req_t*)ctx;
@ -2687,34 +2725,36 @@ static void tmr_dns_tmout_handle (qse_tmr_t* tmr, const qse_ntime_t* now, void*
/* destory the unanswered request if timed out */
dns_req_t* req = (dns_req_t*)ctx;
dns_req_t* preq, * xreq;
dns_ctx_t* dc = req->dc;
qse_uint16_t xid;
/* when this handler is called, the event should be removed from the timer */
/* when this handler is called, the event must be removed from the timer */
QSE_ASSERT (req->tmr_tmout == QSE_TMR_INVALID);
/* TODO: resend?? + reschedule?? */
/* ---------------------------------------------------------------
* resend
*---------------------------------------------------------------- */
if (req->resends > 0)
{
httpd_xtn_t* httpd_xtn;
qse_tmr_event_t tmout_event;
httpd_xtn = qse_httpd_getxtn (req->dc->httpd);
httpd_xtn = qse_httpd_getxtn (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;
tmout_event.updater = tmr_dns_tmout_update;
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))
if ((!(req->flags & DNS_REQ_A_NX) && req->qalen > 0 && sendto (dc->dns->handle.i, req->qa, req->qalen, 0, (struct sockaddr*)&dc->skad, dc->skadlen) != req->qalen) ||
(!(req->flags & DNS_REQ_AAAA_NX) && req->qaaaalen > 0 && sendto (dc->dns->handle.i, req->qaaaa, req->qaaaalen, 0, (struct sockaddr*)&dc->skad, dc->skadlen) != req->qaaaalen))
{
/* error. fall thru */
/* resend failed. fall thru and destroy the request*/
}
else
{
req->tmr_tmout = qse_tmr_insert (req->dc->httpd->tmr, &tmout_event);
req->tmr_tmout = qse_tmr_insert (dc->httpd->tmr, &tmout_event);
if (req->tmr_tmout != QSE_TMR_INVALID)
{
req->resends--;
@ -2723,27 +2763,27 @@ static void tmr_dns_tmout_handle (qse_tmr_t* tmr, const qse_ntime_t* now, void*
}
}
printf ("dns timed out....\n");
xid = req->seqa;
QSE_ASSERT (xid >= 0 && QSE_COUNTOF(req->dc->reqs));
/* TODO: doubly linked list??? speed up ??? */
for (preq = QSE_NULL, xreq = req->dc->reqs[xid]; xreq; preq = xreq, xreq = xreq->next)
{
if (req == xreq) break;
}
/* ---------------------------------------------------------------
* dns timed out + no resend
*---------------------------------------------------------------- */
/* this request that timed out must be inside the request list */
QSE_ASSERT (req == xreq);
/* it's safe to use req->seqa to find the hash index
* because seqa is always set regardless of A or AAAA */
xid = req->seqa % QSE_COUNTOF(dc->reqs);
/* detach the request off dc->reqs */
if (preq) preq->next = req->next;
else req->dc->reqs[xid] = req->next;
if (req == dc->reqs[xid]) dc->reqs[xid] = req->next;
else req->prev->next = req->next;
if (req->next) req->next->prev = req->prev;
/* dns timed out. report that name resolution failed */
req->resol (req->dc->httpd, req->name, QSE_NULL, req->ctx);
req->resol (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);
qse_httpd_freemem (dc->httpd, req);
/* decrement the number of pending requests */
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, void* ctx)
@ -2752,6 +2792,7 @@ static int dns_send (qse_httpd_t* httpd, qse_httpd_dns_t* dns, const qse_mchar_t
httpd_xtn_t* httpd_xtn;
qse_uint32_t seq;
qse_uint16_t xid;
dns_req_t* req;
qse_size_t name_len;
dns_ans_t* ans;
@ -2760,6 +2801,7 @@ static int dns_send (qse_httpd_t* httpd, qse_httpd_dns_t* dns, const qse_mchar_t
httpd_xtn = qse_httpd_getxtn (httpd);
printf ("DNS REALLY SENING>>>>>>>>>>>>>>>>>>>>>>>\n");
ans = dns_get_answer_from_cache (dc, name);
if (ans)
{
@ -2767,10 +2809,18 @@ printf ("DNS REALLY SENING>>>>>>>>>>>>>>>>>>>>>>>\n");
return 0;
}
seq = dc->seq;
seq = (seq + 1) % QSE_COUNTOF(dc->reqs);
if (dc->req_count >= QSE_COUNTOF(dc->reqs))
{
/* too many pending requests */
qse_httpd_seterrnum (httpd, QSE_HTTPD_ENOBUF);
return -1;
}
seq = ((qse_uint32_t)dc->seq + 1) % DNS_SEQ_RANGE_SIZE;
dc->seq = seq;
xid = seq % QSE_COUNTOF(dc->reqs);
name_len = qse_mbslen(name);
/* dn is at most as long as the source length + 2.
@ -2779,8 +2829,10 @@ printf ("DNS REALLY SENING>>>>>>>>>>>>>>>>>>>>>>>\n");
req = qse_httpd_callocmem (httpd, QSE_SIZEOF(*req) + (name_len + 1) + (name_len + 2));
if (req == QSE_NULL) return -1;
/* seqa is between 0 and DNS_SEQ_RANGE_SIZE - 1 inclusive.
* seqaaaa is between DNS_SEQ_RANGE_SIZE and DNS_SEQ_RANGE_SIZE * 2 - 1 inclusive. */
req->seqa = seq;
req->seqaaaa = seq + QSE_COUNTOF(dc->reqs); /* this must not go beyond the qse_uint16_t max */
req->seqaaaa = seq + DNS_SEQ_RANGE_SIZE; /* this must not go beyond QSE_TYPE_MAX(qse_uint16_t) */
req->name = (qse_mchar_t*)(req + 1);
req->dn = (qse_uint8_t*)(req->name + name_len + 1);
@ -2816,12 +2868,12 @@ printf ("DNS REALLY SENING>>>>>>>>>>>>>>>>>>>>>>>\n");
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;
tmout_event.updater = tmr_dns_tmout_update;
req->tmr_tmout = qse_tmr_insert (httpd->tmr, &tmout_event);
if (req->tmr_tmout == QSE_TMR_INVALID)
{
qse_httpd_seterrnum (httpd, SKERR_TO_ERRNUM());
qse_httpd_seterrnum (httpd, QSE_HTTPD_ENOMEM);
qse_httpd_freemem (httpd, req);
return -1;
}
@ -2837,14 +2889,443 @@ printf ("DNS REALLY SENING>>>>>>>>>>>>>>>>>>>>>>>\n");
return -1;
}
/* NOTE:
* if the sequence number is repeated before it timed out or resolved,
* the newer request gets chained together with the older one.
* it may not be so easy to determine which request to match an incoming
* response.
*/
req->dc = dc;
req->next = dc->reqs[seq];
dc->reqs[seq] = req;
/* link the request to the front of the chain */
if (dc->reqs[xid]) dc->reqs[xid]->prev = req;
req->next = dc->reqs[xid];
dc->reqs[xid] = req;
/* increment the number of pending requests */
dc->req_count++;
printf ("DNS REALLY SENT>>>>>>>>>>>>>>>>>>>>>>>\n");
return 0;
}
/* ------------------------------------------------------------------- */
#define URS_SEQ_RANGE_SIZE (QSE_TYPE_MAX(qse_uint16_t) - 2)
#define URS_MAX_URL_LEN 50000
typedef struct urs_hdr_t urs_hdr_t;
typedef struct urs_pkt_t urs_pkt_t;
typedef struct urs_ctx_t urs_ctx_t;
typedef struct urs_req_t urs_req_t;
#include <qse/pack1.h>
struct urs_hdr_t
{
qse_uint16_t seq; /* in network-byte order */
qse_uint16_t rcode; /* response code */
qse_uint32_t qusum;/* checksum of url in the request */
qse_uint16_t len; /* url length in network-byte order */
};
struct urs_pkt_t
{
struct urs_hdr_t hdr;
qse_mchar_t url[1];
};
#include <qse/unpack.h>
struct urs_ctx_t
{
qse_httpd_t* httpd;
qse_httpd_urs_t* urs;
qse_skad_t skad;
int skadlen;
qse_uint16_t seq; /* TODO: change to uint32_t??? */
urs_req_t* reqs[1024]; /* TOOD: choose the right size */
qse_uint16_t req_count;
qse_uint8_t rcvbuf[URS_MAX_URL_LEN + QSE_SIZEOF(urs_pkt_t)];
};
struct urs_req_t
{
qse_uint16_t seq; /* in host-byte order */
qse_uint32_t pktlen;
urs_pkt_t* pkt;
qse_httpd_rewrite_t rewrite;
void* ctx;
urs_ctx_t* dc;
qse_size_t tmr_tmout;
int resends;
urs_req_t* prev;
urs_req_t* next;
};
#if 0
int init_urs_query (qse_uint8_t* buf, qse_size_t len, const qse_mchar_t* name, qse_uint16_t seq)
{
urs_hdr_t* hdr;
urs_qdtrail_t* qdtrail;
qse_size_t x;
if (len < QSE_SIZEOF(*hdr)) return -1;
QSE_MEMSET (buf, 0, len);
hdr = (urs_hdr_t*)buf;
hdr->id = qse_hton16(seq);
hdr->opcode = URS_OPCODE_QUERY;
hdr->rd = 1; /* recursion desired*/
hdr->qdcount = qse_hton16(1); /* 1 question */
len -= QSE_SIZEOF(*hdr);
x = to_dn (name, (qse_uint8_t*)(hdr + 1), len);
if (x <= 0) return -1;
len -= x;
if (len < QSE_SIZEOF(*qdtrail)) return -1;
qdtrail = (urs_qdtrail_t*)((qse_uint8_t*)(hdr + 1) + x);
qdtrail->qtype = qse_hton16(qtype);
qdtrail->qclass = qse_hton16(URS_QCLASS_IN);
return QSE_SIZEOF(*hdr) + x + QSE_SIZEOF(*qdtrail);
}
#endif
static int urs_open (qse_httpd_t* httpd, qse_httpd_urs_t* urs)
{
#if defined(__DOS__)
qse_httpd_seterrnum (httpd, QSE_HTTPD_ENOIMPL);
return -1;
#else
sock_t fd = SOCK_INIT;
int flag;
qse_nwad_t nwad;
urs_ctx_t* dc;
httpd_xtn_t* httpd_xtn;
httpd_xtn = qse_httpd_getxtn (httpd);
dc = (urs_ctx_t*) qse_httpd_callocmem (httpd, QSE_SIZEOF(urs_ctx_t));
if (dc == NULL) goto oops;
dc->httpd = httpd;
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)
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 ");
qse_nwadtombs (&nwad, &msg.u.mdbgmsg[pos], QSE_COUNTOF(msg.u.mdbgmsg) - pos, QSE_NWADTOMBS_ALL);
httpd->opt.rcb.logact (httpd, &msg);
}
fd = socket (qse_skadfamily(&dc->skad), SOCK_DGRAM, IPPROTO_UDP);
if (!is_valid_socket(fd))
{
qse_httpd_seterrnum (httpd, SKERR_TO_ERRNUM());
goto oops;
}
/* TODO: set socket send/recv buffer size. it's needed as urs may be long */
#if defined(FD_CLOEXEC)
flag = fcntl (fd, F_GETFD);
if (flag >= 0) fcntl (fd, F_SETFD, flag | FD_CLOEXEC);
#endif
#if defined(SO_REUSEADDR)
flag = 1;
setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, (void*)&flag, QSE_SIZEOF(flag));
#endif
#if defined(SO_REUSEPORT)
flag = 1;
setsockopt (fd, SOL_SOCKET, SO_REUSEPORT, (void*)&flag, QSE_SIZEOF(flag));
#endif
if (set_socket_nonblock (httpd, fd, 1) <= -1) goto oops;
urs->handle.i = fd;
urs->ctx = dc;
return 0;
oops:
if (is_valid_socket(fd)) close_socket (fd);
if (dc) qse_httpd_freemem (httpd, dc);
return -1;
#endif
}
static void urs_remove_tmr_tmout (urs_req_t* req)
{
if (req->tmr_tmout != QSE_TMR_INVALID)
{
qse_tmr_remove (req->dc->httpd->tmr, req->tmr_tmout);
req->tmr_tmout = QSE_TMR_INVALID;
}
}
static void urs_close (qse_httpd_t* httpd, qse_httpd_urs_t* urs)
{
urs_ctx_t* dc = (urs_ctx_t*)urs->ctx;
qse_size_t i;
for (i = 0; i < QSE_COUNTOF(dc->reqs); i++)
{
urs_req_t* next_req;
while (dc->reqs[i])
{
next_req = dc->reqs[i]->next;
urs_remove_tmr_tmout (dc->reqs[i]);
qse_httpd_freemem (httpd, dc->reqs[i]);
dc->reqs[i] = next_req;
dc->req_count--;
}
}
QSE_ASSERT (dc->req_count == 0);
close_socket (urs->handle.i);
qse_httpd_freemem (httpd, urs->ctx);
}
static int urs_recv (qse_httpd_t* httpd, qse_httpd_urs_t* urs)
{
urs_ctx_t* dc = (urs_ctx_t*)urs->ctx;
httpd_xtn_t* httpd_xtn;
qse_skad_t fromaddr;
socklen_t fromlen;
qse_uint16_t xid;
qse_ssize_t len;
urs_pkt_t* pkt;
urs_req_t* req;
printf ("URS_RECV....\n");
httpd_xtn = qse_httpd_getxtn (httpd);
fromlen = QSE_SIZEOF(fromaddr);
len = recvfrom (urs->handle.i, dc->rcvbuf, QSE_SIZEOF(dc->rcvbuf) - 1, 0, (struct sockaddr*)&fromaddr, &fromlen);
/* TODO: check if fromaddr matches the dc->skad... */
pkt = (urs_pkt_t*)dc->rcvbuf;
if (len >= QSE_SIZEOF(pkt->hdr) && len >= QSE_SIZEOF(pkt->hdr) + qse_ntoh16(pkt->hdr.len))
{
xid = qse_ntoh16(pkt->hdr.seq) % QSE_COUNTOF(dc->reqs);
for (req = dc->reqs[xid]; req; req = req->next)
{
if (req->pkt->hdr.seq == pkt->hdr.seq && req->pkt->hdr.qusum == pkt->hdr.qusum)
{
pkt->url[qse_ntoh16(pkt->hdr.len)] = QSE_MT('\0');
urs_remove_tmr_tmout (req);
req->rewrite (httpd, req->pkt->url, pkt->url, req->ctx);
/* detach the request off dc->reqs */
if (req == dc->reqs[xid]) dc->reqs[xid] = req->next;
else req->prev->next = req->next;
if (req->next) req->next->prev = req->prev;
qse_httpd_freemem (httpd, req);
dc->req_count--;
break;
}
}
}
return 0;
}
static void tmr_urs_tmout_updated (qse_tmr_t* tmr, qse_size_t old_index, qse_size_t new_index, void* ctx)
{
urs_req_t* req = (urs_req_t*)ctx;
printf (">>tmr_urs_tmout_updated %d %d\n", (int)req->tmr_tmout, (int)old_index);
QSE_ASSERT (req->tmr_tmout == old_index);
req->tmr_tmout = new_index;
}
static void tmr_urs_tmout_handle (qse_tmr_t* tmr, const qse_ntime_t* now, void* ctx)
{
/* destory the unanswered request if timed out */
urs_req_t* req = (urs_req_t*)ctx;
urs_ctx_t* dc = req->dc;
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);
/* ---------------------------------------------------------------
* resend
*---------------------------------------------------------------- */
if (req->resends > 0)
{
httpd_xtn_t* httpd_xtn;
qse_tmr_event_t tmout_event;
httpd_xtn = qse_httpd_getxtn (dc->httpd);
qse_gettime (&tmout_event.when);
qse_addtime (&tmout_event.when, &httpd_xtn->urs.tmout, &tmout_event.when);
tmout_event.ctx = req;
tmout_event.handler = tmr_urs_tmout_handle;
tmout_event.updater = tmr_urs_tmout_updated;
if (sendto (dc->urs->handle.i, req->pkt, req->pktlen, 0, (struct sockaddr*)&dc->skad, dc->skadlen) != req->pktlen)
{
/* error. fall thru */
}
else
{
req->tmr_tmout = qse_tmr_insert (dc->httpd->tmr, &tmout_event);
if (req->tmr_tmout != QSE_TMR_INVALID)
{
req->resends--;
return; /* resend ok */
}
}
}
printf ("urs timed out....\n");
/* ---------------------------------------------------------------
* timed out + no resend
*---------------------------------------------------------------- */
xid = req->seq % QSE_COUNTOF(dc->reqs);
/* detach the request off dc->reqs */
if (req == dc->reqs[xid]) dc->reqs[xid] = req->next;
else req->prev->next = req->next;
if (req->next) req->next->prev = req->prev;
/* urs timed out. report that name resolution failed */
req->rewrite (dc->httpd, req->pkt->url, QSE_NULL, req->ctx);
/* i don't cache the items that have timed out */
qse_httpd_freemem (dc->httpd, req);
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, void* ctx)
{
urs_ctx_t* dc = (urs_ctx_t*)urs->ctx;
httpd_xtn_t* httpd_xtn;
qse_uint16_t xid;
qse_uint32_t seq;
urs_req_t* req;
qse_size_t url_len;
qse_tmr_event_t tmout_event;
httpd_xtn = qse_httpd_getxtn (httpd);
printf ("URS REALLY SENING>>>>>>>>>>>>>>>>>>>>>>>\n");
if (dc->req_count >= QSE_COUNTOF(dc->reqs))
{
/* too many pending requests */
qse_httpd_seterrnum (httpd, QSE_HTTPD_ENOBUF);
return -1;
}
url_len = qse_mbslen(url);
if (url_len > URS_MAX_URL_LEN) /* TODO: change the limit */
{
qse_httpd_seterrnum (httpd, QSE_HTTPD_EINVAL);
return -1;
}
seq = ((qse_uint32_t)dc->seq + 1) % URS_SEQ_RANGE_SIZE;
dc->seq = seq;
xid = seq % QSE_COUNTOF(dc->reqs);
req = qse_httpd_callocmem (httpd, QSE_SIZEOF(*req) + url_len + QSE_SIZEOF(urs_pkt_t));
if (req == QSE_NULL) return -1;
req->seq = seq;
req->pkt = (urs_pkt_t*)(req + 1);
req->pkt->hdr.seq = qse_hton16(seq);
req->pkt->hdr.len = qse_hton16(url_len);
req->pkt->hdr.qusum = hash_string (url);
qse_mbscpy (req->pkt->url, url);
req->pktlen = QSE_SIZEOF(urs_pkt_t) + url_len - 1; /* to exclude the terminating '\0' */
req->rewrite = rewrite;
req->ctx = ctx;
qse_gettime (&tmout_event.when);
qse_addtime (&tmout_event.when, &httpd_xtn->urs.tmout, &tmout_event.when);
tmout_event.ctx = req;
tmout_event.handler = tmr_urs_tmout_handle;
tmout_event.updater = tmr_urs_tmout_updated;
req->tmr_tmout = qse_tmr_insert (httpd->tmr, &tmout_event);
if (req->tmr_tmout == QSE_TMR_INVALID)
{
qse_httpd_seterrnum (httpd, QSE_HTTPD_ENOMEM);
qse_httpd_freemem (httpd, req);
return -1;
}
req->resends = httpd_xtn->urs.resends;
if (sendto (urs->handle.i, req->pkt, req->pktlen, 0, (struct sockaddr*)&dc->skad, dc->skadlen) != req->pktlen)
{
qse_tmr_remove (httpd->tmr, req->tmr_tmout);
req->tmr_tmout = QSE_TMR_INVALID;
qse_httpd_seterrnum (httpd, SKERR_TO_ERRNUM());
qse_httpd_freemem (httpd, req);
return -1;
}
req->dc = dc;
/* link the request to the front of the chain */
if (dc->reqs[xid]) dc->reqs[xid]->prev = req;
req->next = dc->reqs[xid];
dc->reqs[xid] = req;
/* increment the number of pending requests */
dc->req_count++;
printf ("URS REALLY SENT>>>>>>>>>>>>>>>>>>>>>>>\n");
return 0;
}
/* ------------------------------------------------------------------- */
#if 0
static qse_htb_walk_t walk (qse_htb_t* htb, qse_htb_pair_t* pair, void* ctx)
@ -3164,7 +3645,13 @@ static qse_httpd_scb_t httpd_system_callbacks =
{ dns_open,
dns_close,
dns_recv,
dns_send }
dns_send },
/* urs */
{ urs_open,
urs_close,
urs_recv,
urs_send }
};
static qse_httpd_rcb_t httpd_request_callbacks =

View File

@ -382,7 +382,7 @@ static qse_htrd_recbs_t htrd_recbs =
};
/* ----------------------------------------------------------------------- */
static void tmr_idle_updated (qse_tmr_t* tmr, qse_size_t old_index, qse_size_t new_index, void* ctx);
static void tmr_idle_update (qse_tmr_t* tmr, qse_size_t old_index, qse_size_t new_index, void* ctx);
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)
@ -420,7 +420,7 @@ static qse_httpd_client_t* new_client (qse_httpd_t* httpd, qse_httpd_client_t* t
qse_addtime (&idle_event.when, &httpd->opt.idle_limit, &idle_event.when);
idle_event.ctx = client;
idle_event.handler = tmr_idle_handle;
idle_event.updater = tmr_idle_updated;
idle_event.updater = tmr_idle_update;
client->tmr_idle = qse_tmr_insert (httpd->tmr, &idle_event);
if (client->tmr_idle == QSE_TMR_INVALID)
@ -618,7 +618,7 @@ printf ("MUX ADDHND CLIENT READ %d\n", client->handle.i);
}
static void tmr_idle_updated (qse_tmr_t* tmr, qse_size_t old_index, qse_size_t new_index, void* ctx)
static void tmr_idle_update (qse_tmr_t* tmr, qse_size_t old_index, qse_size_t new_index, void* ctx)
{
qse_httpd_client_t* client = (qse_httpd_client_t*)ctx;
printf ("tmr_idle updated old_index %d new_index %d tmr_idle %d\n", (int)old_index, (int)new_index, (int)client->tmr_idle);
@ -650,7 +650,7 @@ printf ("client is idle purging....\n");
qse_addtime (&idle_event.when, &client->server->httpd->opt.idle_limit, &idle_event.when);
idle_event.ctx = client;
idle_event.handler = tmr_idle_handle;
idle_event.updater = tmr_idle_updated;
idle_event.updater = tmr_idle_update;
/* the timer must have been deleted when this callback is called. */
QSE_ASSERT (client->tmr_idle == QSE_TMR_INVALID);
@ -833,6 +833,29 @@ static void deactivate_dns (qse_httpd_t* httpd)
httpd->opt.scb.mux.delhnd (httpd, httpd->mux, httpd->dns.handle);
httpd->opt.scb.dns.close (httpd, &httpd->dns);
}
/* ----------------------------------------------------------------------- */
static int activate_urs (qse_httpd_t* httpd)
{
/* TODO: how to disable URS??? */
if (httpd->opt.scb.urs.open (httpd, &httpd->urs) <= -1) return -1;
httpd->urs.type = QSE_HTTPD_URS;
if (httpd->opt.scb.mux.addhnd (httpd, httpd->mux, httpd->urs.handle, QSE_HTTPD_MUX_READ, &httpd->urs) <= -1)
{
httpd->opt.scb.urs.close (httpd, &httpd->urs);
return -1;
}
return 0;
}
static void deactivate_urs (qse_httpd_t* httpd)
{
httpd->opt.scb.mux.delhnd (httpd, httpd->mux, httpd->urs.handle);
httpd->opt.scb.urs.close (httpd, &httpd->urs);
}
/* ----------------------------------------------------------------------- */
@ -1384,6 +1407,16 @@ static int perform_dns (qse_httpd_t* httpd, void* mux, qse_ubi_t handle, int mas
return httpd->opt.scb.dns.recv (httpd, dns);
}
static int perform_urs (qse_httpd_t* httpd, void* mux, qse_ubi_t handle, int mask, void* cbarg)
{
qse_httpd_urs_t* urs = (qse_httpd_urs_t*)cbarg;
QSE_ASSERT (mask & QSE_HTTPD_MUX_READ);
QSE_ASSERT (&httpd->urs == urs);
return httpd->opt.scb.urs.recv (httpd, urs);
}
static void purge_bad_clients (qse_httpd_t* httpd)
{
qse_httpd_client_t* client;
@ -1450,6 +1483,9 @@ static int dispatch_mux (
case QSE_HTTPD_DNS:
return perform_dns (httpd, mux, handle, mask, cbarg);
case QSE_HTTPD_URS:
return perform_urs (httpd, mux, handle, mask, cbarg);
}
httpd->errnum = QSE_HTTPD_EINTERN;
@ -1501,6 +1537,18 @@ int qse_httpd_loop (qse_httpd_t* httpd)
}
else httpd->dnsactive = 1;
if (activate_urs (httpd) <= -1)
{
if (httpd->opt.trait & QSE_HTTPD_LOGACT)
{
qse_httpd_act_t msg;
msg.code = QSE_HTTPD_CATCH_MWARNMSG;
qse_mbscpy (msg.u.mwarnmsg, QSE_MT("cannot activate urs"));
httpd->opt.rcb.logact (httpd, &msg);
}
}
else httpd->ursactive = 1;
if (activate_servers (httpd) <= -1)
{
if (httpd->dnsactive) deactivate_dns (httpd);
@ -1544,6 +1592,7 @@ int qse_httpd_loop (qse_httpd_t* httpd)
purge_client_list (httpd);
deactivate_servers (httpd);
if (httpd->ursactive) deactivate_urs (httpd);
if (httpd->dnsactive) deactivate_dns (httpd);
httpd->opt.scb.mux.close (httpd, httpd->mux);
@ -1684,7 +1733,7 @@ printf ("DNS_SEND.........................\n");
#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);
return httpd->opt.scb.urs.send (httpd, &httpd->dns, name, resol, ctx);
}
#endif

View File

@ -27,7 +27,7 @@
#define QSE_HTTPD_DEFAULT_PORT 80
#define QSE_HTTPD_DEFAULT_SECURE_PORT 443
#define QSE_HTTPD_DEFAULT_DNS_PORT 53
struct qse_httpd_t
{
qse_mmgr_t* mmgr;
@ -47,6 +47,7 @@ struct qse_httpd_t
int stopreq: 1;
int impedereq: 1;
int dnsactive: 1;
int ursactive: 1;
qse_mchar_t sname[128]; /* server name for the server header */
qse_mchar_t gtbuf[10][64]; /* GMT time buffers */
@ -81,6 +82,7 @@ struct qse_httpd_t
void* mux;
qse_httpd_dns_t dns;
qse_httpd_urs_t urs;
};
/* qse_httpd_real_task_t is a private type to hide some private fields