An alternative interface is defined by <sofia-resolv/sres.h>, <sofia-resolv/sres_record.h>, <sofia-resolv/sres_async.h>, and <sofia-resolv/sres_cache.h>.
Sofia resolver uses the usual configuration for DNS. In Unix-based systems, the DNS configuration is stored in the file /etc/resolv.conf, on Windows, it is available through the registry. Sofia resolvers reloads the configuration when it detect that it has been changed.
In addition to the configuration files, the environment variables SRES_OPTIONS and RES_OPTIONS can be used to change the behaviour of the resolver.
The application can either explicitly poll(2) or select(2) on file descriptors used by resolver and call the driver functions, or it can use su root a pointer to a su_root_t object. Third option is to use resolver synchronously with sres_blocking_query().
There is an internal cache used by sresolv. The query functions add records to the cache: using the cache is made similar as if receiving entries directly from DNS server.
Please note that you have to create a separate resolver object for each thread using Sofia resolver. The resolver objects can share the cache, however.
#include <sofia-sip/sresolv.h> sres_resolver_t *sres_resolver_create(su_root_t *root, char const *resolv_conf, tag_type_t, tag_value_t, ...); int sres_resolver_destroy(sres_resolver_t *res);
sres_query_t *sres_query(sres_resolver_t *res, sres_answer_f *callback, sres_context_t *context, int socket, uint16_t type, char const *domain); sres_query_t *sres_query_sockaddr(sres_resolver_t *res, sres_answer_f *callback, sres_context_t *context, int socket, uint16_t type, struct sockaddr const *addr); void sres_query_bind(sres_query_t *q, sres_answer_f *callback, sres_context_t *context);
sres_record_t **sres_cached_answers(sres_resolver_t *res, uint16_t type, char const *domain); sres_record_t **sres_cached_answers_sockaddr(sres_resolver_t *res, uint16_t type, struct sockaddr const *addr); int sres_sort_answers(sres_resolver_t *res, sres_record_t **answers); int sres_filter_answers(sres_resolver_t *sres, sres_record_t **answers, uint16_t type); void sres_free_answers(sres_resolver_t *res, sres_record_t **answers); void sres_free_answer(sres_resolver_t *res, sres_record_t *answer);
#include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <sofia-resolv/sres.h> sres_resolver_t *sres_resolver_new(char const *resolv_conf_path); sres_resolver_t *sres_resolver_new_with_cache(char const *conf_file_path, sres_cache_t *cache, char const *options, ...); sres_resolver_t *sres_resolver_ref(sres_resolver_t *res); void sres_resolver_unref(sres_resolver_t *res); sres_resolver_t *sres_resolver_copy(sres_resolver_t *); void *sres_resolver_set_userdata(sres_resolver_t *res, void *userdata); void *sres_resolver_get_userdata(sres_resolver_t const *res);
#include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <sofia-resolv/sres.h> int sres_blocking_query(sres_resolver_t *res, uint16_t type, char const *domain, sres_record_t ***return_records); int sres_blocking_query_sockaddr(sres_resolver_t *res, uint16_t type, struct sockaddr const *addr, sres_record_t ***return_records);
#include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <sofia-resolv/sres_async.h> sres_async_t *sres_resolver_set_async(sres_resolver_t *res, sres_update_f *update, sres_async_t *async, int update_all); sres_async_t *sres_resolver_get_async(sres_resolver_t const *res, sres_update_f *update); int sres_resolver_sockets(sres_resolver_t const *res, int *sockets, int n); void sres_resolver_timer(sres_resolver_t *, int socket); int sres_resolver_receive(sres_resolver_t *res, int socket); int sres_resolver_error(sres_resolver_t *res, int socket);
Here is a short code fragment showing how to use resolver driven from su_root_t:
#define SRES_CONTEXT_T struct context #include <sofia-sip/sresolv.h> ... struct context { ... su_root_t *root; sres_resolver_t *sres; sres_query_t *query; ... } *context; ... context->sres = sres_resolver_create(context->root, NULL, TAG_END()); ... sres_record_t *results; results = sres_cached_answers(context->sres, sres_type_naptr, domain); if (results) { process_natpr(context, NULL, results); } else { context->query = sres_query(context->sres, process_natpr, context, sres_type_naptr, domain); if (!context->query) process_naptr(context, NULL, NULL); } } ... void process_natpr(sres_context_t *context, sres_query_t *q, sres_record_t *answers[]) { sres_sort_answers(context->sres, answers); ... sres_free_answers(context->sres, answers); }