Here’s a minimalistic operate that will get the timestamp from apple’s ntp server. It will get the time from time.apple.com with none further libraries.

+ (NSDate *)lsDateFromOnlineServer
{
    struct hostent *server = gethostbyname("time.apple.com");
    if (!server)
        return nil;
    
    int udpSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if (udpSocket < 0)
        return nil;
    
    struct timeval timeout;
    timeout.tv_sec = 30;
    timeout.tv_usec = 0;
    setsockopt(udpSocket, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
    
    struct sockaddr_in socketAddress = {0};
    socketAddress.sin_family = AF_INET;
    socketAddress.sin_port = htons(123);
    memcpy(&socketAddress.sin_addr, server->h_addr_list[0], server->h_length);
    
    if (join(udpSocket, (struct sockaddr *)&socketAddress, sizeof(socketAddress)) < 0) {
        shut(udpSocket);
        return nil;
    }
    
    unsigned char ntpPacket[48] = {0};
    ntpPacket[0] = 0x1B;
    
    if (write(udpSocket, &ntpPacket, sizeof(ntpPacket)) < 0) {
        shut(udpSocket);
        return nil;
    }
    
    if (learn(udpSocket, &ntpPacket, sizeof(ntpPacket)) < 0) {
        shut(udpSocket);
        return nil;
    }
    
    shut(udpSocket);
    
    NSTimeInterval ntpTimestampDelta = 2208988800u;
    NSTimeInterval ntpTimestamp = ntohl(*((uint32_t *)(ntpPacket + 40)));
    NSTimeInterval ntpOverflowDelta = ntpTimestamp < ntpTimestampDelta ? 0xFFFFFFFF : 0;
    
    if (ntpTimestamp == 0)
        return nil;
    
    NSTimeInterval timestamp = ntpTimestamp - ntpTimestampDelta + ntpOverflowDelta;
    return [NSDate dateWithTimeIntervalSince1970:timestamp];
}

Word that it makes use of synchronous socket so that you may need to use it from a background thread. Additionally it’s included in my library with numerous extensions: LSCategories

By admin

Leave a Reply

Your email address will not be published.