46
46
#include "echttp_cors.h"
47
47
#include "echttp_static.h"
48
48
#include "houseportalclient.h"
49
+ #include "houselog.h"
49
50
50
51
static pid_t parent ;
51
52
53
+ static long hc_known_clients [256 ]; // Enough to store IP v4 address.
54
+ static long hc_known_servers [256 ]; // Enough to store IP v4 address.
52
55
53
56
static hc_clock_status * clock_db = 0 ;
54
57
static hc_nmea_status * nmea_db = 0 ;
@@ -63,6 +66,7 @@ static char JsonBuffer[16384];
63
66
static void hc_background (int fd , int mode ) {
64
67
static time_t LastParentCheck = 0 ;
65
68
static time_t LastRenewal = 0 ;
69
+ static time_t LastActivityCheck = 0 ;
66
70
67
71
time_t now = time (0 );
68
72
@@ -90,6 +94,89 @@ static void hc_background (int fd, int mode) {
90
94
LastRenewal = now ;
91
95
}
92
96
}
97
+
98
+ if (ntp_db && (now >= LastActivityCheck + 5 )) {
99
+
100
+
101
+ // Generate events for new or unsynchronized clients.
102
+ // We generate a local "cache" of known clients to limit the number of
103
+ // events generated when the clent is not synchronized. The cache key
104
+ // is the low 7 bits of the IP address, plus the ninth bit: this works
105
+ // best for me because I have two subnets, while I don't have anywhere
106
+ // close to 127 machines at home.
107
+ // This should work fine for most home networks.
108
+ //
109
+ int i ;
110
+ for (i = 0 ; i < HC_NTP_DEPTH ; ++ i ) {
111
+ struct hc_ntp_client * client = ntp_db -> clients + i ;
112
+
113
+ // Do not consider events that are empty or too old (risk of
114
+ // race condition)
115
+ //
116
+ if ((client -> local .tv_sec < LastActivityCheck )
117
+ || (client -> local .tv_sec == 0 )) continue ;
118
+
119
+ // Do not consider events that were already detected.
120
+ //
121
+ if (client -> logged ) continue ;
122
+
123
+ if (abs (client -> origin .tv_sec - client -> local .tv_sec ) > 600 ) {
124
+ houselog_event ("CLIENT" , hc_broadcast_format (& (client -> address )),
125
+ "ACTIVE" , "NOT SYNCHRONIZED" );
126
+ } else {
127
+ long adr = ntohl (client -> address .sin_addr .s_addr );
128
+ int hash = (int ) ((adr & 0x7f ) | ((adr & 0x100 ) >> 1 ));
129
+
130
+ int delta =
131
+ ((client -> origin .tv_sec - client -> local .tv_sec ) * 1000 )
132
+ + ((client -> origin .tv_usec - client -> local .tv_usec ) / 1000 );
133
+
134
+ if ((hc_known_clients [hash ] == adr ) && (abs (delta ) < 10000 )) continue ;
135
+ houselog_event ("CLIENT" , hc_broadcast_format (& (client -> address )),
136
+ "ACTIVE" , "DELTA %d MS" , delta );
137
+
138
+ hc_known_clients [hash ] = adr ;
139
+ }
140
+ client -> logged = 1 ;
141
+ }
142
+
143
+ // Generate events for newly detected servers, using a similar cache
144
+ // as for clients to limit the rate of events when synchronized.
145
+ //
146
+ for (i = 0 ; i < HC_NTP_POOL ; ++ i ) {
147
+ struct hc_ntp_server * server = ntp_db -> pool + i ;
148
+
149
+ // Do not consider events that are empty or too old (risk of
150
+ // race condition)
151
+ //
152
+ if ((server -> local .tv_sec < LastActivityCheck )
153
+ || (server -> local .tv_sec == 0 )) continue ;
154
+
155
+ // Do not consider events that were already detected.
156
+ //
157
+ if (server -> logged ) continue ;
158
+
159
+ if (abs (server -> origin .tv_sec - server -> local .tv_sec ) > 600 ) {
160
+ houselog_event ("SERVER" , server -> name , "ACTIVE" ,
161
+ "STRATUM %d, NOT SYNCHRONIZED" , server -> stratum );
162
+ } else {
163
+ long adr = ntohl (server -> address .sin_addr .s_addr );
164
+ int hash = (int ) ((adr & 0x7f ) | ((adr & 0x100 ) >> 1 ));
165
+
166
+ int delta =
167
+ ((server -> origin .tv_sec - server -> local .tv_sec ) * 1000 )
168
+ + ((server -> origin .tv_usec - server -> local .tv_usec ) / 1000 );
169
+
170
+ if ((hc_known_servers [hash ] == adr ) && (abs (delta ) < 10000 )) continue ;
171
+ houselog_event ("SERVER" , server -> name , "ACTIVE" ,
172
+ "STRATUM %d, DELTA %d MS" , server -> stratum , delta );
173
+
174
+ hc_known_servers [hash ] = adr ;
175
+ }
176
+ server -> logged = 1 ;
177
+ }
178
+ LastActivityCheck = now ;
179
+ }
93
180
}
94
181
95
182
static void * hc_http_attach (const char * name ) {
@@ -474,6 +561,7 @@ void hc_http (int argc, const char **argv) {
474
561
houseportal_initialize (argc , argv );
475
562
use_houseportal = 1 ;
476
563
}
564
+ houselog_initialize ("ntp" , argc , argv );
477
565
478
566
echttp_cors_allow_method ("GET" );
479
567
echttp_protect (0 , hc_protect );
@@ -485,6 +573,7 @@ void hc_http (int argc, const char **argv) {
485
573
echttp_route_uri ("/ntp/server" , hc_http_ntp );
486
574
echttp_static_route ("/" , "/usr/local/share/house/public" );
487
575
echttp_background (& hc_background );
576
+ houselog_event ("SERVICE" , "ntp" , "STARTED" , "ON %s" , houselog_host ());
488
577
echttp_loop ();
489
578
exit (0 );
490
579
}
0 commit comments