blob: 9833c37f2519b10120f0f1f01817e3c4c98bedab [file] [log] [blame]
Mike J. Chen6c929512011-08-15 11:59:47 -07001/*
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/*
18 * A service that exchanges time synchronization information between
19 * a master that defines a timeline and clients that follow the timeline.
20 */
21
22#define LOG_TAG "common_time"
23#include <utils/Log.h>
24
25#include <arpa/inet.h>
26#include <stdint.h>
27
28#include "common_time_server_packets.h"
29
30namespace android {
31
32const uint32_t TimeServicePacketHeader::kMagic =
33 (static_cast<uint32_t>('c') << 24) |
34 (static_cast<uint32_t>('c') << 16) |
35 (static_cast<uint32_t>('l') << 8) |
36 static_cast<uint32_t>('k');
37
38const uint16_t TimeServicePacketHeader::kCurVersion = 1;
39
40#define SERIALIZE_FIELD(field_name, type, converter) \
41 do { \
42 if ((offset + sizeof(field_name)) > length) \
43 return -1; \
44 *((type*)(data + offset)) = converter(field_name); \
45 offset += sizeof(field_name); \
46 } while (0)
47#define SERIALIZE_INT16(field_name) SERIALIZE_FIELD(field_name, int16_t, htons)
48#define SERIALIZE_INT32(field_name) SERIALIZE_FIELD(field_name, int32_t, htonl)
49#define SERIALIZE_INT64(field_name) SERIALIZE_FIELD(field_name, int64_t, htonq)
50
51#define DESERIALIZE_FIELD(field_name, type, converter) \
52 do { \
53 if ((offset + sizeof(field_name)) > length) \
54 return -1; \
55 field_name = converter(*((type*)(data + offset))); \
56 offset += sizeof(field_name); \
57 } while (0)
58#define DESERIALIZE_INT16(field_name) DESERIALIZE_FIELD(field_name, int16_t, ntohs)
59#define DESERIALIZE_INT32(field_name) DESERIALIZE_FIELD(field_name, int32_t, ntohl)
60#define DESERIALIZE_INT64(field_name) DESERIALIZE_FIELD(field_name, int64_t, ntohq)
61
62#define kDevicePriorityShift 56
63#define kDeviceIDMask ((static_cast<uint64_t>(1) << kDevicePriorityShift) - 1)
64
65inline uint64_t packDeviceID(uint64_t devID, uint8_t prio) {
66 return (devID & kDeviceIDMask) |
67 (static_cast<uint64_t>(prio) << kDevicePriorityShift);
68}
69
70inline uint64_t unpackDeviceID(uint64_t packed) {
71 return (packed & kDeviceIDMask);
72}
73
74inline uint8_t unpackDevicePriority(uint64_t packed) {
75 return static_cast<uint8_t>(packed >> kDevicePriorityShift);
76}
77
78ssize_t TimeServicePacketHeader::serializeHeader(uint8_t* data,
79 uint32_t length) {
80 ssize_t offset = 0;
81 int16_t pktType = static_cast<int16_t>(packetType);
82 SERIALIZE_INT32(magic);
83 SERIALIZE_INT16(version);
84 SERIALIZE_INT16(pktType);
85 SERIALIZE_INT64(timelineID);
86 SERIALIZE_INT64(syncGroupID);
87 return offset;
88}
89
90ssize_t TimeServicePacketHeader::deserializeHeader(const uint8_t* data,
91 uint32_t length) {
92 ssize_t offset = 0;
93 int16_t tmp;
94 DESERIALIZE_INT32(magic);
95 DESERIALIZE_INT16(version);
96 DESERIALIZE_INT16(tmp);
97 DESERIALIZE_INT64(timelineID);
98 DESERIALIZE_INT64(syncGroupID);
99 packetType = static_cast<TimeServicePacketType>(tmp);
100 return offset;
101}
102
103ssize_t TimeServicePacketHeader::serializePacket(uint8_t* data,
104 uint32_t length) {
105 ssize_t ret, tmp;
106
107 ret = serializeHeader(data, length);
108 if (ret < 0)
109 return ret;
110
111 data += ret;
112 length -= ret;
113
114 switch (packetType) {
115 case TIME_PACKET_WHO_IS_MASTER_REQUEST:
116 tmp =((WhoIsMasterRequestPacket*)(this))->serializePacket(data,
117 length);
118 break;
119 case TIME_PACKET_WHO_IS_MASTER_RESPONSE:
120 tmp =((WhoIsMasterResponsePacket*)(this))->serializePacket(data,
121 length);
122 break;
123 case TIME_PACKET_SYNC_REQUEST:
124 tmp =((SyncRequestPacket*)(this))->serializePacket(data, length);
125 break;
126 case TIME_PACKET_SYNC_RESPONSE:
127 tmp =((SyncResponsePacket*)(this))->serializePacket(data, length);
128 break;
129 case TIME_PACKET_MASTER_ANNOUNCEMENT:
130 tmp =((MasterAnnouncementPacket*)(this))->serializePacket(data,
131 length);
132 break;
133 default:
134 return -1;
135 }
136
137 if (tmp < 0)
138 return tmp;
139
140 return ret + tmp;
141}
142
143ssize_t UniversalTimeServicePacket::deserializePacket(
144 const uint8_t* data,
145 uint32_t length,
146 uint64_t expectedSyncGroupID) {
147 ssize_t ret;
148 TimeServicePacketHeader* header;
149 if (length < 8)
150 return -1;
151
152 packetType = ntohs(*((uint16_t*)(data + 6)));
153 switch (packetType) {
154 case TIME_PACKET_WHO_IS_MASTER_REQUEST:
155 ret = p.who_is_master_request.deserializePacket(data, length);
156 header = &p.who_is_master_request;
157 break;
158 case TIME_PACKET_WHO_IS_MASTER_RESPONSE:
159 ret = p.who_is_master_response.deserializePacket(data, length);
160 header = &p.who_is_master_response;
161 break;
162 case TIME_PACKET_SYNC_REQUEST:
163 ret = p.sync_request.deserializePacket(data, length);
164 header = &p.sync_request;
165 break;
166 case TIME_PACKET_SYNC_RESPONSE:
167 ret = p.sync_response.deserializePacket(data, length);
168 header = &p.sync_response;
169 break;
170 case TIME_PACKET_MASTER_ANNOUNCEMENT:
171 ret = p.master_announcement.deserializePacket(data, length);
172 header = &p.master_announcement;
173 break;
174 default:
175 return -1;
176 }
177
178 if ((ret >= 0) && !header->checkPacket(expectedSyncGroupID))
179 ret = -1;
180
181 return ret;
182}
183
184ssize_t WhoIsMasterRequestPacket::serializePacket(uint8_t* data,
185 uint32_t length) {
186 ssize_t offset = serializeHeader(data, length);
187 if (offset > 0) {
188 uint64_t packed = packDeviceID(senderDeviceID, senderDevicePriority);
189 SERIALIZE_INT64(packed);
190 }
191 return offset;
192}
193
194ssize_t WhoIsMasterRequestPacket::deserializePacket(const uint8_t* data,
195 uint32_t length) {
196 ssize_t offset = deserializeHeader(data, length);
197 if (offset > 0) {
198 uint64_t packed;
199 DESERIALIZE_INT64(packed);
200 senderDeviceID = unpackDeviceID(packed);
201 senderDevicePriority = unpackDevicePriority(packed);
202 }
203 return offset;
204}
205
206ssize_t WhoIsMasterResponsePacket::serializePacket(uint8_t* data,
207 uint32_t length) {
208 ssize_t offset = serializeHeader(data, length);
209 if (offset > 0) {
210 uint64_t packed = packDeviceID(deviceID, devicePriority);
211 SERIALIZE_INT64(packed);
212 }
213 return offset;
214}
215
216ssize_t WhoIsMasterResponsePacket::deserializePacket(const uint8_t* data,
217 uint32_t length) {
218 ssize_t offset = deserializeHeader(data, length);
219 if (offset > 0) {
220 uint64_t packed;
221 DESERIALIZE_INT64(packed);
222 deviceID = unpackDeviceID(packed);
223 devicePriority = unpackDevicePriority(packed);
224 }
225 return offset;
226}
227
228ssize_t SyncRequestPacket::serializePacket(uint8_t* data,
229 uint32_t length) {
230 ssize_t offset = serializeHeader(data, length);
231 if (offset > 0) {
232 SERIALIZE_INT64(clientTxLocalTime);
233 }
234 return offset;
235}
236
237ssize_t SyncRequestPacket::deserializePacket(const uint8_t* data,
238 uint32_t length) {
239 ssize_t offset = deserializeHeader(data, length);
240 if (offset > 0) {
241 DESERIALIZE_INT64(clientTxLocalTime);
242 }
243 return offset;
244}
245
246ssize_t SyncResponsePacket::serializePacket(uint8_t* data,
247 uint32_t length) {
248 ssize_t offset = serializeHeader(data, length);
249 if (offset > 0) {
250 SERIALIZE_INT64(clientTxLocalTime);
251 SERIALIZE_INT64(masterRxCommonTime);
252 SERIALIZE_INT64(masterTxCommonTime);
253 SERIALIZE_INT32(nak);
254 }
255 return offset;
256}
257
258ssize_t SyncResponsePacket::deserializePacket(const uint8_t* data,
259 uint32_t length) {
260 ssize_t offset = deserializeHeader(data, length);
261 if (offset > 0) {
262 DESERIALIZE_INT64(clientTxLocalTime);
263 DESERIALIZE_INT64(masterRxCommonTime);
264 DESERIALIZE_INT64(masterTxCommonTime);
265 DESERIALIZE_INT32(nak);
266 }
267 return offset;
268}
269
270ssize_t MasterAnnouncementPacket::serializePacket(uint8_t* data,
271 uint32_t length) {
272 ssize_t offset = serializeHeader(data, length);
273 if (offset > 0) {
274 uint64_t packed = packDeviceID(deviceID, devicePriority);
275 SERIALIZE_INT64(packed);
276 }
277 return offset;
278}
279
280ssize_t MasterAnnouncementPacket::deserializePacket(const uint8_t* data,
281 uint32_t length) {
282 ssize_t offset = deserializeHeader(data, length);
283 if (offset > 0) {
284 uint64_t packed;
285 DESERIALIZE_INT64(packed);
286 deviceID = unpackDeviceID(packed);
287 devicePriority = unpackDevicePriority(packed);
288 }
289 return offset;
290}
291
292} // namespace android
293