4

Can someone find what I'm missing on my ntp implementation?

I'm programming an 32-bit microcontroller ARM Cortex M3. I have three functions - wifiSend which calls the bsdUdpClient and bsdUdpServer. The bsdUdpClient sends data to the server and bsdUdpServer listens to the reserved NTP port and receive the data of the NTP server.

I got no error messages at all but the buffer received is empty.

    static void wifiSend(xTimerHandle xTimer){

         uint16_t AddrSize = sizeof(SlSockAddrIn_t);

         if (STATUS_OK != bsdUdpClient(SERVER_PORT, AddrSize)){
               printf("Failed to send udp packet\n\r");
               assert(false);
         }

         if (STATUS_OK != bsdUdpServer(SERVER_PORT, AddrSize))
            printf("Failed to receive udp packet\n\r");
    }


    static returnTypes_t bsdUdpClient(uint16_t port, uint16_t AddrSize){

          int16_t Status = (int16_t) ZERO;

          memset(packetBuffer, 0, NTP_PACKET_SIZE);

          packetBuffer[0] = 0xE3; //0b11100011;   // LI, Version, Mode
          packetBuffer[1] = 0x00;     // Stratum, or type of clock
          packetBuffer[2] = 0x06;     // Polling Interval
          packetBuffer[3] = 0xEC;  // Peer Clock Precision
          // 8 bytes of zero for Root Delay & Root Dispersion
          packetBuffer[12]  = 49;
          packetBuffer[13]  = 0x4E;
          packetBuffer[14]  = 49;
          packetBuffer[15]  = 52;
          Addr.sin_family = SL_AF_INET;
          Addr.sin_port = sl_Htons((uint16_t) port);
          Addr.sin_addr.s_addr = sl_Htonl(SERVER_IP);

          SockID = sl_Socket(SL_AF_INET, SL_SOCK_DGRAM, (uint32_t) ZERO);
          if (SockID < (int16_t) ZERO)
               return (SOCKET_ERROR);

          Status = sl_SendTo(SockID, packetBuffer, NTP_PACKET_SIZE *     sizeof(uint8_t), (uint32_t) ZERO, (SlSockAddr_t *) &Addr, AddrSize);


          if (Status <= (int16_t) ZERO) {
              Status = sl_Close(SockID);
              if (Status < 0)
                     return (SEND_ERROR);
              return (SEND_ERROR);
          }

          Status = sl_Close(SockID);
          if (Status < 0)
               return (SEND_ERROR);

          return (STATUS_OK);
    }

    static returnTypes_t bsdUdpServer(uint16_t port, uint16_t AddrSize){

          int16_t Status = (int16_t) ZERO;

          LocalAddr.sin_family = SL_AF_INET;
          LocalAddr.sin_port = sl_Htons(5001);
          LocalAddr.sin_addr.s_addr = 0;

          SockID = sl_Socket(SL_AF_INET,SL_SOCK_STREAM, (uint32_t) ZERO);
          if (SockID < 0){
               printf("error on sl_Socket\n\r");
               return SOCKET_ERROR;
          }

          Status = sl_Bind(SockID, (SlSockAddr_t *) &LocalAddr, AddrSize);
          if (Status < 0){
               printf("problem on sl_Bind\n\r");
               return SOCKET_ERROR;
          }

          Status = sl_RecvFrom(SockID, packetBuffer, NTP_PACKET_SIZE * sizeof(uint8_t), (uint32_t) ZERO, (SlSockAddr_t *) &Addr, &AddrSize);
          if (Status < (int16_t) ZERO){
               printf("error - no bytes received: %d\n\r", (int16_t)Status);
               return SOCKET_ERROR;
          }

          Status = sl_Close(SockID);
          if (Status < 0)
               printf("problem on sl_Close\n\r");

          uint8_t index3 = packetBuffer[40];
          uint8_t index2 = packetBuffer[41];
          uint8_t index1 = packetBuffer[42];
          uint8_t index0 = packetBuffer[43];

          uint16_t highWord = index3 << 16 | index2;
          uint16_t lowWord = index1 << 16 | index0;

          uint32_t secondsSince1900 = highWord << 16 | lowWord;

          printf("Seconds since 1 Janeiro de 1900: %ld\n\r", secondsSince1900);

          return (STATUS_OK);

 }
