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/*
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
294