Example #1
0
/*!
 * \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;
}
Example #2
0
/*!
 * \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;
}
Example #3
0
/*!
 * \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;
}
Example #4
0
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;
}