mirror of
https://gitlab.freedesktop.org/xorg/xserver.git
synced 2025-12-20 23:20:03 +01:00
359 lines
7.5 KiB
C
359 lines
7.5 KiB
C
|
|
/*
|
||
|
|
* Copyright © 2008 Novell, Inc.
|
||
|
|
*
|
||
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||
|
|
* copy of this software and associated documentation files (the "Software"),
|
||
|
|
* to deal in the Software without restriction, including without limitation
|
||
|
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||
|
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||
|
|
* Software is furnished to do so, subject to the following conditions:
|
||
|
|
*
|
||
|
|
* The above copyright notice and this permission notice (including the next
|
||
|
|
* paragraph) shall be included in all copies or substantial portions of the
|
||
|
|
* Software.
|
||
|
|
*
|
||
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||
|
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||
|
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||
|
|
* DEALINGS IN THE SOFTWARE.
|
||
|
|
*
|
||
|
|
* Authors: Hubert Figuiere <hfiguiere@novell.com>
|
||
|
|
* David Reveman <davidr@novell.com>
|
||
|
|
*/
|
||
|
|
|
||
|
|
#ifdef HAVE_DMX_CONFIG_H
|
||
|
|
#include <dmx-config.h>
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#include <stdlib.h>
|
||
|
|
#include <unistd.h>
|
||
|
|
#include <avahi-client/client.h>
|
||
|
|
#include <avahi-client/publish.h>
|
||
|
|
#include <avahi-common/watch.h>
|
||
|
|
|
||
|
|
#include "dix.h"
|
||
|
|
#include "os.h"
|
||
|
|
#include "opaque.h"
|
||
|
|
#include "dmxavahi.h"
|
||
|
|
|
||
|
|
typedef struct _DMXAvahiPoll DMXAvahiPoll;
|
||
|
|
|
||
|
|
struct AvahiWatch {
|
||
|
|
struct AvahiWatch *next;
|
||
|
|
|
||
|
|
int fd;
|
||
|
|
AvahiWatchEvent event;
|
||
|
|
AvahiWatchCallback callback;
|
||
|
|
void *userdata;
|
||
|
|
|
||
|
|
DMXAvahiPoll *p;
|
||
|
|
};
|
||
|
|
|
||
|
|
struct AvahiTimeout {
|
||
|
|
struct AvahiTimeout *next;
|
||
|
|
|
||
|
|
AvahiTimeoutCallback callback;
|
||
|
|
void *userdata;
|
||
|
|
|
||
|
|
DMXAvahiPoll *p;
|
||
|
|
OsTimerPtr timer;
|
||
|
|
};
|
||
|
|
|
||
|
|
struct _DMXAvahiPoll {
|
||
|
|
AvahiPoll base;
|
||
|
|
|
||
|
|
AvahiWatch *watches;
|
||
|
|
AvahiTimeout *timeouts;
|
||
|
|
};
|
||
|
|
|
||
|
|
static DMXAvahiPoll avahi_poll;
|
||
|
|
static AvahiClient *avahi_client;
|
||
|
|
static AvahiEntryGroup *avahi_group;
|
||
|
|
|
||
|
|
static const char * _service_name = "DMX service on %s";
|
||
|
|
|
||
|
|
static AvahiWatch *
|
||
|
|
dmx_avahi_watch_new (const AvahiPoll *api,
|
||
|
|
int fd,
|
||
|
|
AvahiWatchEvent event,
|
||
|
|
AvahiWatchCallback callback,
|
||
|
|
void *userdata)
|
||
|
|
{
|
||
|
|
DMXAvahiPoll *p = (DMXAvahiPoll *) api;
|
||
|
|
AvahiWatch *w;
|
||
|
|
|
||
|
|
w = xalloc (sizeof (AvahiWatch));
|
||
|
|
if (!w)
|
||
|
|
return NULL;
|
||
|
|
|
||
|
|
w->fd = fd;
|
||
|
|
w->event = event;
|
||
|
|
w->callback = callback;
|
||
|
|
w->userdata = userdata;
|
||
|
|
w->p = p;
|
||
|
|
|
||
|
|
w->next = p->watches;
|
||
|
|
p->watches = w;
|
||
|
|
|
||
|
|
if (w->event & AVAHI_WATCH_IN)
|
||
|
|
AddEnabledDevice (fd);
|
||
|
|
|
||
|
|
return w;
|
||
|
|
}
|
||
|
|
|
||
|
|
static void
|
||
|
|
dmx_avahi_watch_update (AvahiWatch *w,
|
||
|
|
AvahiWatchEvent event)
|
||
|
|
{
|
||
|
|
if (event & AVAHI_WATCH_IN)
|
||
|
|
{
|
||
|
|
if (!(w->event & AVAHI_WATCH_IN))
|
||
|
|
AddEnabledDevice (w->fd);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
if (w->event & AVAHI_WATCH_IN)
|
||
|
|
RemoveEnabledDevice (w->fd);
|
||
|
|
}
|
||
|
|
|
||
|
|
w->event = event;
|
||
|
|
}
|
||
|
|
|
||
|
|
static AvahiWatchEvent
|
||
|
|
dmx_avahi_watch_get_events (AvahiWatch *w)
|
||
|
|
{
|
||
|
|
return AVAHI_WATCH_IN;
|
||
|
|
}
|
||
|
|
|
||
|
|
static void
|
||
|
|
dmx_avahi_watch_free (AvahiWatch *w)
|
||
|
|
{
|
||
|
|
DMXAvahiPoll *p = w->p;
|
||
|
|
AvahiWatch *prev;
|
||
|
|
|
||
|
|
for (prev = p->watches; prev; prev = prev->next)
|
||
|
|
if (prev->next == w)
|
||
|
|
break;
|
||
|
|
|
||
|
|
if (prev)
|
||
|
|
prev->next = w->next;
|
||
|
|
else
|
||
|
|
p->watches = w->next;
|
||
|
|
|
||
|
|
if (w->event & AVAHI_WATCH_IN)
|
||
|
|
RemoveEnabledDevice (w->fd);
|
||
|
|
|
||
|
|
free (w);
|
||
|
|
}
|
||
|
|
|
||
|
|
static CARD32
|
||
|
|
avahi_poll_timeout (OsTimerPtr timer,
|
||
|
|
CARD32 time,
|
||
|
|
pointer arg)
|
||
|
|
{
|
||
|
|
AvahiTimeout *t = (AvahiTimeout *) arg;
|
||
|
|
|
||
|
|
(*t->callback) (t, t->userdata);
|
||
|
|
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
static AvahiTimeout *
|
||
|
|
dmx_avahi_timeout_new (const AvahiPoll *api,
|
||
|
|
const struct timeval *tv,
|
||
|
|
AvahiTimeoutCallback callback,
|
||
|
|
void *userdata)
|
||
|
|
{
|
||
|
|
DMXAvahiPoll *p = (DMXAvahiPoll *) api;
|
||
|
|
AvahiTimeout *t;
|
||
|
|
|
||
|
|
t = xalloc (sizeof (AvahiTimeout));
|
||
|
|
if (!t)
|
||
|
|
return NULL;
|
||
|
|
|
||
|
|
t->callback = callback;
|
||
|
|
t->userdata = userdata;
|
||
|
|
t->timer = NULL;
|
||
|
|
t->p = p;
|
||
|
|
|
||
|
|
t->next = p->timeouts;
|
||
|
|
p->timeouts = t;
|
||
|
|
|
||
|
|
if (tv)
|
||
|
|
t->timer = TimerSet (NULL,
|
||
|
|
0,
|
||
|
|
((CARD16) tv->tv_sec) * 1000 + tv->tv_usec / 1000,
|
||
|
|
avahi_poll_timeout,
|
||
|
|
t);
|
||
|
|
|
||
|
|
return t;
|
||
|
|
}
|
||
|
|
|
||
|
|
static void
|
||
|
|
dmx_avahi_timeout_update (AvahiTimeout *t,
|
||
|
|
const struct timeval *tv)
|
||
|
|
{
|
||
|
|
if (tv)
|
||
|
|
t->timer = TimerSet (t->timer,
|
||
|
|
0,
|
||
|
|
((CARD16) tv->tv_sec) * 1000 + tv->tv_usec / 1000,
|
||
|
|
avahi_poll_timeout,
|
||
|
|
t);
|
||
|
|
else
|
||
|
|
TimerCancel (t->timer);
|
||
|
|
}
|
||
|
|
|
||
|
|
static void
|
||
|
|
dmx_avahi_timeout_free (AvahiTimeout *t)
|
||
|
|
{
|
||
|
|
DMXAvahiPoll *p = t->p;
|
||
|
|
AvahiTimeout *prev;
|
||
|
|
|
||
|
|
for (prev = p->timeouts; prev; prev = prev->next)
|
||
|
|
if (prev->next == t)
|
||
|
|
break;
|
||
|
|
|
||
|
|
if (prev)
|
||
|
|
prev->next = t->next;
|
||
|
|
else
|
||
|
|
p->timeouts = t->next;
|
||
|
|
|
||
|
|
TimerFree (t->timer);
|
||
|
|
|
||
|
|
free (t);
|
||
|
|
}
|
||
|
|
|
||
|
|
static void
|
||
|
|
avahi_poll_block_handler (pointer blockData,
|
||
|
|
OSTimePtr pTimeout,
|
||
|
|
pointer pReadMask)
|
||
|
|
{
|
||
|
|
}
|
||
|
|
|
||
|
|
static void
|
||
|
|
avahi_poll_wakeup_handler (pointer blockData,
|
||
|
|
int result,
|
||
|
|
pointer pReadMask)
|
||
|
|
{
|
||
|
|
DMXAvahiPoll *p = (DMXAvahiPoll *) blockData;
|
||
|
|
AvahiWatch *w = p->watches;
|
||
|
|
fd_set *fds = (fd_set *) pReadMask;
|
||
|
|
|
||
|
|
while (w)
|
||
|
|
{
|
||
|
|
AvahiWatch *next = w->next;
|
||
|
|
|
||
|
|
if (FD_ISSET (w->fd, fds))
|
||
|
|
(*w->callback) (w, w->fd, AVAHI_WATCH_IN, w->userdata);
|
||
|
|
|
||
|
|
w = next;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
static void
|
||
|
|
dmx_avahi_poll_init (DMXAvahiPoll *p)
|
||
|
|
{
|
||
|
|
p->base.watch_new = dmx_avahi_watch_new;
|
||
|
|
p->base.watch_update = dmx_avahi_watch_update;
|
||
|
|
p->base.watch_get_events = dmx_avahi_watch_get_events;
|
||
|
|
p->base.watch_free = dmx_avahi_watch_free;
|
||
|
|
p->base.timeout_new = dmx_avahi_timeout_new;
|
||
|
|
p->base.timeout_update = dmx_avahi_timeout_update;
|
||
|
|
p->base.timeout_free = dmx_avahi_timeout_free;
|
||
|
|
|
||
|
|
RegisterBlockAndWakeupHandlers (avahi_poll_block_handler,
|
||
|
|
avahi_poll_wakeup_handler,
|
||
|
|
p);
|
||
|
|
}
|
||
|
|
|
||
|
|
static void
|
||
|
|
dmx_avahi_poll_fini (DMXAvahiPoll *p)
|
||
|
|
{
|
||
|
|
while (p->timeouts)
|
||
|
|
dmx_avahi_timeout_free (p->timeouts);
|
||
|
|
|
||
|
|
while (p->watches)
|
||
|
|
dmx_avahi_watch_free (p->watches);
|
||
|
|
|
||
|
|
RemoveBlockAndWakeupHandlers (avahi_poll_block_handler,
|
||
|
|
avahi_poll_wakeup_handler,
|
||
|
|
p);
|
||
|
|
}
|
||
|
|
|
||
|
|
static void
|
||
|
|
avahi_client_callback (AvahiClient *c,
|
||
|
|
AvahiClientState state,
|
||
|
|
void *userdata)
|
||
|
|
{
|
||
|
|
switch (state) {
|
||
|
|
case AVAHI_CLIENT_S_RUNNING: {
|
||
|
|
char hname[512], name[576];
|
||
|
|
|
||
|
|
if (gethostname (hname, sizeof (hname)))
|
||
|
|
break;
|
||
|
|
|
||
|
|
sprintf (name, _service_name, hname);
|
||
|
|
|
||
|
|
avahi_group = avahi_entry_group_new (c, 0, 0);
|
||
|
|
if (avahi_group)
|
||
|
|
{
|
||
|
|
avahi_entry_group_add_service (avahi_group,
|
||
|
|
AVAHI_IF_UNSPEC,
|
||
|
|
AVAHI_PROTO_UNSPEC,
|
||
|
|
0,
|
||
|
|
name,
|
||
|
|
"_dmx._tcp",
|
||
|
|
0,
|
||
|
|
0,
|
||
|
|
6000 + atoi (display),
|
||
|
|
NULL);
|
||
|
|
|
||
|
|
avahi_entry_group_commit (avahi_group);
|
||
|
|
}
|
||
|
|
} break;
|
||
|
|
case AVAHI_CLIENT_FAILURE:
|
||
|
|
case AVAHI_CLIENT_S_COLLISION:
|
||
|
|
case AVAHI_CLIENT_CONNECTING:
|
||
|
|
break;
|
||
|
|
case AVAHI_CLIENT_S_REGISTERING:
|
||
|
|
if (avahi_group)
|
||
|
|
avahi_entry_group_reset (avahi_group);
|
||
|
|
default:
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void
|
||
|
|
dmx_avahi_init (void)
|
||
|
|
{
|
||
|
|
dmx_avahi_poll_init (&avahi_poll);
|
||
|
|
|
||
|
|
avahi_group = NULL;
|
||
|
|
avahi_client = avahi_client_new (&avahi_poll.base,
|
||
|
|
0,
|
||
|
|
avahi_client_callback,
|
||
|
|
NULL,
|
||
|
|
NULL);
|
||
|
|
}
|
||
|
|
|
||
|
|
void
|
||
|
|
dmx_avahi_fini (void)
|
||
|
|
{
|
||
|
|
if (avahi_group)
|
||
|
|
{
|
||
|
|
avahi_entry_group_free (avahi_group);
|
||
|
|
avahi_group = NULL;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (avahi_client)
|
||
|
|
{
|
||
|
|
avahi_client_free (avahi_client);
|
||
|
|
avahi_client = NULL;
|
||
|
|
}
|
||
|
|
|
||
|
|
dmx_avahi_poll_fini (&avahi_poll);
|
||
|
|
}
|