summaryrefslogtreecommitdiffstats
path: root/media/libstagefright/wifi-display/SNTPClient.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'media/libstagefright/wifi-display/SNTPClient.cpp')
-rw-r--r--media/libstagefright/wifi-display/SNTPClient.cpp174
1 files changed, 174 insertions, 0 deletions
diff --git a/media/libstagefright/wifi-display/SNTPClient.cpp b/media/libstagefright/wifi-display/SNTPClient.cpp
new file mode 100644
index 0000000..5c0af6a
--- /dev/null
+++ b/media/libstagefright/wifi-display/SNTPClient.cpp
@@ -0,0 +1,174 @@
+/*
+ * Copyright 2013, 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.
+ */
+
+#include "SNTPClient.h"
+
+#include <media/stagefright/foundation/ALooper.h>
+#include <media/stagefright/Utils.h>
+
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <unistd.h>
+
+namespace android {
+
+SNTPClient::SNTPClient() {
+}
+
+status_t SNTPClient::requestTime(const char *host) {
+ struct hostent *ent;
+ int64_t requestTimeNTP, requestTimeUs;
+ ssize_t n;
+ int64_t responseTimeUs, responseTimeNTP;
+ int64_t originateTimeNTP, receiveTimeNTP, transmitTimeNTP;
+ int64_t roundTripTimeNTP, clockOffsetNTP;
+
+ status_t err = UNKNOWN_ERROR;
+
+ int s = socket(AF_INET, SOCK_DGRAM, 0);
+
+ if (s < 0) {
+ err = -errno;
+
+ goto bail;
+ }
+
+ ent = gethostbyname(host);
+
+ if (ent == NULL) {
+ err = -ENOENT;
+ goto bail2;
+ }
+
+ struct sockaddr_in hostAddr;
+ memset(hostAddr.sin_zero, 0, sizeof(hostAddr.sin_zero));
+ hostAddr.sin_family = AF_INET;
+ hostAddr.sin_port = htons(kNTPPort);
+ hostAddr.sin_addr.s_addr = *(in_addr_t *)ent->h_addr;
+
+ uint8_t packet[kNTPPacketSize];
+ memset(packet, 0, sizeof(packet));
+
+ packet[0] = kNTPModeClient | (kNTPVersion << 3);
+
+ requestTimeNTP = getNowNTP();
+ requestTimeUs = ALooper::GetNowUs();
+ writeTimeStamp(&packet[kNTPTransmitTimeOffset], requestTimeNTP);
+
+ n = sendto(
+ s, packet, sizeof(packet), 0,
+ (const struct sockaddr *)&hostAddr, sizeof(hostAddr));
+
+ if (n < 0) {
+ err = -errno;
+ goto bail2;
+ }
+
+ memset(packet, 0, sizeof(packet));
+
+ do {
+ n = recv(s, packet, sizeof(packet), 0);
+ } while (n < 0 && errno == EINTR);
+
+ if (n < 0) {
+ err = -errno;
+ goto bail2;
+ }
+
+ responseTimeUs = ALooper::GetNowUs();
+
+ responseTimeNTP = requestTimeNTP + makeNTP(responseTimeUs - requestTimeUs);
+
+ originateTimeNTP = readTimeStamp(&packet[kNTPOriginateTimeOffset]);
+ receiveTimeNTP = readTimeStamp(&packet[kNTPReceiveTimeOffset]);
+ transmitTimeNTP = readTimeStamp(&packet[kNTPTransmitTimeOffset]);
+
+ roundTripTimeNTP =
+ makeNTP(responseTimeUs - requestTimeUs)
+ - (transmitTimeNTP - receiveTimeNTP);
+
+ clockOffsetNTP =
+ ((receiveTimeNTP - originateTimeNTP)
+ + (transmitTimeNTP - responseTimeNTP)) / 2;
+
+ mTimeReferenceNTP = responseTimeNTP + clockOffsetNTP;
+ mTimeReferenceUs = responseTimeUs;
+ mRoundTripTimeNTP = roundTripTimeNTP;
+
+ err = OK;
+
+bail2:
+ close(s);
+ s = -1;
+
+bail:
+ return err;
+}
+
+int64_t SNTPClient::adjustTimeUs(int64_t timeUs) const {
+ uint64_t nowNTP =
+ mTimeReferenceNTP + makeNTP(timeUs - mTimeReferenceUs);
+
+ int64_t nowUs =
+ (nowNTP >> 32) * 1000000ll
+ + ((nowNTP & 0xffffffff) * 1000000ll) / (1ll << 32);
+
+ nowUs -= ((70ll * 365 + 17) * 24) * 60 * 60 * 1000000ll;
+
+ return nowUs;
+}
+
+// static
+void SNTPClient::writeTimeStamp(uint8_t *dst, uint64_t ntpTime) {
+ *dst++ = (ntpTime >> 56) & 0xff;
+ *dst++ = (ntpTime >> 48) & 0xff;
+ *dst++ = (ntpTime >> 40) & 0xff;
+ *dst++ = (ntpTime >> 32) & 0xff;
+ *dst++ = (ntpTime >> 24) & 0xff;
+ *dst++ = (ntpTime >> 16) & 0xff;
+ *dst++ = (ntpTime >> 8) & 0xff;
+ *dst++ = ntpTime & 0xff;
+}
+
+// static
+uint64_t SNTPClient::readTimeStamp(const uint8_t *dst) {
+ return U64_AT(dst);
+}
+
+// static
+uint64_t SNTPClient::getNowNTP() {
+ struct timeval tv;
+ gettimeofday(&tv, NULL /* time zone */);
+
+ uint64_t nowUs = tv.tv_sec * 1000000ll + tv.tv_usec;
+
+ nowUs += ((70ll * 365 + 17) * 24) * 60 * 60 * 1000000ll;
+
+ return makeNTP(nowUs);
+}
+
+// static
+uint64_t SNTPClient::makeNTP(uint64_t deltaUs) {
+ uint64_t hi = deltaUs / 1000000ll;
+ uint64_t lo = ((1ll << 32) * (deltaUs % 1000000ll)) / 1000000ll;
+
+ return (hi << 32) | lo;
+}
+
+} // namespace android
+