mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-02-01 17:35:17 +00:00
Introduce generic RPC module for advertising via MDNS
Allow RPC servers to advertise themselves using MDNS, via Avahi * src/rpc/virnetserver.c, src/rpc/virnetserver.h: Allow registration of MDNS services via avahi * src/rpc/virnetserverservice.c, src/rpc/virnetserverservice.h: Add API to fetch the listen port number * src/rpc/virnetsocket.c, src/rpc/virnetsocket.h: Add API to fetch the local port number * src/rpc/virnetservermdns.c, src/rpc/virnetservermdns.h: Represent an MDNS advertisement
This commit is contained in:
parent
4e00b1da8a
commit
e23ec81db6
3
cfg.mk
3
cfg.mk
@ -128,6 +128,9 @@ useless_free_options = \
|
|||||||
--name=virNetMessageFree \
|
--name=virNetMessageFree \
|
||||||
--name=virNetServerFree \
|
--name=virNetServerFree \
|
||||||
--name=virNetServerClientFree \
|
--name=virNetServerClientFree \
|
||||||
|
--name=virNetServerMDNSFree \
|
||||||
|
--name=virNetServerMDNSEntryFree \
|
||||||
|
--name=virNetServerMDNSGroupFree \
|
||||||
--name=virNetServerProgramFree \
|
--name=virNetServerProgramFree \
|
||||||
--name=virNetServerServiceFree \
|
--name=virNetServerServiceFree \
|
||||||
--name=virNetSocketFree \
|
--name=virNetSocketFree \
|
||||||
|
@ -74,6 +74,7 @@ src/rpc/virnetsaslcontext.c
|
|||||||
src/rpc/virnetsocket.c
|
src/rpc/virnetsocket.c
|
||||||
src/rpc/virnetserver.c
|
src/rpc/virnetserver.c
|
||||||
src/rpc/virnetserverclient.c
|
src/rpc/virnetserverclient.c
|
||||||
|
src/rpc/virnetservermdns.c
|
||||||
src/rpc/virnetserverprogram.c
|
src/rpc/virnetserverprogram.c
|
||||||
src/rpc/virnettlscontext.c
|
src/rpc/virnettlscontext.c
|
||||||
src/secret/secret_driver.c
|
src/secret/secret_driver.c
|
||||||
|
@ -1220,10 +1220,19 @@ libvirt_net_rpc_server_la_SOURCES = \
|
|||||||
rpc/virnetserverservice.h rpc/virnetserverservice.c \
|
rpc/virnetserverservice.h rpc/virnetserverservice.c \
|
||||||
rpc/virnetserverclient.h rpc/virnetserverclient.c \
|
rpc/virnetserverclient.h rpc/virnetserverclient.c \
|
||||||
rpc/virnetserver.h rpc/virnetserver.c
|
rpc/virnetserver.h rpc/virnetserver.c
|
||||||
|
if HAVE_AVAHI
|
||||||
|
libvirt_net_rpc_server_la_SOURCES += \
|
||||||
|
rpc/virnetservermdns.h rpc/virnetservermdns.c
|
||||||
|
else
|
||||||
|
EXTRA_DIST += \
|
||||||
|
rpc/virnetservermdns.h rpc/virnetservermdns.c
|
||||||
|
endif
|
||||||
libvirt_net_rpc_server_la_CFLAGS = \
|
libvirt_net_rpc_server_la_CFLAGS = \
|
||||||
|
$(AVAHI_CFLAGS) \
|
||||||
$(AM_CFLAGS)
|
$(AM_CFLAGS)
|
||||||
libvirt_net_rpc_server_la_LDFLAGS = \
|
libvirt_net_rpc_server_la_LDFLAGS = \
|
||||||
$(AM_LDFLAGS) \
|
$(AM_LDFLAGS) \
|
||||||
|
$(AVAHI_LIBS) \
|
||||||
$(CYGWIN_EXTRA_LDFLAGS) \
|
$(CYGWIN_EXTRA_LDFLAGS) \
|
||||||
$(MINGW_EXTRA_LDFLAGS)
|
$(MINGW_EXTRA_LDFLAGS)
|
||||||
libvirt_net_rpc_server_la_LIBADD = \
|
libvirt_net_rpc_server_la_LIBADD = \
|
||||||
|
@ -36,6 +36,9 @@
|
|||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "files.h"
|
#include "files.h"
|
||||||
#include "event.h"
|
#include "event.h"
|
||||||
|
#if HAVE_AVAHI
|
||||||
|
# include "virnetservermdns.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#define VIR_FROM_THIS VIR_FROM_RPC
|
#define VIR_FROM_THIS VIR_FROM_RPC
|
||||||
#define virNetError(code, ...) \
|
#define virNetError(code, ...) \
|
||||||
@ -75,6 +78,12 @@ struct _virNetServer {
|
|||||||
int sigwrite;
|
int sigwrite;
|
||||||
int sigwatch;
|
int sigwatch;
|
||||||
|
|
||||||
|
char *mdnsGroupName;
|
||||||
|
#if HAVE_AVAHI
|
||||||
|
virNetServerMDNSPtr mdns;
|
||||||
|
virNetServerMDNSGroupPtr mdnsGroup;
|
||||||
|
#endif
|
||||||
|
|
||||||
size_t nservices;
|
size_t nservices;
|
||||||
virNetServerServicePtr *services;
|
virNetServerServicePtr *services;
|
||||||
|
|
||||||
@ -260,6 +269,7 @@ static void virNetServerFatalSignal(int sig, siginfo_t *siginfo ATTRIBUTE_UNUSED
|
|||||||
virNetServerPtr virNetServerNew(size_t min_workers,
|
virNetServerPtr virNetServerNew(size_t min_workers,
|
||||||
size_t max_workers,
|
size_t max_workers,
|
||||||
size_t max_clients,
|
size_t max_clients,
|
||||||
|
const char *mdnsGroupName,
|
||||||
virNetServerClientInitHook clientInitHook)
|
virNetServerClientInitHook clientInitHook)
|
||||||
{
|
{
|
||||||
virNetServerPtr srv;
|
virNetServerPtr srv;
|
||||||
@ -282,6 +292,20 @@ virNetServerPtr virNetServerNew(size_t min_workers,
|
|||||||
srv->clientInitHook = clientInitHook;
|
srv->clientInitHook = clientInitHook;
|
||||||
srv->privileged = geteuid() == 0 ? true : false;
|
srv->privileged = geteuid() == 0 ? true : false;
|
||||||
|
|
||||||
|
if (mdnsGroupName &&
|
||||||
|
!(srv->mdnsGroupName = strdup(mdnsGroupName))) {
|
||||||
|
virReportOOMError();
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
#if HAVE_AVAHI
|
||||||
|
if (srv->mdnsGroupName) {
|
||||||
|
if (!(srv->mdns = virNetServerMDNSNew()))
|
||||||
|
goto error;
|
||||||
|
if (!(srv->mdnsGroup = virNetServerMDNSAddGroup(srv->mdns, mdnsGroupName)))
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (virMutexInit(&srv->lock) < 0) {
|
if (virMutexInit(&srv->lock) < 0) {
|
||||||
virNetError(VIR_ERR_INTERNAL_ERROR, "%s",
|
virNetError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||||
_("cannot initialize mutex"));
|
_("cannot initialize mutex"));
|
||||||
@ -494,13 +518,26 @@ error:
|
|||||||
|
|
||||||
|
|
||||||
int virNetServerAddService(virNetServerPtr srv,
|
int virNetServerAddService(virNetServerPtr srv,
|
||||||
virNetServerServicePtr svc)
|
virNetServerServicePtr svc,
|
||||||
|
const char *mdnsEntryName ATTRIBUTE_UNUSED)
|
||||||
{
|
{
|
||||||
virNetServerLock(srv);
|
virNetServerLock(srv);
|
||||||
|
|
||||||
if (VIR_EXPAND_N(srv->services, srv->nservices, 1) < 0)
|
if (VIR_EXPAND_N(srv->services, srv->nservices, 1) < 0)
|
||||||
goto no_memory;
|
goto no_memory;
|
||||||
|
|
||||||
|
#if HAVE_AVAHI
|
||||||
|
if (mdnsEntryName) {
|
||||||
|
int port = virNetServerServiceGetPort(svc);
|
||||||
|
virNetServerMDNSEntryPtr entry;
|
||||||
|
|
||||||
|
if (!(entry = virNetServerMDNSAddEntry(srv->mdnsGroup,
|
||||||
|
mdnsEntryName,
|
||||||
|
port)))
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
srv->services[srv->nservices-1] = svc;
|
srv->services[srv->nservices-1] = svc;
|
||||||
virNetServerServiceRef(svc);
|
virNetServerServiceRef(svc);
|
||||||
|
|
||||||
@ -513,6 +550,9 @@ int virNetServerAddService(virNetServerPtr srv,
|
|||||||
|
|
||||||
no_memory:
|
no_memory:
|
||||||
virReportOOMError();
|
virReportOOMError();
|
||||||
|
#if HAVE_AVAHI
|
||||||
|
error:
|
||||||
|
#endif
|
||||||
virNetServerUnlock(srv);
|
virNetServerUnlock(srv);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -582,6 +622,12 @@ void virNetServerRun(virNetServerPtr srv)
|
|||||||
|
|
||||||
virNetServerLock(srv);
|
virNetServerLock(srv);
|
||||||
|
|
||||||
|
#if HAVE_AVAHI
|
||||||
|
if (srv->mdns &&
|
||||||
|
virNetServerMDNSStart(srv->mdns) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (srv->autoShutdownTimeout &&
|
if (srv->autoShutdownTimeout &&
|
||||||
(timerid = virEventAddTimeout(-1,
|
(timerid = virEventAddTimeout(-1,
|
||||||
virNetServerAutoShutdownTimer,
|
virNetServerAutoShutdownTimer,
|
||||||
|
@ -37,6 +37,7 @@ typedef int (*virNetServerClientInitHook)(virNetServerPtr srv,
|
|||||||
virNetServerPtr virNetServerNew(size_t min_workers,
|
virNetServerPtr virNetServerNew(size_t min_workers,
|
||||||
size_t max_workers,
|
size_t max_workers,
|
||||||
size_t max_clients,
|
size_t max_clients,
|
||||||
|
const char *mdnsGroupName,
|
||||||
virNetServerClientInitHook clientInitHook);
|
virNetServerClientInitHook clientInitHook);
|
||||||
|
|
||||||
typedef int (*virNetServerAutoShutdownFunc)(virNetServerPtr srv, void *opaque);
|
typedef int (*virNetServerAutoShutdownFunc)(virNetServerPtr srv, void *opaque);
|
||||||
@ -58,7 +59,8 @@ int virNetServerAddSignalHandler(virNetServerPtr srv,
|
|||||||
void *opaque);
|
void *opaque);
|
||||||
|
|
||||||
int virNetServerAddService(virNetServerPtr srv,
|
int virNetServerAddService(virNetServerPtr srv,
|
||||||
virNetServerServicePtr svc);
|
virNetServerServicePtr svc,
|
||||||
|
const char *mdnsEntryName);
|
||||||
|
|
||||||
int virNetServerAddProgram(virNetServerPtr srv,
|
int virNetServerAddProgram(virNetServerPtr srv,
|
||||||
virNetServerProgramPtr prog);
|
virNetServerProgramPtr prog);
|
||||||
|
614
src/rpc/virnetservermdns.c
Normal file
614
src/rpc/virnetservermdns.c
Normal file
@ -0,0 +1,614 @@
|
|||||||
|
/*
|
||||||
|
* virnetservermdns.c: advertise server sockets
|
||||||
|
*
|
||||||
|
* Copyright (C) 2011 Red Hat, Inc.
|
||||||
|
* Copyright (C) 2007 Daniel P. Berrange
|
||||||
|
*
|
||||||
|
* Derived from Avahi example service provider code.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library 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
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
* Author: Daniel P. Berrange <berrange@redhat.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
|
#include <time.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <avahi-client/client.h>
|
||||||
|
#include <avahi-client/publish.h>
|
||||||
|
|
||||||
|
#include <avahi-common/alternative.h>
|
||||||
|
#include <avahi-common/simple-watch.h>
|
||||||
|
#include <avahi-common/malloc.h>
|
||||||
|
#include <avahi-common/error.h>
|
||||||
|
#include <avahi-common/timeval.h>
|
||||||
|
|
||||||
|
#include "virnetservermdns.h"
|
||||||
|
#include "event.h"
|
||||||
|
#include "event_poll.h"
|
||||||
|
#include "memory.h"
|
||||||
|
#include "virterror_internal.h"
|
||||||
|
#include "logging.h"
|
||||||
|
|
||||||
|
#define VIR_FROM_THIS VIR_FROM_RPC
|
||||||
|
#define virNetError(code, ...) \
|
||||||
|
virReportErrorHelper(VIR_FROM_THIS, code, __FILE__, \
|
||||||
|
__FUNCTION__, __LINE__, __VA_ARGS__)
|
||||||
|
|
||||||
|
struct _virNetServerMDNSEntry {
|
||||||
|
char *type;
|
||||||
|
int port;
|
||||||
|
virNetServerMDNSEntryPtr next;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _virNetServerMDNSGroup {
|
||||||
|
virNetServerMDNSPtr mdns;
|
||||||
|
AvahiEntryGroup *handle;
|
||||||
|
char *name;
|
||||||
|
virNetServerMDNSEntryPtr entry;
|
||||||
|
virNetServerMDNSGroupPtr next;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _virNetServerMDNS {
|
||||||
|
AvahiClient *client;
|
||||||
|
AvahiPoll *poller;
|
||||||
|
virNetServerMDNSGroupPtr group;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Avahi API requires this struct name in the app :-( */
|
||||||
|
struct AvahiWatch {
|
||||||
|
int watch;
|
||||||
|
int fd;
|
||||||
|
int revents;
|
||||||
|
AvahiWatchCallback callback;
|
||||||
|
void *userdata;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Avahi API requires this struct name in the app :-( */
|
||||||
|
struct AvahiTimeout {
|
||||||
|
int timer;
|
||||||
|
AvahiTimeoutCallback callback;
|
||||||
|
void *userdata;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void virNetServerMDNSCreateServices(virNetServerMDNSGroupPtr group);
|
||||||
|
|
||||||
|
/* Called whenever the entry group state changes */
|
||||||
|
static void virNetServerMDNSGroupCallback(AvahiEntryGroup *g ATTRIBUTE_UNUSED,
|
||||||
|
AvahiEntryGroupState state,
|
||||||
|
void *data)
|
||||||
|
{
|
||||||
|
virNetServerMDNSGroupPtr group = data;
|
||||||
|
|
||||||
|
switch (state) {
|
||||||
|
case AVAHI_ENTRY_GROUP_ESTABLISHED:
|
||||||
|
/* The entry group has been established successfully */
|
||||||
|
VIR_DEBUG("Group '%s' established", group->name);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AVAHI_ENTRY_GROUP_COLLISION:
|
||||||
|
{
|
||||||
|
char *n;
|
||||||
|
|
||||||
|
/* A service name collision happened. Let's pick a new name */
|
||||||
|
n = avahi_alternative_service_name(group->name);
|
||||||
|
VIR_FREE(group->name);
|
||||||
|
group->name = n;
|
||||||
|
|
||||||
|
VIR_DEBUG("Group name collision, renaming service to '%s'", group->name);
|
||||||
|
|
||||||
|
/* And recreate the services */
|
||||||
|
virNetServerMDNSCreateServices(group);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AVAHI_ENTRY_GROUP_FAILURE :
|
||||||
|
VIR_DEBUG("Group failure: %s",
|
||||||
|
avahi_strerror(avahi_client_errno(group->mdns->client)));
|
||||||
|
|
||||||
|
/* Some kind of failure happened while we were registering our services */
|
||||||
|
//avahi_simple_poll_quit(simple_poll);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AVAHI_ENTRY_GROUP_UNCOMMITED:
|
||||||
|
case AVAHI_ENTRY_GROUP_REGISTERING:
|
||||||
|
;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void virNetServerMDNSCreateServices(virNetServerMDNSGroupPtr group)
|
||||||
|
{
|
||||||
|
virNetServerMDNSPtr mdns = group->mdns;
|
||||||
|
virNetServerMDNSEntryPtr entry;
|
||||||
|
int ret;
|
||||||
|
VIR_DEBUG("Adding services to '%s'", group->name);
|
||||||
|
|
||||||
|
/* If we've no services to advertise, just reset the group to make
|
||||||
|
* sure it is emptied of any previously advertised services */
|
||||||
|
if (!group->entry) {
|
||||||
|
if (group->handle)
|
||||||
|
avahi_entry_group_reset(group->handle);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If this is the first time we're called, let's create a new entry group */
|
||||||
|
if (!group->handle) {
|
||||||
|
VIR_DEBUG("Creating initial group %s", group->name);
|
||||||
|
if (!(group->handle =
|
||||||
|
avahi_entry_group_new(mdns->client,
|
||||||
|
virNetServerMDNSGroupCallback,
|
||||||
|
group))) {
|
||||||
|
VIR_DEBUG("avahi_entry_group_new() failed: %s",
|
||||||
|
avahi_strerror(avahi_client_errno(mdns->client)));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
entry = group->entry;
|
||||||
|
while (entry) {
|
||||||
|
if ((ret = avahi_entry_group_add_service(group->handle,
|
||||||
|
AVAHI_IF_UNSPEC,
|
||||||
|
AVAHI_PROTO_UNSPEC,
|
||||||
|
0,
|
||||||
|
group->name,
|
||||||
|
entry->type,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
entry->port,
|
||||||
|
NULL)) < 0) {
|
||||||
|
VIR_DEBUG("Failed to add %s service on port %d: %s",
|
||||||
|
entry->type, entry->port, avahi_strerror(ret));
|
||||||
|
avahi_entry_group_reset(group->handle);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
entry = entry->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tell the server to register the service */
|
||||||
|
if ((ret = avahi_entry_group_commit(group->handle)) < 0) {
|
||||||
|
avahi_entry_group_reset(group->handle);
|
||||||
|
VIR_DEBUG("Failed to commit entry_group: %s",
|
||||||
|
avahi_strerror(ret));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void virNetServerMDNSClientCallback(AvahiClient *c,
|
||||||
|
AvahiClientState state,
|
||||||
|
void *data)
|
||||||
|
{
|
||||||
|
virNetServerMDNSPtr mdns = data;
|
||||||
|
virNetServerMDNSGroupPtr group;
|
||||||
|
if (!mdns->client)
|
||||||
|
mdns->client = c;
|
||||||
|
|
||||||
|
VIR_DEBUG("Callback state=%d", state);
|
||||||
|
|
||||||
|
/* Called whenever the client or server state changes */
|
||||||
|
switch (state) {
|
||||||
|
case AVAHI_CLIENT_S_RUNNING:
|
||||||
|
/* The server has startup successfully and registered its host
|
||||||
|
* name on the network, so it's time to create our services */
|
||||||
|
VIR_DEBUG("Client running %p", mdns->client);
|
||||||
|
group = mdns->group;
|
||||||
|
while (group) {
|
||||||
|
virNetServerMDNSCreateServices(group);
|
||||||
|
group = group->next;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AVAHI_CLIENT_FAILURE:
|
||||||
|
VIR_DEBUG("Client failure: %s",
|
||||||
|
avahi_strerror(avahi_client_errno(c)));
|
||||||
|
virNetServerMDNSStop(mdns);
|
||||||
|
virNetServerMDNSStart(mdns);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AVAHI_CLIENT_S_COLLISION:
|
||||||
|
/* Let's drop our registered services. When the server is back
|
||||||
|
* in AVAHI_SERVER_RUNNING state we will register them
|
||||||
|
* again with the new host name. */
|
||||||
|
|
||||||
|
/* Fallthrough */
|
||||||
|
|
||||||
|
case AVAHI_CLIENT_S_REGISTERING:
|
||||||
|
/* The server records are now being established. This
|
||||||
|
* might be caused by a host name change. We need to wait
|
||||||
|
* for our own records to register until the host name is
|
||||||
|
* properly established. */
|
||||||
|
VIR_DEBUG("Client collision/connecting %p", mdns->client);
|
||||||
|
group = mdns->group;
|
||||||
|
while (group) {
|
||||||
|
if (group->handle)
|
||||||
|
avahi_entry_group_reset(group->handle);
|
||||||
|
group = group->next;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AVAHI_CLIENT_CONNECTING:
|
||||||
|
VIR_DEBUG("Client connecting.... %p", mdns->client);
|
||||||
|
;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void virNetServerMDNSWatchDispatch(int watch, int fd, int events, void *opaque)
|
||||||
|
{
|
||||||
|
AvahiWatch *w = opaque;
|
||||||
|
int fd_events = virEventPollToNativeEvents(events);
|
||||||
|
VIR_DEBUG("Dispatch watch %d FD %d Event %d", watch, fd, fd_events);
|
||||||
|
w->revents = fd_events;
|
||||||
|
w->callback(w, fd, fd_events, w->userdata);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void virNetServerMDNSWatchDofree(void *w)
|
||||||
|
{
|
||||||
|
VIR_FREE(w);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static AvahiWatch *virNetServerMDNSWatchNew(const AvahiPoll *api ATTRIBUTE_UNUSED,
|
||||||
|
int fd, AvahiWatchEvent event,
|
||||||
|
AvahiWatchCallback cb, void *userdata)
|
||||||
|
{
|
||||||
|
AvahiWatch *w;
|
||||||
|
virEventHandleType hEvents;
|
||||||
|
if (VIR_ALLOC(w) < 0) {
|
||||||
|
virReportOOMError();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
w->fd = fd;
|
||||||
|
w->revents = 0;
|
||||||
|
w->callback = cb;
|
||||||
|
w->userdata = userdata;
|
||||||
|
|
||||||
|
VIR_DEBUG("New handle %p FD %d Event %d", w, w->fd, event);
|
||||||
|
hEvents = virEventPollFromNativeEvents(event);
|
||||||
|
if ((w->watch = virEventAddHandle(fd, hEvents,
|
||||||
|
virNetServerMDNSWatchDispatch,
|
||||||
|
w,
|
||||||
|
virNetServerMDNSWatchDofree)) < 0) {
|
||||||
|
virNetError(VIR_ERR_INTERNAL_ERROR,
|
||||||
|
_("Failed to add watch for fd %d events %d"), fd, hEvents);
|
||||||
|
VIR_FREE(w);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return w;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void virNetServerMDNSWatchUpdate(AvahiWatch *w, AvahiWatchEvent event)
|
||||||
|
{
|
||||||
|
VIR_DEBUG("Update handle %p FD %d Event %d", w, w->fd, event);
|
||||||
|
virEventUpdateHandle(w->watch, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
static AvahiWatchEvent virNetServerMDNSWatchGetEvents(AvahiWatch *w)
|
||||||
|
{
|
||||||
|
VIR_DEBUG("Get handle events %p %d", w, w->fd);
|
||||||
|
return w->revents;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void virNetServerMDNSWatchFree(AvahiWatch *w)
|
||||||
|
{
|
||||||
|
VIR_DEBUG("Free handle %p %d", w, w->fd);
|
||||||
|
virEventRemoveHandle(w->watch);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void virNetServerMDNSTimeoutDispatch(int timer ATTRIBUTE_UNUSED, void *opaque)
|
||||||
|
{
|
||||||
|
AvahiTimeout *t = (AvahiTimeout*)opaque;
|
||||||
|
VIR_DEBUG("Dispatch timeout %p %d", t, timer);
|
||||||
|
virEventUpdateTimeout(t->timer, -1);
|
||||||
|
t->callback(t, t->userdata);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void virNetServerMDNSTimeoutDofree(void *t)
|
||||||
|
{
|
||||||
|
VIR_FREE(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
static AvahiTimeout *virNetServerMDNSTimeoutNew(const AvahiPoll *api ATTRIBUTE_UNUSED,
|
||||||
|
const struct timeval *tv,
|
||||||
|
AvahiTimeoutCallback cb,
|
||||||
|
void *userdata)
|
||||||
|
{
|
||||||
|
AvahiTimeout *t;
|
||||||
|
struct timeval now;
|
||||||
|
long long nowms, thenms, timeout;
|
||||||
|
VIR_DEBUG("Add timeout TV %p", tv);
|
||||||
|
if (VIR_ALLOC(t) < 0) {
|
||||||
|
virReportOOMError();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gettimeofday(&now, NULL) < 0) {
|
||||||
|
virReportSystemError(errno, "%s",
|
||||||
|
_("Unable to get current time"));
|
||||||
|
VIR_FREE(t);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
VIR_DEBUG("Trigger timed for %d %d %d %d",
|
||||||
|
(int)now.tv_sec, (int)now.tv_usec,
|
||||||
|
(int)(tv ? tv->tv_sec : 0), (int)(tv ? tv->tv_usec : 0));
|
||||||
|
nowms = (now.tv_sec * 1000ll) + (now.tv_usec / 1000ll);
|
||||||
|
if (tv) {
|
||||||
|
thenms = (tv->tv_sec * 1000ll) + (tv->tv_usec/1000ll);
|
||||||
|
timeout = thenms > nowms ? nowms - thenms : 0;
|
||||||
|
if (timeout < 0)
|
||||||
|
timeout = 0;
|
||||||
|
} else {
|
||||||
|
timeout = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
t->timer = virEventAddTimeout(timeout,
|
||||||
|
virNetServerMDNSTimeoutDispatch,
|
||||||
|
t,
|
||||||
|
virNetServerMDNSTimeoutDofree);
|
||||||
|
t->callback = cb;
|
||||||
|
t->userdata = userdata;
|
||||||
|
|
||||||
|
if (t->timer < 0) {
|
||||||
|
virNetError(VIR_ERR_INTERNAL_ERROR,
|
||||||
|
_("Failed to add timer with timeout %d"), (int)timeout);
|
||||||
|
VIR_FREE(t);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void virNetServerMDNSTimeoutUpdate(AvahiTimeout *t, const struct timeval *tv)
|
||||||
|
{
|
||||||
|
struct timeval now;
|
||||||
|
long long nowms, thenms, timeout;
|
||||||
|
VIR_DEBUG("Update timeout %p TV %p", t, tv);
|
||||||
|
if (gettimeofday(&now, NULL) < 0) {
|
||||||
|
VIR_FREE(t);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
nowms = (now.tv_sec * 1000ll) + (now.tv_usec / 1000ll);
|
||||||
|
if (tv) {
|
||||||
|
thenms = ((tv->tv_sec * 1000ll) + (tv->tv_usec/1000ll));
|
||||||
|
timeout = thenms > nowms ? nowms - thenms : 0;
|
||||||
|
if (timeout < 0)
|
||||||
|
timeout = 0;
|
||||||
|
} else {
|
||||||
|
timeout = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
virEventUpdateTimeout(t->timer, timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void virNetServerMDNSTimeoutFree(AvahiTimeout *t)
|
||||||
|
{
|
||||||
|
VIR_DEBUG("Free timeout %p", t);
|
||||||
|
virEventRemoveTimeout(t->timer);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static AvahiPoll *virNetServerMDNSCreatePoll(void)
|
||||||
|
{
|
||||||
|
AvahiPoll *p;
|
||||||
|
if (VIR_ALLOC(p) < 0) {
|
||||||
|
virReportOOMError();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
p->userdata = NULL;
|
||||||
|
|
||||||
|
p->watch_new = virNetServerMDNSWatchNew;
|
||||||
|
p->watch_update = virNetServerMDNSWatchUpdate;
|
||||||
|
p->watch_get_events = virNetServerMDNSWatchGetEvents;
|
||||||
|
p->watch_free = virNetServerMDNSWatchFree;
|
||||||
|
|
||||||
|
p->timeout_new = virNetServerMDNSTimeoutNew;
|
||||||
|
p->timeout_update = virNetServerMDNSTimeoutUpdate;
|
||||||
|
p->timeout_free = virNetServerMDNSTimeoutFree;
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virNetServerMDNS *virNetServerMDNSNew(void)
|
||||||
|
{
|
||||||
|
virNetServerMDNS *mdns;
|
||||||
|
if (VIR_ALLOC(mdns) < 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* Allocate main loop object */
|
||||||
|
if (!(mdns->poller = virNetServerMDNSCreatePoll())) {
|
||||||
|
VIR_FREE(mdns);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return mdns;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int virNetServerMDNSStart(virNetServerMDNS *mdns)
|
||||||
|
{
|
||||||
|
int error;
|
||||||
|
VIR_DEBUG("Starting client %p", mdns);
|
||||||
|
mdns->client = avahi_client_new(mdns->poller,
|
||||||
|
AVAHI_CLIENT_NO_FAIL,
|
||||||
|
virNetServerMDNSClientCallback,
|
||||||
|
mdns, &error);
|
||||||
|
|
||||||
|
if (!mdns->client) {
|
||||||
|
virNetError(VIR_ERR_INTERNAL_ERROR,
|
||||||
|
_("Failed to create mDNS client: %s"),
|
||||||
|
avahi_strerror(error));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virNetServerMDNSGroupPtr virNetServerMDNSAddGroup(virNetServerMDNS *mdns,
|
||||||
|
const char *name)
|
||||||
|
{
|
||||||
|
virNetServerMDNSGroupPtr group;
|
||||||
|
|
||||||
|
VIR_DEBUG("Adding group '%s'", name);
|
||||||
|
if (VIR_ALLOC(group) < 0) {
|
||||||
|
virReportOOMError();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(group->name = strdup(name))) {
|
||||||
|
VIR_FREE(group);
|
||||||
|
virReportOOMError();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
group->mdns = mdns;
|
||||||
|
group->next = mdns->group;
|
||||||
|
mdns->group = group;
|
||||||
|
return group;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void virNetServerMDNSRemoveGroup(virNetServerMDNSPtr mdns,
|
||||||
|
virNetServerMDNSGroupPtr group)
|
||||||
|
{
|
||||||
|
virNetServerMDNSGroupPtr tmp = mdns->group, prev = NULL;
|
||||||
|
|
||||||
|
while (tmp) {
|
||||||
|
if (tmp == group) {
|
||||||
|
VIR_FREE(group->name);
|
||||||
|
if (prev)
|
||||||
|
prev->next = group->next;
|
||||||
|
else
|
||||||
|
group->mdns->group = group->next;
|
||||||
|
VIR_FREE(group);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
prev = tmp;
|
||||||
|
tmp = tmp->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virNetServerMDNSEntryPtr virNetServerMDNSAddEntry(virNetServerMDNSGroupPtr group,
|
||||||
|
const char *type,
|
||||||
|
int port)
|
||||||
|
{
|
||||||
|
virNetServerMDNSEntryPtr entry;
|
||||||
|
|
||||||
|
VIR_DEBUG("Adding entry %s %d to group %s", type, port, group->name);
|
||||||
|
if (VIR_ALLOC(entry) < 0) {
|
||||||
|
virReportOOMError();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
entry->port = port;
|
||||||
|
if (!(entry->type = strdup(type))) {
|
||||||
|
VIR_FREE(entry);
|
||||||
|
virReportOOMError();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
entry->next = group->entry;
|
||||||
|
group->entry = entry;
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void virNetServerMDNSRemoveEntry(virNetServerMDNSGroupPtr group,
|
||||||
|
virNetServerMDNSEntryPtr entry)
|
||||||
|
{
|
||||||
|
virNetServerMDNSEntryPtr tmp = group->entry, prev = NULL;
|
||||||
|
|
||||||
|
while (tmp) {
|
||||||
|
if (tmp == entry) {
|
||||||
|
VIR_FREE(entry->type);
|
||||||
|
if (prev)
|
||||||
|
prev->next = entry->next;
|
||||||
|
else
|
||||||
|
group->entry = entry->next;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
prev = tmp;
|
||||||
|
tmp = tmp->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void virNetServerMDNSStop(virNetServerMDNSPtr mdns)
|
||||||
|
{
|
||||||
|
virNetServerMDNSGroupPtr group = mdns->group;
|
||||||
|
while (group) {
|
||||||
|
if (group->handle) {
|
||||||
|
avahi_entry_group_free(group->handle);
|
||||||
|
group->handle = NULL;
|
||||||
|
}
|
||||||
|
group = group->next;
|
||||||
|
}
|
||||||
|
if (mdns->client)
|
||||||
|
avahi_client_free(mdns->client);
|
||||||
|
mdns->client = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void virNetServerMDNSFree(virNetServerMDNSPtr mdns)
|
||||||
|
{
|
||||||
|
virNetServerMDNSGroupPtr group, tmp;
|
||||||
|
|
||||||
|
if (!mdns)
|
||||||
|
return;
|
||||||
|
|
||||||
|
group = mdns->group;
|
||||||
|
while (group) {
|
||||||
|
tmp = group->next;
|
||||||
|
virNetServerMDNSGroupFree(group);
|
||||||
|
group = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
VIR_FREE(mdns);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void virNetServerMDNSGroupFree(virNetServerMDNSGroupPtr grp)
|
||||||
|
{
|
||||||
|
virNetServerMDNSEntryPtr entry, tmp;
|
||||||
|
|
||||||
|
if (!grp)
|
||||||
|
return;
|
||||||
|
|
||||||
|
entry = grp->entry;
|
||||||
|
while (entry) {
|
||||||
|
tmp = entry->next;
|
||||||
|
virNetServerMDNSEntryFree(entry);
|
||||||
|
entry = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
VIR_FREE(grp);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void virNetServerMDNSEntryFree(virNetServerMDNSEntryPtr entry)
|
||||||
|
{
|
||||||
|
if (!entry)
|
||||||
|
return;
|
||||||
|
|
||||||
|
VIR_FREE(entry);
|
||||||
|
}
|
109
src/rpc/virnetservermdns.h
Normal file
109
src/rpc/virnetservermdns.h
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
/*
|
||||||
|
* virnetservermdns.c: advertise server sockets
|
||||||
|
*
|
||||||
|
* Copyright (C) 2011 Red Hat, Inc.
|
||||||
|
* Copyright (C) 2007 Daniel P. Berrange
|
||||||
|
*
|
||||||
|
* Derived from Avahi example service provider code.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library 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
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
* Author: Daniel P. Berrange <berrange@redhat.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __VIR_NET_SERVER_MDNS_H__
|
||||||
|
# define __VIR_NET_SERVER_MDNS_H__
|
||||||
|
|
||||||
|
# include "internal.h"
|
||||||
|
|
||||||
|
typedef struct _virNetServerMDNS virNetServerMDNS;
|
||||||
|
typedef virNetServerMDNS *virNetServerMDNSPtr;
|
||||||
|
typedef struct _virNetServerMDNSGroup virNetServerMDNSGroup;
|
||||||
|
typedef virNetServerMDNSGroup *virNetServerMDNSGroupPtr;
|
||||||
|
typedef struct _virNetServerMDNSEntry virNetServerMDNSEntry;
|
||||||
|
typedef virNetServerMDNSEntry *virNetServerMDNSEntryPtr;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepares a new mdns manager object for use
|
||||||
|
*/
|
||||||
|
virNetServerMDNSPtr virNetServerMDNSNew(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts the mdns client, advertising any groups/entries currently registered
|
||||||
|
*
|
||||||
|
* @mdns: manager to start advertising
|
||||||
|
*
|
||||||
|
* Starts the mdns client. Services may not be immediately visible, since
|
||||||
|
* it may asynchronously wait for the mdns service to startup
|
||||||
|
*
|
||||||
|
* returns -1 upon failure, 0 upon success.
|
||||||
|
*/
|
||||||
|
int virNetServerMDNSStart(virNetServerMDNSPtr mdns);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stops the mdns client, removing any advertisements
|
||||||
|
*
|
||||||
|
* @mdns: manager to start advertising
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void virNetServerMDNSStop(virNetServerMDNSPtr mdns);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a group container for advertisement
|
||||||
|
*
|
||||||
|
* @mdns manager to attach the group to
|
||||||
|
* @name unique human readable service name
|
||||||
|
*
|
||||||
|
* returns the group record, or NULL upon failure
|
||||||
|
*/
|
||||||
|
virNetServerMDNSGroupPtr virNetServerMDNSAddGroup(virNetServerMDNSPtr mdns,
|
||||||
|
const char *name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes a group container from advertisement
|
||||||
|
*
|
||||||
|
* @mdns amanger to detach group from
|
||||||
|
* @group group to remove
|
||||||
|
*/
|
||||||
|
void virNetServerMDNSRemoveGroup(virNetServerMDNSPtr mdns,
|
||||||
|
virNetServerMDNSGroupPtr group);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a service entry in a group
|
||||||
|
*
|
||||||
|
* @group group to attach the entry to
|
||||||
|
* @type service type string
|
||||||
|
* @port tcp port number
|
||||||
|
*
|
||||||
|
* returns the service record, or NULL upon failure
|
||||||
|
*/
|
||||||
|
virNetServerMDNSEntryPtr virNetServerMDNSAddEntry(virNetServerMDNSGroupPtr group,
|
||||||
|
const char *type, int port);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes a service entry from a group
|
||||||
|
*
|
||||||
|
* @group group to detach service entry from
|
||||||
|
* @entry service entry to remove
|
||||||
|
*/
|
||||||
|
void virNetServerMDNSRemoveEntry(virNetServerMDNSGroupPtr group,
|
||||||
|
virNetServerMDNSEntryPtr entry);
|
||||||
|
|
||||||
|
void virNetServerMDNSFree(virNetServerMDNSPtr ptr);
|
||||||
|
void virNetServerMDNSGroupFree(virNetServerMDNSGroupPtr ptr);
|
||||||
|
void virNetServerMDNSEntryFree(virNetServerMDNSEntryPtr ptr);
|
||||||
|
|
||||||
|
#endif /* __VIR_NET_SERVER_MDNS_H__ */
|
@ -187,6 +187,14 @@ error:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int virNetServerServiceGetPort(virNetServerServicePtr svc)
|
||||||
|
{
|
||||||
|
/* We're assuming if there are multiple sockets
|
||||||
|
* for IPv4 & 6, then they are all on same port */
|
||||||
|
return virNetSocketGetPort(svc->socks[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int virNetServerServiceGetAuth(virNetServerServicePtr svc)
|
int virNetServerServiceGetAuth(virNetServerServicePtr svc)
|
||||||
{
|
{
|
||||||
return svc->auth;
|
return svc->auth;
|
||||||
|
@ -48,6 +48,8 @@ virNetServerServicePtr virNetServerServiceNewUNIX(const char *path,
|
|||||||
bool readonly,
|
bool readonly,
|
||||||
virNetTLSContextPtr tls);
|
virNetTLSContextPtr tls);
|
||||||
|
|
||||||
|
int virNetServerServiceGetPort(virNetServerServicePtr svc);
|
||||||
|
|
||||||
int virNetServerServiceGetAuth(virNetServerServicePtr svc);
|
int virNetServerServiceGetAuth(virNetServerServicePtr svc);
|
||||||
bool virNetServerServiceIsReadonly(virNetServerServicePtr svc);
|
bool virNetServerServiceIsReadonly(virNetServerServicePtr svc);
|
||||||
|
|
||||||
|
@ -682,6 +682,12 @@ bool virNetSocketIsLocal(virNetSocketPtr sock)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int virNetSocketGetPort(virNetSocketPtr sock)
|
||||||
|
{
|
||||||
|
return virSocketGetPort(&sock->localAddr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef SO_PEERCRED
|
#ifdef SO_PEERCRED
|
||||||
int virNetSocketGetLocalIdentity(virNetSocketPtr sock,
|
int virNetSocketGetLocalIdentity(virNetSocketPtr sock,
|
||||||
uid_t *uid,
|
uid_t *uid,
|
||||||
|
@ -77,6 +77,8 @@ int virNetSocketNewConnectExternal(const char **cmdargv,
|
|||||||
int virNetSocketGetFD(virNetSocketPtr sock);
|
int virNetSocketGetFD(virNetSocketPtr sock);
|
||||||
bool virNetSocketIsLocal(virNetSocketPtr sock);
|
bool virNetSocketIsLocal(virNetSocketPtr sock);
|
||||||
|
|
||||||
|
int virNetSocketGetPort(virNetSocketPtr sock);
|
||||||
|
|
||||||
int virNetSocketGetLocalIdentity(virNetSocketPtr sock,
|
int virNetSocketGetLocalIdentity(virNetSocketPtr sock,
|
||||||
uid_t *uid,
|
uid_t *uid,
|
||||||
pid_t *pid);
|
pid_t *pid);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user