]>
Commit | Line | Data |
---|---|---|
3a9e1344 ML |
1 | /* |
2 | chronyd/chronyc - Programs for keeping computer clocks accurate. | |
3 | ||
4 | ********************************************************************** | |
f7e08d0c | 5 | * Copyright (C) Miroslav Lichvar 2009 |
3a9e1344 ML |
6 | * |
7 | * This program is free software; you can redistribute it and/or modify | |
8 | * it under the terms of version 2 of the GNU General Public License as | |
9 | * published by the Free Software Foundation. | |
10 | * | |
11 | * This program is distributed in the hope that it will be useful, but | |
12 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
14 | * General Public License for more details. | |
15 | * | |
16 | * You should have received a copy of the GNU General Public License along | |
17 | * with this program; if not, write to the Free Software Foundation, Inc., | |
8e23110a | 18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
3a9e1344 ML |
19 | * |
20 | ********************************************************************** | |
21 | ||
22 | ======================================================================= | |
23 | ||
24 | Unix domain socket refclock driver. | |
25 | ||
26 | */ | |
27 | ||
da2c8d90 ML |
28 | #include "config.h" |
29 | ||
6ca73bf6 ML |
30 | #include "sysincl.h" |
31 | ||
3a9e1344 ML |
32 | #include "refclock.h" |
33 | #include "logging.h" | |
34 | #include "util.h" | |
35 | #include "sched.h" | |
207f9fb1 | 36 | #include "socket.h" |
3a9e1344 | 37 | |
dd5405a2 ML |
38 | #define SOCK_MAGIC 0x534f434b |
39 | ||
3a9e1344 | 40 | struct sock_sample { |
ba25fb1b | 41 | /* Time of the measurement (system time) */ |
3a9e1344 | 42 | struct timeval tv; |
ba25fb1b ML |
43 | |
44 | /* Offset between the true time and the system time (in seconds) */ | |
3a9e1344 | 45 | double offset; |
ba25fb1b ML |
46 | |
47 | /* Non-zero if the sample is from a PPS signal, i.e. another source | |
48 | is needed to obtain seconds */ | |
6d242a33 | 49 | int pulse; |
ba25fb1b ML |
50 | |
51 | /* 0 - normal, 1 - insert leap second, 2 - delete leap second */ | |
3a9e1344 | 52 | int leap; |
ba25fb1b ML |
53 | |
54 | /* Padding, ignored */ | |
dd5405a2 | 55 | int _pad; |
ba25fb1b ML |
56 | |
57 | /* Protocol identifier (0x534f434b) */ | |
dd5405a2 | 58 | int magic; |
3a9e1344 ML |
59 | }; |
60 | ||
0a105453 | 61 | static void read_sample(int sockfd, int event, void *anything) |
3a9e1344 ML |
62 | { |
63 | struct sock_sample sample; | |
d0dfa1de | 64 | struct timespec ts; |
3a9e1344 | 65 | RCL_Instance instance; |
0a105453 | 66 | int s; |
3a9e1344 ML |
67 | |
68 | instance = (RCL_Instance)anything; | |
3a9e1344 | 69 | |
dd5405a2 ML |
70 | s = recv(sockfd, &sample, sizeof (sample), 0); |
71 | ||
72 | if (s < 0) { | |
e15c7cd2 | 73 | DEBUG_LOG("Could not read SOCK sample : %s", strerror(errno)); |
dd5405a2 ML |
74 | return; |
75 | } | |
76 | ||
77 | if (s != sizeof (sample)) { | |
e15c7cd2 ML |
78 | DEBUG_LOG("Unexpected length of SOCK sample : %d != %ld", |
79 | s, (long)sizeof (sample)); | |
dd5405a2 ML |
80 | return; |
81 | } | |
82 | ||
83 | if (sample.magic != SOCK_MAGIC) { | |
e15c7cd2 ML |
84 | DEBUG_LOG("Unexpected magic number in SOCK sample : %x != %x", |
85 | (unsigned int)sample.magic, (unsigned int)SOCK_MAGIC); | |
3a9e1344 | 86 | return; |
dd5405a2 | 87 | } |
3a9e1344 | 88 | |
d0dfa1de ML |
89 | UTI_TimevalToTimespec(&sample.tv, &ts); |
90 | UTI_NormaliseTimespec(&ts); | |
91 | ||
6d242a33 | 92 | if (sample.pulse) { |
d0dfa1de | 93 | RCL_AddPulse(instance, &ts, sample.offset); |
6d242a33 | 94 | } else { |
d0dfa1de | 95 | RCL_AddSample(instance, &ts, sample.offset, sample.leap); |
6d242a33 | 96 | } |
3a9e1344 ML |
97 | } |
98 | ||
99 | static int sock_initialise(RCL_Instance instance) | |
100 | { | |
3a9e1344 ML |
101 | int sockfd; |
102 | char *path; | |
103 | ||
a78031ce ML |
104 | RCL_CheckDriverOptions(instance, NULL); |
105 | ||
3a9e1344 ML |
106 | path = RCL_GetDriverParameter(instance); |
107 | ||
207f9fb1 ML |
108 | sockfd = SCK_OpenUnixDatagramSocket(NULL, path, 0); |
109 | if (sockfd < 0) | |
110 | LOG_FATAL("Could not open socket %s", path); | |
3a9e1344 ML |
111 | |
112 | RCL_SetDriverData(instance, (void *)(long)sockfd); | |
0a105453 | 113 | SCH_AddFileHandler(sockfd, SCH_FILE_INPUT, read_sample, instance); |
3a9e1344 ML |
114 | return 1; |
115 | } | |
116 | ||
117 | static void sock_finalise(RCL_Instance instance) | |
118 | { | |
5a3d85b4 ML |
119 | int sockfd; |
120 | ||
121 | sockfd = (long)RCL_GetDriverData(instance); | |
0a105453 | 122 | SCH_RemoveFileHandler(sockfd); |
c651ea9b | 123 | SCK_RemoveSocket(sockfd); |
207f9fb1 | 124 | SCK_CloseSocket(sockfd); |
3a9e1344 ML |
125 | } |
126 | ||
127 | RefclockDriver RCL_SOCK_driver = { | |
128 | sock_initialise, | |
129 | sock_finalise, | |
130 | NULL | |
131 | }; |