]> git.ipfire.org Git - thirdparty/chrony.git/commitdiff
Add SOCK refclock driver
authorMiroslav Lichvar <mlichvar@redhat.com>
Wed, 19 Aug 2009 13:39:06 +0000 (15:39 +0200)
committerMiroslav Lichvar <mlichvar@redhat.com>
Wed, 19 Aug 2009 13:39:06 +0000 (15:39 +0200)
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
refclock.c
refclock_sock.c [new file with mode: 0644]

index cd6a3f02571cb6bd90e2a52bad9ecbca5085cfcb..632ef72a0fed61a71aa290edad2eeab7461c28b8 100644 (file)
@@ -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@
 
index 8d0526a8660446ef609f5aee9135f71ade9c0b6d..1d8167f3715156f84c4eaf39998c1b98784b6a73 100644 (file)
@@ -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 (file)
index 0000000..188e4dd
--- /dev/null
@@ -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 <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <unistd.h>
+
+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
+};