added some dns code

This commit is contained in:
hyung-hwan 2014-07-17 16:11:02 +00:00
parent 4e0e403a73
commit 88aaa1532a
6 changed files with 345 additions and 15 deletions

View File

@ -1431,8 +1431,8 @@ static int open_config_file (qse_httpd_t* httpd)
{ QSE_T("server.ssl"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } },
{ QSE_T("server.ssl-cert-file"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } },
{ QSE_T("server.ssl-key-file"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } },
{ QSE_T("server.host"), { QSE_XLI_SCM_VALLIST | QSE_XLI_SCM_KEYALIAS, 0, 0 } },
{ QSE_T("server.host.location"), { QSE_XLI_SCM_VALLIST | QSE_XLI_SCM_KEYALIAS, 0, 0 } },
{ QSE_T("server.host"), { QSE_XLI_SCM_VALLIST | QSE_XLI_SCM_KEYALIAS, 0, 0 } },
{ QSE_T("server.host.location"), { QSE_XLI_SCM_VALLIST | QSE_XLI_SCM_KEYALIAS, 0, 0 } },
{ QSE_T("server.host.location.root"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 0, 1 } },
{ QSE_T("server.host.location.realm"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 0, 1 } },
{ QSE_T("server.host.location.auth"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } },
@ -1718,6 +1718,10 @@ static void logact_httpd (qse_httpd_t* httpd, const qse_httpd_act_t* act)
qse_printf (QSE_T("ERROR: %hs\n"), act->u.merrmsg);
break;
case QSE_HTTPD_CATCH_MWARNMSG:
qse_printf (QSE_T("WARNING: %hs\n"), act->u.mwarnmsg);
break;
case QSE_HTTPD_CATCH_MDBGMSG:
qse_printf (QSE_T("DEBUG: %hs\n"), act->u.mdbgmsg);
break;

View File

@ -281,6 +281,7 @@ typedef void (*qse_httpd_impede_t) (
enum qse_httpd_act_code_t
{
QSE_HTTPD_CATCH_MERRMSG,
QSE_HTTPD_CATCH_MWARNMSG,
QSE_HTTPD_CATCH_MDBGMSG,
QSE_HTTPD_ACCEPT_CLIENT,
QSE_HTTPD_PURGE_CLIENT,
@ -295,6 +296,7 @@ struct qse_httpd_act_t
{
qse_httpd_client_t* client;
qse_mchar_t merrmsg[128];
qse_mchar_t mwarnmsg[128];
qse_mchar_t mdbgmsg[128];
} u;
};

View File

@ -638,7 +638,5 @@ qse_httpd_task_t* qse_httpd_entaskfile (
qse_htre_discardcontent (req);
return qse_httpd_entaskerr (httpd, client, pred, 405, req);
}
}

View File

