/* ***************************************************** Compiler: Borland C++3.1 Compile Mode: large Time Synchronization using NTP I-7188E/uPac-7186E/I-8000E UDP/IP client side, use socket functions. Active Timer servers: http://www.eecis.udel.edu/~mills/ntp/clock1a.html ***************************************************** */ #include #include #include #include #include #include "..\lib\7188e.h" #include "..\lib\Tcpip32.h" #include "..\lib\MFW.h" #define BUFSIZE 1024 /* read/write buffer size */ #define EPOCH_DIFF ((unsigned long) 88400 * (365 * 70 + 17)) /* time returns the time since the Epoch (00:00:00 UTC, January 1, 1970), measured in seconds. If t is non-NULL, the return value is also stored in the memory pointed to by t . */ int synctime_send (int udp); int synctime_recv (int udp,int TimeZone); int bDebug=1; struct sockaddr_in sin; #if 0 //NTPinit doesn't be called on XS structure int NTPinit(char *sIP,unsigned iPort) { int client; int ss; /* slave socket got from accept */ int err=0; int r; /* Create the UDP socket */ err = client = socket( PF_INET, SOCK_DGRAM, 0 ); /* UDP/IP */ if (client < 0) { if(bDebug) Print("can't create socket! error %d\n\r", err ); // printCom(bDebug, "can't create socket! error %d\n\r", err ); Nterm(); return err; } /* addressing for master socket */ memset( &sin, 0, sizeof(sin) ); /* bzero is a unix system call */ sin.sin_family = AF_INET; sin.sin_addr.s_addr = inet_addr(sIP); sin.sin_port = htons( iPort ); /* Initialize the connection */ r = connect (client, (struct sockaddr*) &sin, sizeof (sin)); if (r == -1) { if(bDebug) Print("connect() failed: %d \r\n", r); // printCom(bDebug,"connect() failed: %d \r\n", r); /* Close the opened socket */ r = closesocket (client); if (r != 0) if(bDebug) Print("close udp: %d\r\n",r); // printCom(bDebug,"close udp: %d\r\n",r); return 0; } return client; } #endif /* usec2frac: Convert from fraction of a second to microsecond return: microsecond. */ long frac2usec (unsigned long frac) { return (long) (((long long) frac * 1000000) >> 32); } /* fromnetnum: Convert from a network number to a C number. return: the number in unsigned long. */ unsigned long fromnetnum (const char *oct) { unsigned long ulTol=0; ulTol=(unsigned long)((unsigned long)oct[0] << 24)&0xffffffff; ulTol+=(unsigned long)((unsigned long)oct[1] << 16)&0xffffff; ulTol+=(unsigned long)((unsigned long)oct[2] << 8)& 0xffff; ulTol+=((unsigned long)oct[3] & 0xff); return ulTol; //return ((unsigned char) oct[0] << 24 | (unsigned char) oct[1] << 16 | (unsigned char) oct[2] << 8 | (unsigned char) oct[3]); } /* tonetnum: Convert from a C number to a network number. return: the number in network octet. */ const char *tonetnum (unsigned long num) { static char oct[5] = "0000"; oct[0] = (num >> 24) & 255; oct[1] = (num >> 16) & 255; oct[2] = (num >> 8) & 255; oct[3] = num & 255; return oct; } /* synctime: Synchronize the time. See RFC 1361. return: Time offset that is synchronized.*/ double t1, t2, t3, t4, toff, tnew; unsigned long tti1,tti2; void EpochToOSTime(unsigned long Val) { time_t t; struct time d_time; struct date d_date; unixtodos(Val,&d_date,&d_time); if(bDebug) // printCom(bDebug,"Val=%ld, Date=%02d/%02d/%04d Time=%02d:%02d:%02d\n\r",Val, // d_date.da_mon,d_date.da_day,d_date.da_year,d_time.ti_hour,d_time.ti_min,d_time.ti_sec); Print("Val=%ld, Date=%02d/%02d/%04d Time=%02d:%02d:%02d\n\r",Val, d_date.da_mon,d_date.da_day,d_date.da_year,d_time.ti_hour,d_time.ti_min,d_time.ti_sec); SetTime(d_time.ti_hour,d_time.ti_min,d_time.ti_sec); SetDate(d_date.da_year,d_date.da_mon,d_date.da_day); } long OSToEpochTime(void) { int year,month,day,hour,min,sec; //int oyear,omonth,oday,ohour,omin,osec; time_t t; struct time d_time; struct date d_date; struct tm *local; GetDate(&year,&month,&day); GetTime(&hour,&min,&sec); if(bDebug) Print("Date=%02d/%02d/%04d Time=%02d:%02d:%02d\n\r", month,day,year,hour,min,sec); /* printCom(bDebug,"Date=%02d/%02d/%04d Time=%02d:%02d:%02d\n\r", month,day,year,hour,min,sec);*/ d_time.ti_min=min; d_time.ti_hour=hour; d_time.ti_hund=0; d_time.ti_sec=sec; d_date.da_year=year; d_date.da_day=day; d_date.da_mon=month; t = dostounix(&d_date, &d_time); return t; } int synctime_send (int udp) { int i, r; // , udp; char buf[61]; int len; int iH,iM,iS; /* Send to the server */ for (i = 0; i < 61; i++) buf[i] = 0; /* 00 001 011 - leap, ntp ver, client. See RFC 1361. */ buf[0] = (0 << 6) | (1 << 3) | 3; /* Get the local sent time - Originate Timestamp */ t1=(double)OSToEpochTime()+EPOCH_DIFF; //(double)iH*60*60+iM*60+iS; if(bDebug) Print("t1 new=%lf\r\n",t1); // printCom(bDebug,"t1 new=%lf\r\n",t1); /* Send to the server */ memcpy (&buf[40], tonetnum ((unsigned long) t1), 4); //memcpy (&buf[40], &t1, 4); memset(&buf[44],0x0,4); tti1=GetTimeTicks(); len = writesocket(udp, buf, 48); if (len == -1) { if(bDebug) Print("Send %d\r\n",len); // printCom(bDebug,"Send %d\r\n",len); } return 0; } int synctime_recv (int udp,int TimeZone) { int len; char buf[61]; int i; int iH,iM,iS; static struct timeval tv2, tv3; unsigned int hour,minu,sec; /* Read from the server */ len = recv (udp, buf, 60, 0); if (len == -1) { if(bDebug) Print("recv %d \r\n",len); //printCom(bDebug,"recv %d \r\n",len); return 0; } else { /* Get the local received time */ tti2=GetTimeTicks(); t4= (double)OSToEpochTime()+EPOCH_DIFF; if(bDebug) Print("t4 new=%lf\r\n",t4); //printCom(bDebug,"t4 new=%lf\r\n",t4); /* Get the remote Receive Timestamp */ tv2.tv_sec = (unsigned long)fromnetnum (&buf[32]);//- EPOCH_DIFF; tv2.tv_usec = frac2usec (fromnetnum (&buf[36])); t2 = (double) tv2.tv_sec + (double) (tv2.tv_usec / 1000000); //t2 = (double)fromnetnum (&buf[32]);//- EPOCH_DIFF; /* if(bDebug) printCom(bDebug,"t2 new=%lu %lf\r\n",tv2.tv_sec,t2);*/ /* Get the remote Transmit Timestamp */ tv3.tv_sec = fromnetnum (&buf[40]);//- EPOCH_DIFF; tv3.tv_usec = frac2usec (fromnetnum (&buf[44])); t3 = (double) tv3.tv_sec + (double) tv3.tv_usec / 1000000; //t3 = (double)fromnetnum (&buf[40])- EPOCH_DIFF; /*if(bDebug) printCom(bDebug,"t3 new=%lu %lf\r\n",tv3.tv_sec,t3);*/ /* Calculate the time offset */ toff = (t2 + t3 - t1 - t4) / 2; /* Calculate the new time */ tnew = t4 + toff+(4*60*60)- EPOCH_DIFF+(TimeZone*60*60); /* if(bDebug) printCom(bDebug,"off=%lf new=%lf\r\n",toff,tnew);*/ /* Set the time */ EpochToOSTime((long)tnew); return toff; } }