#include #include #include #include #include "util/dbg.h" #include "proto/socket.h" PrrtSocket *s = NULL; static volatile int keepRunning = true; static char doc[] = "PRRT Receiver"; static struct argp_option options[] = { {"port", 'p', "PORT", 0, "Target Port" }, {"rounds", 'r', "ROUNDS", 0, "Rounds" }, {"output", 'o', "FILE", 0, "Output to FILE instead of standard output" }, {"threadpinning", 'T', 0, 0, "Enable thread pinning"}, {"hardwaretimestamping", 777, "INTERFACE", 0, "Enable hardware timestamping and bind to interface"}, { 0 } }; typedef struct arguments { uint16_t port; uint16_t rounds; char* outfile; bool thread_pinning; char* hardwarestamping_interface; } arguments_t; static char args_doc[] = ""; static error_t parse_opt (int key, char *arg, struct argp_state *state) { arguments_t *arguments = state->input; char* pEnd; switch (key) { case 'p': arguments->port = (uint16_t) strtol(arg, &pEnd, 10); break; case 'r': arguments->rounds = (uint16_t) strtol(arg, &pEnd, 10); break; case 'o': arguments->outfile = arg; break; case 'T': arguments->thread_pinning = true; break; case 777: arguments->hardwarestamping_interface = arg; break; case ARGP_KEY_END: break; default: return ARGP_ERR_UNKNOWN; } return 0; } void intHandler(int dummy) { keepRunning = false; PrrtSocket_interrupt(s); } int main(int argc, char **argv) { signal(SIGINT, intHandler); struct argp argp = { options, parse_opt, args_doc, doc }; struct arguments arguments = { .port = 5000, .rounds = 127, .outfile = "-", .thread_pinning = false, .hardwarestamping_interface = "-" }; argp_parse (&argp, argc, argv, 0, 0, &arguments); bool file_output = false; FILE *out_desc = stdout; if (strcmp(arguments.outfile, "-") != 0) { file_output = true; out_desc = fopen(arguments.outfile, "w"); } uint32_t rounds = arguments.rounds; #ifdef XLAP if (rounds >= TS_ROWS) { printf("Receiver: Too many rounds for use with XLAP (max: %d).\n", TS_ROWS-1); return -1; } #endif s = PrrtSocket_create(1500, HALF_TIMESTAMP - 1); check(s != NULL, "Could not create socket."); if(strcmp(arguments.hardwarestamping_interface, "-") != 0) { PrrtSocket_enable_hardware_timestamping(s, arguments.hardwarestamping_interface); } if(arguments.thread_pinning) { PrrtSocket_enable_thread_pinning(s); } check(PrrtSocket_bind(s, "0.0.0.0", arguments.port) == 0, "bind failed"); XlapTimestampTable *tstable_data = malloc(sizeof(XlapTimestampTable)); XlapTimestampTable *tstable_redundancy = malloc(sizeof(XlapTimestampTable)); check(tstable_data != NULL, "malloc failed"); check(tstable_redundancy != NULL, "malloc failed"); XlapTimestampTableInstall(s, ts_data_packet, tstable_data); XlapTimestampTableInstall(s, ts_redundancy_packet, tstable_redundancy); uint32_t i = 0; struct sockaddr_in addr; while (i < rounds && keepRunning) { char buffer[MAX_PAYLOAD_LENGTH + 1]; debug(DEBUG_RECEIVER, "About to receive."); int n = PrrtSocket_recv(s, buffer, (struct sockaddr *) &addr); if (n < 0) { continue; } buffer[n] = '\0'; unsigned int seqno; sscanf(buffer, "%u", &seqno); prrtTimestamp_t current_time = PrrtClock_get_current_time_us(); prrtTimestamp_t prrt_time = PrrtClock_get_prrt_time_us(&s->clock); printf("C: %d\nP: %d\nD: \n%d\n\n", current_time, prrt_time, prrt_time - current_time); debug(DEBUG_RECEIVER, "[B (n: %3d, i: %3d)] %s", n, i, buffer); i++; } XlapTimestampTableDumpHeader(out_desc); XlapTimestampTableDump(out_desc, ts_data_packet, tstable_data); XlapTimestampTableDump(out_desc, ts_redundancy_packet, tstable_redundancy); if (file_output) { fclose(out_desc); } PrrtSocket_close(s); free(s); free(tstable_data); free(tstable_redundancy); pthread_exit(NULL); return 0; error: return -1; }