#define period 20000 #define theserver "80.199.27.122" #define _GNU_SOURCE 1 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include struct time_shm { int shm_mode; int stamp_count; time_t clock_sec; int clock_usec; time_t receive_sec; int receive_usec; int leap_indicator; int precision; int number_of_samples; int is_valid; int place_holder[10]; }; struct time_shm *sh; struct time_shm *attach_shm(int unit) { int shm_id=0; shm_id=shmget(0x4e545030+unit, sizeof(struct time_shm), IPC_CREAT|0700); if(shm_id==-1) { fprintf(stderr,"shmget failed.\n"); perror("shmget"); exit(1); } sh=(struct time_shm *) shmat(shm_id, 0, 0); if(sh==(void *) -1 || sh==0) { fprintf(stderr,"shmat failed.\n"); perror("shmat"); exit(1); } return sh; } void set_shm(unsigned r_sec, unsigned r_usec, unsigned c_sec, unsigned c_usec, unsigned prec) { sh->shm_mode=1; sh->leap_indicator=0; sh->is_valid=0; __asm__ __volatile__("": : :"memory"); sh->stamp_count++; __asm__ __volatile__("": : :"memory"); sh->precision=prec; sh->clock_sec=c_sec; sh->clock_usec=c_usec; sh->receive_sec=r_sec; sh->receive_usec=r_usec; __asm__ __volatile__("": : :"memory"); sh->stamp_count++; __asm__ __volatile__("": : :"memory"); sh->is_valid=1; } int waitsok(int sok) { struct timeval stTimeOut; fd_set stReadFDS; FD_ZERO(&stReadFDS); // Timeout 3 sec stTimeOut.tv_sec = 3; stTimeOut.tv_usec = 0; FD_SET(sok, &stReadFDS); return select(sok+1, &stReadFDS, 0, 0, &stTimeOut); } int sockfd,n; struct sockaddr_in servaddr,cliaddr; unsigned sendbuf[10]; unsigned recvbuf[10]; int dt; struct timeval tv,rtv; struct timezone tz; extern int errno; int main(argc, argv) int argc; char *argv[]; { int i, f, f1, f2, f3, fx, whatitis; int sp_fd = 0, pp_fd = 0, n_fd=0, zoo_poll = 0, hitolow = 0, flap = 0; int deviceis_serial = 0, deviceis_parallel = 0, deviceis_nic=0, bogon = 0; int unit = 0; int locked=0; unsigned int pp_nfds = 1; struct pollfd pp_pollfd[2]; struct ppdev_frob_struct frobit; struct sched_param sp; struct rlimit rl; char *prog; char *pps_dev[256]; char *pps_sig[256]; /* name of sig line: CD RTS DSR */ int sig = TIOCM_CD; prog = argv[0]; attach_shm(0); if (1) { if(fork()!=0) return(0); setsid(); setpgrp(); setsid(); getrlimit(RLIMIT_NOFILE, &rl); for (i = 0; i <= rl.rlim_max; i++) (void) close(i); } sockfd=socket(AF_INET,SOCK_DGRAM,0); bzero(&servaddr,sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr=inet_addr("217.198.219.102"); servaddr.sin_port=htons(124); for(;;) { loopstart: gettimeofday(&tv,&tz); usleep(100000); //100 ms for the peer to have updated the table entry for this second sendbuf[0]=54656866; sendbuf[1]=tv.tv_sec&255; servaddr.sin_port=htons(124); servaddr.sin_addr.s_addr=inet_addr("127.0.0.1"); sendto(sockfd,sendbuf,8,0,(struct sockaddr *)&servaddr,sizeof(servaddr)); rerx2: if (waitsok(sockfd)) { n=recvfrom(sockfd,recvbuf,40,0,NULL,NULL); if (n!=20) goto rerx2; if (recvbuf[0]!=54652345) goto rerx2; if (recvbuf[1]!=sendbuf[1]) goto rerx2; // printf("local arrival time:%i\n",recvbuf[2]); dt=-recvbuf[2]; } else { // printf("failed to get local time\n"); sleep(14); goto loopstart; } servaddr.sin_addr.s_addr=inet_addr(theserver); servaddr.sin_port=htons(124); sendto(sockfd,sendbuf,8,0,(struct sockaddr *)&servaddr,sizeof(servaddr)); rerx1: if (waitsok(sockfd)) { n=recvfrom(sockfd,recvbuf,40,0,NULL,NULL); if (n!=20) goto rerx1; if (recvbuf[0]!=54652345) goto rerx1; if (recvbuf[1]!=sendbuf[1]) goto rerx1; // printf("remote arrival time: %i\n",recvbuf[2]); dt=dt+recvbuf[2]; } else { // printf("failed to get time\n"); sleep(14); goto loopstart; } /* if the remote clock is fast, dt is positive. */ // dt-= 10000; this is the place to compensate if you picked different phases dt=((dt+(5*period)+(period/2))%period)-(period/2); //printf("delta (positive means that remote clock is ahead):%i\n",dt); if ((dt>-4000)&&(dt<4000)) locked=1; if (locked) { rtv.tv_sec=tv.tv_sec-1; rtv.tv_usec=tv.tv_usec+1000000; //pre adjust rtv.tv_usec += dt; while (rtv.tv_usec>=1000000) { rtv.tv_sec+=1; rtv.tv_usec-=1000000; } set_shm(tv.tv_sec,tv.tv_usec, rtv.tv_sec,rtv.tv_usec, -15); //30 usec precision } sleep(14); } }