# HG changeset patch # User thijsalkemade@gmail.com # Date 1301008949 0 # Node ID 08dcd2d4f0b7f0cb8c8eca8ebd8ddc9efbdcb606 # Parent 5043fc53f95729d4b1cc055841dcd401fb33a674 Added PurpleSrvTxtQueryUiOps which allow UIs to specify their own mechanisms to resolve SRV and/or TXT queries. Additionally, some functions and datatypes have been renamed to show which are SRV only, which TXT only, and which are used by both. diff -r 5043fc53f957 -r 08dcd2d4f0b7 ChangeLog.API --- a/ChangeLog.API Thu Mar 24 15:18:14 2011 +0000 +++ b/ChangeLog.API Thu Mar 24 23:22:29 2011 +0000 @@ -14,6 +14,9 @@ * purple_media_manager_set_video_caps (Jakub Adam) (#13095) * Added add_buddy_with_invite to PurplePluginProtocolInfo * Added add_buddies_with_invite to PurplePluginProtocolInfo + * Added PurpleSrvTxtQueryUiOps which allow UIs to specify their + own mechanisms to resolve SRV and/or TXT queries. It works + similar to PurpleDnsQueryUiOps Deprecated: * purple_account_add_buddy diff -r 5043fc53f957 -r 08dcd2d4f0b7 libpurple/dnsquery.h --- a/libpurple/dnsquery.h Thu Mar 24 15:18:14 2011 +0000 +++ b/libpurple/dnsquery.h Thu Mar 24 23:22:29 2011 +0000 @@ -58,7 +58,8 @@ */ typedef struct { - /** If implemented, the UI is responsible for DNS queries */ + /** If implemented, return TRUE if the UI takes responsibility for DNS + * queries. When returning FALSE, the standard implementation is used. */ gboolean (*resolve_host)(PurpleDnsQueryData *query_data, PurpleDnsQueryResolvedCallback resolved_cb, PurpleDnsQueryFailedCallback failed_cb); diff -r 5043fc53f957 -r 08dcd2d4f0b7 libpurple/dnssrv.c --- a/libpurple/dnssrv.c Thu Mar 24 15:18:14 2011 +0000 +++ b/libpurple/dnssrv.c Thu Mar 24 23:22:29 2011 +0000 @@ -31,19 +31,19 @@ #include #endif #ifndef T_SRV -#define T_SRV 33 +#define T_SRV PurpleDnsTypeSrv #endif #ifndef T_TXT -#define T_TXT 16 +#define T_TXT PurpleDnsTypeTxt #endif #else /* WIN32 */ #include /* Missing from the mingw headers */ #ifndef DNS_TYPE_SRV -# define DNS_TYPE_SRV 33 +# define DNS_TYPE_SRV PurpleDnsTypeSrv #endif #ifndef DNS_TYPE_TXT -# define DNS_TYPE_TXT 16 +# define DNS_TYPE_TXT PurpleDnsTypeTxt #endif #endif @@ -52,6 +52,8 @@ #include "eventloop.h" #include "network.h" +static PurpleSrvTxtQueryUiOps *srv_txt_query_ui_ops = NULL; + #ifndef _WIN32 typedef union { HEADER hdr; @@ -66,11 +68,7 @@ DNS_FREE_TYPE FreeType) = NULL; #endif -struct _PurpleTxtResponse { - char *content; -}; - -struct _PurpleSrvQueryData { +struct _PurpleSrvTxtQueryData { union { PurpleSrvCallback srv; PurpleTxtCallback txt; @@ -79,9 +77,9 @@ gpointer extradata; guint handle; int type; + char *query; #ifdef _WIN32 GThread *resolver; - char *query; char *error_message; GList *results; #else @@ -100,6 +98,8 @@ int sum; } PurpleSrvResponseContainer; +static gboolean purple_srv_txt_query_ui_resolve(PurpleSrvTxtQueryData *query_data); + /** * Sort by priority, then by weight. Strictly numerically--no * randomness. Technically we only need to sort by pref and then @@ -430,7 +430,7 @@ { int size; int type; - PurpleSrvQueryData *query_data = (PurpleSrvQueryData*)data; + PurpleSrvTxtQueryData *query_data = (PurpleSrvTxtQueryData*)data; int i; int status; @@ -532,7 +532,7 @@ res_main_thread_cb(gpointer data) { PurpleSrvResponse *srvres = NULL; - PurpleSrvQueryData *query_data = data; + PurpleSrvTxtQueryData *query_data = data; if(query_data->error_message != NULL) { purple_debug_error("dnssrv", "%s", query_data->error_message); if (query_data->type == DNS_TYPE_SRV) { @@ -592,7 +592,7 @@ PDNS_RECORD dr = NULL; int type; DNS_STATUS ds; - PurpleSrvQueryData *query_data = data; + PurpleSrvTxtQueryData *query_data = data; type = query_data->type; ds = MyDnsQuery_UTF8(query_data->query, type, DNS_QUERY_STANDARD, NULL, &dr, NULL); if (ds != ERROR_SUCCESS) { @@ -672,12 +672,12 @@ #endif -PurpleSrvQueryData * +PurpleSrvTxtQueryData * purple_srv_resolve(const char *protocol, const char *transport, const char *domain, PurpleSrvCallback cb, gpointer extradata) { char *query; char *hostname; - PurpleSrvQueryData *query_data; + PurpleSrvTxtQueryData *query_data; #ifndef _WIN32 PurpleSrvInternalQuery internal_query; int in[2], out[2]; @@ -709,6 +709,17 @@ purple_debug_info("dnssrv","querying SRV record for %s: %s\n", domain, query); g_free(hostname); + + query_data = g_new0(PurpleSrvTxtQueryData, 1); + query_data->type = T_SRV; + query_data->cb.srv = cb; + query_data->extradata = extradata; + query_data->query = query; + + if (purple_srv_txt_query_ui_resolve(query_data)) + { + return query_data; + } #ifndef _WIN32 if(pipe(in) || pipe(out)) { @@ -747,10 +758,6 @@ if (write(in[1], &internal_query, sizeof(internal_query)) < 0) purple_debug_error("dnssrv", "Could not write to SRV resolver\n"); - query_data = g_new0(PurpleSrvQueryData, 1); - query_data->type = T_SRV; - query_data->cb.srv = cb; - query_data->extradata = extradata; query_data->pid = pid; query_data->fd_out = out[0]; query_data->fd_in = in[1]; @@ -767,7 +774,7 @@ initialized = TRUE; } - query_data = g_new0(PurpleSrvQueryData, 1); + query_data = g_new0(PurpleSrvTxtQueryData, 1); query_data->type = DNS_TYPE_SRV; query_data->cb.srv = cb; query_data->query = query; @@ -793,11 +800,11 @@ #endif } -PurpleSrvQueryData *purple_txt_resolve(const char *owner, const char *domain, PurpleTxtCallback cb, gpointer extradata) +PurpleSrvTxtQueryData *purple_txt_resolve(const char *owner, const char *domain, PurpleTxtCallback cb, gpointer extradata) { char *query; char *hostname; - PurpleSrvQueryData *query_data; + PurpleSrvTxtQueryData *query_data; #ifndef _WIN32 PurpleSrvInternalQuery internal_query; int in[2], out[2]; @@ -823,6 +830,18 @@ purple_debug_info("dnssrv","querying TXT record for %s: %s\n", domain, query); g_free(hostname); + + query_data = g_new0(PurpleSrvTxtQueryData, 1); + query_data->type = T_TXT; + query_data->cb.txt = cb; + query_data->extradata = extradata; + query_data->query = query; + + if (purple_srv_txt_query_ui_resolve(query_data)) { + /* query intentionally not freed + */ + return query_data; + } #ifndef _WIN32 if(pipe(in) || pipe(out)) { @@ -860,11 +879,7 @@ if (write(in[1], &internal_query, sizeof(internal_query)) < 0) purple_debug_error("dnssrv", "Could not write to TXT resolver\n"); - - query_data = g_new0(PurpleSrvQueryData, 1); - query_data->type = T_TXT; - query_data->cb.txt = cb; - query_data->extradata = extradata; + query_data->pid = pid; query_data->fd_out = out[0]; query_data->fd_in = in[1]; @@ -881,7 +896,7 @@ initialized = TRUE; } - query_data = g_new0(PurpleSrvQueryData, 1); + query_data = g_new0(PurpleSrvTxtQueryData, 1); query_data->type = DNS_TYPE_TXT; query_data->cb.txt = cb; query_data->query = query; @@ -908,8 +923,13 @@ } void -purple_srv_cancel(PurpleSrvQueryData *query_data) +purple_srv_cancel(PurpleSrvTxtQueryData *query_data) { + PurpleSrvTxtQueryUiOps *ops = purple_srv_txt_query_get_ui_ops(); + + if (ops && ops->destroy) + ops->destroy(query_data); + if (query_data->handle > 0) purple_input_remove(query_data->handle); #ifdef _WIN32 @@ -933,7 +953,7 @@ } void -purple_txt_cancel(PurpleSrvQueryData *query_data) +purple_txt_cancel(PurpleSrvTxtQueryData *query_data) { purple_srv_cancel(query_data); } @@ -953,3 +973,85 @@ g_free(resp->content); g_free(resp); } + +/* + * Only used as the callback for the ui ops. + */ +static void +purple_srv_query_resolved(PurpleSrvTxtQueryData *query_data, GList *records) +{ + g_return_if_fail(records != NULL); + + purple_debug_info("dnssrv", "SRV records resolved for %s, count: %d\n", query_data->query, g_list_length(records)); + + if (query_data->cb.srv != NULL) + query_data->cb.srv(purple_srv_sort(records)->data, g_list_length(records), query_data->extradata); +} + +/* + * Only used as the callback for the ui ops. + */ +static void +purple_txt_query_resolved(PurpleSrvTxtQueryData *query_data, GList *entries) +{ + g_return_if_fail(entries != NULL); + + purple_debug_info("dnssrv", "TXT entries resolved for %s, count: %d\n", query_data->query, g_list_length(entries)); + + if (query_data->cb.txt != NULL) + query_data->cb.txt(entries, query_data->extradata); +} + +static void +purple_srv_query_failed(PurpleSrvTxtQueryData *query_data, const gchar *error_message) +{ + purple_debug_error("dnssrv", "%s\n", error_message); + + if (query_data->cb.srv != NULL) + query_data->cb.srv(NULL, 0, query_data->extradata); + + purple_srv_cancel(query_data); +} + +static gboolean +purple_srv_txt_query_ui_resolve(PurpleSrvTxtQueryData *query_data) +{ + PurpleSrvTxtQueryUiOps *ops = purple_srv_txt_query_get_ui_ops(); + + if (ops && ops->resolve) + return ops->resolve(query_data, (query_data->type == T_SRV ? purple_srv_query_resolved : purple_txt_query_resolved), purple_srv_query_failed); + + return FALSE; +} + +void +purple_srv_txt_query_set_ui_ops(PurpleSrvTxtQueryUiOps *ops) +{ + srv_txt_query_ui_ops = ops; +} + +PurpleSrvTxtQueryUiOps * +purple_srv_txt_query_get_ui_ops(void) +{ + /* It is perfectly acceptable for srv_txt_query_ui_ops to be NULL; this just + * means that the default platform-specific implementation will be used. + */ + return srv_txt_query_ui_ops; +} + +char * +purple_srv_txt_query_get_query(PurpleSrvTxtQueryData *query_data) +{ + g_return_val_if_fail(query_data != NULL, NULL); + + return query_data->query; +} + + +int +purple_srv_txt_query_get_type(PurpleSrvTxtQueryData *query_data) +{ + g_return_val_if_fail(query_data != NULL, 0); + + return query_data->type; +} \ No newline at end of file diff -r 5043fc53f957 -r 08dcd2d4f0b7 libpurple/dnssrv.h --- a/libpurple/dnssrv.h Thu Mar 24 15:18:14 2011 +0000 +++ b/libpurple/dnssrv.h Thu Mar 24 23:22:29 2011 +0000 @@ -28,12 +28,21 @@ extern "C" { #endif -typedef struct _PurpleSrvQueryData PurpleSrvQueryData; +typedef struct _PurpleSrvTxtQueryData PurpleSrvTxtQueryData; typedef struct _PurpleSrvResponse PurpleSrvResponse; typedef struct _PurpleTxtResponse PurpleTxtResponse; +/* For compatibility, should be removed for 3.0.0 + */ +typedef struct _PurpleSrvTxtQueryData PurpleSrvQueryData; + #include +enum PurpleDnsType { + PurpleDnsTypeTxt = 16, + PurpleDnsTypeSrv = 33 +}; + struct _PurpleSrvResponse { char hostname[256]; int port; @@ -41,6 +50,40 @@ int pref; }; +struct _PurpleTxtResponse { + char *content; +}; + +typedef void (*PurpleSrvTxtQueryResolvedCallback) (PurpleSrvTxtQueryData *query_data, GList *records); +typedef void (*PurpleSrvTxtQueryFailedCallback) (PurpleSrvTxtQueryData *query_data, const gchar *error_message); + +/** + * SRV Request UI operations; UIs should implement this if they want to do SRV + * lookups themselves, rather than relying on the core. + * + * @see @ref ui-ops + */ +typedef struct +{ + /** If implemented, return TRUE if the UI takes responsibility for SRV + * queries. When returning FALSE, the standard implementation is used. + * These callbacks MUST be called asynchronously. */ + gboolean (*resolve)(PurpleSrvTxtQueryData *query_data, + PurpleSrvTxtQueryResolvedCallback resolved_cb, + PurpleSrvTxtQueryFailedCallback failed_cb); + + /** Called just before @a query_data is freed; this should cancel any + * further use of @a query_data the UI would make. Unneeded if + * #resolve_host is not implemented. + */ + void (*destroy)(PurpleSrvTxtQueryData *query_data); + + void (*_purple_reserved1)(void); + void (*_purple_reserved2)(void); + void (*_purple_reserved3)(void); + void (*_purple_reserved4)(void); +} PurpleSrvTxtQueryUiOps; + /** * @param resp An array of PurpleSrvResponse of size results. The array * is sorted based on the order described in the DNS SRV RFC. @@ -66,14 +109,14 @@ * @param cb A callback which will be called with the results * @param extradata Extra data to be passed to the callback */ -PurpleSrvQueryData *purple_srv_resolve(const char *protocol, const char *transport, const char *domain, PurpleSrvCallback cb, gpointer extradata); +PurpleSrvTxtQueryData *purple_srv_resolve(const char *protocol, const char *transport, const char *domain, PurpleSrvCallback cb, gpointer extradata); /** - * Cancel an SRV DNS query. + * Cancel an SRV or DNS query. * * @param query_data The request to cancel. */ -void purple_srv_cancel(PurpleSrvQueryData *query_data); +void purple_srv_cancel(PurpleSrvTxtQueryData *query_data); /** * Queries an TXT record. @@ -85,7 +128,7 @@ * * @since 2.6.0 */ -PurpleSrvQueryData *purple_txt_resolve(const char *owner, const char *domain, PurpleTxtCallback cb, gpointer extradata); +PurpleSrvTxtQueryData *purple_txt_resolve(const char *owner, const char *domain, PurpleTxtCallback cb, gpointer extradata); /** * Cancel an TXT DNS query. @@ -93,7 +136,7 @@ * @param query_data The request to cancel. * @since 2.6.0 */ -void purple_txt_cancel(PurpleSrvQueryData *query_data); +void purple_txt_cancel(PurpleSrvTxtQueryData *query_data); /** * Get the value of the current TXT record. @@ -112,6 +155,47 @@ */ void purple_txt_response_destroy(PurpleTxtResponse *response); +/** + * Cancel a SRV/TXT query and destroy the associated data structure. + * + * @param query_data The SRV/TXT query to cancel. This data structure + * is freed by this function. + */ +void purple_srv_txt_query_destroy(PurpleSrvTxtQueryData *query_data); + +/** + * Sets the UI operations structure to be used when doing a SRV/TXT + * resolve. The UI operations need only be set if the UI wants to + * handle the resolve itself; otherwise, leave it as NULL. + * + * @param ops The UI operations structure. + */ +void purple_srv_txt_query_set_ui_ops(PurpleSrvTxtQueryUiOps *ops); + +/** + * Returns the UI operations structure to be used when doing a SRV/TXT + * resolve. + * + * @return The UI operations structure. + */ +PurpleSrvTxtQueryUiOps *purple_srv_txt_query_get_ui_ops(void); + +/** + * Get the query from a PurpleDnsQueryData + * + * @param query_data The SRV/TXT query + * @return The query. + */ +char *purple_srv_txt_query_get_query(PurpleSrvTxtQueryData *query_data); + +/** + * Get the type from a PurpleDnsQueryData (TXT or SRV) + * + * @param query_data The query + * @return The query. + */ +int purple_srv_txt_query_get_type(PurpleSrvTxtQueryData *query_data); + #ifdef __cplusplus } #endif diff -r 5043fc53f957 -r 08dcd2d4f0b7 libpurple/gaim-compat.h --- a/libpurple/gaim-compat.h Thu Mar 24 15:18:14 2011 +0000 +++ b/libpurple/gaim-compat.h Thu Mar 24 23:22:29 2011 +0000 @@ -841,7 +841,7 @@ /* from dnssrv.h */ #define GaimSrvResponse PurpleSrvResponse -#define GaimSrvQueryData PurpleSrvQueryData +#define GaimSrvQueryData PurpleSrvTxtQueryData #define GaimSrvCallback PurpleSrvCallback #define gaim_srv_resolve purple_srv_resolve diff -r 5043fc53f957 -r 08dcd2d4f0b7 libpurple/protocols/jabber/jabber.h --- a/libpurple/protocols/jabber/jabber.h Thu Mar 24 15:18:14 2011 +0000 +++ b/libpurple/protocols/jabber/jabber.h Thu Mar 24 23:22:29 2011 +0000 @@ -100,7 +100,7 @@ { int fd; - PurpleSrvQueryData *srv_query_data; + PurpleSrvTxtQueryData *srv_query_data; xmlParserCtxt *context; xmlnode *current; diff -r 5043fc53f957 -r 08dcd2d4f0b7 libpurple/protocols/simple/simple.h --- a/libpurple/protocols/simple/simple.h Thu Mar 24 15:18:14 2011 +0000 +++ b/libpurple/protocols/simple/simple.h Thu Mar 24 23:22:29 2011 +0000 @@ -83,7 +83,7 @@ gchar *username; gchar *password; PurpleDnsQueryData *query_data; - PurpleSrvQueryData *srv_query_data; + PurpleSrvTxtQueryData *srv_query_data; PurpleNetworkListenData *listen_data; int fd; int cseq;