rtps-fpga/sw/standalone/udp_client.cpp

122 lines
3.3 KiB
C++

#include <sys/socket.h> //socket, inet_aton
#include <netinet/in.h> //socket, inet_aton
#include <netinet/udp.h> //socket
#include <arpa/inet.h> //htons, ntohs, htonl, ntohl, inet_aton
#include <signal.h> //signal
#include <stdio.h> //fprintf
#include <errno.h> //perror
#include <stdlib.h> //strtol
#include <unistd.h> //close
/*PROTOTYPES*/
void bail(int code);
void sig_handler(int signum);
void usage(char* name);
/*DEFINES*/
//Magic Number used to distinguish our UDP Packets (First 8 Bytes of Payload)
#define MAGIC 0xDEADBEEFCAFEFEED
//Receive Buffer Size
#define BUFFER_SIZE 1000
/*GLOBAL VARIABLES*/
long port = 0;
int sock_fd = -1;
struct sockaddr_in src_addr;
int main(int argc, char **argv){
/*Parse Arguments*/
if (argc < 3) {
fprintf(stderr, "Insufficient arguments\n");
usage(argv[0]);
}
//Source Address
in_addr_t src_ip_addr = inet_addr(argv[1]);
if (src_ip_addr == INADDR_NONE) {
fprintf(stderr, "Invalid SRC IP Address\n");
usage(argv[0]);
}
//Port Number
errno = 0;
port = strtol(argv[2], NULL, 10);
if (errno != 0) {
fprintf(stderr, "Invalid Port Number\n");
usage(argv[0]);
}
/*MISC MAIN THREAD*/
//Register Signal Handling
signal(SIGHUP, sig_handler);
signal(SIGINT, sig_handler);
signal(SIGQUIT, sig_handler);
signal(SIGABRT, sig_handler);
/*SOCKET OPERATIONS*/
src_addr = {AF_INET, htons(port), {src_ip_addr}};
//Open Socket
sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
//Bind Socket
if (bind(sock_fd, (const struct sockaddr*) &src_addr, sizeof(src_addr)) < 0) {
perror("Bind failed");
bail(EXIT_FAILURE);
}
//Set Receive Timeout
const struct timeval tv = {.tv_usec = 1000}; //1 ms
setsockopt(sock_fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
char buffer[BUFFER_SIZE];
uint64_t* p = (uint64_t*) buffer;
socklen_t addrlen;
struct sockaddr_in src;
int n;
printf("Entering Main loop\n");
while(true){
//Receive Packet
n = recvfrom(sock_fd, buffer, BUFFER_SIZE, MSG_TRUNC, (struct sockaddr*) &src, &addrlen);
if (n < 0){
// Error
if (errno != EAGAIN && errno != EWOULDBLOCK) {
perror("rcvfrom() error");
}
continue;
}
//Packet not relevant
if (src.sin_family != src_addr.sin_family && src.sin_port != src_addr.sin_port && n >= 8 && p[0] != MAGIC){
continue;
}
//Sent Packet Back
if (sendto(sock_fd, buffer, n, 0, (const struct sockaddr*) &src, addrlen) < 0) {
perror("sendto failed");
}
}
}
void bail(int code){
//Close Sockets
if (sock_fd != -1) {
close(sock_fd);
}
//DONE
exit(code);
}
void sig_handler(int signum){
fprintf(stderr, "Received Signal %d.\n Exiting...\n", signum);
bail(EXIT_SUCCESS);
}
void usage(char* name){
printf("USAGE: %s SRC_ADDRESS PORT\n", name);
printf("SRC_ADDRESS The local source IPv4 Address from which to send and listen to (In x.x.x.x format)\n");
printf("PORT The port number of the Addresses\n");
bail(EXIT_SUCCESS);
}