Skip to content

Instantly share code, notes, and snippets.

@vi
Created June 25, 2013 21:29
Show Gist options
  • Select an option

  • Save vi/5862606 to your computer and use it in GitHub Desktop.

Select an option

Save vi/5862606 to your computer and use it in GitHub Desktop.
UDP relay - for implementing other programs working with UDP
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <string.h>
#ifndef WIN32
#include <netdb.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <netinet/in.h>
#else
#define WINVER 0x0501
#include <winsock2.h>
#include <windows.h>
#include <ws2tcpip.h>
#include <fcntl.h>
#endif
#include <errno.h>
#include <signal.h>
#include <sys/time.h>
#define BUFSIZE 4096
int s_recv = -1;
int s_send = -1;
int start = 0;
int end = 0;
unsigned char buf[BUFSIZE];
int main(int argc, char* argv[]) {
if (argc<5 || !strcmp(argv[1], "--help") || !strcmp(argv[1], "-?")) {
fprintf (stderr,
"Usage:\n"
"\tudprelay recv_host recv_port send_host send_port"
"\tCreated by Vitaly \"_Vi\" Shukela\n"
);
return 1;
}
struct addrinfo hints;
struct addrinfo *recv_addr;
struct addrinfo *send_addr;
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */
hints.ai_flags = AI_PASSIVE;
char* recv_host = argv[1];
char* recv_port = argv[2];
char* send_host = argv[3];
char* send_port = argv[4];
if (!strcmp(recv_host, "NULL")) recv_host=NULL;
if (!strcmp(recv_port, "NULL")) recv_port=NULL;
if (!strcmp(send_host, "NULL")) send_host=NULL;
if (!strcmp(send_port, "NULL")) send_port=NULL;
int gai_error;
gai_error=getaddrinfo(recv_host,recv_port, &hints, &recv_addr);
if (gai_error) { fprintf(stderr, "getaddrinfo 1: %s\n",gai_strerror(gai_error)); return 4; }
if (!recv_addr) { fprintf(stderr, "getaddrinfo returned no addresses\n"); return 6; }
if (recv_addr->ai_next) {
fprintf(stderr, "Warning: using only one of addresses retuned by getaddrinfo\n");
}
hints.ai_flags &= !AI_PASSIVE;
gai_error=getaddrinfo(send_host, send_port, &hints, &send_addr);
if (gai_error) { fprintf(stderr, "getaddrinfo 2: %s\n",gai_strerror(gai_error)); return 13; }
if (!send_addr) { fprintf(stderr, "getaddrinfo 2 returned no addresses\n"); return 15; }
if (send_addr->ai_next) {
fprintf(stderr, "Warning: using only one of addresses retuned by getaddrinfo 2\n");
}
s_recv = socket(recv_addr->ai_family, recv_addr->ai_socktype, recv_addr->ai_protocol);
if (s_recv == -1) { perror("socket"); return 7; }
{
int one = 1;
setsockopt(s_recv, SOL_SOCKET, SO_REUSEADDR, &one, sizeof one);
}
if (bind(s_recv, recv_addr->ai_addr, recv_addr->ai_addrlen)) { perror("bind"); return 5; }
s_send = socket(send_addr->ai_family, send_addr->ai_socktype, send_addr->ai_protocol);
if (s_send == -1) { perror("socket 2"); return 12; }
//char should_be_enough[1024];
struct sockaddr peeraddr ;
socklen_t peeraddrlen = sizeof peeraddr;
for (;;) {
fd_set rfds;
FD_ZERO(&rfds);
int maxfd = 0;
FD_SET(s_recv, &rfds);
FD_SET(s_send, &rfds);
if (s_recv >= maxfd) maxfd = s_recv+1;
if (s_send >= maxfd) maxfd = s_send+1;
struct timeval *timeout = NULL;
struct timeval tv;
int select_ret = select(maxfd, &rfds, NULL, NULL, timeout);
if (select_ret==-1) {
if (errno==EAGAIN || errno==EINTR) continue;
perror("select");
return 91;
}
if (FD_ISSET(s_recv, &rfds)) {
int ret = recvfrom(s_recv, buf, BUFSIZE, 0, &peeraddr, &peeraddrlen);
sendto(s_send, buf, ret, 0, send_addr->ai_addr, send_addr->ai_addrlen);
}
if (FD_ISSET(s_send, &rfds)) {
int ret = recv(s_send, buf, BUFSIZE, 0);
sendto(s_recv, buf, ret, 0, &peeraddr, peeraddrlen);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment