/* * Copyright (C) 2012 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef ANDROID_COMMON_TIME_SERVER_PACKETS_H #define ANDROID_COMMON_TIME_SERVER_PACKETS_H #include <stdint.h> #include <common_time/ICommonClock.h> namespace android { /***** time sync protocol packets *****/ enum TimeServicePacketType { TIME_PACKET_WHO_IS_MASTER_REQUEST = 1, TIME_PACKET_WHO_IS_MASTER_RESPONSE, TIME_PACKET_SYNC_REQUEST, TIME_PACKET_SYNC_RESPONSE, TIME_PACKET_MASTER_ANNOUNCEMENT, }; class TimeServicePacketHeader { public: friend class UniversalTimeServicePacket; // magic number identifying the protocol uint32_t magic; // protocol version of the packet uint16_t version; // type of the packet TimeServicePacketType packetType; // the timeline ID uint64_t timelineID; // synchronization group this packet belongs to (used to operate multiple // synchronization domains which all use the same master election endpoint) uint64_t syncGroupID; ssize_t serializePacket(uint8_t* data, uint32_t length); protected: void initHeader(TimeServicePacketType type, const uint64_t tlID, const uint64_t groupID) { magic = kMagic; version = kCurVersion; packetType = type; timelineID = tlID; syncGroupID = groupID; } bool checkPacket(uint64_t expectedSyncGroupID) const { return ((magic == kMagic) && (version == kCurVersion) && (!expectedSyncGroupID || (syncGroupID == expectedSyncGroupID))); } ssize_t serializeHeader(uint8_t* data, uint32_t length); ssize_t deserializeHeader(const uint8_t* data, uint32_t length); private: static const uint32_t kMagic; static const uint16_t kCurVersion; }; // packet querying for a suitable master class WhoIsMasterRequestPacket : public TimeServicePacketHeader { public: uint64_t senderDeviceID; uint8_t senderDevicePriority; void initHeader(const uint64_t groupID) { TimeServicePacketHeader::initHeader(TIME_PACKET_WHO_IS_MASTER_REQUEST, ICommonClock::kInvalidTimelineID, groupID); } ssize_t serializePacket(uint8_t* data, uint32_t length); ssize_t deserializePacket(const uint8_t* data, uint32_t length); }; // response to a WhoIsMaster request class WhoIsMasterResponsePacket : public TimeServicePacketHeader { public: uint64_t deviceID; uint8_t devicePriority; void initHeader(const uint64_t tlID, const uint64_t groupID) { TimeServicePacketHeader::initHeader(TIME_PACKET_WHO_IS_MASTER_RESPONSE, tlID, groupID); } ssize_t serializePacket(uint8_t* data, uint32_t length); ssize_t deserializePacket(const uint8_t* data, uint32_t length); }; // packet sent by a client requesting correspondence between local // and common time class SyncRequestPacket : public TimeServicePacketHeader { public: // local time when this request was transmitted int64_t clientTxLocalTime; void initHeader(const uint64_t tlID, const uint64_t groupID) { TimeServicePacketHeader::initHeader(TIME_PACKET_SYNC_REQUEST, tlID, groupID); } ssize_t serializePacket(uint8_t* data, uint32_t length); ssize_t deserializePacket(const uint8_t* data, uint32_t length); }; // response to a sync request sent by the master class SyncResponsePacket : public TimeServicePacketHeader { public: // local time when this request was transmitted by the client int64_t clientTxLocalTime; // common time when the master received the request int64_t masterRxCommonTime; // common time when the master transmitted the response int64_t masterTxCommonTime; // flag that is set if the recipient of the sync request is not acting // as a master for the requested timeline uint32_t nak; void initHeader(const uint64_t tlID, const uint64_t groupID) { TimeServicePacketHeader::initHeader(TIME_PACKET_SYNC_RESPONSE, tlID, groupID); } ssize_t serializePacket(uint8_t* data, uint32_t length); ssize_t deserializePacket(const uint8_t* data, uint32_t length); }; // announcement of the master's presence class MasterAnnouncementPacket : public TimeServicePacketHeader { public: // the master's device ID uint64_t deviceID; uint8_t devicePriority; void initHeader(const uint64_t tlID, const uint64_t groupID) { TimeServicePacketHeader::initHeader(TIME_PACKET_MASTER_ANNOUNCEMENT, tlID, groupID); } ssize_t serializePacket(uint8_t* data, uint32_t length); ssize_t deserializePacket(const uint8_t* data, uint32_t length); }; class UniversalTimeServicePacket { public: uint16_t packetType; union { WhoIsMasterRequestPacket who_is_master_request; WhoIsMasterResponsePacket who_is_master_response; SyncRequestPacket sync_request; SyncResponsePacket sync_response; MasterAnnouncementPacket master_announcement; } p; ssize_t deserializePacket(const uint8_t* data, uint32_t length, uint64_t expectedSyncGroupID); }; }; // namespace android #endif // ANDROID_COMMON_TIME_SERVER_PACKETS_H