mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-29 02:21:44 +00:00
[wpiutil] Handle multicast service collision on linux (#3734)
This commit is contained in:
@@ -40,6 +40,8 @@ AvahiFunctionTable::AvahiFunctionTable() {
|
||||
AvahiFunctionLoad(string_list_new_from_array);
|
||||
AvahiFunctionLoad(string_list_free);
|
||||
AvahiFunctionLoad(unescape_label);
|
||||
AvahiFunctionLoad(alternative_service_name);
|
||||
AvahiFunctionLoad(free);
|
||||
|
||||
lib = dlopen("libavahi-client.so.3", RTLD_LAZY);
|
||||
|
||||
@@ -60,6 +62,7 @@ AvahiFunctionTable::AvahiFunctionTable() {
|
||||
AvahiFunctionLoad(entry_group_reset);
|
||||
AvahiFunctionLoad(entry_group_is_empty);
|
||||
AvahiFunctionLoad(entry_group_commit);
|
||||
AvahiFunctionLoad(entry_group_get_client);
|
||||
|
||||
valid = true;
|
||||
}
|
||||
|
||||
@@ -159,6 +159,70 @@ enum { AVAHI_IF_UNSPEC = -1 };
|
||||
|
||||
enum { AVAHI_PROTO_INET = 0, AVAHI_PROTO_INET6 = 1, AVAHI_PROTO_UNSPEC = -1 };
|
||||
|
||||
enum {
|
||||
AVAHI_OK = 0,
|
||||
AVAHI_ERR_FAILURE = -1,
|
||||
AVAHI_ERR_BAD_STATE = -2,
|
||||
AVAHI_ERR_INVALID_HOST_NAME = -3,
|
||||
AVAHI_ERR_INVALID_DOMAIN_NAME = -4,
|
||||
AVAHI_ERR_NO_NETWORK = -5,
|
||||
AVAHI_ERR_INVALID_TTL = -6,
|
||||
AVAHI_ERR_IS_PATTERN = -7,
|
||||
AVAHI_ERR_COLLISION = -8,
|
||||
AVAHI_ERR_INVALID_RECORD = -9,
|
||||
|
||||
AVAHI_ERR_INVALID_SERVICE_NAME = -10,
|
||||
AVAHI_ERR_INVALID_SERVICE_TYPE = -11,
|
||||
AVAHI_ERR_INVALID_PORT = -12,
|
||||
AVAHI_ERR_INVALID_KEY = -13,
|
||||
AVAHI_ERR_INVALID_ADDRESS = -14,
|
||||
AVAHI_ERR_TIMEOUT = -15,
|
||||
AVAHI_ERR_TOO_MANY_CLIENTS = -16,
|
||||
AVAHI_ERR_TOO_MANY_OBJECTS = -17,
|
||||
AVAHI_ERR_TOO_MANY_ENTRIES = -18,
|
||||
AVAHI_ERR_OS = -19,
|
||||
|
||||
AVAHI_ERR_ACCESS_DENIED = -20,
|
||||
AVAHI_ERR_INVALID_OPERATION = -21,
|
||||
AVAHI_ERR_DBUS_ERROR = -22,
|
||||
AVAHI_ERR_DISCONNECTED = -23,
|
||||
AVAHI_ERR_NO_MEMORY = -24,
|
||||
AVAHI_ERR_INVALID_OBJECT = -25,
|
||||
AVAHI_ERR_NO_DAEMON = -26,
|
||||
AVAHI_ERR_INVALID_INTERFACE = -27,
|
||||
AVAHI_ERR_INVALID_PROTOCOL = -28,
|
||||
AVAHI_ERR_INVALID_FLAGS = -29,
|
||||
|
||||
AVAHI_ERR_NOT_FOUND = -30,
|
||||
AVAHI_ERR_INVALID_CONFIG = -31,
|
||||
AVAHI_ERR_VERSION_MISMATCH = -32,
|
||||
AVAHI_ERR_INVALID_SERVICE_SUBTYPE = -33,
|
||||
AVAHI_ERR_INVALID_PACKET = -34,
|
||||
AVAHI_ERR_INVALID_DNS_ERROR = -35,
|
||||
AVAHI_ERR_DNS_FORMERR = -36,
|
||||
AVAHI_ERR_DNS_SERVFAIL = -37,
|
||||
AVAHI_ERR_DNS_NXDOMAIN = -38,
|
||||
AVAHI_ERR_DNS_NOTIMP = -39,
|
||||
|
||||
AVAHI_ERR_DNS_REFUSED = -40,
|
||||
AVAHI_ERR_DNS_YXDOMAIN = -41,
|
||||
AVAHI_ERR_DNS_YXRRSET = -42,
|
||||
AVAHI_ERR_DNS_NXRRSET = -43,
|
||||
AVAHI_ERR_DNS_NOTAUTH = -44,
|
||||
AVAHI_ERR_DNS_NOTZONE = -45,
|
||||
AVAHI_ERR_INVALID_RDATA = -46,
|
||||
AVAHI_ERR_INVALID_DNS_CLASS = -47,
|
||||
AVAHI_ERR_INVALID_DNS_TYPE = -48,
|
||||
AVAHI_ERR_NOT_SUPPORTED = -49,
|
||||
|
||||
AVAHI_ERR_NOT_PERMITTED = -50,
|
||||
AVAHI_ERR_INVALID_ARGUMENT = -51,
|
||||
AVAHI_ERR_IS_EMPTY = -52,
|
||||
AVAHI_ERR_NO_CHANGE = -53,
|
||||
|
||||
AVAHI_ERR_MAX = -54
|
||||
};
|
||||
|
||||
namespace wpi {
|
||||
class AvahiFunctionTable {
|
||||
public:
|
||||
@@ -208,6 +272,7 @@ class AvahiFunctionTable {
|
||||
AvahiFunction(entry_group_reset, int, (AvahiEntryGroup*));
|
||||
AvahiFunction(entry_group_is_empty, int, (AvahiEntryGroup*));
|
||||
AvahiFunction(entry_group_commit, int, (AvahiEntryGroup*));
|
||||
AvahiFunction(entry_group_get_client, AvahiClient*, (AvahiEntryGroup*));
|
||||
|
||||
AvahiFunction(string_list_new_from_array, AvahiStringList*,
|
||||
(const char** array, int len));
|
||||
@@ -217,6 +282,8 @@ class AvahiFunctionTable {
|
||||
(AvahiServiceBrowser*));
|
||||
|
||||
AvahiFunction(unescape_label, char*, (const char**, char*, size_t));
|
||||
AvahiFunction(alternative_service_name, char*, (const char*));
|
||||
AvahiFunction(free, void, (void*));
|
||||
|
||||
bool IsValid() const { return valid; }
|
||||
|
||||
|
||||
@@ -29,22 +29,49 @@ struct MulticastServiceAnnouncer::Impl {
|
||||
}
|
||||
};
|
||||
|
||||
static void EntryGroupCallback(AvahiEntryGroup*, AvahiEntryGroupState, void*) {}
|
||||
static void RegisterService(AvahiClient* client,
|
||||
MulticastServiceAnnouncer::Impl* impl);
|
||||
|
||||
static void EntryGroupCallback(AvahiEntryGroup* group,
|
||||
AvahiEntryGroupState state, void* userdata) {
|
||||
if (state == AVAHI_ENTRY_GROUP_COLLISION) {
|
||||
// Remote collision
|
||||
MulticastServiceAnnouncer::Impl* impl =
|
||||
reinterpret_cast<MulticastServiceAnnouncer::Impl*>(userdata);
|
||||
char* newName =
|
||||
impl->table.alternative_service_name(impl->serviceName.c_str());
|
||||
impl->serviceName = newName;
|
||||
impl->table.free(newName);
|
||||
RegisterService(impl->table.entry_group_get_client(group), impl);
|
||||
}
|
||||
}
|
||||
|
||||
static void RegisterService(AvahiClient* client,
|
||||
MulticastServiceAnnouncer::Impl* impl) {
|
||||
if (impl->group == nullptr) {
|
||||
impl->group =
|
||||
impl->table.entry_group_new(client, EntryGroupCallback, nullptr);
|
||||
impl->group = impl->table.entry_group_new(client, EntryGroupCallback, impl);
|
||||
}
|
||||
|
||||
if (impl->table.entry_group_is_empty(impl->group)) {
|
||||
impl->table.entry_group_add_service_strlst(
|
||||
impl->group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC,
|
||||
AVAHI_PUBLISH_USE_MULTICAST, impl->serviceName.c_str(),
|
||||
impl->serviceType.c_str(), "local", nullptr, impl->port,
|
||||
impl->stringList);
|
||||
impl->table.entry_group_commit(impl->group);
|
||||
while (true) {
|
||||
if (impl->table.entry_group_is_empty(impl->group)) {
|
||||
auto ret = impl->table.entry_group_add_service_strlst(
|
||||
impl->group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC,
|
||||
AVAHI_PUBLISH_USE_MULTICAST, impl->serviceName.c_str(),
|
||||
impl->serviceType.c_str(), "local", nullptr, impl->port,
|
||||
impl->stringList);
|
||||
if (ret == AVAHI_ERR_COLLISION) {
|
||||
// Local collision
|
||||
char* newName =
|
||||
impl->table.alternative_service_name(impl->serviceName.c_str());
|
||||
impl->serviceName = newName;
|
||||
impl->table.free(newName);
|
||||
continue;
|
||||
} else if (ret != AVAHI_OK) {
|
||||
break;
|
||||
}
|
||||
impl->table.entry_group_commit(impl->group);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user