Home --> Documentations --> PJLIB-UTIL Reference
|
void | pj_dns_settings_default (pj_dns_settings *s) |
|
pj_status_t | pj_dns_resolver_create (pj_pool_factory *pf, const char *name, unsigned options, pj_timer_heap_t *timer, pj_ioqueue_t *ioqueue, pj_dns_resolver **p_resolver) |
|
pj_status_t | pj_dns_resolver_set_ns (pj_dns_resolver *resolver, unsigned count, const pj_str_t servers[], const pj_uint16_t ports[]) |
|
pj_status_t | pj_dns_resolver_get_settings (pj_dns_resolver *resolver, pj_dns_settings *st) |
|
pj_status_t | pj_dns_resolver_set_settings (pj_dns_resolver *resolver, const pj_dns_settings *st) |
|
void | pj_dns_resolver_handle_events (pj_dns_resolver *resolver, const pj_time_val *timeout) |
|
pj_status_t | pj_dns_resolver_destroy (pj_dns_resolver *resolver, pj_bool_t notify) |
|
pj_status_t | pj_dns_resolver_start_query (pj_dns_resolver *resolver, const pj_str_t *name, int type, unsigned options, pj_dns_callback *cb, void *user_data, pj_dns_async_query **p_query) |
|
pj_status_t | pj_dns_resolver_cancel_query (pj_dns_async_query *query, pj_bool_t notify) |
|
pj_status_t | pj_dns_parse_a_response (const pj_dns_parsed_packet *pkt, pj_dns_a_record *rec) |
|
pj_status_t | pj_dns_parse_addr_response (const pj_dns_parsed_packet *pkt, pj_dns_addr_record *rec) |
|
pj_status_t | pj_dns_resolver_add_entry (pj_dns_resolver *resolver, const pj_dns_parsed_packet *pkt, pj_bool_t set_ttl) |
|
unsigned | pj_dns_resolver_get_cached_count (pj_dns_resolver *resolver) |
|
void | pj_dns_resolver_dump (pj_dns_resolver *resolver, pj_bool_t detail) |
|
This module manages the host/server resolution by performing asynchronous DNS queries and caching the results in the cache. It uses PJLIB-UTIL low-level DNS parsing functions (see DNS and Asynchronous DNS Resolver) and currently supports several types of DNS resource records such as A record (typical query with gethostbyname()) and SRV record.
Features
Asynchronous Query and Query Aggregation
The DNS queries are performed asychronously, with timeout setting configured on per resolver instance basis. Application can issue multiple asynchronous queries simultaneously. Subsequent queries to the same resource (name and DNS resource type) while existing query is still pending will be merged into one query, so that only one DNS request packet is issued.
Query Retransmission
Asynchronous query will be retransmitted if no response is received within the preconfigured time. Once maximum retransmission count is exceeded and no response is received, the query will time out and the callback will be called when error status.
Response Caching with TTL
The resolver instance caches the results returned by nameservers, to enhance the performance by minimizing the message round-trip to the server. The TTL of the cached resposne is calculated from minimum TTL value found across all resource record (RR) TTL in the response and further more it can be limited to some preconfigured maximum TTL in the resolver.
Response caching can be disabled by setting the maximum TTL value of the resolver to zero.
Parallel and Backup Name Servers
When the resolver is configured with multiple nameservers, initially the queries will be issued to multiple name servers simultaneously to probe which servers are not active. Once the probing stage is done, subsequent queries will be directed to only one ACTIVE server which provides the best response time.
Name servers are probed periodically to see which nameservers are active and which are down. This probing is done when a query is sent, thus no timer is needed to maintain this. Also probing will be done in parallel so that there would be no additional delay for the query.
Supported Resource Records
The low-level DNS parsing utility (see DNS and Asynchronous DNS Resolver) supports parsing of the following DNS resource records (RR):
- DNS A record
- DNS SRV record
- DNS PTR record
- DNS NS record
- DNS CNAME record
For other types of record, application can parse the raw resource record data (rdata) from the parsed DNS packet (pj_dns_parsed_packet).
Using the Resolver
To use the resolver, application first creates the resolver instance by calling pj_dns_resolver_create(). If application already has its own timer and ioqueue instances, it can instruct the resolver to use these instances so that application does not need to poll the resolver periodically to process events. If application does not specify the timer and ioqueue instance for the resolver, an internal timer and ioqueue will be created by the resolver. And since the resolver does not create it's own thread, application MUST poll the resolver periodically by calling pj_dns_resolver_handle_events() to allow events (network and timer) to be processed.
Next, application MUST configure the nameservers to be used by the resolver, by calling pj_dns_resolver_set_ns().
Application performs asynchronous query by submitting the query with pj_dns_resolver_start_query(). Once the query completes (either successfully or times out), the callback will be called.
Application can cancel a pending query by calling pj_dns_resolver_cancel_query().
Resolver must be destroyed by calling pj_dns_resolver_destroy() to release all resources back to the system.
Resolver Limitations
Current implementation mainly suffers from a growing memory problem, which mainly is caused by the response caching. Although there is only one cache entry per {query, name} combination, these cache entry will never get deleted since there is no timer is created to invalidate these entries. So the more unique names being queried by application, there more enties will be created in the response cache.
Note that a single response entry will occupy about 600-700 bytes of pool memory (the PJ_DNS_RESOLVER_RES_BUF_SIZE value plus internal structure).
Application can work around this problem by doing one of these:
- disable caching by setting PJ_DNS_RESOLVER_MAX_TTL and PJ_DNS_RESOLVER_INVALID_TTL to zero.
- periodically query pj_dns_resolver_get_cached_count() and destroy- recreate the resolver to recycle the memory used by the resolver.
Note that future improvement may solve this problem by introducing expiration timer to the cached entries.
Reference
The PJLIB-UTIL resolver was built from the information in the following standards:
◆ pj_dns_async_query
Opaque data type for asynchronous DNS query object.
◆ pj_dns_callback
Type of asynchronous callback which will be called when the asynchronous query completes.
- Parameters
-
user_data | The user data set by application when creating the asynchronous query. |
status | Status of the DNS resolution. |
response | The response packet received from the server. This argument may be NULL when status is not PJ_SUCCESS. |
◆ pj_dns_resolver
Opaque data type for DNS resolver object.
◆ pj_dns_parse_a_response()
A utility function to parse a DNS response containing A records into DNS A record.
- Parameters
-
pkt | The DNS response packet. |
rec | The structure to be initialized with the parsed DNS A record from the packet. |
- Returns
- PJ_SUCCESS if response can be parsed successfully.
◆ pj_dns_parse_addr_response()
A utility function to parse a DNS response containing AAAA records into DNS AAAA record.
- Parameters
-
pkt | The DNS response packet. |
rec | The structure to be initialized with the parsed DNS AAAA record from the packet. |
- Returns
- PJ_SUCCESS if response can be parsed successfully.
◆ pj_dns_resolver_add_entry()
Put the specified DNS packet into DNS cache. This function is mainly used for testing the resolver, however it can also be used to inject entries into the resolver.
The packet MUST contain either answer section or query section so that it can be indexed.
- Parameters
-
resolver | The resolver instance. |
pkt | DNS packet to be added to the DNS cache. If the packet matches existing entry, it will update the entry. |
set_ttl | If the value is PJ_FALSE, the entry will not expire (so use with care). Otherwise cache expiration will be calculated based on the TTL of the answeres. |
- Returns
- PJ_SUCCESS on success, or the appropriate error code.
◆ pj_dns_resolver_cancel_query()
Cancel a pending query.
- Parameters
-
query | The pending asynchronous query to be cancelled. |
notify | If non-zero, the callback will be called with failure status to notify that the query has been cancelled. |
- Returns
- PJ_SUCCESS on success, or the appropriate error code,
◆ pj_dns_resolver_create()
Create DNS resolver instance. After the resolver is created, application MUST configure the nameservers with pj_dns_resolver_set_ns().
When creating the resolver, application may specify both timer heap and ioqueue instance, so that it doesn't need to poll the resolver periodically.
- Parameters
-
pf | Pool factory where the memory pool will be created from. |
name | Optional resolver name to identify the instance in the log. |
options | Optional options, must be zero for now. |
timer | Optional timer heap instance to be used by the resolver. If timer heap is not specified, an internal timer will be created, and application would need to poll the resolver periodically. |
ioqueue | Optional I/O Queue instance to be used by the resolver. If ioqueue is not specified, an internal one will be created, and application would need to poll the resolver periodically. |
p_resolver | Pointer to receive the resolver instance. |
- Returns
- PJ_SUCCESS on success, or the appropriate error code,
◆ pj_dns_resolver_destroy()
Destroy DNS resolver instance.
- Parameters
-
resolver | The resolver object to be destryed |
notify | If non-zero, all pending asynchronous queries will be cancelled and its callback will be called. If FALSE, then no callback will be called. |
- Returns
- PJ_SUCCESS on success, or the appropriate error code,
◆ pj_dns_resolver_dump()
Dump resolver state to the log.
- Parameters
-
resolver | The resolver instance. |
detail | Will print detailed entries. |
References PJ_END_DECL.
◆ pj_dns_resolver_get_cached_count()
Get the total number of response in the response cache.
- Parameters
-
resolver | The resolver instance. |
- Returns
- Current number of entries being stored in the response cache.
◆ pj_dns_resolver_get_settings()
Get the resolver current settings.
- Parameters
-
resolver | The resolver instance. |
st | Buffer to be filled up with resolver settings. |
- Returns
- The query timeout setting, in seconds.
◆ pj_dns_resolver_handle_events()
Poll for events from the resolver. This function MUST be called periodically when the resolver is using it's own timer or ioqueue (in other words, when NULL is specified as either timer or ioqueue argument in pj_dns_resolver_create()).
- Parameters
-
resolver | The resolver instance. |
timeout | Maximum time to wait for event occurence. If this argument is NULL, this function will wait forever until events occur. |
◆ pj_dns_resolver_set_ns()
Update the name servers for the DNS resolver. The name servers MUST be configured before any resolution can be done. The order of nameservers specifies their priority; the first name server will be tried first before the next in the list.
- Parameters
-
resolver | The resolver instance. |
count | Number of name servers in the array. |
servers | Array of name server IP addresses or hostnames. If hostname is specified, the hostname must be resolvable with pj_gethostbyname(). |
ports | Optional array of ports. If this argument is NULL, the nameserver will use default port. |
- Returns
- PJ_SUCCESS on success, or the appropriate error code,
◆ pj_dns_resolver_set_settings()
Modify the resolver settings. Application should initialize the settings by retrieving current settings first before applying new settings, to ensure that all fields are initialized properly.
- Parameters
-
resolver | The resolver instance. |
st | The resolver settings. |
- Returns
- PJ_SUCCESS on success, or the appropriate error code,
◆ pj_dns_resolver_start_query()
Create and start asynchronous DNS query for a single resource. Depending on whether response cache is available, this function will either start an asynchronous DNS query or call the callback immediately.
If response is not available in the cache, an asynchronous query will be started, and callback will be called at some time later when the query completes. If p_query argument is not NULL, it will be filled with the asynchronous query object.
If response is available in the cache, the callback will be called immediately before this function returns. In this case, if p_query argument is not NULL, the value will be set to NULL since no new query is started.
- Parameters
-
resolver | The resolver object. |
name | The name to be resolved. |
type | The type of resource (see pj_dns_type constants). |
options | Optional options, must be zero for now. |
cb | Callback to be called when the query completes, either successfully or with failure. |
user_data | Arbitrary user data to be associated with the query, and which will be given back in the callback. |
p_query | Optional pointer to receive the query object, if one was started. If this pointer is specified, a NULL may be returned if response cache is available immediately. |
- Returns
- PJ_SUCCESS if either an asynchronous query has been started successfully or response cache is available and the user callback has been called.
◆ pj_dns_settings_default()
Set default values to the DNS settings.
- Parameters
-
s | The DNS settings to be initialized. |
PJLIB-UTIL Open Source, small footprint, and portable asynchronous/caching DNS resolver, text scanner, STUN client, and XML library
Copyright (C) 2006-2009 Teluu Inc.
|