Commit a2a896ab authored by Mike Hibler's avatar Mike Hibler

First crack at a frisbee "master server" for handling GET (download) requests.

There are a couple of new packet types in the frisbee protocol which are
exchanged via TCP with the master server: GETREQUEST and GETREPLY.  The
client passes to the master server an opaque imageid and a couple of options
and gets back the addr/port to use to actually download the image.  The
implementation of the master server is fragile and is more of a test
framework, Grant is working on a more robust master server.  I am mostly
doing a backend that communicates with the Emulab DB to do its authentication
and making the client changes.

The client now uses the -S option to specify the IP address of the master
server and the -F option to specify an imageid.  If no error is returned,
the image is downloaded using the returned addr/port.  If -Q is used in place
of -F, then the client makes a "status only" call getting back info about
whether the named image is accessible to the client and whether a server is
currently running.

On the server side, the new master server (mserver.c) has an Emulab
configuration "backend" that supports host-based authentication.
The IP address of the caller is mapped to a node_id/pid/gid/eid combo
that is used to determine access.  On a request, the specified imageid is
treated either as a pathname (if it starts with '/') or an image identifier
of the form "<pid>/<imagename>".  If it is a pathname, we check to make
sure that pathname (after running through "realpath") is contained in one
of the directories accessible to that node in its current experiment context;
i.e., /share, /proj/<pid>, /groups/<pid>/<gid>, or /users/<swapper-uid>.
If it is an image identifier, the DB is queried to ensure that access is
allowed to that image; i.e., it must be "global" or in the appropriate
project/group.

The master server forks a frisbeed for each valid request, if one is not
already running.  The multicast address selection is still based on the
emulab_indicies.frisbee_index field, but the address/port/server info is no
longer stored in the frisbee_blobs table (frisbee_pid, load_address,
load_busy are not set).