lmbcerqueira
  • 187
  • 1
  • 1
  • 14

2 Answers2

2

Your client code sends a query, but then closes the socket and never listens for a reply.

Your server code waits for a query, but then never sends any response.

Neither of them appear to do anything particularly useful. You should complete the client code so that it listens for a reply before it closes the socket. Note that you should use a timeout so that you don't wait forever in the event that either the query or the response is lost.

David Schwartz
  • 179,497
  • 17
  • 214
  • 278
2

Thanks to @DavidSchwartz, I have now a working solution.

I also fixed a bug I had when I was trying to extract the number of seconds since 1st January of 1900 from the packet received.

I hope this can help someone.

TO BE IMPROVED: add a timeout to avoid a blocking state if there is no response from the server

#define NTP_PACKET_SIZE         48
uint8_t packetBuffer[ NTP_PACKET_SIZE];

static returnTypes_t bsdUdpClient(uint16_t AddrSize){

    int16_t Status = (int16_t) ZERO;

    memset(packetBuffer, 0, NTP_PACKET_SIZE);

    // Initialize values needed to form NTP request
    packetBuffer[0] = 0xE3; //0b11100011;   // LI, Version, Mode
    packetBuffer[1] = 0x00;     // Stratum, or type of clock
    packetBuffer[2] = 0x06;     // Polling Interval
    packetBuffer[3] = 0xEC;  // Peer Clock Precision
    // 8 bytes of zero for Root Delay & Root Dispersion
    packetBuffer[12]  = 49;
    packetBuffer[13]  = 0x4E;
    packetBuffer[14]  = 49;
    packetBuffer[15]  = 52;

    SockID = sl_Socket(SL_AF_INET, SL_SOCK_DGRAM, (uint32_t) ZERO);
    if (SockID < (int16_t) ZERO)
        return (SOCKET_ERROR);

    /*make the request to the server*/
    Status = sl_SendTo(SockID, packetBuffer, NTP_PACKET_SIZE * sizeof(uint8_t), (uint32_t) ZERO, (SlSockAddr_t *) &Addr, AddrSize);

    /*Check if 0 transmitted bytes sent or error condition*/
    if (Status <= (int16_t) ZERO) {
        sl_Close(SockID);
        return (SEND_ERROR);
    }
    else
        printf("request sent successfully\n\r");

    /* receive the reply from the server*/
    Status = sl_RecvFrom(SockID, packetBuffer, NTP_PACKET_SIZE * sizeof(uint8_t), (uint32_t) ZERO, (SlSockAddr_t *) &Addr, &AddrSize);
    if (Status < (int16_t) ZERO){
        printf("error - no bytes received: %d\n\r", (int16_t)Status);
        return SOCKET_ERROR;
    }
    else
        printf("reply received\n\r");

    Status = sl_Close(SockID);
    if (Status < 0)
        printf("problem on sl_Close\n\r");

    uint8_t index3 = packetBuffer[40];
    uint8_t index2 = packetBuffer[41];
    uint8_t index1 = packetBuffer[42];
    uint8_t index0 = packetBuffer[43];

    uint16_t highWord = index3 << 8 | index2;
    uint16_t lowWord = index1 << 8 | index0;

    uint32_t secondsSince1900 = highWord << 16 | lowWord;

    printf("Seconds since 1 Janeiro de 1900: %lu\n\r", secondsSince1900);

    return (STATUS_OK);

}
lmbcerqueira
  • 187
  • 1
  • 1
  • 14