From 3a9e13445f474c5f7583d9a744fc56b11e929d57 Mon Sep 17 00:00:00 2001 From: Miroslav Lichvar Date: Wed, 19 Aug 2009 15:39:06 +0200 Subject: [PATCH] Add SOCK refclock driver This adds a support for receiving samples over unix domain socket. It's a better alternative to the SHM refclock, the resolution is not limited to microseconds and it doesn't require polling. --- Makefile.in | 2 +- refclock.c | 3 ++ refclock_sock.c | 99 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 103 insertions(+), 1 deletion(-) create mode 100644 refclock_sock.c diff --git a/Makefile.in b/Makefile.in index cd6a3f0..632ef72 100644 --- a/Makefile.in +++ b/Makefile.in @@ -41,7 +41,7 @@ OBJS = util.o sched.o regress.o local.o \ logging.o conf.o cmdmon.o md5.o keys.o \ nameserv.o acquire.o manual.o addrfilt.o \ cmdparse.o mkdirpp.o rtc.o pktlength.o clientlog.o \ - broadcast.o refclock.o refclock_shm.o + broadcast.o refclock.o refclock_shm.o refclock_sock.o EXTRA_OBJS=@EXTRA_OBJECTS@ diff --git a/refclock.c b/refclock.c index 8d0526a..1d8167f 100644 --- a/refclock.c +++ b/refclock.c @@ -36,6 +36,7 @@ /* list of refclock drivers */ extern RefclockDriver RCL_SHM_driver; +extern RefclockDriver RCL_SOCK_driver; struct FilterSample { double offset; @@ -116,6 +117,8 @@ RCL_AddRefclock(RefclockParameters *params) if (strncmp(params->driver_name, "SHM", 4) == 0) { inst->driver = &RCL_SHM_driver; + } else if (strncmp(params->driver_name, "SOCK", 4) == 0) { + inst->driver = &RCL_SOCK_driver; } else { LOG_FATAL(LOGF_Refclock, "unknown refclock driver %s", params->driver_name); return 0; diff --git a/refclock_sock.c b/refclock_sock.c new file mode 100644 index 0000000..188e4dd --- /dev/null +++ b/refclock_sock.c @@ -0,0 +1,99 @@ +/* + chronyd/chronyc - Programs for keeping computer clocks accurate. + + ********************************************************************** + * Copyright (C) Richard P. Curnow 2009 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * 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; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + ********************************************************************** + + ======================================================================= + + Unix domain socket refclock driver. + + */ + +#include "refclock.h" +#include "logging.h" +#include "util.h" +#include "sched.h" + +#include +#include +#include +#include + +struct sock_sample { + struct timeval tv; + double offset; + int leap; +}; + +static void read_sample(void *anything) +{ + struct sock_sample sample; + RCL_Instance instance; + int sockfd; + + instance = (RCL_Instance)anything; + sockfd = (long)RCL_GetDriverData(instance); + + if (recv(sockfd, &sample, sizeof (sample), 0) != sizeof (sample)) + return; + + RCL_AddSample(instance, &sample.tv, sample.offset, sample.leap); +} + +static int sock_initialise(RCL_Instance instance) +{ + struct sockaddr_un s; + int sockfd; + char *path; + + path = RCL_GetDriverParameter(instance); + + s.sun_family = AF_UNIX; + if (snprintf(s.sun_path, sizeof (s.sun_path), "%s", path) >= sizeof (s.sun_path)) { + LOG_FATAL(LOGF_Refclock, "path %s is too long", path); + return 0; + } + + sockfd = socket(AF_UNIX, SOCK_DGRAM, 0); + if (sockfd < 0) { + LOG_FATAL(LOGF_Refclock, "socket() failed"); + return 0; + } + + unlink(path); + if (bind(sockfd, (struct sockaddr *)&s, sizeof (s)) < 0) { + LOG_FATAL(LOGF_Refclock, "bind() failed"); + return 0; + } + + RCL_SetDriverData(instance, (void *)(long)sockfd); + SCH_AddInputFileHandler(sockfd, read_sample, instance); + return 1; +} + +static void sock_finalise(RCL_Instance instance) +{ + SCH_RemoveInputFileHandler((long)RCL_GetDriverData(instance)); +} + +RefclockDriver RCL_SOCK_driver = { + sock_initialise, + sock_finalise, + NULL +};