Note that this is not yet integrated in the os_load path.  Further work is
required to replace frisbeelauncher.
parent b1e4b205
......@@ -46,6 +46,8 @@
#undef TPM
#undef NOSHAREDFS
#undef NFSRACY
#undef FRISEBEEMCASTADDR
#undef FRISEBEEMCASTPORT
#undef HAVE_SRANDOMDEV
......
......@@ -1784,6 +1784,14 @@ cat >> confdefs.h <<EOF
#define BOSSEVENTPORT "$BOSSEVENTPORT"
EOF
cat >> confdefs.h <<EOF
#define FRISEBEEMCASTADDR "$FRISEBEEMCASTADDR"
EOF
cat >> confdefs.h <<EOF
#define FRISEBEEMCASTPORT "$FRISEBEEMCASTPORT"
EOF
if test $OPSDBSUPPORT -eq 1; then
cat >> confdefs.h <<EOF
......@@ -2222,17 +2230,17 @@ for ac_hdr in ulxmlrpcpp/ulxr_config.h
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
echo "configure:2225: checking for $ac_hdr" >&5
echo "configure:2234: checking for $ac_hdr" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 2230 "configure"
#line 2239 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:2235: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
{ (eval echo configure:2244: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
......@@ -2271,17 +2279,17 @@ for ac_hdr in linux/videodev.h
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
echo "configure:2274: checking for $ac_hdr" >&5
echo "configure:2283: checking for $ac_hdr" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 2279 "configure"
#line 2288 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:2284: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
{ (eval echo configure:2293: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
......@@ -2314,7 +2322,7 @@ done
# Extract the first word of "gtk-config", so it can be a program name with args.
set dummy gtk-config; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:2317: checking for $ac_word" >&5
echo "configure:2326: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_GTK_CONFIG'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
......@@ -2371,7 +2379,7 @@ ac_link='${CXX-g++} -o conftest${ac_exeext} $CXXFLAGS $CPPFLAGS $LDFLAGS conftes
cross_compiling=$ac_cv_prog_cxx_cross
echo $ac_n "checking how to run the C++ preprocessor""... $ac_c" 1>&6
echo "configure:2374: checking how to run the C++ preprocessor" >&5
echo "configure:2383: checking how to run the C++ preprocessor" >&5
if test -z "$CXXCPP"; then
if eval "test \"`echo '$''{'ac_cv_prog_CXXCPP'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
......@@ -2384,12 +2392,12 @@ ac_link='${CXX-g++} -o conftest${ac_exeext} $CXXFLAGS $CPPFLAGS $LDFLAGS conftes
cross_compiling=$ac_cv_prog_cxx_cross
CXXCPP="${CXX-g++} -E"
cat > conftest.$ac_ext <<EOF
#line 2387 "configure"
#line 2396 "configure"
#include "confdefs.h"
#include <stdlib.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:2392: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
{ (eval echo configure:2401: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
:
......@@ -2415,17 +2423,17 @@ echo "$ac_t""$CXXCPP" 1>&6
ac_safe=`echo "xercesc/dom/DOM.hpp" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for xercesc/dom/DOM.hpp""... $ac_c" 1>&6
echo "configure:2418: checking for xercesc/dom/DOM.hpp" >&5
echo "configure:2427: checking for xercesc/dom/DOM.hpp" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 2423 "configure"
#line 2432 "configure"
#include "confdefs.h"
#include <xercesc/dom/DOM.hpp>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:2428: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
{ (eval echo configure:2437: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
......@@ -2489,7 +2497,7 @@ fi
# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
# ./install, which can be erroneously created by make from ./install.sh.
echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
echo "configure:2492: checking for a BSD compatible install" >&5
echo "configure:2501: checking for a BSD compatible install" >&5
if test -z "$INSTALL"; then
if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
......@@ -2550,7 +2558,7 @@ esac
# Extract the first word of "rsync", so it can be a program name with args.
set dummy rsync; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
echo "configure:2553: checking for $ac_word" >&5
echo "configure:2562: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_path_RSYNC'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
......
......@@ -406,6 +406,8 @@ if test -n "$FSDIR_SCRATCH"; then
AC_DEFINE_UNQUOTED(FSDIR_SCRATCH, "$FSDIR_SCRATCH")
fi
AC_DEFINE_UNQUOTED(BOSSEVENTPORT, "$BOSSEVENTPORT")
AC_DEFINE_UNQUOTED(FRISEBEEMCASTADDR, "$FRISEBEEMCASTADDR")
AC_DEFINE_UNQUOTED(FRISEBEEMCASTPORT, "$FRISEBEEMCASTPORT")
if test $OPSDBSUPPORT -eq 1; then
AC_DEFINE_UNQUOTED(OPSDBSUPPORT, 1)
......
......@@ -175,6 +175,12 @@ mydb_update(char *query, ...)
return 1;
}
int
mydb_insertid()
{
return (int)mysql_insert_id(&db);
}
/*
* Map IP to node ID.
*/
......
......@@ -33,6 +33,7 @@ int mydb_seteventschedulerpid(char *pid, char *eid, int processid);
*/
MYSQL_RES *mydb_query(char *query, int ncols, ...);
int mydb_update(char *query, ...);
int mydb_insertid(void);
unsigned long mydb_escape_string(char *to, const char *from,
unsigned long length);
#
# EMULAB-COPYRIGHT
# Copyright (c) 2000-2009 University of Utah and the Flux Group.
# Copyright (c) 2000-2010 University of Utah and the Flux Group.
# All rights reserved.
#
......@@ -63,7 +63,13 @@ SERVERFLAGS = $(CFLAGS)
SERVERLIBS = $(PTHREADLIBS)
SERVEROBJS = server.o $(SHAREDOBJS)
CFLAGS = -O2 -g -Wall -fno-builtin-log $(LDSTATIC) $(PTHREADCFLAGS) -DSTATS
MYSQLCFLAGS = -I/usr/local/include
MYSQLLIBS = -L/usr/local/lib/mysql -lmysqlclient
MSERVERFLAGS = $(CFLAGS) $(MYSQLCFLAGS) -DUSE_EMULAB_CONFIG -I$(TESTBED_SRCDIR)/lib/libtb -I$(OBJDIR)
MSERVERLIBS = $(OBJDIR)/lib/libtb/libtb.a $(MYSQLLIBS) $(PTHREADLIBS)
MSERVEROBJS = mserver.o config.o config_emulab.o $(SHAREDOBJS)
CFLAGS = -O2 -g -Wall -fno-builtin-log $(LDSTATIC) $(PTHREADCFLAGS) -DSTATS -DMASTER_SERVER
LDFLAGS = $(LDSTATIC)
#
......@@ -110,6 +116,15 @@ frisbeed: $(SERVEROBJS)
cp frisbeed frisbeed.debug
strip frisbeed
mfrisbeed: $(MSERVEROBJS)
$(CC) $(LDFLAGS) $(MSERVERFLAGS) $(MSERVEROBJS) $(MSERVERLIBS) -o mfrisbeed
cp mfrisbeed mfrisbeed.debug
strip mfrisbeed
config.o: $(SRCDIR)/config.c configdefs.h log.h
$(CC) -c $(MSERVERFLAGS) $(SRCDIR)/config.c
config_emulab.o: $(SRCDIR)/config_emulab.c configdefs.h log.h
$(CC) -c $(MSERVERFLAGS) $(SRCDIR)/config_emulab.c
log.o: $(SRCDIR)/log.c decls.h log.h
$(CC) $(CFLAGS) -DLOG_TESTBED=$(LOG_TESTBED) -c $(SRCDIR)/log.c
......
......@@ -60,6 +60,8 @@ int zero = 0;
int portnum;
struct in_addr mcastaddr;
struct in_addr mcastif;
char *imageid;
int askonly;
static struct timeval stamp;
static struct in_addr serverip;
......@@ -137,18 +139,28 @@ ClientStats_t Stats;
#endif
char *usagestr =
"usage: frisbee [-drzbn] [-s #] <-p #> <-m ipaddr> <output filename>\n"
"usage: frisbee [-drzbnN] [-s #] <-m ipaddr> <-p #> <output filename>\n"
" or\n"
"usage: frisbee [-drzbnN] [-s #] <-S server> <-F fileid> <output filename>\n"
"\n"
" -d Turn on debugging. Multiple -d options increase output.\n"
" -r Randomly delay first request by up to one second.\n"
" -z Zero fill unused block ranges (default is to seek past).\n"
" -b Use broadcast instead of multicast\n"
" -n Do not use extra threads in diskwriter\n"
" -N Do not decompress the received data, just write to output.\n"
" -S server-IP Specify the IP address of the server to use.\n"
" -p portnum Specify a port number.\n"
" -m mcastaddr Specify a multicast address in dotted notation.\n"
" -i mcastif Specify a multicast interface in dotted notation.\n"
" -s slice Output to DOS slice (DOS numbering 1-4)\n"
" NOTE: Must specify a raw disk device for output filename.\n"
" -D DOS-type With -s, sets the DOS type of the slice in the MBR\n"
" -F file-ID Specify the ID of the file (image) to download.\n"
" Here -S specifies the 'master' server which will\n"
" return unicast/multicast info to use for image download.\n"
" -Q file-ID Ask the server (-S) about the indicated file (image).\n"
" Tells whether the image is accessible by this node/user.\n"
"\n"
"tuning options (if you don't know what they are, don't use em!):\n"
" -C MB Max MB of memory to use for network chunk buffering.\n"
......@@ -187,11 +199,11 @@ int
main(int argc, char **argv)
{
int ch, mem;
char *filename;
char *filename = NULL;
int dostype = -1;
int slice = 0;
while ((ch = getopt(argc, argv, "dhp:m:s:i:tbznT:r:E:D:C:W:S:M:R:I:ON")) != -1)
while ((ch = getopt(argc, argv, "dhp:m:s:i:tbznT:r:E:D:C:W:S:M:R:I:ONF:Q:")) != -1)
switch(ch) {
case 'd':
debug++;
......@@ -239,6 +251,15 @@ main(int argc, char **argv)
}
break;
case 'F':
imageid = optarg;
break;
case 'Q':
imageid = optarg;
askonly = 1;
break;
case 't':
tracing++;
break;
......@@ -314,14 +335,26 @@ main(int argc, char **argv)
argc -= optind;
argv += optind;
if (argc != 1)
usage();
filename = argv[0];
if (!askonly) {
if (argc != 1)
usage();
filename = argv[0];
}
if (!portnum || ! mcastaddr.s_addr)
if (!((imageid != NULL && serverip.s_addr != 0) ||
(mcastaddr.s_addr != 0 && portnum != 0)))
usage();
ClientLogInit();
#ifdef MASTER_SERVER
if (imageid && !ClientNetFindServer(&serverip, imageid, askonly, 5)) {
fprintf(stderr, "Could not get download info for '%s'\n",
imageid);
exit(1);
}
if (askonly)
exit(0);
#endif
ClientNetInit();
#ifdef DOEVENTS
......
/*
* Configuration file functions.
*/
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <assert.h>
#include "configdefs.h"
#include "log.h"
static struct config *myconfig;
/*
* Got a SIGHUP.
* Reread the config file.
*/
static void
config_signal(int sig)
{
void *savedconfig = NULL;
if (myconfig == NULL)
return;
savedconfig = myconfig->config_save();
if (myconfig->config_read() != 0) {
warning("WARNING: could not load new configuration, "
"restoring old config.");
if (savedconfig == NULL ||
myconfig->config_restore(savedconfig)) {
error("*** Could not restore old configuration; "
"aborting!");
abort();
}
} else
log("New configuration loaded.");
if (savedconfig)
myconfig->config_free(savedconfig);
}
int
config_init(int readit)
{
int rv;
#ifdef USE_EMULAB_CONFIG
extern struct config emulab_config;
myconfig = &emulab_config;
#else
extern struct config file_config;
myconfig = &file_config;
#endif
rv = myconfig->config_init();
if (rv)
return rv;
if (readit) {
rv = myconfig->config_read();
if (rv) {
myconfig->config_deinit();
return rv;
}
}
signal(SIGHUP, config_signal);
return 0;
}
int
config_read(void)
{
assert(myconfig != NULL);
return myconfig->config_read();
}
int
config_get_host_authinfo(struct in_addr *in, char *imageid,
struct config_host_authinfo **get,
struct config_host_authinfo **put)
{
assert(myconfig != NULL);
return myconfig->config_get_host_authinfo(in, imageid, get, put);
}
void
config_free_host_authinfo(struct config_host_authinfo *ai)
{
assert(myconfig != NULL);
return myconfig->config_free_host_authinfo(ai);
}
/*
* Authenticate access to an image based on the IP address of a host.
* Return zero and (optionally) a pointer to authentication information
* on success, an error code otherwise.
*/
int
config_auth_by_IP(struct in_addr *host, char *imageid,
struct config_host_authinfo **aip)
{
struct config_host_authinfo *ai;
if (config_get_host_authinfo(host, imageid, &ai, 0))
return CONFIG_ERR_HA_FAILED;
if (ai->hostid == NULL) {
config_free_host_authinfo(ai);
return CONFIG_ERR_HA_NOHOST;
}
if (ai->numimages == 0) {
config_free_host_authinfo(ai);
return CONFIG_ERR_HA_NOACCESS;
}
if (aip)
*aip = ai;
return 0;
}
int
config_get_server_address(struct config_host_authinfo *ai, int methods,
in_addr_t *addr, in_port_t *port, int *method)
{
assert(myconfig != NULL);
return myconfig->config_get_server_address(ai, methods,
addr, port, method);
}
char *
config_perror(int code)
{
switch (code) {
case CONFIG_ERR_HA_FAILED:
return "host authentication failed";
case CONFIG_ERR_HA_NOHOST:
return "unknown host";
case CONFIG_ERR_HA_NOIMAGE:
return "unknown image";
case CONFIG_ERR_HA_NOACCESS:
return "permission denied";
case CONFIG_ERR_HA_NOMETHOD:
return "invalid method";
default:
return "unknown error";
}
}
void
config_dump(FILE *fd)
{
signal(SIGHUP, SIG_IGN);
if (myconfig == NULL)
warning("config_dump: config file not yet read.");
else
myconfig->config_dump(fd);
signal(SIGHUP, config_signal);
}
This diff is collapsed.
#include <netinet/in.h>
#include <arpa/inet.h>
/*
* Config info for a single image
* XXX needs to be extended for REs.
*/
struct config_imageinfo {
char *imageid; /* unique name of image */
char *path; /* path where image is stored */
int flags; /* */
char *get_options; /* options for GET operation */
int get_methods; /* allowed GET transfer mechanisms */
char *put_options; /* options for PUT operation */
void *extra; /* config-type specific info */
};
/* flags */
#define CONFIG_IMAGE_ISFILE 0x1 /* path is an image file */
#define CONFIG_IMAGE_ISDIR 0x2 /* path is a directory */
#define CONFIG_IMAGE_ISGLOB 0x4 /* path is a file glob */
#define CONFIG_IMAGE_ISRE 0x8 /* path is a perl RE */
/* methods */
#define CONFIG_IMAGE_UNKNOWN 0x0
#define CONFIG_IMAGE_UCAST 0x1
#define CONFIG_IMAGE_MCAST 0x2
#define CONFIG_IMAGE_BCAST 0x4
struct config_host_authinfo {
char *hostid; /* unique name of host */
int numimages; /* number of images in info array */
struct config_imageinfo *imageinfo; /* info array */
void *extra; /* config-type specific info */
};
/*
* Config file functions
*/
struct config {
int (*config_init)(void);
void (*config_deinit)(void);
int (*config_read)(void);
int (*config_get_host_authinfo)(struct in_addr *, char *,
struct config_host_authinfo **,
struct config_host_authinfo **);
void (*config_free_host_authinfo)(struct config_host_authinfo *);
int (*config_get_server_address)(struct config_host_authinfo *, int,
in_addr_t *, in_port_t *, int *);
void *(*config_save)(void);
int (*config_restore)(void *);
void (*config_free)(void *);
void (*config_dump)(FILE *);
};
extern int config_init(int);
extern void config_deinit(void);
extern int config_read(void);
extern int config_get_host_authinfo(struct in_addr *, char *,
struct config_host_authinfo **,
struct config_host_authinfo **);
extern void config_free_host_authinfo(struct config_host_authinfo *);
extern int config_auth_by_IP(struct in_addr *, char *,
struct config_host_authinfo **);
extern int config_get_server_address(struct config_host_authinfo *, int,
in_addr_t *, in_port_t *, int *);
extern char * config_perror(int);
extern void * config_save(void);
extern int config_restore(void *);
extern void config_dump(FILE *);
#define CONFIG_ERR_HA_FAILED 1 /* internal host auth error */
#define CONFIG_ERR_HA_NOHOST 2 /* no such host */
#define CONFIG_ERR_HA_NOIMAGE 3 /* no such image */
#define CONFIG_ERR_HA_NOACCESS 4 /* access not allowed for host */
#define CONFIG_ERR_HA_NOMETHOD 5 /* not avail to host via method */
......@@ -314,6 +314,50 @@ typedef struct {
#define PKTSUBTYPE_PREQUEST 6
#define PKTSUBTYPE_JOIN2 7
#ifdef MASTER_SERVER
#include <netinet/in.h>
/* default port number: 0xfbee */
#define MS_PORTNUM 64494
/* imageid length: large enough to hold an ascii encoded SHA 1024 hash */
#define MS_MAXIDLEN 256
/*
* Master server messages.
* These are sent via unicast TCP.
*/
typedef struct {
int32_t type;
union {
struct {
uint8_t methods;
uint8_t status;
uint16_t idlen;
char imageid[MS_MAXIDLEN];
} __attribute__((__packed__)) getrequest;
struct {
uint8_t method;
uint8_t isrunning;
uint16_t error;
in_addr_t addr;
in_port_t port;
} __attribute__((__packed__)) getreply;
} body;
} MasterMsg_t;
#define MS_MSGTYPE_GETREQUEST 1
#define MS_MSGTYPE_GETREPLY 2
#define MS_MSGTYPE_PUTREQUEST 3
#define MS_MSGTYPE_PUTREPLY 4
#define MS_METHOD_UNKNOWN 0
#define MS_METHOD_UNICAST 1
#define MS_METHOD_MULTICAST 2
#define MS_METHOD_BROADCAST 4
#define MS_METHOD_ANY 7
#endif
/*
* Protos.
*/
......@@ -327,6 +371,11 @@ void PacketSend(Packet_t *p, int *resends);
void PacketReply(Packet_t *p);
int PacketValid(Packet_t *p, int nchunks);
void dump_network(void);
#ifdef MASTER_SERVER
int ClientNetFindServer(struct in_addr *, char *, int, int);
int MsgSend(int, MasterMsg_t *, size_t, int);
int MsgReceive(int, MasterMsg_t *, size_t, int);
#endif
/*
* Globals
......
/*
* EMULAB-COPYRIGHT
* Copyright (c) 2000-2003 University of Utah and the Flux Group.
* Copyright (c) 2000-2010 University of Utah and the Flux Group.
* All rights reserved.
*/
......@@ -47,6 +47,37 @@ ServerLogInit(void)
return 0;
}
int
MasterServerLogInit(void)
{
if (debug) {
usesyslog = 0;
return 1;
}
openlog("mfrisbeed", LOG_PID, LOG_TESTBED);
return 0;
}
void
info(const char *fmt, ...)
{
va_list args;
char buf[BUFSIZ];
va_start(args, fmt);
vsnprintf(buf, sizeof(buf), fmt, args);
va_end(args);
if (!usesyslog) {
fputs(buf, stderr);
fputc('\n', stderr);
}
else
syslog(LOG_INFO, "%s", buf);
}
void
log(const char *fmt, ...)
{
......@@ -90,6 +121,7 @@ error(const char *fmt, ...)
va_start(args, fmt);
if (!usesyslog) {
vfprintf(stderr, fmt, args);
fputc('\n', stderr);
fflush(stderr);
}
else
......
/*
* EMULAB-COPYRIGHT
* Copyright (c) 2000-2002, 2005 University of Utah and the Flux Group.
* Copyright (c) 2000-2010 University of Utah and the Flux Group.
* All rights reserved.
*/
......@@ -11,7 +11,9 @@
int ClientLogInit(void);
int ServerLogInit(void);
int MasterServerLogInit(void);
void log(const char *fmt, ...);
void info(const char *fmt, ...);
void warning(const char *fmt, ...);
void error(const char *fmt, ...);
void fatal(const char *fmt, ...);
......
This diff is collapsed.
......@@ -136,7 +136,7 @@ CommonInit(int dobind)
unsigned int loop = 0, ttl = MCAST_TTL;
struct ip_mreq mreq;
log("Using Multicast");
log("Using Multicast %s", inet_ntoa(mcastaddr));
mreq.imr_multiaddr.s_addr = mcastaddr.s_addr;
......@@ -470,3 +470,204 @@ PacketValid(Packet_t *p, int nchunks)
return 1;
}
#ifdef MASTER_SERVER
int
MsgSend(int msock, MasterMsg_t *msg, size_t size, int timo)
{
void *buf = msg;
int cc;
struct timeval tv, now, then;
fd_set wfds;
if (timo) {
tv.tv_sec = timo;
tv.tv_usec = 0;
gettimeofday(&then, NULL);
timeradd(&then, &tv, &then);
}
while (size > 0) {
if (timo) {
gettimeofday(&now, NULL);
if (timercmp(&now, &then, >=)) {
cc = 0;
} else {
timersub(&then, &now, &tv);
FD_ZERO(&wfds);
FD_SET(msock, &wfds);
cc = select(msock+1, NULL, &wfds, NULL, &tv);
}
if (cc <= 0) {
if (cc == 0) {
errno = ETIMEDOUT;
cc = -1;
}
break;
}
}
cc = write(msock, buf, size);
if (cc <= 0)
break;
size -= cc;
buf += cc;
}
if (size != 0) {
char *estr = "master server message send";
if (cc == 0)
fprintf(stderr, "%s: Unexpected EOF\n", estr);
else
perror(estr);
return 0;
}
return 1;
}
int
MsgReceive(int msock, MasterMsg_t *msg, size_t size, int timo)
{
void *buf = msg;