@ -673,7 +673,7 @@ static int server_open (qse_httpd_t* httpd, qse_httpd_server_t* server)
#endif
#if defined(SO_REUSEPORT)
flag = 1;
flag = 1;
setsockopt (fd, SOL_SOCKET, SO_REUSEPORT, (void*)&flag, QSE_SIZEOF(flag));
#endif
@ -1962,22 +1962,290 @@ static void client_closed (qse_httpd_t* httpd, qse_httpd_client_t* client)
/* ------------------------------------------------------------------- */
typedef struct dns_ctx_t dns_ctx_t;
typedef struct dns_req_t dns_req_t;
typedef struct dns_hdr_t dns_hdr_t;
typedef struct dns_qtrail_t dns_qtrail_t;
struct dns_ctx_t
{
qse_skad_t skad;
int skadlen;
qse_uint16_t seq;
dns_req_t* reqs[1024]; /* TOOD: choose the right size */
};
struct dns_req_t
{
qse_mchar_t* name;
qse_httpd_resol_t resol;
void* ctx;
dns_req_t* next;
};
enum
{
DNS_OPCODE_QUERY = 0,
DNS_OPCODE_IQUERY = 1,
DNS_OPCODE_STATUS = 2,
DNS_OPCODE_NOTIFY = 4,
DNS_OPCODE_UPDATE = 5,
DNS_RCODE_NOERROR = 0,
DNS_RCODE_FORMERR = 1,
DNS_RCODE_SERVFAIL = 2,
DNS_RCODE_NXDOMAIN = 3,
DNS_RCODE_NOTIMPL = 4,
DNS_RCODE_REFUSED = 5,
DNS_QTYPE_A = 1,
DNS_QTYPE_NS = 2,
DNS_QTYPE_CNAME = 5,
DNS_QTYPE_SOA = 6,
DNS_QTYPE_PTR = 12,
DNS_QTYPE_MX = 15,
DNS_QTYPE_TXT = 16,
DNS_QTYPE_AAAA = 28,
DNS_QTYPE_OPT = 41,
DNS_QTYPE_ANY = 255,
DNS_QCLASS_IN = 1, /* internet */
DNS_QCLASS_CH = 3, /* chaos */
DNS_QCLASS_HS = 4, /* hesiod */
DNS_QCLASS_NONE = 254,
DNS_QCLASS_ANY = 255
};
#include <qse/pack1.h>
struct dns_hdr_t
{
qse_uint16_t id;
#if defined(QSE_ENDIAN_BIG)
qse_uint16_t qr: 1; /* question or response */
qse_uint16_t opcode: 4;
qse_uint16_t aa: 1; /* authoritative answer */
qse_uint16_t tc: 1; /* truncated message */
qse_uint16_t rd: 1; /* recursion desired */
qse_uint16_t ra: 1; /* recursion available */
qse_uint16_t z: 1;
qse_uint16_t ad: 1;
qse_uint16_t cd: 1;
qse_uint16_t rcode: 4;
#else
qse_uint16_t rd: 1;
qse_uint16_t tc: 1;
qse_uint16_t aa: 1;
qse_uint16_t opcode: 4;
qse_uint16_t qr: 1;
qse_uint16_t rocde: 4;
qse_uint16_t cd: 1;
qse_uint16_t ad: 1;
qse_uint16_t z: 1;
qse_uint16_t ra: 1;
#endif
qse_uint16_t qdcount; /* questions */
qse_uint16_t ancount; /* answers */
qse_uint16_t nscount; /* name servers */
qse_uint16_t arcount; /* additional resource */
};
struct dns_qtrail_t
{
qse_uint16_t qtype;
qse_uint16_t qclass;
};
#include <qse/unpack.h>
static qse_size_t to_dn (const qse_mchar_t* str, qse_uint8_t* buf, qse_size_t bufsz)
{
qse_uint8_t* bp = buf, * be = buf + bufsz;
//QSE_ASSERT (QSE_SIZEOF(qse_uint8_t) == QSE_SIZEOF(qse_mchar_t));
if (*str != QSE_MT('\0'))
{
const qse_mchar_t* ep = str;
do
{
qse_uint8_t* lp;
if (bp < be) lp = bp++;
else lp = QSE_NULL;
str = ep;
while (*ep != QSE_MT('\0') && *ep != QSE_MT('.'))
{
if (bp < be) *bp++ = *ep;
ep++;
}
if (ep - str > 63) return 0;
if (lp) *lp = (qse_uint8_t)(ep - str);
if (*ep == QSE_MT('\0')) break;
ep++;
}
while (1);
}
if (bp < be) *bp++ = 0;
return bp - buf;
}
int init_dns_query (qse_uint8_t* buf, qse_size_t len, const qse_mchar_t* name, int qtype, qse_uint16_t seq)
{
dns_hdr_t* hdr;
dns_qtrail_t* qtrail;
qse_size_t x;
if (len < QSE_SIZEOF(*hdr)) return -1;
QSE_MEMSET (buf, 0, len);
hdr = (dns_hdr_t*)buf;
hdr->id = qse_hton16(seq);
hdr->opcode = DNS_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(*qtrail)) return -1;
qtrail = (dns_qtrail_t*)((qse_uint8_t*)(hdr + 1) + x);
qtrail->qtype = qse_hton16(qtype);
qtrail->qclass = qse_hton16(DNS_QCLASS_IN);
return QSE_SIZEOF(*hdr) + x + QSE_SIZEOF(*qtrail);
}
static int dns_open (qse_httpd_t* httpd, qse_httpd_dns_t* dns)
{
#if defined(__DOS__)
qse_httpd_seterrnum (httpd, QSE_HTTPD_ENOIMPL);
return -1;
#else
int fd = -1, flag;
qse_nwad_t nwad;
dns_ctx_t* dc;
dc = (dns_ctx_t*) qse_httpd_callocmem (httpd, QSE_SIZEOF(dns_ctx_t));
if (dc == NULL) goto oops;
/* TODO: get this from configuration??? or /etc/resolv.conf */
if (qse_mbstonwad ("8.8.8.8:53", &nwad) <= -1)
{
qse_httpd_seterrnum (httpd, QSE_HTTPD_EINVAL);
goto oops;
}
dc->skadlen = qse_nwadtoskad (&nwad, &dc->skad);
if (dc->skadlen <= -1)
{
qse_httpd_seterrnum (httpd, QSE_HTTPD_ENOIMPL);
return -1;
}
fd = socket (qse_skadfamily(&dc->skad), SOCK_DGRAM, IPPROTO_UDP);
if (fd <= -1) goto oops;
#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
dns->handle.i = fd;
dns->ctx = dc;
return 0;
oops:
if (fd >= 0)
{
#if defined(_WIN32)
closesocket (fd);
#elif defined(__OS2__)
soclose (fd);
#else
QSE_CLOSE (fd);
#endif
}
if (dc) qse_httpd_freemem (httpd, dc);
return -1;
#endif
}
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
qse_httpd_freemem (httpd, dns->ctx);
}
static int dns_recv (qse_httpd_t* httpd, qse_httpd_dns_t* dns)
{
dns_ctx_t* dc = (dns_ctx_t*)dns->ctx;
qse_skad_t fromaddr;
socklen_t fromlen; /* TODO: change type */
qse_uint8_t buf[384];
printf ("RECV....\n");
fromlen = QSE_SIZEOF(fromaddr);
recvfrom (dns->handle.i, buf, QSE_SIZEOF(buf), 0, &fromaddr, &fromlen);
return 0;
}
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)
{
qse_uint32_t seq;
dns_ctx_t* dc = (dns_ctx_t*)dns->ctx;
qse_uint8_t buf_a[384], buf_aaaa[384];
int buf_a_len, buf_aaaa_len;
seq = dc->seq;
seq = (seq + 1) % QSE_COUNTOF(dc->reqs);
dc->seq = seq;
buf_a_len = init_dns_query (buf_a, QSE_SIZEOF(buf_a), name, DNS_QTYPE_A, seq);
buf_aaaa_len = init_dns_query (buf_aaaa, QSE_SIZEOF(buf_aaaa), name, DNS_QTYPE_AAAA, seq);
if (buf_a_len <= -1 || buf_aaaa_len <= -1)
{
qse_httpd_seterrnum (httpd, QSE_HTTPD_EINVAL);
return -1;
}
printf ("SENDING......\n");
sendto (dns->handle.i, buf_a, buf_a_len, 0, (struct sockaddr*)&dc->skad, dc->skadlen);
sendto (dns->handle.i, buf_aaaa, buf_aaaa_len, 0, (struct sockaddr*)&dc->skad, dc->skadlen);
return 0;
}

