X-Git-Url: http://git.pk910.de/?a=blobdiff_plain;f=src%2FIOHandler%2FIODNSEngine_default.c;h=b8189272c7b8c7ed838f1fbb082dfdbb996f5f9d;hb=f40d2e60142d1cb141c46e63ed847b0d821ca920;hp=b9f37641fe7f5e571ee58ecf4c6686dfe54e3d78;hpb=85880e098735c6edd527c4621328ef3494e26be7;p=NextIRCd.git diff --git a/src/IOHandler/IODNSEngine_default.c b/src/IOHandler/IODNSEngine_default.c index b9f3764..b818927 100644 --- a/src/IOHandler/IODNSEngine_default.c +++ b/src/IOHandler/IODNSEngine_default.c @@ -37,8 +37,11 @@ #ifdef IODNS_USE_THREADS -static pthread_t iodns_thread; -static int iodns_thread_running = 1; +#define IODNS_MAX_THREAD 10 +#define IODNS_INC_THREAD_BY_LOAD 5 /* add another thread when there are more than IODNS_INC_THREAD_BY_LOAD querys per thread */ +static pthread_t *iodns_thread[IODNS_MAX_THREAD]; +static int iodns_threads_wanted = 1; +static int iodns_threads_running = 0; static pthread_cond_t iodns_cond; static pthread_mutex_t iodns_sync, iodns_sync2; @@ -50,8 +53,13 @@ static void iodns_process_queries(); #ifdef IODNS_USE_THREADS static void *dnsengine_worker_main(void *arg) { struct _IODNSQuery *query; - while(iodns_thread_running) { + while(1) { IOSYNCHRONIZE(iodns_sync); + if(iodns_threads_wanted < iodns_threads_running) { + iodns_threads_running--; + break; + } + for(query = iodnsquery_first; query; query = query->next) { if((query->flags & IODNSFLAG_RUNNING)) break; @@ -60,11 +68,38 @@ static void *dnsengine_worker_main(void *arg) { if(!query) pthread_cond_wait(&iodns_cond, &iodns_sync2); - if(iodns_thread_running) - iodns_process_queries(); + if(iodns_threads_wanted < iodns_threads_running) { + iodns_threads_running--; + break; + } + + iodns_process_queries(); } return NULL; } + +static int dnsengine_default_start_worker() { + if(iodns_threads_wanted >= IODNS_MAX_THREAD-1) + return 0; + int i; + for(i = 0; i < IODNS_MAX_THREAD; i++) { + if(!iodns_thread[i]) + break; + } + if(i >= IODNS_MAX_THREAD) + return 0; + iodns_thread[i] = malloc(sizeof(**iodns_thread)); + if(!iodns_thread[i]) + return 0; + iodns_threads_wanted++; + if(pthread_create(iodns_thread[i], NULL, dnsengine_worker_main, NULL)) { + iodns_threads_wanted--; + iolog_trigger(IOLOG_ERROR, "could not create pthread in %s:%d (Returned: %i)", __FILE__, __LINE__, thread_err); + return 0; + } + iodns_threads_running++; + return 1; +} #endif static int dnsengine_default_init() { @@ -74,123 +109,164 @@ static int dnsengine_default_init() { IOTHREAD_MUTEX_INIT(iodns_sync); IOTHREAD_MUTEX_INIT(iodns_sync2); - iodns_thread_running = 1; - - int thread_err; - thread_err = pthread_create(&iodns_thread, NULL, dnsengine_worker_main, NULL); - if(thread_err) { - iolog_trigger(IOLOG_ERROR, "could not create pthread in %s:%d (Returned: %i)", __FILE__, __LINE__, thread_err); + if(!dnsengine_default_start_worker()) { iodns_loop_blocking = 1; - iodns_thread_running = 0; + iodns_threads_running = 0; } #else iodns_loop_blocking = 1; #endif - return 1; + return 1; } static void dnsengine_default_stop() { #ifdef IODNS_USE_THREADS + int i; if(iodns_thread_running) { - iodns_thread_running = 0; + iodns_threads_wanted = 0; IOSYNCHRONIZE(iodns_sync2); - pthread_cond_signal(&iodns_cond); + pthread_cond_broadcast(&iodns_cond); IODESYNCHRONIZE(iodns_sync2); - pthread_join(iodns_thread, NULL); + for(i = 0; i < IODNS_MAX_THREAD; i++) { + if(iodns_thread[i]) { + pthread_join(*iodns_thread[i], NULL); + free(iodns_thread[i]); + iodns_thread[i] = NULL; + } + } } #endif } static void dnsengine_default_add(struct _IODNSQuery *iodns) { - #ifdef IODNS_USE_THREADS + #ifdef IODNS_USE_THREADS if(iodns_thread_running) { IOSYNCHRONIZE(iodns_sync2); pthread_cond_signal(&iodns_cond); IODESYNCHRONIZE(iodns_sync2); + + int querycount = 0; + for(iodns = iodnsquery_first; iodns; iodns = iodns->next) { + if(!(iodns->flags & IODNSFLAG_RUNNING)) + continue; + if((iodns->flags & IODNSFLAG_PROCESSING)) + continue; + querycount++; + } + if(querycount / iodns_threads_wanted > IODNS_INC_THREAD_BY_LOAD) { + dnsengine_default_start_worker(); + } } #endif } static void dnsengine_default_remove(struct _IODNSQuery *iodns) { - /* unused */ + /* unused */ } static void dnsengine_default_loop() { - if(iodns_loop_blocking) + if(iodns_loop_blocking) iodns_process_queries(); } static void iodns_process_queries() { enum IODNSEventType querystate; - struct addrinfo hints, *res, *allres; - struct _IODNSQuery *iodns, *next_iodns; - struct IODNSResult *dnsresult; + struct addrinfo hints, *res, *allres; + struct _IODNSQuery *iodns, *next_iodns; + struct IODNSResult *dnsresult; + int ret; iodns_process_queries_start: IOSYNCHRONIZE(iodns_sync); - for(iodns = iodnsquery_first; iodns; iodns = next_iodns) { - next_iodns = iodns->next; + for(iodns = iodnsquery_first; iodns; iodns = next_iodns) { + next_iodns = iodns->next; if(!(iodns->flags & IODNSFLAG_RUNNING)) continue; if((iodns->flags & IODNSFLAG_PROCESSING)) continue; + iodns->flags |= IODNSFLAG_PROCESSING; IODESYNCHRONIZE(iodns_sync); - querystate = IODNSEVENT_FAILED; - - if((iodns->type & IODNS_FORWARD)) { - memset (&hints, 0, sizeof (hints)); - hints.ai_family = PF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - hints.ai_flags |= AI_CANONNAME; - int ret; - if (!(ret = getaddrinfo(iodns->request.host, NULL, &hints, &allres))) { + querystate = IODNSEVENT_FAILED; + + if((iodns->type & IODNS_FORWARD)) { + memset (&hints, 0, sizeof (hints)); + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags |= AI_CANONNAME; + if (!(ret = getaddrinfo(iodns->request.host, NULL, &hints, &allres))) { res = allres; - while (res) { - switch (res->ai_family) { - case AF_INET: - if((iodns->type & IODNS_RECORD_A)) { - dnsresult = malloc(sizeof(*dnsresult)); - dnsresult->type = IODNS_RECORD_A; - dnsresult->result.addr.addresslen = res->ai_addrlen; - dnsresult->result.addr.address = malloc(dnsresult->result.addr.addresslen); - memcpy(dnsresult->result.addr.address, res->ai_addr, dnsresult->result.addr.addresslen); - dnsresult->next = iodns->result; - iodns->result = dnsresult; - - char str[INET_ADDRSTRLEN]; + while (res) { + switch (res->ai_family) { + case AF_INET: + if((iodns->type & IODNS_RECORD_A)) { + dnsresult = malloc(sizeof(*dnsresult)); + dnsresult->type = IODNS_RECORD_A; + dnsresult->result.addr.addresslen = res->ai_addrlen; + dnsresult->result.addr.address = calloc(dnsresult->result.addr.addresslen, 1); + dnsresult->result.addr.address->sa_family = AF_INET; + memcpy(dnsresult->result.addr.address, res->ai_addr, dnsresult->result.addr.addresslen); + dnsresult->next = iodns->result; + iodns->result = dnsresult; + + char str[INET_ADDRSTRLEN]; inet_ntop( AF_INET, &((struct sockaddr_in *)dnsresult->result.addr.address)->sin_addr, str, INET_ADDRSTRLEN ); - iolog_trigger(IOLOG_DEBUG, "Resolved %s to (A): %s", iodns->request.host, str); - - querystate = IODNSEVENT_SUCCESS; - } - break; - case AF_INET6: - if((iodns->type & IODNS_RECORD_AAAA)) { - dnsresult = malloc(sizeof(*dnsresult)); - dnsresult->type = IODNS_RECORD_AAAA; - dnsresult->result.addr.addresslen = res->ai_addrlen; - dnsresult->result.addr.address = calloc(dnsresult->result.addr.addresslen, 1); - memcpy(dnsresult->result.addr.address, res->ai_addr, dnsresult->result.addr.addresslen); - dnsresult->next = iodns->result; - iodns->result = dnsresult; - - char str[INET6_ADDRSTRLEN]; + iolog_trigger(IOLOG_DEBUG, "Resolved %s to (A): %s", iodns->request.host, str); + + querystate = IODNSEVENT_SUCCESS; + } + break; + case AF_INET6: + if((iodns->type & IODNS_RECORD_AAAA)) { + dnsresult = malloc(sizeof(*dnsresult)); + dnsresult->type = IODNS_RECORD_AAAA; + dnsresult->result.addr.addresslen = res->ai_addrlen; + dnsresult->result.addr.address = calloc(dnsresult->result.addr.addresslen, 1); + dnsresult->result.addr.address->sa_family = AF_INET6; + memcpy(dnsresult->result.addr.address, res->ai_addr, dnsresult->result.addr.addresslen); + dnsresult->next = iodns->result; + iodns->result = dnsresult; + + char str[INET6_ADDRSTRLEN]; inet_ntop( AF_INET6, &((struct sockaddr_in6 *)dnsresult->result.addr.address)->sin6_addr, str, INET6_ADDRSTRLEN ); - iolog_trigger(IOLOG_DEBUG, "Resolved %s to (AAAA): %s", iodns->request.host, str); - - querystate = IODNSEVENT_SUCCESS; - } - break; - } - res = res->ai_next; - } - freeaddrinfo(allres); - } else { + iolog_trigger(IOLOG_DEBUG, "Resolved %s to (AAAA): %s", iodns->request.host, str); + + querystate = IODNSEVENT_SUCCESS; + } + break; + } + res = res->ai_next; + } + freeaddrinfo(allres); + } else { iolog_trigger(IOLOG_WARNING, "getaddrinfo returned error code: %d", ret); } - } + } else if((iodns->type & IODNS_REVERSE)) { + char hostname[NI_MAXHOST]; + if(!(ret = getnameinfo(iodns->request.addr.address, iodns->request.addr.addresslen, hostname, sizeof(hostname), NULL, 0, 0))) { + dnsresult = malloc(sizeof(*dnsresult)); + dnsresult->type = IODNS_RECORD_PTR; + dnsresult->result.host = strdup(hostname); + dnsresult->next = iodns->result; + iodns->result = dnsresult; + + if(iodns->request.addr.address->sa_family == AF_INET) { + char str[INET_ADDRSTRLEN]; + inet_ntop(AF_INET, &((struct sockaddr_in *)iodns->request.addr.address)->sin_addr, str, INET_ADDRSTRLEN); + iolog_trigger(IOLOG_DEBUG, "Resolved %s to (PTR): %s", str, hostname); + } else { + char str[INET6_ADDRSTRLEN]; + inet_ntop(AF_INET6, &((struct sockaddr_in6 *)iodns->request.addr.address)->sin6_addr, str, INET6_ADDRSTRLEN); + iolog_trigger(IOLOG_DEBUG, "Resolved %s to (PTR): %s", str, hostname); + } + + querystate = IODNSEVENT_SUCCESS; + } else { + iolog_trigger(IOLOG_WARNING, "getnameinfo returned error code: %d", ret); + } + + } IOSYNCHRONIZE(iodns_sync); if(!(iodns->flags & IODNSFLAG_RUNNING)) { iodns_free_result(iodns->result); @@ -202,14 +278,15 @@ static void iodns_process_queries() { IODESYNCHRONIZE(iodns_sync); iodns_event_callback(iodns, querystate); goto iodns_process_queries_start; - } + } } struct IODNSEngine dnsengine_default = { - .name = "default", - .init = dnsengine_default_init, + .name = "default", + .init = dnsengine_default_init, .stop = dnsengine_default_stop, - .add = dnsengine_default_add, - .remove = dnsengine_default_remove, - .loop = dnsengine_default_loop, + .add = dnsengine_default_add, + .remove = dnsengine_default_remove, + .loop = dnsengine_default_loop, + .socket_callback = NULL, };