⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dnsrv.c

📁 AnyQ服务端源代码(2004/10/28)源码
💻 C
📖 第 1 页 / 共 2 页
字号:
    req = xmlnode_new_tag_pool(p->p,"host");    xmlnode_insert_cdata(req,p->host,-1);    reqs = xmlnode2str(req);    log_debug(ZONE, "dnsrv: Transmitting lookup request: %s", reqs);    pth_write(d->out, reqs, strlen(reqs));}result dnsrv_deliver(instance i, dpacket p, void* args){     dns_io di = (dns_io)args;     xmlnode c;     int timeout = di->cache_timeout;     char *ip;     jid to;     /* if we get a route packet, it has to be to *us* and have the child as the real packet */     if(p->type == p_ROUTE)     {        if(j_strcmp(p->host,i->id) != 0 || (to = jid_new(p->p,xmlnode_get_attrib(xmlnode_get_firstchild(p->x),"to"))) == NULL)            return r_ERR;        p->x=xmlnode_get_firstchild(p->x);        p->id = to;        p->host = to->server;     }     /* Ensure this packet doesn't already have an IP */     if(xmlnode_get_attrib(p->x, "ip") || xmlnode_get_attrib(p->x, "iperror"))     {        log_notice(p->host, "dropping looping dns lookup request: %s", xmlnode2str(p->x));        xmlnode_free(p->x);        return r_DONE;     }     /* try the cache first */     if((c = ghash_get(di->cache_table, p->host)) != NULL)     {         /* if there's no IP, cached failed lookup, time those out 10 times faster! (weird, I know, *shrug*) */         if((ip = xmlnode_get_attrib(c,"ip")) == NULL)            timeout = timeout / 10;         if((time(NULL) - (int)xmlnode_get_vattrib(c,"t")) > timeout)         { /* timed out of the cache, lookup again */             xmlnode_free(c);             ghash_remove(di->cache_table,p->host);         }else{             /* yay, send back right from the cache */             dnsrv_resend(p->x, ip, xmlnode_get_attrib(c,"to"));             return r_DONE;         }     }    dnsrv_lookup(di, p);    return r_DONE;}void dnsrv_process_xstream_io(int type, xmlnode x, void* arg){     dns_io di            = (dns_io)arg;     char* hostname       = NULL;     char* ipaddr         = NULL;     char* resendhost     = NULL;     dns_packet_list head = NULL;     dns_packet_list heado = NULL;     /* Node Format: <host ip="201.83.28.2">foo.org</host> */     if (type == XSTREAM_NODE)     {              log_debug(ZONE,"incoming resolution: %s",xmlnode2str(x));          hostname = xmlnode_get_data(x);          /* whatever the response was, let's cache it */          xmlnode_free((xmlnode)ghash_get(di->cache_table,hostname)); /* free any old cache, shouldn't ever be any */          xmlnode_put_vattrib(x,"t",(void*)time(NULL));          ghash_put(di->cache_table,hostname,(void*)x);          /* Get the hostname and look it up in the hashtable */          head = ghash_get(di->packet_table, hostname);          /* Process the packet list */          if (head != NULL)          {               ipaddr = xmlnode_get_attrib(x, "ip");               resendhost = xmlnode_get_attrib(x, "to");               /* Remove the list from the hashtable */               ghash_remove(di->packet_table, hostname);                              /* Walk the list and insert IPs */               while(head != NULL)               {                    heado = head;                    /* Move to next.. */                    head = head->next;                    /* Deliver the packet */                    dnsrv_resend(heado->packet->x, ipaddr, resendhost);               }          }          /* Host name was not found, something is _TERRIBLY_ wrong! */          else               log_debug(ZONE, "Resolved unknown host/ip request: %s\n", xmlnode2str(x));          return; /* we cached x above, so we don't free it below :) */     }     xmlnode_free(x);} void* dnsrv_process_io(void* threadarg){     /* Get DNS IO info */     dns_io di = (dns_io)threadarg;     int  retcode       = 0;     int  pid           = 0;     int  readlen       = 0;     char readbuf[1024];     xstream  xs       = NULL;            sigset_t sigs;     #ifdef __CYGWIN__     dns_resend_list iternode = NULL;     #endif     sigemptyset(&sigs);     sigaddset(&sigs, SIGHUP);     sigprocmask(SIG_BLOCK, &sigs, NULL);     /* Allocate an xstream for talking to the process */     xs = xstream_new(di->mempool, dnsrv_process_xstream_io, di);     /* Transmit root element to coprocess */     pth_write(di->out, "<stream>", 8);     /* Transmit resend entries to coprocess */     #ifdef __CYGWIN__     iternode = di->svclist;     while (iternode != NULL) {       if (iternode->service) {         sprintf(readbuf, "<resend service=\"%s\">%s</resend>",                 iternode->service, iternode->host);       } else {         sprintf(readbuf, "<resend>%s</resend>",                 iternode->host);       }       pth_write(di->out, readbuf, strlen(readbuf));       iternode = iternode->next;     }     #endif     /* Loop forever */     while (1)     {       /* Hostname lookup completed from coprocess */       readlen = pth_read(di->in, readbuf, sizeof(readbuf));       if (readlen <= 0)       {           log_debug(ZONE,"dnsrv: Read error on coprocess: %d %s",errno,strerror(errno));           break;       }       if (xstream_eat(xs, readbuf, readlen) > XSTREAM_NODE)           break;     }     /* If we reached this point, the coprocess probably is dead, so         process the SIG_CHLD */     pid = pth_waitpid(di->pid, &retcode, 0);     if(pid == -1)     {        log_debug(ZONE, "pth_waitpid returned -1: %s", strerror(errno));     }     else if(pid == 0)     {        log_debug(ZONE, "no child available to call waitpid on");     }     else     {        log_debug(ZONE, "pid %d, exit status: %d", pid, WEXITSTATUS(retcode));     }     /* Cleanup */     close(di->in);     close(di->out);     di->out = 0;     log_debug(ZONE,"child returned %d",WEXITSTATUS(retcode));     if(WIFEXITED(retcode)) /* if the child exited normally */     {        log_debug(ZONE, "child being restarted...");        /* Fork out resolver function/process */        di->pid = dnsrv_fork_and_capture(dnsrv_child_main, di);        /* Start IO thread */        pth_spawn(PTH_ATTR_DEFAULT, dnsrv_process_io, (void*)di);        return NULL;     }     log_debug(ZONE, "child dying...");     return NULL;}void *dnsrv_thread(void *arg){     dns_io di=(dns_io)arg;     /* Fork out resolver function/process */     di->pid = dnsrv_fork_and_capture(dnsrv_child_main, di);     return NULL;}void dnsrv_shutdown(void *arg){     dns_io di=(dns_io)arg;     ghash_destroy(di->packet_table);     /* spawn a thread that get's forked, and wait for it since it sets up the fd's */}/* callback for walking the connecting hash tree */int _dnsrv_beat_packets(void *arg, const void *key, void *data){    dns_io di = (dns_io)arg;    dns_packet_list n, l = (dns_packet_list)data;    int now = time(NULL);    int reap = 0;    /* first, check the head */    if((now - l->stamp) > di->packet_timeout)    {        log_notice(l->packet->host,"timed out from dnsrv queue");        ghash_remove(di->packet_table,l->packet->host);        reap = 1;    }else{        while(l->next != NULL)        {            if((now - l->next->stamp) > di->packet_timeout)            {                reap = 1;                n = l->next;                l->next = NULL; /* chop off packets to be killed */                l = n;                break;            }            l = l->next;        }    }    if(reap == 0) return 1;    /* time out individual queue'd packets */    while(l != NULL)    {        n = l->next;        deliver_fail(l->packet,"Hostname Resolution Timeout");        l = n;    }    return 1;}result dnsrv_beat_packets(void *arg){    dns_io di = (dns_io)arg;    ghash_walk(di->packet_table,_dnsrv_beat_packets,arg);    return r_DONE;}void dnsrv(instance i, xmlnode x){     xdbcache xc = NULL;     xmlnode  config = NULL;     xmlnode  iternode   = NULL;     dns_resend_list tmplist = NULL;     /* Setup a struct to hold dns_io handles */     dns_io di;     di = pmalloco(i->p, sizeof(_dns_io));     di->mempool = i->p;     /* Load config from xdb */     xc = xdb_cache(i);     config = xdb_get(xc, jid_new(xmlnode_pool(x), "config@-internal"), "jabber:config:dnsrv");     /* Build a list of services/resend hosts */     iternode = xmlnode_get_lastchild(config);     while (iternode != NULL)     {          if (j_strcmp("resend", xmlnode_get_name(iternode)) != 0)          {               iternode = xmlnode_get_prevsibling(iternode);               continue;          }          /* Allocate a new list node */          tmplist = pmalloco(di->mempool, sizeof(_dns_resend_list));          tmplist->service = pstrdup(di->mempool, xmlnode_get_attrib(iternode, "service"));          tmplist->host    = pstrdup(di->mempool, xmlnode_get_data(iternode));          /* Insert this node into the list */          tmplist->next = di->svclist;              di->svclist = tmplist;          /* Move to next child */          iternode = xmlnode_get_prevsibling(iternode);     }     log_debug(ZONE, "dnsrv debug: %s\n", xmlnode2str(config));     /* Setup the hash of dns_packet_list */     di->packet_table = ghash_create(j_atoi(xmlnode_get_attrib(config,"queuemax"),101), (KEYHASHFUNC)str_hash_code, (KEYCOMPAREFUNC)j_strcmp);     di->packet_timeout = j_atoi(xmlnode_get_attrib(config,"queuetimeout"),60);     register_beat(di->packet_timeout, dnsrv_beat_packets, (void *)di);     /* Setup the internal hostname cache */     di->cache_table = ghash_create(j_atoi(xmlnode_get_attrib(config,"cachemax"),1999), (KEYHASHFUNC)str_hash_code, (KEYCOMPAREFUNC)j_strcmp);     di->cache_timeout = j_atoi(xmlnode_get_attrib(config,"cachetimeout"),3600); /* 1 hour dns cache? XXX would be nice to get the right value from dns! */     xmlnode_free(config);     /* spawn a thread that get's forked, and wait for it since it sets up the fd's */     pth_join(pth_spawn(PTH_ATTR_DEFAULT,(void*)dnsrv_thread,(void*)di),NULL);     if(di->pid < 0)     {         log_error(i->id,"dnsrv failed to start, unable to fork and/or create pipes");         return;     }     /* Start IO thread */     pth_spawn(PTH_ATTR_DEFAULT, dnsrv_process_io, di);     /* Register an incoming packet handler */     register_phandler(i, o_DELIVER, dnsrv_deliver, (void*)di);     /* register a cleanup function */     pool_cleanup(i->p, dnsrv_shutdown, (void*)di);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -