www.pudn.com > Net_apps.rar > sntp.c
/*
*********************************************************************************************************
* Copyright 2003 Service & Quality Technology CO., LTD. ALL RIGHTS RESERVED.
* This software is provided under license and contains proprietary and
* confidential material which is the property of SQ tech.
*
* FileName : sntp.c
* Description :
*
*
* Version control:
* $Revision: 0.1 $ Date: 2004/06/03 12:00:00 daniel
* first implemetation
*
*********************************************************************************************************
*/
#include "..\include\L3\net_apps\sntp\sntp.h"
#include "..\include\L1\lwip\api.h"
#include "..\include\L1\lwip\sys.h"
#include "..\include\L2\system\timer.h"
#include "..\include\L3\net_apps\IoEnv.h"
#include "..\include\L3\net_apps\httpd\HttpServer.h"
#include "..\include\L3\net_apps\dns\dns.h"
/*-----------------------------------------------------------------------------------*/
void sntp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, u16_t port);
void set_time(u32_t sec);
u32_t check_year(u16_t year);
u16_t check_month(u16_t year ,u32_t *sec);
u16_t check_day(u16_t year,u16_t month ,u32_t *sec);
u16_t check_hour(u32_t *sec);
u16_t check_min(u32_t *sec);
u16_t sun_day(u16_t year,u16_t mon, u16_t day);
u16_t weekday(u16_t year,u16_t mon, u16_t day);
void offset_time_sub(INT16U *year, INT8S *month, INT8S *day,INT8S *hour,INT8S *min,INT8S offset);
void offset_time_add(INT16U *year ,INT8S *month, INT8S *day,INT8S *hour,INT8S *min,INT8S offset);
static struct udp_pcb *sntp_udp;
void sntp_thread(void *arg)
{
u8_t retry,retry1;
retry = 5;
retry1 = 0;
OSTimeDlyHMSM(0,0,15,0); //ÑÓ³Ù15ÃëÆô¶¯
while(1)
{
if(1) //sntp enable
{
while(retry--)
{
sntp_start();
OSTimeDlyHMSM(0,0,3,0);
if(Sntp_Status == OK )
{
retry = 5;
OSTimeDlyHMSM(1,0,0,0);
}
}
if(retry == 0)
{
OSTimeDlyHMSM(0,10,0,0);
retry = 5;
if((retry1++) == 3)
{
retry1 = 0;
OSTimeDlyHMSM(1,0,0,0);
}
}
}
}
}
void sntp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, u16_t port)
{
SNTP_T *sntp_t;
sntp_t = p->payload;
set_time(HTONL(sntp_t->rx_time[0]));
Sntp_Status = OK;
udp_remove(pcb);
sntp_udp = NULL;
}
void sntp_start()
{
struct udp_pcb *sntp_msg;
struct ip_addr ip_addr;
struct pbuf *p;
INT32U *pIpaddressStr;
INT8U *psntp_s;
INT8U ip[4];
INT8U count=0;
Sntp_Status = ERROR;
p = pbuf_alloc(PBUF_TRANSPORT, 48, PBUF_RAM);
memset((INT8U *)p->payload,0,48);
memset((INT8U *)p->payload,0x0b,1);
memcpy((INT8U *)p->payload+40,"\xc3\x9d\xe1\x80",4);
psntp_s = IoSntp("SNTP_SERVER", NULL, IOR, ROOT);
if(atoi(psntp_s) != 0)
{
inet_aton((const char*)psntp_s, &ip_addr);
}
else
{
memset(G_dns_table,0x00,sizeof(G_dns_table));///< add by jjl for clear dns buffer
while(1)
{
switch(dns_table(0, psntp_s , ip, DNS_LOOK_UP))
{
case R_ER: break;
case R_RU: break;
case R_OK:
memcpy(&ip_addr.addr,ip,4);
goto SNTP_REQ;
}
count++ ;
if(count >= 5)
{
break;
}
OSTimeDlyHMSM(0, 0, 1, 0);
}
}
SNTP_REQ:
if(sntp_udp == NULL)
{
sntp_msg = udp_new();
sntp_udp = sntp_msg;
udp_recv(sntp_msg,sntp_recv,NULL);
udp_bind(sntp_msg, IP_ADDR_ANY, 3000);
udp_connect(sntp_msg, &ip_addr, SNTP_PORT);
}
else
{
sntp_msg = sntp_udp;
}
udp_send(sntp_msg, p);
pbuf_free(p);
}
void set_time(u32_t sec)
{
OS_TIME time_set_inf;
u16_t year;
INT8S month,day,hour,min,sum_day,week_day,offset;
u32_t temp;
if(sec < 0xc39de180UL)
{
printf("error");
while(1);
}
else
{
sec -= 0xc39de180UL; //1900/01/01 ~2004/01/01 total sec.
year = 2004;
month = 1;
day = 1;
hour = 0;
min = 0;
}
temp = check_year(year);
while(sec >= temp)
{
sec -=temp;
year++;
temp = check_year(year);
}
month = check_month(year ,&sec);
day = check_day(year,month,&sec);
hour =check_hour(&sec);
min = check_min(&sec);
sum_day = sun_day(year,month,day);
week_day = weekday(year,month,day);
IoSntp("SNTP_SELECT", &offset, IOR, ROOT);
if( offset < 0)
{
offset_time_sub(&year,&month ,&day, &hour ,&min ,offset);
}
else if( offset > 0)
{
offset_time_add(&year,&month ,&day, &hour ,&min ,offset);
}
time_set_inf.tm_year=year;
time_set_inf.tm_mon = month;
time_set_inf.tm_mday = day;
time_set_inf.tm_yday = sum_day;
time_set_inf.tm_wday = week_day;
time_set_inf.tm_hour = hour; //must add time zone
time_set_inf.tm_min = min;
time_set_inf.tm_sec = sec;
timer_settime(&time_set_inf);
}
void offset_time_add(INT16U *year ,INT8S *month, INT8S *day,INT8S *hour,INT8S *min,INT8S offset)
{
INT16S temp,temp1;
if( offset+*hour > 23 )
{
*hour =(*hour + offset)-24;
switch (*month) //change to next month
{
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
temp1 = 31;
break;
case 2:
temp1 =28;
if(*year % 4 == 0)
{
temp1 = 29; //29 days
if(*year %100 == 0)
{
if (*year % 400 != 0)
{
temp1 = 28;
}
}
}
break;
default :
temp1 = 30;
temp = *day;
*day = (temp == temp1)?1:*day+1;
*month =(temp == temp1)?*month+1:*month;
if( *month == 12)
{
*month = 1;
*year +=1;
}
}
}
else // if( offset+*hour > 23 )
{
*hour += offset; //day no change
}
}
void offset_time_sub(INT16U *year ,INT8S *month, INT8S *day,INT8S *hour,INT8S *min,INT8S offset)
{
INT16S temp;
if(offset == -13 ) //offset -3:30
{
temp = *min;
if( (*hour*60+*min) < 210 ) //3*60+30=210 min
{
*min +=(temp < 30)?30:-30;
*hour +=(temp < 30)?20:21;
if(*day == 1) //change to last month
{
if( *month == 3)
{
temp =28;
if(*year % 4 == 0)
{
temp = 29; //29 days
if(*year %100 == 0)
{
if (*year % 400 != 0)
{
temp = 28;
}
}
}
*day = temp;
}
else //if( month == 3)
{
if(*month ==12 || *month == 10 || *month == 7 ||*month == 5 )
{
*day = 30;
}
else
{
*day = 31;
}
}
if( *month == 1)
{
*month =12;
*year -=1;
}
else // if( month == 1)
{
*month -=1;
}
}
else // if(day == 1)
{
*day -= 1;
}
}
else //if( (hour*60+min) < 210 )
{
*min +=(temp < 30)?30:-30; // day no change
*hour -=(temp < 30)?4:-3;
}
}
else if( abs(offset) > *hour ) //if(offset == -13 )
{
*hour = 24 + (*hour + offset);
if(*day == 1) //change to last month
{
if( *month == 3)
{
temp =28;
if(*year % 4 == 0)
{
temp = 29; //29 days
if(*year %100 == 0)
{
if (*year % 400 != 0)
{
temp = 28;
}
}
}
*day = temp;
}
else // if( month == 3)
{
if(*month ==12 || *month == 10 || *month == 7 ||*month == 5 )
{
*day = 30;
}
else
{
*day = 31;
}
}
if( *month == 1)
{
*month =12;
*year -=1;
}
else
{
*month -=1;
}
}
else // if(day == 1)
{
*day -= 1;
}
}
else //if( abs(offset) > hour )
{
*hour += offset; //day no change
}
}
u16_t weekday(u16_t year,u16_t mon, u16_t day)
{
u16_t i,temp,y,sum;
y = year;
sum = 0;
if(year < 2004)
{
printf("error");
return 7;
}
for(y--;y >= 2004;y--) //start 2004/01/01
{
temp = 365;
if(y % 4 == 0)
{
temp = 366; //29 days
if(y %100 == 0)
{
if (y % 400 != 0)
{
temp = 365;
}
}
}
sum += temp;
}
sum += sun_day(year,mon,day);
return ((sum + 3) % 7);
}
u16_t sun_day(u16_t year,u16_t mon, u16_t day)
{
u8_t i,temp;
u16_t sum;
sum = 31;
temp = 0;
if(mon == 1)
{
return day;
}
for(i=2;i= 0x384UL)
{
*sec -=0x384UL;
i+=15;
}
for(j=0;j<=15;j++)
{
if(*sec >= 0x3cUL)
{
*sec -=0x3cUL;
}
else
{
return i+j;
}
}
printf("error");
}
u16_t check_hour(u32_t *sec)
{
u8_t i;
for(i=0;i<=24;i++)
{
if(*sec >=0xe10UL)
{
*sec -= 0xe10UL;
}
else
{
return i;
}
}
printf("error");
}
u16_t check_day(u16_t year,u16_t month ,u32_t *sec)
{
u8_t i,temp;
if(month==1 || month==3 || month==5 || month==7 || month==8 || month==10 || month==12 )
{
temp = 31;
}
else
{
temp =30;
if(month == 2)
{
temp =28;
if(year % 4 == 0)
{
temp = 29; //29 days
if(year %100 == 0)
{
if (year % 400 != 0)
{
temp = 28;
}
}
}
}
}
for(i=1;i <=temp;i++)
{
if(*sec >= 0x15180UL)
{
*sec -= 0x15180UL;
}
else
{
return i;
}
}
printf("error");
}
u16_t check_month(u16_t year ,u32_t *sec)
{
u32_t temp;
int i;
for(i=1;i < 13 ;i++)
{
if(i==1 || i==3 || i==5 || i==7 || i==8 || i==10 || i==12 )
{
temp = Day31;
}
else
{
temp = Day30;
if(i == 2 )
{
temp = Day28;
if(year % 4 == 0)
{
temp = Day29;
if(year %100 == 0)
{
if (year % 400 != 0)
{
temp = Day28;
}
}
}
}
}
if(*sec >= temp)
{
*sec -= temp;
}
else
{
return i;
}
}
return 0; ///error
}
u32_t check_year(u16_t year)
{
u32_t temp;
temp = Year365;
if(year % 4 == 0)
{
temp = Year366;
if(year %100 == 0)
{
if(year % 400 != 0)
{
temp =Year365;
}
}
}
return temp;
}
/*-----------------------------------------------------------------------------------*/
void
sntp_init(void)
{
sys_thread_new(sntp_thread, NULL, DEFAULT_THREAD_PRIO,"sntp_thread");
}