1//
2// NTPPacket.cpp
3//
4// Library: Net
5// Package: NTP
6// Module: NTPPacket
7//
8// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
9// and Contributors.
10//
11// SPDX-License-Identifier: BSL-1.0
12//
13
14
15#include "Poco/Net/NTPPacket.h"
16#include "Poco/Net/NetException.h"
17#include "Poco/Timestamp.h"
18#include "Poco/ByteOrder.h"
19
20
21namespace Poco {
22namespace Net {
23
24
25#if !defined(POCO_COMPILER_SUN)
26#pragma pack(push, 1)
27#else
28#pragma pack(1)
29#endif
30struct NTPPacketData
31{
32 Poco::Int8 mode:3;
33 Poco::Int8 vn:3;
34 Poco::Int8 li:2;
35 Poco::Int8 stratum;
36 Poco::Int8 pool;
37 Poco::Int8 prec;
38 Poco::Int32 rootdelay;
39 Poco::Int32 rootdisp;
40 Poco::Int32 refid;
41 Poco::Int64 rts;
42 Poco::Int64 ots;
43 Poco::Int64 vts;
44 Poco::Int64 tts;
45};
46#if !defined(POCO_COMPILER_SUN)
47#pragma pack(pop)
48#else
49#pragma pack()
50#endif
51
52
53NTPPacket::NTPPacket() :
54 // the next 3 fields must be in reverse order from spec
55 _leapIndicator(3),
56 _version(4),
57 _mode(3),
58 _stratum(0),
59 _pool(6),
60 _precision(-18),
61 _rootDelay(0),
62 _rootDispersion(0),
63 _referenceId(0),
64 _referenceTimestamp(0),
65 _receiveTimestamp(0),
66 _transmitTimestamp(0)
67{
68 Poco::Timestamp ts;
69 _originateTimestamp = ts.utcTime() - 2874597888;
70}
71
72
73NTPPacket::NTPPacket(Poco::UInt8 *packet)
74{
75 setPacket(packet);
76}
77
78
79NTPPacket::~NTPPacket()
80{
81}
82
83
84void NTPPacket::packet(Poco::UInt8 *packet) const
85{
86 NTPPacketData *p = (NTPPacketData*)packet;
87
88 p->li = _leapIndicator;
89 p->vn = _version;
90 p->mode = _mode;
91 p->stratum = _stratum;
92 p->pool = _pool;
93 p->prec = _precision;
94 p->rootdelay = Poco::ByteOrder::toNetwork(_rootDelay);
95 p->rootdisp = Poco::ByteOrder::toNetwork(_rootDispersion);
96 p->refid = Poco::ByteOrder::toNetwork(_referenceId);
97 p->rts = Poco::ByteOrder::toNetwork(_referenceTimestamp);
98 p->ots = Poco::ByteOrder::toNetwork(_originateTimestamp);
99 p->vts = Poco::ByteOrder::toNetwork(_receiveTimestamp);
100 p->tts = Poco::ByteOrder::toNetwork(_transmitTimestamp);
101}
102
103
104void NTPPacket::setPacket(Poco::UInt8 *packet)
105{
106 NTPPacketData *p = (NTPPacketData*)packet;
107
108 _leapIndicator = p->li;
109 _version = p->vn;
110 _mode = p->mode;
111 _stratum = p->stratum;
112 _pool = p->pool;
113 _precision = p->prec;
114 _rootDelay = Poco::ByteOrder::fromNetwork(p->rootdelay);
115 _rootDispersion = Poco::ByteOrder::fromNetwork(p->rootdisp);
116 _referenceId = Poco::ByteOrder::fromNetwork(p->refid);
117 _referenceTimestamp = Poco::ByteOrder::fromNetwork(p->rts);
118 _originateTimestamp = Poco::ByteOrder::fromNetwork(p->ots);
119 _receiveTimestamp = Poco::ByteOrder::fromNetwork(p->vts);
120 _transmitTimestamp = Poco::ByteOrder::fromNetwork(p->tts);
121}
122
123
124Poco::Timestamp NTPPacket::referenceTime() const
125{
126 return convertTime(_referenceTimestamp);
127}
128
129
130Poco::Timestamp NTPPacket::originateTime() const
131{
132 return convertTime(_originateTimestamp);
133}
134
135
136Poco::Timestamp NTPPacket::receiveTime() const
137{
138 return convertTime(_receiveTimestamp);
139}
140
141
142Poco::Timestamp NTPPacket::transmitTime() const
143{
144 return convertTime(_transmitTimestamp);
145}
146
147
148Poco::Timestamp NTPPacket::convertTime(Poco::Int64 tm) const
149{
150 const unsigned long seventyYears = 2208988800UL;
151 Poco::UInt32 secsSince1900 = UInt32(Poco::ByteOrder::toLittleEndian(tm) >> 32);
152 unsigned long epoch = secsSince1900 - seventyYears;
153 return Poco::Timestamp::fromEpochTime(epoch);
154}
155
156
157} } // namespace Poco::Net
158