--- a/libpurple/protocols/bonjour/mdns_dnsapi.c Fri Jan 01 03:26:15 2021 -0500
+++ b/libpurple/protocols/bonjour/mdns_dnsapi.c Mon Jan 04 00:31:06 2021 -0500
@@ -32,13 +32,40 @@
/* data used by win32 bonjour implementation */
+ DNS_SERVICE_INSTANCE instance; + DNS_SERVICE_CANCEL register_cancel; +_mdns_service_register_main_context(gpointer data) + DWORD status = GPOINTER_TO_UINT(data); + /* TODO: deal with collision */ + if (status != ERROR_SUCCESS) { + purple_debug_error("bonjour", "service advertisement - error (%ld)", + purple_debug_info("bonjour", "service advertisement - success."); + return G_SOURCE_REMOVE; +/* This callback occurs in a different thread; so all it does is pass the + * result to the main context thread, or Purple will break. */ +_mdns_service_register_callback(DWORD status, PVOID pQueryContext, + PDNS_SERVICE_INSTANCE pInstance) + g_timeout_add_seconds(0, G_SOURCE_FUNC(_mdns_service_register_main_context), + GUINT_TO_POINTER(status)); /****************************
* mdns_interface functions *
****************************/
@@ -57,10 +84,138 @@
dnsapi_mdns_publish(BonjourDnsSd *data, PublishType type, GSList *records)
Win32SessionImplData *idata = data->mdns_impl_data;
+ PWSTR service_name = NULL; + DWORD dwPropertiesCount = 0; + DNS_SERVICE_REGISTER_REQUEST request; g_return_val_if_fail(idata != NULL, FALSE);
+ dwPropertiesCount = g_slist_length(records); + keys = g_new0(PCWSTR, dwPropertiesCount); + values = g_new0(PCWSTR, dwPropertiesCount); + for (i = 0; i < dwPropertiesCount; i++, records = records->next) { + PurpleKeyValuePair *kvp = records->data; + keys[i] = g_utf8_to_utf16(kvp->key, -1, NULL, NULL, &error); + "Unable to convert record key '%s' to UTF-16: %s", + (const gchar *)kvp->key, error->message); + values[i] = g_utf8_to_utf16(kvp->value, -1, NULL, NULL, &error); + "Unable to convert record value '%s' to UTF-16: %s", + (const gchar *)kvp->value, error->message); + for (i = 0; i < dwPropertiesCount; i++) { + g_free((gpointer)keys[i]); + g_free((gpointer)values[i]); + /* This seems to be required, though it doesn't appear to matter what + * its value is. Use whatever GLib determined to be the host name. */ + hostname = g_utf8_to_utf16(g_get_host_name(), -1, NULL, NULL, &error); + purple_debug_error("bonjour", + "Unable to convert hostname '%s' to UTF-16: %s", + g_get_host_name(), error->message); + for (i = 0; i < dwPropertiesCount; i++) { + g_free((gpointer)keys[i]); + g_free((gpointer)values[i]); + /* The DNS Service API requires this to be specified as one entry, + * including the .local suffix. */ + tmp = g_strjoin(".", bonjour_get_jid(data->account), + LINK_LOCAL_RECORD_NAME "local", NULL); + service_name = g_utf8_to_utf16(tmp, -1, NULL, NULL, &error); + purple_debug_error("bonjour", + "Unable to convert service name '%s' to UTF-16: %s", + for (i = 0; i < dwPropertiesCount; i++) { + g_free((gpointer)keys[i]); + g_free((gpointer)values[i]); + request.Version = DNS_QUERY_REQUEST_VERSION1; + request.InterfaceIndex = 0; + request.pServiceInstance = DnsServiceConstructInstance( + service_name, hostname, NULL, NULL, data->port_p2pj, 0, 0, + dwPropertiesCount, keys, values); + request.pRegisterCompletionCallback = _mdns_service_register_callback; + request.pQueryContext = idata; + request.hCredentials = NULL; + request.unicastEnabled = FALSE; + purple_debug_info("bonjour", "Registering presence on port %d", + status = DnsServiceRegister(&request, &idata->register_cancel); + purple_debug_info("bonjour", "Updating presence"); + status = DnsServiceRegister(&request, &idata->register_cancel); + if (status != DNS_REQUEST_PENDING) { + purple_debug_error("bonjour", + "Failed to publish presence service (%ld)", status); + /* Free the memory used by temp data */ + DnsServiceFreeInstance(request.pServiceInstance); + for (i = 0; i < dwPropertiesCount; i++) { + g_free((gpointer)keys[i]); + g_free((gpointer)values[i]);