2 * Copyright (c) 2010-2022 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
7 * This program and the accompanying materials are made available under the
8 * terms of the Eclipse Public License 2.0 which is available at
9 * http://www.eclipse.org/legal/epl-2.0
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.ntp.server;
15 import java.io.IOException;
16 import java.net.DatagramPacket;
17 import java.net.DatagramSocket;
18 import java.net.SocketException;
20 import org.apache.commons.net.ntp.NtpV3Impl;
21 import org.apache.commons.net.ntp.NtpV3Packet;
22 import org.apache.commons.net.ntp.TimeStamp;
23 import org.openhab.binding.ntp.test.NtpOSGiTest;
24 import org.slf4j.Logger;
25 import org.slf4j.LoggerFactory;
28 * This is a simple NTP server which provides timestamps to the {@link NtpOSGiTest} tests.
29 * Its main purpose is to remove the dependence on a remote ntp server because it is hosted locally.
31 * @author Erdoan Hadzhiyusein - Initial Contribution
34 public class SimpleNTPServer {
36 private DatagramSocket socket;
38 private volatile boolean isRunning;
39 private byte[] array = new byte[48];
40 private final DatagramPacket request = new DatagramPacket(array, array.length);
41 private Logger logger = LoggerFactory.getLogger(SimpleNTPServer.class);
44 * The server must use an available port to be able to start.
45 * According to RFC 793, the port is a 16 bit unsigned int.
49 public SimpleNTPServer(int port) {
50 if (port > 0 && port < 65535) {
53 throw new IllegalArgumentException(
54 "Please choose an available port! This port cannot be used at the moment" + port);
59 * This method opens a new socket and receives requests calling handleRequest() for each one.
61 public void startServer() {
68 socket = new DatagramSocket(port);
69 } catch (SocketException e) {
70 logger.error("Occured an error {}. Couldn't open a socket on this port:", port, e);
74 socket.receive(request);
75 handleRequest(request);
76 } catch (IOException e) {
77 logger.error("There was an error {} while processing the request!", request, e);
85 * Stopping the server which causes closing the socket too
87 public void stopServer() {
90 socket.close(); // force closing of the socket
95 private void handleRequest(DatagramPacket requestPacket) throws IOException {
96 final long receivedTime = System.currentTimeMillis();
97 NtpV3Packet responsePacket = new NtpV3Impl();
98 responsePacket.setMode(NtpV3Packet.MODE_SERVER);
99 responsePacket.setTransmitTime(TimeStamp.getNtpTime(receivedTime));
100 DatagramPacket dataPacket = responsePacket.getDatagramPacket();
101 dataPacket.setPort(requestPacket.getPort());
102 dataPacket.setAddress(requestPacket.getAddress());
103 socket.send(dataPacket);