Initial checkin of serial server-side support
Signed-off-by: Lon Hohberger <lon@users.sourceforge.net>
This commit is contained in:
parent
4ae121d860
commit
30e8654e77
@ -176,6 +176,8 @@ hangup(int fd, int delay)
|
||||
}
|
||||
}
|
||||
|
||||
void do_read_hostlist(int fd, int timeout);
|
||||
|
||||
|
||||
int
|
||||
serial_fence_virt(fence_virt_args_t *args)
|
||||
@ -188,7 +190,7 @@ serial_fence_virt(fence_virt_args_t *args)
|
||||
|
||||
strncpy(speed, args->serial.speed, sizeof(speed));
|
||||
|
||||
printf("Port: %s Speed: %s\n", args->serial.device, speed);
|
||||
//printf("Port: %s Speed: %s\n", args->serial.device, speed);
|
||||
|
||||
if ((flags = strchr(speed, ','))) {
|
||||
*flags = 0;
|
||||
@ -208,8 +210,8 @@ serial_fence_virt(fence_virt_args_t *args)
|
||||
req.request = (uint8_t)args->op;
|
||||
if (args->flags & RF_UUID)
|
||||
req.flags |= RF_UUID;
|
||||
strncpy((char *)req.domain, args->domain, sizeof(req.domain));
|
||||
|
||||
if (args->domain)
|
||||
strncpy((char *)req.domain, args->domain, sizeof(req.domain));
|
||||
|
||||
tv.tv_sec = 3;
|
||||
tv.tv_usec = 0;
|
||||
@ -229,15 +231,12 @@ serial_fence_virt(fence_virt_args_t *args)
|
||||
|
||||
if (resp.magic != SERIAL_MAGIC)
|
||||
return -1;
|
||||
ret = (int)resp.response;
|
||||
|
||||
/* XXX try a response from netcat: e.g.
|
||||
abba1<cr> = fail; abba0<cr>=ok
|
||||
should be removed when we have "real"
|
||||
server side handling; this was just to
|
||||
test communications */
|
||||
if (ret & 0x30)
|
||||
ret &= (~0x30);
|
||||
ret = resp.response;
|
||||
if (resp.response == 253) /* hostlist */ {
|
||||
/* ok read hostlist */
|
||||
do_read_hostlist(fd, args->timeout);
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
|
||||
|
@ -43,7 +43,7 @@ libvirt_qpid_so_SOURCES = uuid-test.c
|
||||
libvirt_qpid_cxx_so_SOURCES = libvirt-qpid.cpp
|
||||
multicast_so_SOURCES = mcast.c history.c
|
||||
checkpoint_so_SOURCES = virt.c vm_states.c history.c checkpoint.c cpg.c
|
||||
serial_so_SOURCES = virt-serial.c uuid-test.c
|
||||
serial_so_SOURCES = virt-serial.c uuid-test.c virt-sockets.c serial.c history.c
|
||||
|
||||
|
||||
################################
|
||||
|
380
server/serial.c
Normal file
380
server/serial.c
Normal file
@ -0,0 +1,380 @@
|
||||
/*
|
||||
Copyright Red Hat, Inc. 2010
|
||||
|
||||
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, 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
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
|
||||
MA 02139, USA.
|
||||
*/
|
||||
/*
|
||||
* Author: Lon Hohberger <lhh at redhat.com>
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/un.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <net/if.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
#include <sys/time.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <nss.h>
|
||||
#include <libgen.h>
|
||||
#include <list.h>
|
||||
#include <simpleconfig.h>
|
||||
#include <server_plugin.h>
|
||||
#include <history.h>
|
||||
#include <xvm.h>
|
||||
|
||||
|
||||
/* Local includes */
|
||||
#include "debug.h"
|
||||
#include "fdops.h"
|
||||
#include "virt-sockets.h"
|
||||
|
||||
#define NAME "serial"
|
||||
#define VERSION "0.3"
|
||||
|
||||
#define SERIAL_PLUG_MAGIC 0x1227a000
|
||||
|
||||
#define VALIDATE(info) \
|
||||
do {\
|
||||
if (!info || info->magic != SERIAL_PLUG_MAGIC)\
|
||||
return -EINVAL;\
|
||||
} while(0)
|
||||
|
||||
|
||||
typedef struct _serial_info {
|
||||
uint64_t magic;
|
||||
const fence_callbacks_t *cb;
|
||||
void *priv;
|
||||
char *uri;
|
||||
history_info_t *history;
|
||||
} serial_info;
|
||||
|
||||
|
||||
struct serial_hostlist_arg {
|
||||
int fd;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* See if we fenced this node recently (successfully)
|
||||
* If so, ignore the request for a few seconds.
|
||||
*
|
||||
* We purge our history when the entries time out.
|
||||
*/
|
||||
static int
|
||||
check_history(void *a, void *b) {
|
||||
fence_req_t *old = a, *current = b;
|
||||
|
||||
if (old->request == current->request &&
|
||||
old->seqno == current->seqno &&
|
||||
!strcasecmp((const char *)old->domain,
|
||||
(const char *)current->domain)) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
serial_hostlist(const char *vm_name, const char *vm_uuid,
|
||||
int state, void *priv)
|
||||
{
|
||||
struct serial_hostlist_arg *arg = (struct serial_hostlist_arg *)priv;
|
||||
host_state_t hinfo;
|
||||
struct timeval tv;
|
||||
int ret;
|
||||
|
||||
strncpy((char *)hinfo.domain, vm_name, sizeof(hinfo.domain));
|
||||
strncpy((char *)hinfo.uuid, vm_uuid, sizeof(hinfo.uuid));
|
||||
hinfo.state = state;
|
||||
|
||||
tv.tv_sec = 1;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
printf("%d\n", arg->fd);
|
||||
ret = _write_retry(arg->fd, &hinfo, sizeof(hinfo), &tv);
|
||||
if (ret == sizeof(hinfo))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
serial_hostlist_begin(int fd)
|
||||
{
|
||||
struct timeval tv;
|
||||
serial_resp_t resp;
|
||||
|
||||
resp.magic = SERIAL_MAGIC;
|
||||
resp.response = 253;
|
||||
|
||||
tv.tv_sec = 1;
|
||||
tv.tv_usec = 0;
|
||||
return _write_retry(fd, &resp, sizeof(resp), &tv);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
serial_hostlist_end(int fd)
|
||||
{
|
||||
host_state_t hinfo;
|
||||
struct timeval tv;
|
||||
int ret;
|
||||
|
||||
printf("Sending terminator packet\n");
|
||||
|
||||
memset(&hinfo, 0, sizeof(hinfo));
|
||||
|
||||
tv.tv_sec = 1;
|
||||
tv.tv_usec = 0;
|
||||
ret = _write_retry(fd, &hinfo, sizeof(hinfo), &tv);
|
||||
if (ret == sizeof(hinfo))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
do_fence_request(int fd, serial_req_t *req, serial_info *info)
|
||||
{
|
||||
char response = 1;
|
||||
struct serial_hostlist_arg arg;
|
||||
serial_resp_t resp;
|
||||
|
||||
arg.fd = fd;
|
||||
|
||||
switch(req->request) {
|
||||
case FENCE_NULL:
|
||||
response = info->cb->null((char *)req->domain, info->priv);
|
||||
break;
|
||||
case FENCE_ON:
|
||||
response = info->cb->on((char *)req->domain, req->seqno,
|
||||
info->priv);
|
||||
break;
|
||||
case FENCE_OFF:
|
||||
response = info->cb->off((char *)req->domain, req->seqno,
|
||||
info->priv);
|
||||
break;
|
||||
case FENCE_REBOOT:
|
||||
response = info->cb->reboot((char *)req->domain, req->seqno,
|
||||
info->priv);
|
||||
break;
|
||||
case FENCE_STATUS:
|
||||
response = info->cb->status((char *)req->domain, info->priv);
|
||||
break;
|
||||
case FENCE_DEVSTATUS:
|
||||
response = info->cb->devstatus(info->priv);
|
||||
break;
|
||||
case FENCE_HOSTLIST:
|
||||
serial_hostlist_begin(arg.fd);
|
||||
response = info->cb->hostlist(serial_hostlist, &arg,
|
||||
info->priv);
|
||||
serial_hostlist_end(arg.fd);
|
||||
break;
|
||||
}
|
||||
|
||||
resp.magic = SERIAL_MAGIC;
|
||||
resp.response = response;
|
||||
|
||||
dbg_printf(3, "Sending response to caller...\n");
|
||||
if (write(fd, &resp, sizeof(resp)) < 0) {
|
||||
perror("write");
|
||||
}
|
||||
|
||||
/* XVM shotguns multicast packets, so we want to avoid
|
||||
* acting on the same request multiple times if the first
|
||||
* attempt was successful.
|
||||
*/
|
||||
history_record(info->history, req);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
serial_dispatch(listener_context_t c, struct timeval *timeout)
|
||||
{
|
||||
serial_info *info;
|
||||
serial_req_t data;
|
||||
fd_set rfds;
|
||||
struct timeval tv;
|
||||
int max;
|
||||
int n, x, ret;
|
||||
|
||||
info = (serial_info *)c;
|
||||
VALIDATE(info);
|
||||
|
||||
FD_ZERO(&rfds);
|
||||
domain_sock_fdset(&rfds, &max);
|
||||
|
||||
n = select(max+1, &rfds, NULL, NULL, timeout);
|
||||
printf("n = %d max = %d\n", n, max);
|
||||
if (n < 0) {
|
||||
perror("select");
|
||||
return n;
|
||||
}
|
||||
|
||||
/*
|
||||
* If no requests, we're done
|
||||
*/
|
||||
if (n == 0)
|
||||
return 0;
|
||||
|
||||
/* find & read request */
|
||||
for (x = 0; x <= max; x++) {
|
||||
if (FD_ISSET(x, &rfds)) {
|
||||
tv.tv_sec = 1;
|
||||
tv.tv_usec = 0;
|
||||
ret = _read_retry(x, &data, sizeof(data), &tv);
|
||||
printf("the read...%d\n",ret);
|
||||
if (ret != sizeof(data)) {
|
||||
if (--n)
|
||||
continue;
|
||||
else
|
||||
return 0;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
printf("Sock %d Request %d seqno %d domain %s\n", x, data.request, data.seqno,
|
||||
data.domain);
|
||||
|
||||
if (history_check(info->history, &data) == 1) {
|
||||
printf("We just did this request; dropping packet\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
do_fence_request(x, &data, info);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
serial_config(config_object_t *config, serial_info *args)
|
||||
{
|
||||
char value[1024];
|
||||
int errors = 0;
|
||||
|
||||
#ifdef _MODULE
|
||||
if (sc_get(config, "fence_virtd/@debug", value, sizeof(value))==0)
|
||||
dset(atoi(value));
|
||||
#endif
|
||||
|
||||
if (sc_get(config, "listeners/serial/@uri",
|
||||
value, sizeof(value)-1) == 0) {
|
||||
dbg_printf(1, "Got %s for uri\n", value);
|
||||
args->uri = strdup(value);
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
serial_init(listener_context_t *c, const fence_callbacks_t *cb,
|
||||
config_object_t *config, void *priv)
|
||||
{
|
||||
serial_info *info;
|
||||
int ret;
|
||||
|
||||
info = malloc(sizeof(*info));
|
||||
if (!info)
|
||||
return -1;
|
||||
memset(info, 0, sizeof(*info));
|
||||
|
||||
info->priv = priv;
|
||||
info->cb = cb;
|
||||
|
||||
ret = serial_config(config, info);
|
||||
if (ret < 0) {
|
||||
perror("serial_config");
|
||||
return -1;
|
||||
} else if (ret > 0) {
|
||||
printf("%d errors found during configuration\n",ret);
|
||||
return -1;
|
||||
}
|
||||
|
||||
info->magic = SERIAL_PLUG_MAGIC;
|
||||
info->history = history_init(check_history, 10, sizeof(fence_req_t));
|
||||
*c = (listener_context_t)info;
|
||||
start_event_listener(info->uri);
|
||||
sleep(1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
serial_shutdown(listener_context_t c)
|
||||
{
|
||||
serial_info *info = (serial_info *)c;
|
||||
|
||||
dbg_printf(3, "Shutting down serial\n");
|
||||
|
||||
VALIDATE(info);
|
||||
info->magic = 0;
|
||||
stop_event_listener();
|
||||
free(info->uri);
|
||||
free(info);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static listener_plugin_t serial_plugin = {
|
||||
.name = NAME,
|
||||
.version = VERSION,
|
||||
.init = serial_init,
|
||||
.dispatch = serial_dispatch,
|
||||
.cleanup = serial_shutdown,
|
||||
};
|
||||
|
||||
|
||||
#ifdef _MODULE
|
||||
double
|
||||
LISTENER_VER_SYM(void)
|
||||
{
|
||||
return PLUGIN_VERSION_LISTENER;
|
||||
}
|
||||
|
||||
const listener_plugin_t *
|
||||
LISTENER_INFO_SYM(void)
|
||||
{
|
||||
return &serial_plugin;
|
||||
}
|
||||
#else
|
||||
static void __attribute__((constructor))
|
||||
serial_register_plugin(void)
|
||||
{
|
||||
plugin_reg_listener(&serial_plugin);
|
||||
}
|
||||
#endif
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/poll.h>
|
||||
@ -12,26 +13,41 @@
|
||||
|
||||
#include <libxml/xmlreader.h>
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
#define DEBUG0(fmt) printf("%s:%d :: " fmt "\n", \
|
||||
__func__, __LINE__)
|
||||
#define DEBUG(fmt, ...) printf("%s:%d: " fmt "\n", \
|
||||
#define DEBUG1(fmt, ...) printf("%s:%d: " fmt "\n", \
|
||||
__func__, __LINE__, __VA_ARGS__)
|
||||
|
||||
#else
|
||||
|
||||
#define DEBUG0(fmt)
|
||||
#define DEBUG1(fmt, ...)
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#include "virt-sockets.h"
|
||||
|
||||
#define STREQ(a,b) (strcmp((a),(b)) == 0)
|
||||
|
||||
/* handle globals */
|
||||
int h_fd = 0;
|
||||
virEventHandleType h_event = 0;
|
||||
virEventHandleCallback h_cb = NULL;
|
||||
virFreeCallback h_ff = NULL;
|
||||
void *h_opaque = NULL;
|
||||
static int h_fd = -1;
|
||||
static virEventHandleType h_event = 0;
|
||||
static virEventHandleCallback h_cb = NULL;
|
||||
static virFreeCallback h_ff = NULL;
|
||||
static void *h_opaque = NULL;
|
||||
|
||||
/* timeout globals */
|
||||
#define TIMEOUT_MS 1000
|
||||
int t_active = 0;
|
||||
int t_timeout = -1;
|
||||
virEventTimeoutCallback t_cb = NULL;
|
||||
virFreeCallback t_ff = NULL;
|
||||
void *t_opaque = NULL;
|
||||
static int t_active = 0;
|
||||
static int t_timeout = -1;
|
||||
static virEventTimeoutCallback t_cb = NULL;
|
||||
static virFreeCallback t_ff = NULL;
|
||||
static void *t_opaque = NULL;
|
||||
static pthread_t event_tid = 0;
|
||||
static int run = 0;
|
||||
|
||||
/* Prototypes */
|
||||
const char *eventToString(int event);
|
||||
@ -116,19 +132,19 @@ myEventAddHandleFunc(int fd, int event,
|
||||
virEventHandleCallback cb,
|
||||
void *opaque, virFreeCallback ff)
|
||||
{
|
||||
DEBUG("Add handle %d %d %p %p", fd, event, cb, opaque);
|
||||
DEBUG1("Add handle %d %d %p %p %p", fd, event, cb, opaque, ff);
|
||||
h_fd = fd;
|
||||
h_event = myEventHandleTypeToPollEvent(event);
|
||||
h_cb = cb;
|
||||
h_ff = ff;
|
||||
h_opaque = opaque;
|
||||
h_ff = ff;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
myEventUpdateHandleFunc(int fd, int event)
|
||||
{
|
||||
DEBUG("Updated Handle %d %d", fd, event);
|
||||
DEBUG1("Updated Handle %d %d", fd, event);
|
||||
h_event = myEventHandleTypeToPollEvent(event);
|
||||
return;
|
||||
}
|
||||
@ -136,7 +152,7 @@ myEventUpdateHandleFunc(int fd, int event)
|
||||
int
|
||||
myEventRemoveHandleFunc(int fd)
|
||||
{
|
||||
DEBUG("Removed Handle %d", fd);
|
||||
DEBUG1("Removed Handle %d", fd);
|
||||
h_fd = 0;
|
||||
if (h_ff)
|
||||
(h_ff) (h_opaque);
|
||||
@ -148,7 +164,7 @@ myEventAddTimeoutFunc(int timeout,
|
||||
virEventTimeoutCallback cb,
|
||||
void *opaque, virFreeCallback ff)
|
||||
{
|
||||
DEBUG("Adding Timeout %d %p %p", timeout, cb, opaque);
|
||||
DEBUG1("Adding Timeout %d %p %p", timeout, cb, opaque);
|
||||
t_active = 1;
|
||||
t_timeout = timeout;
|
||||
t_cb = cb;
|
||||
@ -160,36 +176,20 @@ myEventAddTimeoutFunc(int timeout,
|
||||
void
|
||||
myEventUpdateTimeoutFunc(int timer, int timeout)
|
||||
{
|
||||
/*DEBUG("Timeout updated %d %d", timer, timeout); */
|
||||
/*DEBUG1("Timeout updated %d %d", timer, timeout); */
|
||||
t_timeout = timeout;
|
||||
}
|
||||
|
||||
int
|
||||
myEventRemoveTimeoutFunc(int timer)
|
||||
{
|
||||
DEBUG("Timeout removed %d", timer);
|
||||
DEBUG1("Timeout removed %d", timer);
|
||||
t_active = 0;
|
||||
if (t_ff)
|
||||
(t_ff) (t_opaque);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* main test functions */
|
||||
|
||||
void
|
||||
usage(const char *pname)
|
||||
{
|
||||
printf("%s uri\n", pname);
|
||||
}
|
||||
|
||||
int run = 1;
|
||||
|
||||
static void
|
||||
stop(int sig)
|
||||
{
|
||||
printf("Exiting on signal %d\n", sig);
|
||||
run = 0;
|
||||
}
|
||||
|
||||
static int
|
||||
domainStarted(virDomainPtr mojaDomain)
|
||||
@ -268,6 +268,8 @@ domainStarted(virDomainPtr mojaDomain)
|
||||
printf(">> REGISTER >> %s %s\n",
|
||||
dom_uuid,
|
||||
attr_path->children->content);
|
||||
domain_sock_setup(dom_uuid, (const char *)
|
||||
attr_path->children->content);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -345,24 +347,21 @@ domainStopped(virDomainPtr mojaDomain)
|
||||
printf("UUID: %s\n", dom_uuid);
|
||||
|
||||
printf(">> UNREGISTER >> %s\n", dom_uuid);
|
||||
domain_sock_close(dom_uuid);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
|
||||
static void *
|
||||
event_thread(void *arg)
|
||||
{
|
||||
virConnectPtr dconn = NULL;
|
||||
struct domain_info dinfo;
|
||||
struct sigaction action_stop = {.sa_handler = stop };
|
||||
|
||||
int sts;
|
||||
int callback1ret = -1;
|
||||
|
||||
if (argc > 1 && STREQ(argv[1], "--help")) {
|
||||
usage(argv[0]);
|
||||
return -1;
|
||||
}
|
||||
printf("Event listener starting \n");
|
||||
|
||||
virEventRegisterImpl(myEventAddHandleFunc,
|
||||
myEventUpdateHandleFunc,
|
||||
@ -371,15 +370,12 @@ main(int argc, char **argv)
|
||||
myEventUpdateTimeoutFunc,
|
||||
myEventRemoveTimeoutFunc);
|
||||
|
||||
dconn = virConnectOpen(argv[1] ? argv[1] : NULL);
|
||||
dconn = virConnectOpen((char *)arg);
|
||||
if (!dconn) {
|
||||
printf("error opening\n");
|
||||
return -1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sigaction(SIGTERM, &action_stop, NULL);
|
||||
sigaction(SIGINT, &action_stop, NULL);
|
||||
|
||||
DEBUG0("Registering domain event cbs");
|
||||
|
||||
registerExisting(dconn);
|
||||
@ -398,6 +394,12 @@ main(int argc, char **argv)
|
||||
.revents = 0
|
||||
};
|
||||
|
||||
sts = poll(&pfd, 1, TIMEOUT_MS);
|
||||
/* We are assuming timeout of 0 here - so execute every time */
|
||||
if (t_cb && t_active) {
|
||||
t_cb(t_timeout, t_opaque);
|
||||
}
|
||||
|
||||
if (dinfo.event == VIR_DOMAIN_EVENT_STARTED) {
|
||||
domainStarted(dinfo.dom);
|
||||
virDomainFree(dinfo.dom);
|
||||
@ -410,39 +412,31 @@ main(int argc, char **argv)
|
||||
dinfo.event = VIR_DOMAIN_EVENT_UNDEFINED;
|
||||
}
|
||||
|
||||
sts = poll(&pfd, 1, TIMEOUT_MS);
|
||||
/* We are assuming timeout of 0 here - so execute every time */
|
||||
if (t_cb && t_active) {
|
||||
t_cb(t_timeout, t_opaque);
|
||||
}
|
||||
|
||||
if (sts == 0) {
|
||||
/* DEBUG0("Poll timeout"); */
|
||||
continue;
|
||||
}
|
||||
|
||||
if (sts < 0) {
|
||||
DEBUG0("Poll failed");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pfd.revents & POLLHUP) {
|
||||
DEBUG0("Reset by peer");
|
||||
return -1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (h_cb) {
|
||||
h_cb(0,
|
||||
h_fd,
|
||||
myPollEventToEventHandleType(pfd.
|
||||
revents &
|
||||
h_cb(0, h_fd,
|
||||
myPollEventToEventHandleType(pfd.revents &
|
||||
h_event),
|
||||
h_opaque);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
DEBUG0("Deregistering event handlers");
|
||||
virConnectDomainEventDeregister(dconn, myDomainEventCallback1);
|
||||
|
||||
}
|
||||
|
||||
DEBUG0("Closing connection");
|
||||
@ -451,5 +445,38 @@ main(int argc, char **argv)
|
||||
}
|
||||
|
||||
printf("done\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
start_event_listener(const char *uri)
|
||||
{
|
||||
char *arg = NULL;
|
||||
|
||||
virInitialize();
|
||||
|
||||
if (uri) {
|
||||
arg = strdup(uri);
|
||||
if (uri == NULL)
|
||||
return -1;
|
||||
}
|
||||
|
||||
run = 1;
|
||||
|
||||
return pthread_create(&event_tid, NULL, event_thread, arg);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
stop_event_listener(void)
|
||||
{
|
||||
run = 0;
|
||||
pthread_cancel(event_tid);
|
||||
pthread_join(event_tid, NULL);
|
||||
event_tid = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
128
server/virt-sockets.c
Normal file
128
server/virt-sockets.c
Normal file
@ -0,0 +1,128 @@
|
||||
|
||||
#include <pthread.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <list.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "virt-sockets.h"
|
||||
|
||||
struct socket_list {
|
||||
list_head();
|
||||
char *domain_name;
|
||||
char *socket_path;
|
||||
int socket_fd;
|
||||
};
|
||||
|
||||
static struct socket_list *socks = NULL;
|
||||
static pthread_mutex_t sock_list_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
|
||||
int
|
||||
domain_sock_setup(const char *domain, const char *socket_path)
|
||||
{
|
||||
struct sockaddr_un *sun = NULL;
|
||||
struct socket_list *node = NULL;
|
||||
socklen_t sun_len;
|
||||
int sock = -1;
|
||||
|
||||
sun_len = sizeof(*sun) + strlen(socket_path) + 1;
|
||||
sun = malloc(sun_len);
|
||||
if (!sun)
|
||||
return -1;
|
||||
|
||||
memset((char *)sun, 0, sun_len);
|
||||
sun->sun_family = PF_LOCAL;
|
||||
strncpy(sun->sun_path, socket_path, sun_len - sizeof(*sun));
|
||||
|
||||
sock = socket(PF_LOCAL, SOCK_STREAM, 0);
|
||||
if (sock < 0)
|
||||
goto out_fail;
|
||||
|
||||
if (connect(sock, (struct sockaddr *)sun, SUN_LEN(sun)) < 0)
|
||||
goto out_fail;
|
||||
|
||||
node = malloc(sizeof(*node));
|
||||
if (!node)
|
||||
goto out_fail;
|
||||
|
||||
node->domain_name = strdup(domain);
|
||||
if (!node->domain_name)
|
||||
goto out_fail;
|
||||
|
||||
node->socket_path = strdup(socket_path);
|
||||
if (!node->socket_path)
|
||||
goto out_fail;
|
||||
|
||||
node->socket_fd = sock;
|
||||
|
||||
pthread_mutex_lock(&sock_list_mutex);
|
||||
list_insert(&socks, node);
|
||||
pthread_mutex_unlock(&sock_list_mutex);
|
||||
|
||||
printf("REGISTERED %s on %d\n", domain, sock);
|
||||
return 0;
|
||||
|
||||
out_fail:
|
||||
if (node)
|
||||
free(node->domain_name);
|
||||
if (node)
|
||||
free(node->socket_path);
|
||||
free(node);
|
||||
free(sun);
|
||||
if (sock >= 0)
|
||||
close(sock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
domain_sock_close(const char *domain)
|
||||
{
|
||||
struct socket_list *node = NULL;
|
||||
struct socket_list *dead = NULL;
|
||||
int x;
|
||||
|
||||
pthread_mutex_lock(&sock_list_mutex);
|
||||
list_for(&socks, node, x) {
|
||||
if (!strcasecmp(domain, node->domain_name)) {
|
||||
list_remove(&socks, node);
|
||||
dead = node;
|
||||
break;
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&sock_list_mutex);
|
||||
|
||||
if (dead) {
|
||||
close(dead->socket_fd);
|
||||
free(dead->domain_name);
|
||||
free(dead->socket_path);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
domain_sock_fdset(fd_set *fds, int *max)
|
||||
{
|
||||
struct socket_list *node = NULL;
|
||||
int x = 0, _max = -1;
|
||||
|
||||
pthread_mutex_lock(&sock_list_mutex);
|
||||
list_for(&socks, node, x) {
|
||||
FD_SET(node->socket_fd, fds);
|
||||
if (node->socket_fd > _max)
|
||||
_max = node->socket_fd;
|
||||
}
|
||||
pthread_mutex_unlock(&sock_list_mutex);
|
||||
|
||||
if (max)
|
||||
*max = _max;
|
||||
|
||||
return x;
|
||||
}
|
||||
|
10
server/virt-sockets.h
Normal file
10
server/virt-sockets.h
Normal file
@ -0,0 +1,10 @@
|
||||
#ifndef _VIRT_SOCKETS_H
|
||||
#define _VIRT_SOCKETS_H
|
||||
|
||||
#include <sys/select.h>
|
||||
|
||||
int domain_sock_setup(const char *domain, const char *socket_path);
|
||||
int domain_sock_close(const char *domain);
|
||||
int domain_sock_fdset(fd_set *set, int *max);
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user