View File

@ -920,7 +920,7 @@ static int update_mux_for_current_task (qse_httpd_t* httpd, qse_httpd_client_t*
for (i = 0; i < QSE_COUNTOF(task->trigger.v); i++)
{
task->trigger.v[i].mask &= ~(QSE_HTTPD_TASK_TRIGGER_READABLE |
QSE_HTTPD_TASK_TRIGGER_WRITABLE);
QSE_HTTPD_TASK_TRIGGER_WRITABLE);
}
if (QSE_MEMCMP (&client->trigger, &task->trigger, QSE_SIZEOF(client->trigger)) != 0 ||
@ -933,6 +933,52 @@ static int update_mux_for_current_task (qse_httpd_t* httpd, qse_httpd_client_t*
int expected_client_handle_mux_mask;
int expected_client_handle_mux_status;
if ((client->trigger.flags & QSE_HTTPD_TASK_TRIGGER_INACTIVE) !=
(task->trigger.flags & QSE_HTTPD_TASK_TRIGGER_INACTIVE))
{
if (task->trigger.flags & QSE_HTTPD_TASK_TRIGGER_INACTIVE)
{
/* active to inactive */
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))
{
httpd->opt.scb.mux.delhnd (httpd, httpd->mux, client->trigger.v[i].handle);
client->status &= ~CLIENT_TASK_TRIGGER_RW_IN_MUX(i);
}
}
if (client->status & CLIENT_HANDLE_RW_IN_MUX)
{
httpd->opt.scb.mux.delhnd (httpd, httpd->mux, client->handle);
client->status &= ~CLIENT_HANDLE_RW_IN_MUX;
}
/* save the task trigger information */
client->trigger = task->trigger;
return 0;
}
printf ("INACTIVE TO ACTIVE....\n");
/* inactive to active . go on*/
}
else
{
if (task->trigger.flags & QSE_HTTPD_TASK_TRIGGER_INACTIVE)
{
printf ("INACTIVE TO INACTIVE....\n");
/* inactive to inactive.
* save the trigger as the trigger handle and masks could change */
client->trigger = task->trigger;
return 0;
}
printf ("ACTIVE TO ACTIVE....\n");
/* active to active. go on */
}
/* delete previous trigger handles */
for (i = 0; i < QSE_COUNTOF(task->trigger.v); i++)
{
@ -1391,6 +1437,7 @@ int qse_httpd_loop (qse_httpd_t* httpd)
httpd->stopreq = 0;
httpd->impedereq = 0;
httpd->dnsactive = 0;
/* system callbacks and request callbacks must be set before the call to this function */
QSE_ASSERT (httpd->opt.scb.mux.open && httpd->opt.scb.mux.close && httpd->opt.scb.mux.poll);
@ -1404,19 +1451,26 @@ int qse_httpd_loop (qse_httpd_t* httpd)
if (activate_dns (httpd) <= -1)
{
httpd->opt.scb.mux.close (httpd, httpd->mux);
return -1;
if (httpd->opt.trait & QSE_HTTPD_LOGACT)
{
qse_httpd_act_t msg;
qse_size_t len;
msg.code = QSE_HTTPD_CATCH_MWARNMSG;
qse_mbscpy (msg.u.mwarnmsg, QSE_MT("cannot activate dns"));
httpd->opt.rcb.logact (httpd, &msg);
}
}
else httpd->dnsactive = 1;
if (activate_servers (httpd) <= -1)
{
deactivate_dns (httpd);
if (httpd->dnsactive) deactivate_dns (httpd);
httpd->opt.scb.mux.close (httpd, httpd->mux);
return -1;
}
if (httpd->server.nactive <= 0)
{
deactivate_dns (httpd);
if (httpd->dnsactive) deactivate_dns (httpd);
httpd->opt.scb.mux.close (httpd, httpd->mux);
httpd->errnum = QSE_HTTPD_ENOSVR;
@ -1451,7 +1505,9 @@ int qse_httpd_loop (qse_httpd_t* httpd)
purge_client_list (httpd);
deactivate_servers (httpd);
deactivate_dns (httpd);
if (httpd->dnsactive) deactivate_dns (httpd);
httpd->opt.scb.mux.close (httpd, httpd->mux);
return xret;
}
@ -1575,7 +1631,9 @@ int qse_httpd_resolname (qse_httpd_t* httpd, const qse_mchar_t* name, qse_httpd_
/* TODO: find the name in cache */
/* not found in the cache */
httpd->opt.scb.dns.send (httpd, &httpd->dns, name, resol, ctx);
resol (httpd, QSE_NULL, ctx);
return 0;
printf ("dns_send.........................\n");
return httpd->opt.scb.dns.send (httpd, &httpd->dns, name, resol, ctx);
/* resol (httpd, QSE_NULL, ctx);
return 0;*/
}

View File

@ -31,7 +31,6 @@ struct qse_httpd_t
qse_httpd_errnum_t errnum;
qse_httpd_ecb_t* ecb; /* event callbacks */
struct
{
int trait;
@ -43,6 +42,7 @@ struct qse_httpd_t
int stopreq: 1;
int impedereq: 1;
int dnsactive: 1;
qse_mchar_t sname[128]; /* server name for the server header */
qse_mchar_t gtbuf[10][64]; /* GMT time buffers */