4848#include <string.h>
4949#include <time.h>
5050#include <unistd.h>
51+ #include <stdbool.h>
5152
5253#include <linux/can.h>
5354#include <linux/can/raw.h>
@@ -89,6 +90,12 @@ const int canfx_on = 1;
8990
9091extern int optind , opterr , optopt ;
9192
93+ struct sleep {
94+ struct timeval * sleep_vector ;
95+ size_t idx ;
96+ size_t size ;
97+ };
98+
9299static void print_usage (char * prg )
93100{
94101 fprintf (stderr , "%s - replay a compact CAN frame logfile to CAN devices.\n" , prg );
@@ -117,6 +124,8 @@ static void print_usage(char *prg)
117124 "loopback of sent CAN frames)\n" );
118125 fprintf (stderr , " -v (verbose: print "
119126 "sent CAN frames)\n" );
127+ fprintf (stderr , " -r (real-time: send "
128+ "CAN frames in real-time)\n" );
120129 fprintf (stderr , " -h (show "
121130 "this help message)\n\n" );
122131 fprintf (stderr , "Interface assignment:\n" );
@@ -254,6 +263,40 @@ static int add_assignment(char *mode, int socket, char *txname,
254263 return 0 ;
255264}
256265
266+ static void load_gaps_from_file (FILE * fp , struct sleep * timestamps )
267+ {
268+ char * line = NULL ;
269+ size_t len = 0 ;
270+ ssize_t read ;
271+ struct timeval * current ;
272+
273+ while ((read = getline (& line , & len , fp )) != -1 ) {
274+ if (timestamps -> idx == timestamps -> size ) {
275+ timestamps -> size *= 2 ;
276+ timestamps -> sleep_vector = realloc (timestamps -> sleep_vector , timestamps -> size * sizeof (* (timestamps -> sleep_vector )));
277+ if (!timestamps -> sleep_vector ) {
278+ fprintf (stderr , "Failed to realloc the timestamps vector!\n" );
279+ exit (1 );
280+ }
281+ }
282+ current = & timestamps -> sleep_vector [timestamps -> idx ];
283+ sscanf (line , "(%lu.%lu)" , current -> tv_sec , current -> tv_usec );
284+ timestamps -> idx ++ ;
285+ }
286+ free (line );
287+ }
288+
289+ static void init_timestamps (struct sleep * timestamps , size_t init_size )
290+ {
291+ timestamps -> size = init_size ;
292+ timestamps -> sleep_vector = calloc (init_size , sizeof (* (timestamps -> sleep_vector )));
293+ if (!timestamps -> sleep_vector ) {
294+ fprintf (stderr , "Failed to create the timestamps vector!\n" );
295+ exit (1 );
296+ }
297+ timestamps -> idx = 0 ;
298+ }
299+
257300int main (int argc , char * * argv )
258301{
259302 static char buf [BUFSZ ], device [DEVSZ ], afrbuf [AFRSZ ];
@@ -280,8 +323,11 @@ int main(int argc, char **argv)
280323 int eof , txmtu , i , j ;
281324 char * fret ;
282325 unsigned long long sec , usec ;
326+ bool gap_from_file = false;
327+ struct sleep timestamps ;
328+ struct timeval send_time , act_time , init_time ;
283329
284- while ((opt = getopt (argc , argv , "I:l:tin:g:s:xvh " )) != -1 ) {
330+ while ((opt = getopt (argc , argv , "I:l:tin:g:s:xvrh " )) != -1 ) {
285331 switch (opt ) {
286332 case 'I' :
287333 infile = fopen (optarg , "r" );
@@ -336,6 +382,16 @@ int main(int argc, char **argv)
336382 verbose ++ ;
337383 break ;
338384
385+ case 'r' :
386+ if (!isatty (fileno (infile ))) {
387+ fprintf (stderr , "Specify an input file for option -r !\n" );
388+ exit (EXIT_FAILURE );
389+ }
390+ gap_from_file = true; /* using time delta from file */
391+ init_timestamps (& timestamps , 1 );
392+ load_gaps_from_file (infile , & timestamps );
393+ break ;
394+
339395 case 'h' :
340396 print_usage (basename (argv [0 ]));
341397 exit (EXIT_SUCCESS );
@@ -368,8 +424,10 @@ int main(int argc, char **argv)
368424 printf ("interactive mode: press ENTER to process next CAN frame ...\n" );
369425 }
370426
371- sleep_ts .tv_sec = gap / 1000 ;
372- sleep_ts .tv_nsec = (gap % 1000 ) * 1000000 ;
427+ if (!gap_from_file ) {
428+ sleep_ts .tv_sec = gap / 1000 ;
429+ sleep_ts .tv_nsec = (gap % 1000 ) * 1000000 ;
430+ }
373431
374432 /* open socket */
375433 if ((s = socket (PF_CAN , SOCK_RAW , CAN_RAW )) < 0 ) {
@@ -513,6 +571,23 @@ int main(int argc, char **argv)
513571 addr .can_family = AF_CAN ;
514572 addr .can_ifindex = txidx ; /* send via this interface */
515573
574+ if (gap_from_file && timestamps .idx > 0 ) {
575+ send_time = timestamps .sleep_vector [timestamps .idx ];
576+ gettimeofday (& act_time , NULL );
577+ timersub (& act_time , & init_time , & act_time );
578+
579+ while (timercmp (& act_time , & send_time , < )){
580+ gettimeofday (& act_time , NULL );
581+ timersub (& act_time , & init_time , & act_time );
582+ }
583+ }
584+ if (gap_from_file && timestamps .idx == 0 ) {
585+ gettimeofday (& init_time , NULL );
586+ gettimeofday (& act_time , NULL );
587+ timersub (& act_time , & init_time , & act_time );
588+ }
589+ timestamps .idx ++ ;
590+
516591 if (sendto (s , & cu , txmtu , 0 , (struct sockaddr * )& addr , sizeof (addr )) != txmtu ) {
517592 perror ("sendto" );
518593 return 1 ;
@@ -570,7 +645,7 @@ int main(int argc, char **argv)
570645
571646 } /* while frames_to_send ... */
572647
573- if (nanosleep (& sleep_ts , NULL ))
648+ if (! gap_from_file && nanosleep (& sleep_ts , NULL ))
574649 return 1 ;
575650
576651 delay_loops ++ ; /* private statistics */
0 commit comments