/*! * \brief Thread that performs asynchronous resolution. * * This thread uses the query's user data to determine how to * perform the resolution. The query may either be canceled or * it may be completed with records. * * \param dns_query The ast_dns_query that is being performed * \return NULL */ static void *resolution_thread(void *dns_query) { struct ast_dns_query *query = dns_query; static const char *ADDR1 = "127.0.0.1"; static const size_t ADDR1_BUFSIZE = sizeof(struct in_addr); char addr1_buf[ADDR1_BUFSIZE]; static const char *ADDR2 = "192.168.0.1"; static const size_t ADDR2_BUFSIZE = sizeof(struct in_addr); char addr2_buf[ADDR2_BUFSIZE]; struct ast_dns_query_recurring *recurring = ast_dns_query_get_data(query); struct recurring_data *rdata = recurring->user_data; ast_assert(rdata != NULL); /* Canceling is an interesting dance. This thread needs to signal that it is * ready to be canceled. Then it needs to wait until the query is actually canceled. */ if (rdata->cancel_expected) { ast_mutex_lock(&rdata->lock); rdata->cancel_ready = 1; ast_cond_signal(&rdata->cond); while (!rdata->canceled) { ast_cond_wait(&rdata->cond, &rdata->lock); } ast_mutex_unlock(&rdata->lock); ast_dns_resolver_completed(query); ao2_ref(query, -1); return NULL; } /* When the query isn't canceled, we set the TTL of the results based on what * we've been told to set it to */ ast_dns_resolver_set_result(query, 0, 0, ns_r_noerror, "asterisk.org", DNS_ANSWER, DNS_ANSWER_SIZE); inet_pton(AF_INET, ADDR1, addr1_buf); ast_dns_resolver_add_record(query, ns_t_a, ns_c_in, rdata->ttl1, addr1_buf, ADDR1_BUFSIZE); inet_pton(AF_INET, ADDR2, addr2_buf); ast_dns_resolver_add_record(query, ns_t_a, ns_c_in, rdata->ttl2, addr2_buf, ADDR2_BUFSIZE); ++rdata->complete_resolutions; ast_dns_resolver_completed(query); ao2_ref(query, -1); return NULL; }
/*! * \brief Callback to handle processing the query from the ast_taskprocessor instance. * * \internal * * \param data A void pointer to the ast_dns_query being processed. * * \retval -1 on search failure * \retval 0 on no records found * \retval 1 on success */ static int dns_system_resolver_process_query(void *data) { struct ast_dns_query *query = data; /* Perform the DNS search */ enum ast_dns_search_result res = ast_search_dns_ex(query, ast_dns_query_get_name(query), ast_dns_query_get_rr_class(query), ast_dns_query_get_rr_type(query), dns_system_resolver_set_response, dns_system_resolver_add_record); /* Handle the possible return values from the DNS search */ if (res == AST_DNS_SEARCH_FAILURE) { ast_log(LOG_ERROR, "DNS search failed for query: '%s'\n", ast_dns_query_get_name(query)); } else if (res == AST_DNS_SEARCH_NO_RECORDS) { ast_log(LOG_WARNING, "DNS search failed to yield any results for query: '%s'\n", ast_dns_query_get_name(query)); } /* Mark the query as complete */ ast_dns_resolver_completed(query); /* Reduce the reference count on the query object */ ao2_ref(query, -1); return res; }
/*! * \brief Thread spawned by the mock resolver * * All DNS resolvers are required to be asynchronous. The mock resolver * spawns this thread for every DNS query that is executed. * * This thread waits for 5 seconds and then returns the same A record * every time. The 5 second wait is to allow for the query to be * canceled if desired * * \param dns_query The ast_dns_query that is being resolved * \return NULL */ static void *resolution_thread(void *dns_query) { struct ast_dns_query *query = dns_query; struct timespec timeout; static const char *V4 = "127.0.0.1"; static const size_t V4_BUFSIZE = sizeof(struct in_addr); char v4_buf[V4_BUFSIZE]; clock_gettime(CLOCK_REALTIME, &timeout); timeout.tv_sec += 5; ast_mutex_lock(&test_resolver_data.lock); while (!test_resolver_data.canceled) { if (ast_cond_timedwait(&test_resolver_data.cancel_cond, &test_resolver_data.lock, &timeout) == ETIMEDOUT) { break; } } ast_mutex_unlock(&test_resolver_data.lock); if (test_resolver_data.canceled) { ast_dns_resolver_completed(query); ao2_ref(query, -1); return NULL; } ast_dns_resolver_set_result(query, 0, 0, ns_r_noerror, "asterisk.org", DNS_ANSWER, DNS_ANSWER_SIZE); inet_pton(AF_INET, V4, v4_buf); ast_dns_resolver_add_record(query, ns_t_a, ns_c_in, 12345, v4_buf, V4_BUFSIZE); test_resolver_data.resolution_complete = 1; ast_dns_resolver_completed(query); ao2_ref(query, -1); return NULL; }
static void *srv_thread(void *dns_query) { struct ast_dns_query *query = dns_query; int i; int ans_size; ans_size = ast_dns_test_generate_result(query, test_records, num_test_records, sizeof(struct srv_record), generate_srv_record, ans_buffer); ast_dns_resolver_set_result(query, 0, 0, ns_r_noerror, "goose.feathers", ans_buffer, ans_size); for (i = 0; i < num_test_records; ++i) { char record[128]; int srv_size; srv_size = generate_srv_record(&test_records[i], record); ast_dns_resolver_add_record(query, ns_t_srv, ns_c_in, 12345, record, srv_size); } ast_dns_resolver_completed(query); ao2_ref(query, -1); return NULL; }