extern void send_dummy_signal (void) { /* Activate signal handling if necessary*/ activate_signal_handling (); (void) kill (getpid(), SIGDUMMY); }
extern int evt_wait (int *p_fd, boolean *p_read, timeout_t *timeout) { fd_set select_read_mask, select_write_mask; timeout_t exp_time, *timeout_ptr; boolean timeout_is_active; int start_fd; int n; ssize_t size; char c; /* Activate signal handling if necessary*/ activate_signal_handling (); /* Compute exp_time = cur_time + timeout_ms */ timeout_is_active = (timeout->tv_sec >= 0) && (timeout->tv_usec >= 0); if (timeout_is_active) { get_time (&exp_time); add_time (&exp_time, timeout); timeout_ptr = timeout; } else { timeout_ptr = NULL; } /* Init wake-up pipe */ init_sig_and_wake_up (); for (;;) { /* Check for signal */ if (check_signal() ) { *p_fd = SIG_EVENT; evt_time_remaining (timeout, &exp_time); return (WAIT_OK); } /* Copy select mask */ memcpy (&select_read_mask, &global_read_mask, sizeof(fd_set)); memcpy (&select_write_mask, &global_write_mask, sizeof(fd_set)); /* Default result */ *p_fd = NO_EVENT; *p_read = TRUE; /* Compute select timeout */ if (timeout_is_active) { evt_time_remaining (timeout, &exp_time); } /* The select */ n = select (last_fd + 1, &select_read_mask, &select_write_mask, NULL, timeout_ptr); if (n > 0) { /* Start from 0 or from prev fd + 1 (round robin) */ if (n == 1) { start_fd = 0; } else { start_fd = (prev_fd + 1) % (last_fd + 1); } /* Check read events first */ *p_fd = check_fd (start_fd, &select_read_mask); if (*p_fd != NO_EVENT) { *p_read = TRUE; } else { /* Check write events second */ *p_read = FALSE; *p_fd = check_fd (start_fd, &select_write_mask); } /* Check if p_fd is wake-up fd) */ if (*p_fd == wake_up_fds[0] ) { for (;;) { size = read (wake_up_fds[0], &c, sizeof(c)); if ( (size == -1) && (errno != EINTR) ) { #ifdef DEBUG perror ("read"); #endif break; } if (size == 1) { break; } } *p_fd = WAKE_EVENT; } else if (*p_fd == NO_EVENT) { #ifdef DEBUG fprintf (stderr, "No fd found\n"); #endif return (WAIT_ERR); } prev_fd = *p_fd; if (prev_fd < -1) { /* Not a fd => end of round robin */ prev_fd = -1; } evt_time_remaining (timeout, &exp_time); return (WAIT_OK); } else if (n < 0) { if (errno != EINTR) { /* Real error */ #ifdef DEBUG perror ("select"); #endif return (WAIT_ERR); } } /* Check for timeout reached */ if ( (!check_signal()) && timeout_is_active && time_is_reached (&exp_time) ) { /* Done on timeout */ *p_fd = NO_EVENT; timeout->tv_sec = 0; timeout->tv_usec = 0; return (WAIT_OK); } } /* for (;;) */ }
/* THE MAIN */ int main (const int argc, const char * argv[]) { /* Socket data */ soc_token soc = init_soc; soc_host lan; soc_port port; int soc_fd, fd; /* Socket message */ msg_type msg; /* Times and timeouts */ timeout_t start_time, end_time, current_time; timeout_t wait_timeout; double local_time, remote_time; /* Dynamic list of server infos */ dlist list; info_type info; /* Utilities */ boolean for_read; char buff[256]; int res; char *index; /*********/ /* Start */ /*********/ /* Save prog name */ strcpy (prog, argv[0]); strcpy (prog, basename (prog)); /*******************/ /* Parse arguments */ /*******************/ /* Check args */ if (argc != 2) { error ("Invalid argument"); } /* Parse IPM address and port */ strcpy (buff, argv[1]); index = strstr (buff, ":"); if (index == NULL) { error ("Invalid argument"); } *index = '\0'; index++; if (soc_str2host (buff, &lan) != SOC_OK) { sprintf (buff, "Invalid ipm address %s", buff); error (buff); } if (soc_str2port (index, &port) != SOC_OK) { sprintf (buff, "Invalid port num %s", index); error (buff); } /**************/ /* Initialize */ /**************/ /* Init dynamic list */ dlist_init (& list, sizeof(info_type)); /* Init socket */ if (soc_open (&soc, udp_socket) != SOC_OK) { perror ("opening socket"); error ("Socket initialization failed"); } if (soc_set_dest_host_port (soc, &lan, port) != SOC_OK) { perror ("setting destination"); error ("Socket initialization failed"); } if (soc_link_port (soc, port) != SOC_OK) { perror ("linking to port"); error ("Socket initialization failed"); } if (soc_get_dest_host (soc, &lan) != SOC_OK) { perror ("getting dest lan"); error ("Socket initialization failed"); } if (soc_get_dest_port (soc, &port) != SOC_OK) { perror ("getting dest port"); error ("Socket initialization failed"); } /* Add socket to waiting point */ if (soc_get_id(soc, &soc_fd) != SOC_OK) { perror ("getting socket id"); error ("Socket initialization failed"); } if (evt_add_fd(soc_fd, TRUE) != WAIT_OK) { perror("Adding fd"); error ("Socket initialization failed"); } /* Activate signal catching */ activate_signal_handling(); /* Report starting */ buff[0]='\0'; addr_image (&lan, buff); printf ("%s mcasting at address %s on port %d.\n", prog, buff, (int) port); /* Init times */ get_time (&start_time); current_time = start_time; end_time = start_time; incr_time (&end_time, DELAY_CLIENT_MS); /* Send initial ping request */ msg.ping = TRUE; msg.time = start_time; if (soc_send (soc, (soc_message) &msg, sizeof(msg)) != SOC_OK) { perror ("sending ping"); error ("Sending ping request failed"); } /*************/ /* Main loop */ /*************/ for (;;) { /* First step is to loop until timeout */ if (wait_timeout.tv_sec != -1) { wait_timeout = end_time; res = sub_time (&wait_timeout, ¤t_time); if (res <= 0) { break; } } if (evt_wait (&fd, &for_read, &wait_timeout) != WAIT_OK) { perror ("waiting for event"); error ("Waiting for events failed"); } if (! for_read) { error ("Write event received"); } /* Termination signal */ if (fd == SIG_EVENT) { if (get_signal () == SIG_TERMINATE) { break; } } else if (fd == NO_EVENT) { /* Timeout: first step ends with a dump of servers */ if (dlist_length(&list) != 0) { dlist_rewind (&list, TRUE); for (;;) { dlist_read (&list, &info); /* Get host name if possible, else dump address */ res = soc_host_name_of (&info.host, buff, sizeof(buff)); if (res != SOC_OK) { buff[0]='\0'; addr_image (&info.host, buff); } /* Compute (Start_time + Reception_time) / 2 */ local_time = (time_to_double (&start_time) + time_to_double (&info.reception_time) ) / 2.0; remote_time = time_to_double (&info.server_time); printf ("Host %s is shifted by %4.03fs\n", buff, remote_time - local_time); /* Done when last record has been put */ if (dlist_get_pos (&list, FALSE) == 1) { break; } dlist_move (&list, TRUE); } } /* Now entering second step: infinite timeout */ wait_timeout.tv_sec = -1; wait_timeout.tv_usec = -1; printf ("%s ready.\n", prog); } else if (fd != soc_fd) { sprintf (buff, "Invalid fd %d received", fd); error (buff); } else { /* Now this is the socket, read message */ res = soc_receive (soc, (soc_message) &msg, sizeof(msg), TRUE); if (res < 0) { perror ("reading from socket"); error ("Reading message failed"); } else if (res != sizeof(msg)) { sprintf (buff, "Invalid size received, expected %d, got %d", (int)sizeof(msg), res); error (buff); } get_time (¤t_time); /* Client and server different behaviours */ if ((wait_timeout.tv_sec != -1) && !msg.ping) { /* First step: store the address and time of server, if pong */ if (soc_get_dest_host (soc, &(info.host)) != SOC_OK) { perror ("getting dest host"); error ("Getting server address failed"); } info.server_time = msg.time; info.reception_time = current_time; dlist_insert (&list, &info, TRUE); } else if ( (wait_timeout.tv_sec == -1) && msg.ping) { /* Second step: reply pong and time to ping */ msg.time = current_time; msg.ping = FALSE; if (soc_send (soc, (soc_message) &msg, sizeof(msg)) != SOC_OK) { perror ("sending pong"); error ("Sending pong request failed"); } } } } /* End of main loop */ /* Clean - Close */ dlist_delete_all (&list); (void) evt_del_fd (soc_fd, TRUE); (void) soc_close (&soc); printf ("Done.\n"); exit (0); }