Forum: Mikrocontroller und Digitale Elektronik NTP-Request mit uIP


von SchallRauch (Gast)


Lesenswert?

Hallo,


ich will mit dem uIP-Stack von Adam Dunkels eine NTP-Zeit abfrage 
machen, dass man per UDP machen muss.

Ich habe folgenden Code geschrieben, aber ich bekomme bei jeder Abfrage 
keine korrekte Zeit zurück, sondern ein konstant falsche Zeit, egal zu 
welchem Zeitpunkt ich abfrage. Ich vermute stark, dass das nicht die 
Zeit ist.

Hier ist der Code, vielleicht kann mir jemand, der sich mit uIP und NTP 
auskennt, den Fehler zu finden.





#include "ntp_getTime.h"
#include <avr/pgmspace.h>
#include <stdio.h>
#include <string.h>

#include "uip/uip.h"
#include "uip/timer.h"
#include "uip/pt.h"
#include "uip/uip_arp.h"



/*---------------------------------------------------------------------- 
-------------*/
/** \internal
 * The main UDP function.
 */
/*---------------------------------------------------------------------- 
-------------*/


PROGMEM const char NTP_Request[] = {0xd9, 0x00, 0x0a ,0xfa ,0x00 ,0x00,
0x00 ,0x00 ,0x00 ,0x01 ,0x04 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 
,0x00 ,0x00 ,0x00 ,0x00,
0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 
,0x00 ,0x00 ,0x00 ,0x00,
0x00 ,0x00 ,0xca ,0x1a ,0xab ,0x0c ,0x48 ,0x7a ,0xe1 ,0x47};


struct {
#define STATE_IDLE   0
#define STATE_NEW    1
#define STATE_ASKING 2
#define STATE_ERROR  3
  u8_t state;
} ntpstat;


static struct uip_udp_conn *ntp_conn = NULL;




// Prüfen, ob eine ntp-Anfrage vorliegt.
// Falls ja, ntp Request abschicken

void check_ntp_req(void)
{
  char *ntpp;

  if (ntpstat.state == STATE_NEW)           // neue NTP-Anfrage?
     {
     ntpstat.state = STATE_ASKING;          // als "laufend" markieren
     }

  else if (ntpstat.state == STATE_ASKING)        // laufende 
NTP-Anfrage?
     {

       ntpp = (char *)uip_appdata;
       memcpy_P (ntpp, NTP_Request, sizeof(NTP_Request));
       uip_udp_send (sizeof(NTP_Request));
       }
   else                                   // keine Zeitabfrage gestellt
     return;                              // weiter warten
}


/*---------------------------------------------------------------------- 
-------------*/
/** \internal
 * Called when new NTP data arrives.
 */
/*---------------------------------------------------------------------- 
-------------*/
void ntp_newdata(void)
{
  unsigned long timestamp = 0L;
  struct timedata
    {
    char dummy[40];
    unsigned long t_time;
    } *str_udp;

  str_udp = (struct timedata *)uip_appdata;

  if(ntpstat.state == STATE_ASKING)
    {
    // NTP request is now finished.
    ntpstat.state = STATE_IDLE;

  memcpy_P (&timestamp, &(str_udp->t_time), sizeof(timestamp));


 timestamp = timestamp - 0x83AA7E80; // the seconds from Jan 1, 1900 to 
Jan 1, 1970


}
  }



void ntp_init(void)
{
  ntpstat.state = STATE_IDLE;

  uip_ipaddr_t ntpIP;

  uip_ipaddr(ntpIP, 134,130,4,17);

    if(ntp_conn != NULL) {
      uip_udp_remove(ntp_conn);
    }

    ntp_conn = uip_udp_new(&ntpIP, HTONS(123));
    if(ntp_conn != NULL) {
  uip_udp_bind(ntp_conn, HTONS(123)); }
}

void GetNTP_Time(void)
{
  ntpstat.state = STATE_NEW;
}



void ntp_appcall(void)
{
  if(uip_udp_conn->rport == HTONS(123)) {  // NTP protocol

    if(uip_newdata()) {
      ntp_newdata();
      }

     if(uip_poll()) {
      check_ntp_req();
    }

  }

}



Der Code des Headers:



#ifndef NTP_GETTIME_H_
#define NTP_GETTIME_H_




#define UIP_UDP_APPCALL ntp_appcall


// initialize the ntp client
void ntp_init(void);

// called by uIP when it executes the ntp client
void ntp_appcall(void);


void GetNTP_Time(void);



#endif /* NTP_GETTIME_H_ */

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

SchallRauch schrieb:
> aber ich bekomme bei jeder Abfrage keine korrekte Zeit zurück, sondern
> ein konstant falsche Zeit,

Beispiel?

von Jojo S. (Gast)


Lesenswert?

ich würde sagen falscher Offset weil du über uip_appdata zugreifst, da 
ist der address+TCP Header schon abgezogen:
1
uip_appdata = &uip_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN];
also direkt die uip_buf Adresse benutzen oder für ohne Adressheader 
(6+6+2 Bytes) das Makro UDPBUF:
1
#define UDPBUF ((struct uip_udpip_hdr *)&uip_buf[UIP_LLH_LEN])

von SchallRauch (Gast)


Lesenswert?

Jojo S. schrieb:
> ich würde sagen falscher Offset weil du über uip_appdata
> zugreifst, da
> ist der address+TCP Header schon abgezogen:uip_appdata =
> &uip_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN];
> also direkt die uip_buf Adresse benutzen oder für ohne Adressheader
> (6+6+2 Bytes) das Makro UDPBUF:#define UDPBUF ((struct uip_udpip_hdr
> *)&uip_buf[UIP_LLH_LEN])


Du sprichst hier bestimmt auf 40 dummy Bytes an. Das ist absichtlich so 
gewählt, weil die empfangenen Daten erst nach 40 Bytes der brauchbare 
timestamp steht.

Aber dennoch danke für den Tipp. Übrigens ist die Übertragung hier mit 
UDP.

von Jojo S. (Gast)


Lesenswert?

SchallRauch schrieb:
> Aber dennoch danke für den Tipp. Übrigens ist die Übertragung hier mit
> UDP.

deshalb ja, du verwendest aber die uip_appdata Adresse und die ist für 
den TCP Header.

von SchallRauch (Gast)


Lesenswert?

Jojo S. schrieb:
> SchallRauch schrieb:
>> Aber dennoch danke für den Tipp. Übrigens ist die Übertragung hier mit
>> UDP.
>
> deshalb ja, du verwendest aber die uip_appdata Adresse und die ist für
> den TCP Header.


Achso,

kannst Du mir sagen, wie ich an die Daten des UDPBUF drankomme.

Soll ich es einfach als Pointer benutzen?

von Jojo S. (Gast)


Lesenswert?

ok, war nicht ganz richtig was ich schrieb. Wenn ein UDP Paket kommt 
wird uip_appdata auf den Anfang der UDP Daten gesetzt. Wenn 40 der 
richtige Offset ab Nutzdatenanfang ist sollte das richtig sein.
Das define UIP_UDP ist gesetzt? Ansonsten mit Wireshark mitlauschen was 
hin- und hergeht.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.