1 /*
2  * Copyright (C) 2012 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef ANDROID_COMMON_TIME_SERVER_PACKETS_H
18 #define ANDROID_COMMON_TIME_SERVER_PACKETS_H
19 
20 #include <stdint.h>
21 #include <common_time/ICommonClock.h>
22 
23 namespace android {
24 
25 /***** time sync protocol packets *****/
26 
27 enum TimeServicePacketType {
28     TIME_PACKET_WHO_IS_MASTER_REQUEST = 1,
29     TIME_PACKET_WHO_IS_MASTER_RESPONSE,
30     TIME_PACKET_SYNC_REQUEST,
31     TIME_PACKET_SYNC_RESPONSE,
32     TIME_PACKET_MASTER_ANNOUNCEMENT,
33 };
34 
35 class TimeServicePacketHeader {
36   public:
37     friend class UniversalTimeServicePacket;
38     // magic number identifying the protocol
39     uint32_t magic;
40 
41     // protocol version of the packet
42     uint16_t version;
43 
44     // type of the packet
45     TimeServicePacketType packetType;
46 
47     // the timeline ID
48     uint64_t timelineID;
49 
50     // synchronization group this packet belongs to (used to operate multiple
51     // synchronization domains which all use the same master election endpoint)
52     uint64_t syncGroupID;
53 
54     ssize_t serializePacket(uint8_t* data, uint32_t length);
55 
56   protected:
initHeader(TimeServicePacketType type,const uint64_t tlID,const uint64_t groupID)57     void initHeader(TimeServicePacketType type,
58                     const uint64_t tlID,
59                     const uint64_t groupID) {
60         magic              = kMagic;
61         version            = kCurVersion;
62         packetType         = type;
63         timelineID         = tlID;
64         syncGroupID        = groupID;
65     }
66 
checkPacket(uint64_t expectedSyncGroupID)67     bool checkPacket(uint64_t expectedSyncGroupID) const {
68         return ((magic       == kMagic) &&
69                 (version     == kCurVersion) &&
70                 (!expectedSyncGroupID || (syncGroupID == expectedSyncGroupID)));
71     }
72 
73     ssize_t serializeHeader(uint8_t* data, uint32_t length);
74     ssize_t deserializeHeader(const uint8_t* data, uint32_t length);
75 
76   private:
77     static const uint32_t kMagic;
78     static const uint16_t kCurVersion;
79 };
80 
81 // packet querying for a suitable master
82 class WhoIsMasterRequestPacket : public TimeServicePacketHeader {
83   public:
84     uint64_t senderDeviceID;
85     uint8_t senderDevicePriority;
86 
initHeader(const uint64_t groupID)87     void initHeader(const uint64_t groupID) {
88         TimeServicePacketHeader::initHeader(TIME_PACKET_WHO_IS_MASTER_REQUEST,
89                                             ICommonClock::kInvalidTimelineID,
90                                             groupID);
91     }
92 
93     ssize_t serializePacket(uint8_t* data, uint32_t length);
94     ssize_t deserializePacket(const uint8_t* data, uint32_t length);
95 };
96 
97 // response to a WhoIsMaster request
98 class WhoIsMasterResponsePacket : public TimeServicePacketHeader {
99   public:
100     uint64_t deviceID;
101     uint8_t devicePriority;
102 
initHeader(const uint64_t tlID,const uint64_t groupID)103     void initHeader(const uint64_t tlID, const uint64_t groupID) {
104         TimeServicePacketHeader::initHeader(TIME_PACKET_WHO_IS_MASTER_RESPONSE,
105                                             tlID, groupID);
106     }
107 
108     ssize_t serializePacket(uint8_t* data, uint32_t length);
109     ssize_t deserializePacket(const uint8_t* data, uint32_t length);
110 };
111 
112 // packet sent by a client requesting correspondence between local
113 // and common time
114 class SyncRequestPacket : public TimeServicePacketHeader {
115   public:
116     // local time when this request was transmitted
117     int64_t clientTxLocalTime;
118 
initHeader(const uint64_t tlID,const uint64_t groupID)119     void initHeader(const uint64_t tlID, const uint64_t groupID) {
120         TimeServicePacketHeader::initHeader(TIME_PACKET_SYNC_REQUEST,
121                                             tlID, groupID);
122     }
123 
124     ssize_t serializePacket(uint8_t* data, uint32_t length);
125     ssize_t deserializePacket(const uint8_t* data, uint32_t length);
126 };
127 
128 // response to a sync request sent by the master
129 class SyncResponsePacket : public TimeServicePacketHeader {
130   public:
131     // local time when this request was transmitted by the client
132     int64_t clientTxLocalTime;
133 
134     // common time when the master received the request
135     int64_t masterRxCommonTime;
136 
137     // common time when the master transmitted the response
138     int64_t masterTxCommonTime;
139 
140     // flag that is set if the recipient of the sync request is not acting
141     // as a master for the requested timeline
142     uint32_t nak;
143 
initHeader(const uint64_t tlID,const uint64_t groupID)144     void initHeader(const uint64_t tlID, const uint64_t groupID) {
145         TimeServicePacketHeader::initHeader(TIME_PACKET_SYNC_RESPONSE,
146                                             tlID, groupID);
147     }
148 
149     ssize_t serializePacket(uint8_t* data, uint32_t length);
150     ssize_t deserializePacket(const uint8_t* data, uint32_t length);
151 };
152 
153 // announcement of the master's presence
154 class MasterAnnouncementPacket : public TimeServicePacketHeader {
155   public:
156     // the master's device ID
157     uint64_t deviceID;
158     uint8_t devicePriority;
159 
initHeader(const uint64_t tlID,const uint64_t groupID)160     void initHeader(const uint64_t tlID, const uint64_t groupID) {
161         TimeServicePacketHeader::initHeader(TIME_PACKET_MASTER_ANNOUNCEMENT,
162                                             tlID, groupID);
163     }
164 
165     ssize_t serializePacket(uint8_t* data, uint32_t length);
166     ssize_t deserializePacket(const uint8_t* data, uint32_t length);
167 };
168 
169 class UniversalTimeServicePacket {
170   public:
171     uint16_t packetType;
172     union {
173         WhoIsMasterRequestPacket  who_is_master_request;
174         WhoIsMasterResponsePacket who_is_master_response;
175         SyncRequestPacket         sync_request;
176         SyncResponsePacket        sync_response;
177         MasterAnnouncementPacket  master_announcement;
178     } p;
179 
180     ssize_t deserializePacket(const uint8_t* data,
181                               uint32_t       length,
182                               uint64_t       expectedSyncGroupID);
183 };
184 
185 };  // namespace android
186 
187 #endif  // ANDROID_COMMON_TIME_SERVER_PACKETS_H
188 
189 
190