Mercurial > ecos
annotate packages/net/sntp/current/src/sntp.c @ 925:c6d5daaf0c31
* src/sntp.c: In function sntp_fn() changed 'version' to
'new_srv.version' in the CYG_TRACE1() call.
| author | jlarmour |
|---|---|
| date | Wed, 09 Apr 2003 20:31:45 +0000 |
| parents | 018143c925ee |
| children | 8f7a10771d67 |
| rev | line source |
|---|---|
| 748 | 1 //============================================================================= |
| 2 // | |
| 3 // sntp.c | |
| 4 // | |
| 5 // Simple Network Time Protocol | |
| 6 // | |
| 7 //============================================================================= | |
| 8 //####ECOSGPLCOPYRIGHTBEGIN#### | |
| 9 // ------------------------------------------- | |
| 10 // This file is part of eCos, the Embedded Configurable Operating System. | |
| 11 // Copyright (C) 2003 Andrew Lunn | |
| 12 // | |
| 13 // eCos is free software; you can redistribute it and/or modify it under | |
| 14 // the terms of the GNU General Public License as published by the Free | |
| 15 // Software Foundation; either version 2 or (at your option) any later version. | |
| 16 // | |
| 17 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY | |
| 18 // WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 19 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 20 // for more details. | |
| 21 // | |
| 22 // You should have received a copy of the GNU General Public License along | |
| 23 // with eCos; if not, write to the Free Software Foundation, Inc., | |
| 24 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. | |
| 25 // | |
| 26 // As a special exception, if other files instantiate templates or use macros | |
| 27 // or inline functions from this file, or you compile this file and link it | |
| 28 // with other works to produce a work based on this file, this file does not | |
| 29 // by itself cause the resulting work to be covered by the GNU General Public | |
| 30 // License. However the source code for this file must still be made available | |
| 31 // in accordance with section (3) of the GNU General Public License. | |
| 32 // | |
| 33 // This exception does not invalidate any other reasons why a work based on | |
| 34 // this file might be covered by the GNU General Public License. | |
| 35 // | |
| 36 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. | |
| 37 // at http://sources.redhat.com/ecos/ecos-license/ | |
| 38 // ------------------------------------------- | |
| 39 //####ECOSGPLCOPYRIGHTEND#### | |
| 40 //============================================================================= | |
| 41 //#####DESCRIPTIONBEGIN#### | |
| 42 // | |
| 43 // Author(s): andrew.lunn | |
| 44 // Contributors: | |
| 45 // Date: 2003-02-12 | |
| 46 // Description: Provides a Simple Network Time Protocol Client | |
| 47 //####DESCRIPTIONEND#### | |
| 48 // | |
| 49 //============================================================================= | |
| 50 | |
| 51 #include <network.h> | |
| 52 #include <cyg/infra/cyg_type.h> | |
| 53 #include <cyg/infra/cyg_ass.h> | |
|
759
018143c925ee
* tests/sntp1.c (net_test): Strip the trailing "\n" making it more
asl
parents:
748
diff
changeset
|
54 #include <cyg/infra/cyg_trac.h> |
| 748 | 55 #include <cyg/sntp/sntp.h> |
| 56 #include <time.h> | |
| 57 | |
| 58 #define VERSION_MASK 0x38000000 | |
| 59 #define VERSION_SHIFT 27 | |
| 60 #define MODE_MASK 0x07000000 | |
| 61 #define MODE_SHIFT 24 | |
| 62 #define STRATUM_MASK 0x00ff0000 | |
| 63 #define STRATUM_SHIFT 16 | |
| 64 | |
| 65 #define MODE_BROADCAST 5 | |
| 66 | |
| 67 struct sntp_srv_s { | |
| 68 struct sockaddr_in addr; | |
| 69 int stratum; | |
| 70 int version; | |
| 71 cyg_uint32 timestamp; | |
| 72 }; | |
| 73 | |
| 74 #define SECONDSPERMINUTE (cyg_uint32)60 | |
| 75 #define SECONDSPERHOUR (cyg_uint32)(SECONDSPERMINUTE * 60) | |
| 76 #define SECONDSPERDAY (cyg_uint32)(SECONDSPERHOUR * 24) | |
| 77 #define SECONDSPERYEAR (cyg_uint32)(SECONDSPERDAY * 365) | |
| 78 | |
| 79 /* Convert a SNTP timestamp to a time_t. timestamps are seconds from | |
| 80 1/1/1900. time_t is 1/1/1970. That equates to 70 years, or which | |
| 81 17 were leap years.*/ | |
| 82 static time_t timestamp2time(cyg_uint32 timestamp) { | |
| 83 | |
| 84 return timestamp - | |
| 85 (SECONDSPERYEAR * (cyg_uint32)(70)) - | |
| 86 (SECONDSPERDAY * (cyg_uint32)(17)); | |
| 87 } | |
| 88 | |
| 89 /* Is the new server better than the current one? If its the same as | |
| 90 the current, its always better. If the stratum is lower its better. | |
| 91 If we have not heard from the old server for more than 10 minutes, | |
| 92 the new server is better. */ | |
| 93 | |
| 94 static int is_better(struct sntp_srv_s *newer, struct sntp_srv_s *old) { | |
| 95 | |
| 96 time_t last_time, diff; | |
| 97 | |
| 98 if (newer->addr.sin_addr.s_addr == old->addr.sin_addr.s_addr) return 1; | |
| 99 if (newer->stratum < old->stratum) return 1; | |
| 100 | |
| 101 if (old->timestamp != 0xffffffff) { | |
| 102 last_time = timestamp2time(old->timestamp); | |
| 103 | |
| 104 diff = time(NULL) - last_time; | |
| 105 if (diff > 600) return 1; | |
| 106 | |
| 107 return 0; | |
| 108 } | |
| 109 return 1; | |
| 110 } | |
| 111 | |
| 112 static void sntp_fn(cyg_addrword_t data) { | |
| 113 int fd; | |
| 114 int ret; | |
| 115 struct sockaddr_in local; | |
| 116 struct servent *serv; | |
| 117 cyg_uint32 buf[12]; | |
| 118 struct sntp_srv_s new_srv; | |
| 119 struct sntp_srv_s best_srv; | |
| 120 int mode; | |
| 121 int len; | |
| 122 time_t new_time, current_time, diff; | |
| 123 | |
| 124 memset(&best_srv,0xff,sizeof(best_srv)); | |
| 125 | |
| 126 fd = socket(AF_INET,SOCK_DGRAM,0); | |
| 127 CYG_ASSERT(-1 != fd,"Failed to open socket"); | |
| 128 | |
| 129 serv = getservbyname("ntp","udp"); | |
| 130 CYG_ASSERT(serv,"getservbyname(sntp,udp)"); | |
| 131 | |
| 132 memset(&local,0,sizeof(local)); | |
| 133 local.sin_family = AF_INET; | |
| 134 local.sin_port = serv->s_port; | |
| 135 local.sin_addr.s_addr = INADDR_ANY; | |
| 136 | |
| 137 ret=bind(fd,(struct sockaddr *)&local,sizeof(local)); | |
| 138 CYG_ASSERT(0 == ret, "Bind failed"); | |
| 139 | |
| 140 while (1) { | |
| 141 len = sizeof(new_srv.addr); | |
| 142 ret=recvfrom(fd,buf,sizeof(buf),0,(struct sockaddr *)&new_srv.addr,&len); | |
| 143 CYG_ASSERT(0 < ret,"recvfrom"); | |
| 144 | |
| 145 /* We expect at least enough bytes to fill the buffer. There could | |
| 146 be more if there is a digest, but we ignore that. */ | |
| 147 if (ret < sizeof(buf)) | |
| 148 continue; | |
| 149 | |
| 150 new_srv.version = (htonl(buf[0]) & VERSION_MASK) >> VERSION_SHIFT; | |
| 151 new_srv.stratum = (htonl(buf[0]) & STRATUM_MASK) >> STRATUM_SHIFT; | |
| 152 new_srv.timestamp = htonl(buf[10]); | |
| 153 mode = (htonl(buf[0]) & MODE_MASK) >> MODE_SHIFT; | |
| 154 | |
| 155 /* Only support protocol versions 3 or 4 */ | |
|
759
018143c925ee
* tests/sntp1.c (net_test): Strip the trailing "\n" making it more
asl
parents:
748
diff
changeset
|
156 if (new_srv.version < 3 || new_srv.version > 4) { |
|
925
c6d5daaf0c31
* src/sntp.c: In function sntp_fn() changed 'version' to
jlarmour
parents:
759
diff
changeset
|
157 CYG_TRACE1(1, "Unsupported version of NTP. Version %d",new_srv.version); |
| 748 | 158 continue; |
|
759
018143c925ee
* tests/sntp1.c (net_test): Strip the trailing "\n" making it more
asl
parents:
748
diff
changeset
|
159 } |
| 748 | 160 |
| 161 /* Only process broadcast packet */ | |
| 162 if (mode != MODE_BROADCAST) | |
| 163 continue; | |
| 164 | |
| 165 /* Is the packet from a better server than our current one */ | |
| 166 if (is_better(&new_srv,&best_srv)) { | |
| 167 best_srv = new_srv; | |
| 168 | |
| 169 /* Work out the difference between server and our time */ | |
| 170 new_time = timestamp2time(best_srv.timestamp); | |
| 171 current_time = time(NULL); | |
| 172 diff = current_time - new_time; | |
| 173 | |
| 174 if (diff < 0) | |
| 175 diff = -diff; | |
| 176 | |
| 177 if (diff > 2) | |
| 178 cyg_libc_time_settime(new_time); | |
| 179 } | |
| 180 } | |
| 181 } | |
| 182 | |
| 183 /* Start the SNTP server */ | |
| 184 void cyg_sntp_start(void) { | |
| 185 | |
| 186 static char sntp_stack[CYGNUM_HAL_STACK_SIZE_TYPICAL]; | |
| 187 static cyg_thread sntp_thread_data; | |
| 188 static cyg_handle_t sntp_handle; | |
| 189 | |
| 190 cyg_thread_create(CYGPKG_NET_THREAD_PRIORITY+1, | |
| 191 sntp_fn, // entry | |
| 192 0, // entry parameter | |
| 193 "sntp", // Name | |
| 194 &sntp_stack, // stack | |
| 195 sizeof(sntp_stack), // stack size | |
| 196 &sntp_handle, // Handle | |
| 197 &sntp_thread_data); // Thread data structure | |
| 198 | |
| 199 cyg_thread_resume(sntp_handle); | |
| 200 } |
