qulogic/pidgin

Implement buddy icon retrieval using DNS Service API.
draft win-mdns
2021-01-07, Elliott Sales de Andrade
29414c681827
Parents f4d6dbbdc4af
Children a7d8e214eaf9
Implement buddy icon retrieval using DNS Service API.
--- a/libpurple/protocols/bonjour/mdns_dnsapi.c Tue Jan 05 06:13:59 2021 -0500
+++ b/libpurple/protocols/bonjour/mdns_dnsapi.c Thu Jan 07 05:38:13 2021 -0500
@@ -44,7 +44,7 @@
} DnsAPIRecordData;
typedef struct {
- gpointer unused;
+ PMDNS_QUERY_HANDLE null_query;
} Win32BuddyImplData;
static void
@@ -280,6 +280,63 @@
}
}
+static gboolean
+_mdns_null_query_error(gpointer _data)
+{
+ DWORD status = GPOINTER_TO_UINT(_data);
+
+ purple_debug_error("bonjour", "record query - callback error (%ld)",
+ status);
+
+ return G_SOURCE_REMOVE;
+}
+
+static gboolean
+_mdns_null_query_parse(gpointer _data)
+{
+ DnsAPIRecordData *data = _data;
+ PDNS_RECORD pDnsRecord = data->dns_record;
+ BonjourBuddy *bb = (BonjourBuddy *)data->context;
+ Win32BuddyImplData *idata = bb->mdns_impl_data;
+
+ g_return_val_if_fail(idata != NULL, G_SOURCE_REMOVE);
+
+ if (pDnsRecord) {
+ /* } else if (flags & kDNSServiceFlagsAdd && rrtype == kDNSServiceType_NULL) { */
+ /* Buddy Icon response */
+
+ /* bonjour_buddy_got_buddy_icon(bb, rdata, rdlen); */
+
+ /* We've got what we need; stop listening */
+ DnsStopMulticastQuery(idata->null_query);
+ g_clear_pointer(&idata->null_query, g_free);
+ }
+
+ return G_SOURCE_REMOVE;
+}
+
+/* This callback occurs in a different thread; so all it does is pass this to
+ * the main context thread, or Purple will break. */
+static void
+_mdns_null_query_callback(PVOID pQueryContext, PMDNS_QUERY_HANDLE pQueryHandle,
+ PDNS_QUERY_RESULT pQueryResults)
+{
+ if (pQueryResults->QueryStatus == ERROR_SUCCESS) {
+ DnsAPIRecordData *data = g_new(DnsAPIRecordData, 1);
+ data->dns_record = pQueryResults->pQueryRecords;
+ data->context = pQueryContext;
+ g_timeout_add_seconds_full(G_PRIORITY_DEFAULT, 0,
+ G_SOURCE_FUNC(_mdns_null_query_parse), data,
+ (GDestroyNotify)_mdns_record_data_free);
+ } else {
+ g_timeout_add_seconds(0, G_SOURCE_FUNC(_mdns_null_query_error),
+ GUINT_TO_POINTER(pQueryResults->QueryStatus));
+ if (pQueryResults->pQueryRecords) {
+ DnsRecordListFree(pQueryResults->pQueryRecords, DnsFreeRecordList);
+ }
+ }
+}
+
/****************************
* mdns_interface functions *
****************************/
@@ -493,6 +550,11 @@
g_return_if_fail(idata != NULL);
+ if (idata->null_query != NULL) {
+ DnsStopMulticastQuery(idata->null_query);
+ g_free(idata->null_query);
+ }
+
g_clear_pointer(&buddy->mdns_impl_data, g_free);
}
@@ -500,8 +562,46 @@
dnsapi_mdns_retrieve_buddy_icon(BonjourBuddy *buddy)
{
Win32BuddyImplData *idata = buddy->mdns_impl_data;
+ gchar *service_name = NULL;
+ MDNS_QUERY_REQUEST query;
+ DNS_STATUS status;
+ GError *error = NULL;
g_return_if_fail(idata != NULL);
+
+ /* Cancel any existing query */
+ if (idata->null_query != NULL) {
+ DnsStopMulticastQuery(idata->null_query);
+ g_clear_pointer(&idata->null_query, g_free);
+ }
+
+ service_name = g_strjoin(".", buddy->name, LINK_LOCAL_DOMAIN_NAME, NULL);
+ query.Version = DNS_QUERY_REQUEST_VERSION1;
+ query.Query = g_utf8_to_utf16(service_name, -1, NULL, NULL, &error);
+ if (error != NULL) {
+ purple_debug_error("bonjour",
+ "Unable to convert service name '%s' to UTF-16: %s",
+ service_name, error->message);
+ g_error_free(error);
+ g_free(service_name);
+ return;
+ }
+ query.QueryType = DNS_TYPE_NULL;
+ query.QueryOptions = DNS_QUERY_STANDARD;
+ query.InterfaceIndex = 0;
+ query.pQueryCallback = _mdns_null_query_callback;
+ query.pQueryContext = buddy;
+ idata->null_query = g_new0(MDNS_QUERY_HANDLE, 1);
+
+ status = DnsStartMulticastQuery(&query, idata->null_query);
+ if (status != ERROR_SUCCESS) {
+ purple_debug_error("bonjour",
+ "Unable to query buddy icon record for %s (%ld)",
+ buddy->name, status);
+ }
+
+ g_free((gpointer)query.Query);
+ g_free(service_name);
}
gboolean