pidgin/pidgin
Clone
Summary
Browse
Changes
Graph
Route GLib debug logging directly to the Finch debug window
2021-10-18, Elliott Sales de Andrade
1896a80ff8e3
Route GLib debug logging directly to the Finch debug window
Instead of flowing through purple debug, this merges some bits of the existing GLib log handler, and the purple debug printer.
Testing Done:
Open the Debug window an see some `GLib-*` outputs.
Reviewed at https://reviews.imfreedom.org/r/1057/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301, USA.
*/
#include
<purple.h>
#include
"buddy.h"
#include
"bonjour.h"
#include
<avahi-client/client.h>
#include
<avahi-client/lookup.h>
#include
<avahi-client/publish.h>
#include
<avahi-common/address.h>
#include
<avahi-common/malloc.h>
#include
<avahi-common/error.h>
#include
<avahi-common/strlst.h>
#include
<avahi-glib/glib-malloc.h>
#include
<avahi-glib/glib-watch.h>
/* Avahi only defines the types that it actually uses (which at this time doesn't include NULL) */
#ifndef AVAHI_DNS_TYPE_NULL
#define AVAHI_DNS_TYPE_NULL 0x0A
#endif
/* data used by avahi bonjour implementation */
typedef
struct
{
AvahiClient
*
client
;
AvahiGLibPoll
*
glib_poll
;
AvahiServiceBrowser
*
sb
;
AvahiEntryGroup
*
group
;
AvahiEntryGroup
*
buddy_icon_group
;
}
AvahiSessionImplData
;
typedef
struct
{
AvahiServiceResolver
*
resolver
;
AvahiIfIndex
interface
;
AvahiProtocol
protocol
;
gchar
*
name
;
gchar
*
type
;
gchar
*
domain
;
/* This is a reference to the entry in BonjourBuddy->ips */
const
char
*
ip
;
}
AvahiSvcResolverData
;
typedef
struct
{
GSList
*
resolvers
;
AvahiRecordBrowser
*
buddy_icon_rec_browser
;
}
AvahiBuddyImplData
;
static
gint
_find_resolver_data
(
gconstpointer
a
,
gconstpointer
b
)
{
const
AvahiSvcResolverData
*
rd_a
=
a
;
const
AvahiSvcResolverData
*
rd_b
=
b
;
gint
ret
=
1
;
if
(
rd_a
->
interface
==
rd_b
->
interface
&&
rd_a
->
protocol
==
rd_b
->
protocol
&&
purple_strequal
(
rd_a
->
name
,
rd_b
->
name
)
&&
purple_strequal
(
rd_a
->
type
,
rd_b
->
type
)
&&
purple_strequal
(
rd_a
->
domain
,
rd_b
->
domain
))
{
ret
=
0
;
}
return
ret
;
}
static
gint
_find_resolver_data_by_resolver
(
gconstpointer
a
,
gconstpointer
b
)
{
const
AvahiSvcResolverData
*
rd_a
=
a
;
const
AvahiServiceResolver
*
resolver
=
b
;
gint
ret
=
1
;
if
(
rd_a
->
resolver
==
resolver
)
ret
=
0
;
return
ret
;
}
static
void
_cleanup_resolver_data
(
AvahiSvcResolverData
*
rd
)
{
if
(
rd
->
resolver
)
avahi_service_resolver_free
(
rd
->
resolver
);
g_free
(
rd
->
name
);
g_free
(
rd
->
type
);
g_free
(
rd
->
domain
);
g_free
(
rd
);
}
static
void
_resolver_callback
(
AvahiServiceResolver
*
r
,
AvahiIfIndex
interface
,
AvahiProtocol
protocol
,
AvahiResolverEvent
event
,
const
char
*
name
,
const
char
*
type
,
const
char
*
domain
,
const
char
*
host_name
,
const
AvahiAddress
*
a
,
uint16_t
port
,
AvahiStringList
*
txt
,
AvahiLookupResultFlags
flags
,
void
*
userdata
)
{
PurpleBuddy
*
pb
;
BonjourBuddy
*
bb
;
PurpleAccount
*
account
=
userdata
;
AvahiStringList
*
l
;
size_t
size
;
char
*
key
,
*
value
;
char
ip
[
AVAHI_ADDRESS_STR_MAX
];
AvahiBuddyImplData
*
b_impl
;
AvahiSvcResolverData
*
rd
;
GSList
*
res
;
g_return_if_fail
(
r
!=
NULL
);
pb
=
purple_blist_find_buddy
(
account
,
name
);
bb
=
(
pb
!=
NULL
)
?
purple_buddy_get_protocol_data
(
pb
)
:
NULL
;
switch
(
event
)
{
case
AVAHI_RESOLVER_FAILURE
:
purple_debug_error
(
"bonjour"
,
"_resolve_callback - Failure: %s
\n
"
,
avahi_strerror
(
avahi_client_errno
(
avahi_service_resolver_get_client
(
r
))));
avahi_service_resolver_free
(
r
);
if
(
bb
!=
NULL
)
{
b_impl
=
bb
->
mdns_impl_data
;
res
=
g_slist_find_custom
(
b_impl
->
resolvers
,
r
,
_find_resolver_data_by_resolver
);
if
(
res
!=
NULL
)
{
rd
=
res
->
data
;
b_impl
->
resolvers
=
g_slist_delete_link
(
b_impl
->
resolvers
,
res
);
/* We've already freed the resolver */
rd
->
resolver
=
NULL
;
_cleanup_resolver_data
(
rd
);
/* If this was the last resolver, remove the buddy */
if
(
b_impl
->
resolvers
==
NULL
)
bonjour_buddy_signed_off
(
pb
);
}
}
break
;
case
AVAHI_RESOLVER_FOUND
:
purple_debug_info
(
"bonjour"
,
"_resolve_callback - name:%s account:%p bb:%p
\n
"
,
name
,
account
,
bb
);
/* create a buddy record */
if
(
bb
==
NULL
)
bb
=
bonjour_buddy_new
(
name
,
account
);
b_impl
=
bb
->
mdns_impl_data
;
/* If we're reusing an existing buddy, it may be a new resolver or an existing one. */
res
=
g_slist_find_custom
(
b_impl
->
resolvers
,
r
,
_find_resolver_data_by_resolver
);
if
(
res
!=
NULL
)
rd
=
res
->
data
;
else
{
rd
=
g_new0
(
AvahiSvcResolverData
,
1
);
rd
->
resolver
=
r
;
rd
->
interface
=
interface
;
rd
->
protocol
=
protocol
;
rd
->
name
=
g_strdup
(
name
);
rd
->
type
=
g_strdup
(
type
);
rd
->
domain
=
g_strdup
(
domain
);
b_impl
->
resolvers
=
g_slist_prepend
(
b_impl
->
resolvers
,
rd
);
}
/* Get the ip as a string */
ip
[
0
]
=
'\0'
;
avahi_address_snprint
(
ip
,
AVAHI_ADDRESS_STR_MAX
,
a
);
if
(
protocol
==
AVAHI_PROTO_INET6
)
append_iface_if_linklocal
(
ip
,
interface
);
purple_debug_info
(
"bonjour"
,
"_resolve_callback - name:%s ip:%s prev_ip:%s
\n
"
,
name
,
ip
,
rd
->
ip
);
if
(
rd
->
ip
==
NULL
||
!
purple_strequal
(
rd
->
ip
,
ip
))
{
/* We store duplicates in bb->ips, so we always remove the one */
if
(
rd
->
ip
!=
NULL
)
{
bb
->
ips
=
g_slist_remove
(
bb
->
ips
,
rd
->
ip
);
g_free
((
gchar
*
)
rd
->
ip
);
}
rd
->
ip
=
g_strdup
(
ip
);
/* IPv6 goes at the front of the list and IPv4 at the end so that we "prefer" IPv6, if present */
if
(
protocol
==
AVAHI_PROTO_INET6
)
{
bb
->
ips
=
g_slist_prepend
(
bb
->
ips
,
(
gchar
*
)
rd
->
ip
);
}
else
{
bb
->
ips
=
g_slist_append
(
bb
->
ips
,
(
gchar
*
)
rd
->
ip
);
}
}
bb
->
port_p2pj
=
port
;
/* Obtain the parameters from the text_record */
clear_bonjour_buddy_values
(
bb
);
for
(
l
=
txt
;
l
!=
NULL
;
l
=
l
->
next
)
{
if
(
avahi_string_list_get_pair
(
l
,
&
key
,
&
value
,
&
size
)
<
0
)
continue
;
set_bonjour_buddy_value
(
bb
,
key
,
value
,
size
);
/* TODO: Since we're using the glib allocator, I think we
* can use the values instead of re-copying them */
avahi_free
(
key
);
avahi_free
(
value
);
}
if
(
!
bonjour_buddy_check
(
bb
))
{
b_impl
->
resolvers
=
g_slist_remove
(
b_impl
->
resolvers
,
rd
);
_cleanup_resolver_data
(
rd
);
/* If this was the last resolver, remove the buddy */
if
(
b_impl
->
resolvers
==
NULL
)
{
if
(
pb
!=
NULL
)
bonjour_buddy_signed_off
(
pb
);
else
bonjour_buddy_delete
(
bb
);
}
}
else
/* Add or update the buddy in our buddy list */
bonjour_buddy_add_to_purple
(
bb
,
pb
);
break
;
default
:
purple_debug_info
(
"bonjour"
,
"Unrecognized Service Resolver event: %d.
\n
"
,
event
);
}
}
static
void
_browser_callback
(
AvahiServiceBrowser
*
b
,
AvahiIfIndex
interface
,
AvahiProtocol
protocol
,
AvahiBrowserEvent
event
,
const
char
*
name
,
const
char
*
type
,
const
char
*
domain
,
AvahiLookupResultFlags
flags
,
void
*
userdata
)
{
PurpleAccount
*
account
=
userdata
;
PurpleBuddy
*
pb
=
NULL
;
switch
(
event
)
{
case
AVAHI_BROWSER_FAILURE
:
purple_debug_error
(
"bonjour"
,
"_browser_callback - Failure: %s
\n
"
,
avahi_strerror
(
avahi_client_errno
(
avahi_service_browser_get_client
(
b
))));
/* TODO: This is an error that should be handled. */
break
;
case
AVAHI_BROWSER_NEW
:
/* A new peer has joined the network and uses iChat bonjour */
purple_debug_info
(
"bonjour"
,
"_browser_callback - new service
\n
"
);
/* Make sure it isn't us */
if
(
purple_utf8_strcasecmp
(
name
,
bonjour_get_jid
(
account
))
!=
0
)
{
if
(
!
avahi_service_resolver_new
(
avahi_service_browser_get_client
(
b
),
interface
,
protocol
,
name
,
type
,
domain
,
protocol
,
0
,
_resolver_callback
,
account
))
{
purple_debug_warning
(
"bonjour"
,
"_browser_callback -- Error initiating resolver: %s
\n
"
,
avahi_strerror
(
avahi_client_errno
(
avahi_service_browser_get_client
(
b
))));
}
}
break
;
case
AVAHI_BROWSER_REMOVE
:
purple_debug_info
(
"bonjour"
,
"_browser_callback - Remove service
\n
"
);
pb
=
purple_blist_find_buddy
(
account
,
name
);
if
(
pb
!=
NULL
)
{
BonjourBuddy
*
bb
=
purple_buddy_get_protocol_data
(
pb
);
AvahiBuddyImplData
*
b_impl
;
GSList
*
l
;
AvahiSvcResolverData
*
rd_search
;
g_return_if_fail
(
bb
!=
NULL
);
b_impl
=
bb
->
mdns_impl_data
;
/* There may be multiple presences, we should only get rid of this one */
rd_search
=
g_new0
(
AvahiSvcResolverData
,
1
);
rd_search
->
interface
=
interface
;
rd_search
->
protocol
=
protocol
;
rd_search
->
name
=
(
gchar
*
)
name
;
rd_search
->
type
=
(
gchar
*
)
type
;
rd_search
->
domain
=
(
gchar
*
)
domain
;
l
=
g_slist_find_custom
(
b_impl
->
resolvers
,
rd_search
,
_find_resolver_data
);
g_free
(
rd_search
);
if
(
l
!=
NULL
)
{
AvahiSvcResolverData
*
rd
=
l
->
data
;
b_impl
->
resolvers
=
g_slist_delete_link
(
b_impl
->
resolvers
,
l
);
/* This IP is no longer available */
if
(
rd
->
ip
!=
NULL
)
{
bb
->
ips
=
g_slist_remove
(
bb
->
ips
,
rd
->
ip
);
g_free
((
gchar
*
)
rd
->
ip
);
}
_cleanup_resolver_data
(
rd
);
/* If this was the last resolver, remove the buddy */
if
(
b_impl
->
resolvers
==
NULL
)
bonjour_buddy_signed_off
(
pb
);
}
}
break
;
case
AVAHI_BROWSER_ALL_FOR_NOW
:
case
AVAHI_BROWSER_CACHE_EXHAUSTED
:
break
;
default
:
purple_debug_info
(
"bonjour"
,
"Unrecognized Service browser event: %d.
\n
"
,
event
);
}
}
static
void
_buddy_icon_group_cb
(
AvahiEntryGroup
*
g
,
AvahiEntryGroupState
state
,
void
*
userdata
)
{
BonjourDnsSd
*
data
=
userdata
;
AvahiSessionImplData
*
idata
=
data
->
mdns_impl_data
;
g_return_if_fail
(
g
==
idata
->
buddy_icon_group
||
idata
->
buddy_icon_group
==
NULL
);
switch
(
state
)
{
case
AVAHI_ENTRY_GROUP_ESTABLISHED
:
purple_debug_info
(
"bonjour"
,
"Successfully registered buddy icon data.
\n
"
);
break
;
case
AVAHI_ENTRY_GROUP_COLLISION
:
purple_debug_error
(
"bonjour"
,
"Collision registering buddy icon data.
\n
"
);
break
;
case
AVAHI_ENTRY_GROUP_FAILURE
:
purple_debug_error
(
"bonjour"
,
"Error registering buddy icon data: %s.
\n
"
,
avahi_strerror
(
avahi_client_errno
(
avahi_entry_group_get_client
(
g
))));
break
;
case
AVAHI_ENTRY_GROUP_UNCOMMITED
:
case
AVAHI_ENTRY_GROUP_REGISTERING
:
break
;
}
}
static
void
_entry_group_cb
(
AvahiEntryGroup
*
g
,
AvahiEntryGroupState
state
,
void
*
userdata
)
{
AvahiSessionImplData
*
idata
=
userdata
;
g_return_if_fail
(
g
==
idata
->
group
||
idata
->
group
==
NULL
);
switch
(
state
)
{
case
AVAHI_ENTRY_GROUP_ESTABLISHED
:
purple_debug_info
(
"bonjour"
,
"Successfully registered service.
\n
"
);
break
;
case
AVAHI_ENTRY_GROUP_COLLISION
:
purple_debug_error
(
"bonjour"
,
"Collision registering entry group.
\n
"
);
/* TODO: Handle error - this should log out the account. (Possibly with "wants to die")*/
break
;
case
AVAHI_ENTRY_GROUP_FAILURE
:
purple_debug_error
(
"bonjour"
,
"Error registering entry group: %s
\n
."
,
avahi_strerror
(
avahi_client_errno
(
avahi_entry_group_get_client
(
g
))));
/* TODO: Handle error - this should log out the account.*/
break
;
case
AVAHI_ENTRY_GROUP_UNCOMMITED
:
case
AVAHI_ENTRY_GROUP_REGISTERING
:
break
;
}
}
static
void
_buddy_icon_record_cb
(
AvahiRecordBrowser
*
b
,
AvahiIfIndex
interface
,
AvahiProtocol
protocol
,
AvahiBrowserEvent
event
,
const
char
*
name
,
uint16_t
clazz
,
uint16_t
type
,
const
void
*
rdata
,
size_t
size
,
AvahiLookupResultFlags
flags
,
void
*
userdata
)
{
BonjourBuddy
*
buddy
=
userdata
;
AvahiBuddyImplData
*
idata
=
buddy
->
mdns_impl_data
;
switch
(
event
)
{
case
AVAHI_BROWSER_CACHE_EXHAUSTED
:
case
AVAHI_BROWSER_ALL_FOR_NOW
:
/* Ignore these "meta" informational events */
return
;
case
AVAHI_BROWSER_NEW
:
bonjour_buddy_got_buddy_icon
(
buddy
,
rdata
,
size
);
break
;
case
AVAHI_BROWSER_REMOVE
:
case
AVAHI_BROWSER_FAILURE
:
purple_debug_error
(
"bonjour"
,
"Error retrieving buddy icon record: %s
\n
"
,
avahi_strerror
(
avahi_client_errno
(
avahi_record_browser_get_client
(
b
))));
break
;
}
/* Stop listening */
avahi_record_browser_free
(
b
);
if
(
idata
->
buddy_icon_rec_browser
==
b
)
{
idata
->
buddy_icon_rec_browser
=
NULL
;
}
}
/****************************
* mdns_interface functions *
****************************/
static
gboolean
avahi_mdns_init_session
(
BonjourDnsSd
*
data
)
{
AvahiSessionImplData
*
idata
=
g_new0
(
AvahiSessionImplData
,
1
);
const
AvahiPoll
*
poll_api
;
int
error
;
/* Tell avahi to use g_malloc and g_free */
avahi_set_allocator
(
avahi_glib_allocator
());
/* This currently depends on the glib mainloop,
* we should make it use the libpurple abstraction */
idata
->
glib_poll
=
avahi_glib_poll_new
(
NULL
,
G_PRIORITY_DEFAULT
);
poll_api
=
avahi_glib_poll_get
(
idata
->
glib_poll
);
idata
->
client
=
avahi_client_new
(
poll_api
,
0
,
NULL
,
data
,
&
error
);
if
(
idata
->
client
==
NULL
)
{
purple_debug_error
(
"bonjour"
,
"Error initializing Avahi: %s
\n
"
,
avahi_strerror
(
error
));
avahi_glib_poll_free
(
idata
->
glib_poll
);
g_free
(
idata
);
return
FALSE
;
}
data
->
mdns_impl_data
=
idata
;
bonjour_dns_sd_set_jid
(
data
->
account
,
avahi_client_get_host_name
(
idata
->
client
));
return
TRUE
;
}
static
gboolean
avahi_mdns_publish
(
BonjourDnsSd
*
data
,
PublishType
type
,
GSList
*
records
)
{
int
publish_result
=
0
;
AvahiSessionImplData
*
idata
=
data
->
mdns_impl_data
;
AvahiStringList
*
lst
=
NULL
;
g_return_val_if_fail
(
idata
!=
NULL
,
FALSE
);
if
(
!
idata
->
group
)
{
idata
->
group
=
avahi_entry_group_new
(
idata
->
client
,
_entry_group_cb
,
idata
);
if
(
!
idata
->
group
)
{
purple_debug_error
(
"bonjour"
,
"Unable to initialize the data for the mDNS (%s).
\n
"
,
avahi_strerror
(
avahi_client_errno
(
idata
->
client
)));
return
FALSE
;
}
}
while
(
records
)
{
PurpleKeyValuePair
*
kvp
=
records
->
data
;
lst
=
avahi_string_list_add_pair
(
lst
,
kvp
->
key
,
kvp
->
value
);
records
=
records
->
next
;
}
/* Publish the service */
switch
(
type
)
{
case
PUBLISH_START
:
publish_result
=
avahi_entry_group_add_service_strlst
(
idata
->
group
,
AVAHI_IF_UNSPEC
,
AVAHI_PROTO_UNSPEC
,
0
,
bonjour_get_jid
(
data
->
account
),
LINK_LOCAL_RECORD_NAME
,
NULL
,
NULL
,
data
->
port_p2pj
,
lst
);
break
;
case
PUBLISH_UPDATE
:
publish_result
=
avahi_entry_group_update_service_txt_strlst
(
idata
->
group
,
AVAHI_IF_UNSPEC
,
AVAHI_PROTO_UNSPEC
,
0
,
bonjour_get_jid
(
data
->
account
),
LINK_LOCAL_RECORD_NAME
,
NULL
,
lst
);
break
;
}
/* Free the memory used by temp data */
avahi_string_list_free
(
lst
);
if
(
publish_result
<
0
)
{
purple_debug_error
(
"bonjour"
,
"Failed to add the "
LINK_LOCAL_RECORD_NAME
" service. Error: %s
\n
"
,
avahi_strerror
(
publish_result
));
return
FALSE
;
}
if
(
type
==
PUBLISH_START
&&
(
publish_result
=
avahi_entry_group_commit
(
idata
->
group
))
<
0
)
{
purple_debug_error
(
"bonjour"
,
"Failed to commit "
LINK_LOCAL_RECORD_NAME
" service. Error: %s
\n
"
,
avahi_strerror
(
publish_result
));
return
FALSE
;
}
return
TRUE
;
}
static
gboolean
avahi_mdns_browse
(
BonjourDnsSd
*
data
)
{
AvahiSessionImplData
*
idata
=
data
->
mdns_impl_data
;
g_return_val_if_fail
(
idata
!=
NULL
,
FALSE
);
idata
->
sb
=
avahi_service_browser_new
(
idata
->
client
,
AVAHI_IF_UNSPEC
,
AVAHI_PROTO_UNSPEC
,
LINK_LOCAL_RECORD_NAME
,
NULL
,
0
,
_browser_callback
,
data
->
account
);
if
(
!
idata
->
sb
)
{
purple_debug_error
(
"bonjour"
,
"Unable to initialize service browser. Error: %s.
\n
"
,
avahi_strerror
(
avahi_client_errno
(
idata
->
client
)));
return
FALSE
;
}
return
TRUE
;
}
static
gboolean
avahi_mdns_set_buddy_icon_data
(
BonjourDnsSd
*
data
,
gconstpointer
avatar_data
,
gsize
avatar_len
)
{
AvahiSessionImplData
*
idata
=
data
->
mdns_impl_data
;
if
(
idata
==
NULL
||
idata
->
client
==
NULL
)
return
FALSE
;
if
(
avatar_data
!=
NULL
)
{
gboolean
new_group
=
FALSE
;
gchar
*
svc_name
;
int
ret
;
AvahiPublishFlags
flags
=
0
;
if
(
idata
->
buddy_icon_group
==
NULL
)
{
purple_debug_info
(
"bonjour"
,
"Setting new buddy icon.
\n
"
);
new_group
=
TRUE
;
idata
->
buddy_icon_group
=
avahi_entry_group_new
(
idata
->
client
,
_buddy_icon_group_cb
,
data
);
}
else
{
purple_debug_info
(
"bonjour"
,
"Updating existing buddy icon.
\n
"
);
flags
|=
AVAHI_PUBLISH_UPDATE
;
}
if
(
idata
->
buddy_icon_group
==
NULL
)
{
purple_debug_error
(
"bonjour"
,
"Unable to initialize the buddy icon group (%s).
\n
"
,
avahi_strerror
(
avahi_client_errno
(
idata
->
client
)));
return
FALSE
;
}
svc_name
=
g_strdup_printf
(
"%s."
LINK_LOCAL_RECORD_NAME
"local"
,
bonjour_get_jid
(
data
->
account
));
ret
=
avahi_entry_group_add_record
(
idata
->
buddy_icon_group
,
AVAHI_IF_UNSPEC
,
AVAHI_PROTO_UNSPEC
,
flags
,
svc_name
,
AVAHI_DNS_CLASS_IN
,
AVAHI_DNS_TYPE_NULL
,
120
,
avatar_data
,
avatar_len
);
g_free
(
svc_name
);
if
(
ret
<
0
)
{
purple_debug_error
(
"bonjour"
,
"Failed to register buddy icon. Error: %s
\n
"
,
avahi_strerror
(
ret
));
if
(
new_group
)
{
avahi_entry_group_free
(
idata
->
buddy_icon_group
);
idata
->
buddy_icon_group
=
NULL
;
}
return
FALSE
;
}
if
(
new_group
&&
(
ret
=
avahi_entry_group_commit
(
idata
->
buddy_icon_group
))
<
0
)
{
purple_debug_error
(
"bonjour"
,
"Failed to commit buddy icon group. Error: %s
\n
"
,
avahi_strerror
(
ret
));
avahi_entry_group_free
(
idata
->
buddy_icon_group
);
idata
->
buddy_icon_group
=
NULL
;
return
FALSE
;
}
}
else
if
(
idata
->
buddy_icon_group
!=
NULL
)
{
purple_debug_info
(
"bonjour"
,
"Removing existing buddy icon.
\n
"
);
avahi_entry_group_free
(
idata
->
buddy_icon_group
);
idata
->
buddy_icon_group
=
NULL
;
}
return
TRUE
;
}
static
void
avahi_mdns_stop
(
BonjourDnsSd
*
data
)
{
AvahiSessionImplData
*
idata
=
data
->
mdns_impl_data
;
if
(
idata
==
NULL
||
idata
->
client
==
NULL
)
return
;
if
(
idata
->
sb
!=
NULL
)
avahi_service_browser_free
(
idata
->
sb
);
avahi_client_free
(
idata
->
client
);
avahi_glib_poll_free
(
idata
->
glib_poll
);
g_free
(
idata
);
data
->
mdns_impl_data
=
NULL
;
}
static
void
avahi_mdns_init_buddy
(
BonjourBuddy
*
buddy
)
{
buddy
->
mdns_impl_data
=
g_new0
(
AvahiBuddyImplData
,
1
);
}
static
void
avahi_mdns_delete_buddy
(
BonjourBuddy
*
buddy
)
{
AvahiBuddyImplData
*
idata
=
buddy
->
mdns_impl_data
;
g_return_if_fail
(
idata
!=
NULL
);
if
(
idata
->
buddy_icon_rec_browser
!=
NULL
)
avahi_record_browser_free
(
idata
->
buddy_icon_rec_browser
);
g_slist_free_full
(
idata
->
resolvers
,
(
GDestroyNotify
)
_cleanup_resolver_data
);
g_free
(
idata
);
buddy
->
mdns_impl_data
=
NULL
;
}
static
void
avahi_mdns_retrieve_buddy_icon
(
BonjourBuddy
*
buddy
)
{
PurpleConnection
*
conn
=
purple_account_get_connection
(
buddy
->
account
);
BonjourData
*
bd
=
purple_connection_get_protocol_data
(
conn
);
AvahiSessionImplData
*
session_idata
=
bd
->
dns_sd_data
->
mdns_impl_data
;
AvahiBuddyImplData
*
idata
=
buddy
->
mdns_impl_data
;
gchar
*
name
;
g_return_if_fail
(
idata
!=
NULL
);
if
(
idata
->
buddy_icon_rec_browser
!=
NULL
)
avahi_record_browser_free
(
idata
->
buddy_icon_rec_browser
);
purple_debug_info
(
"bonjour"
,
"Retrieving buddy icon for '%s'.
\n
"
,
buddy
->
name
);
name
=
g_strdup_printf
(
"%s."
LINK_LOCAL_RECORD_NAME
"local"
,
buddy
->
name
);
idata
->
buddy_icon_rec_browser
=
avahi_record_browser_new
(
session_idata
->
client
,
AVAHI_IF_UNSPEC
,
AVAHI_PROTO_UNSPEC
,
name
,
AVAHI_DNS_CLASS_IN
,
AVAHI_DNS_TYPE_NULL
,
0
,
_buddy_icon_record_cb
,
buddy
);
g_free
(
name
);
if
(
!
idata
->
buddy_icon_rec_browser
)
{
purple_debug_error
(
"bonjour"
,
"Unable to initialize buddy icon record browser. Error: %s.
\n
"
,
avahi_strerror
(
avahi_client_errno
(
session_idata
->
client
)));
}
}
gboolean
mdns_available
(
void
)
{
_mdns_init_session
=
avahi_mdns_init_session
;
_mdns_publish
=
avahi_mdns_publish
;
_mdns_browse
=
avahi_mdns_browse
;
_mdns_stop
=
avahi_mdns_stop
;
_mdns_set_buddy_icon_data
=
avahi_mdns_set_buddy_icon_data
;
_mdns_init_buddy
=
avahi_mdns_init_buddy
;
_mdns_delete_buddy
=
avahi_mdns_delete_buddy
;
_mdns_retrieve_buddy_icon
=
avahi_mdns_retrieve_buddy_icon
;
return
TRUE
;
}