From 88aaa1532affad73b01a587158fba9b3a9b093a9 Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Thu, 17 Jul 2014 16:11:02 +0000 Subject: [PATCH] added some dns code --- qse/cmd/http/httpd.c | 8 +- qse/include/qse/http/httpd.h | 2 + qse/lib/http/httpd-file.c | 2 - qse/lib/http/httpd-std.c | 270 ++++++++++++++++++++++++++++++++++- qse/lib/http/httpd.c | 76 ++++++++-- qse/lib/http/httpd.h | 2 +- 6 files changed, 345 insertions(+), 15 deletions(-) diff --git a/qse/cmd/http/httpd.c b/qse/cmd/http/httpd.c index 60eb48f9..71a11df3 100644 --- a/qse/cmd/http/httpd.c +++ b/qse/cmd/http/httpd.c @@ -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; diff --git a/qse/include/qse/http/httpd.h b/qse/include/qse/http/httpd.h index f8a2bcba..87397305 100644 --- a/qse/include/qse/http/httpd.h +++ b/qse/include/qse/http/httpd.h @@ -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; }; diff --git a/qse/lib/http/httpd-file.c b/qse/lib/http/httpd-file.c index 1a665438..1dd7ba1b 100644 --- a/qse/lib/http/httpd-file.c +++ b/qse/lib/http/httpd-file.c @@ -638,7 +638,5 @@ qse_httpd_task_t* qse_httpd_entaskfile ( qse_htre_discardcontent (req); return qse_httpd_entaskerr (httpd, client, pred, 405, req); } - - } diff --git a/qse/lib/http/httpd-std.c b/qse/lib/http/httpd-std.c index 2df4fc99..35b4307f 100644 --- a/qse/lib/http/httpd-std.c +++ b/qse/lib/http/httpd-std.c @@ -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 +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 + + +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; } diff --git a/qse/lib/http/httpd.c b/qse/lib/http/httpd.c index 3f996fff..a4dd5f93 100644 --- a/qse/lib/http/httpd.c +++ b/qse/lib/http/httpd.c @@ -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;*/ } diff --git a/qse/lib/http/httpd.h b/qse/lib/http/httpd.h index 575c0864..2f69966a 100644 --- a/qse/lib/http/httpd.h +++ b/qse/lib/http/httpd.h @@ -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 */