linbpq/UDPtoTCP/UDPtoTCP/UDPtoTCP.c

392 lines
7.0 KiB
C

// UDPtoTCP.cpp : Defines the entry point for the console application.
//
#include <stdio.h>
#ifdef WIN32
#include "winsock2.h"
#include "WS2tcpip.h"
#else
#define VOID void
#define SOCKET int
#define BOOL int
#define TRUE 1
#define FALSE 0
#define SOCKADDR_IN struct sockaddr_in
#define INVALID_SOCKET -1
#define SOCKET_ERROR -1
#define closesocket close
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#endif
#define MaxSockets 64
struct SocketConnectionInfo
{
int Number; // Number of record - for AGWConnections display
SOCKET socket;
struct sockaddr_in sin;
BOOL SocketActive;
};
static struct SocketConnectionInfo Sockets[MaxSockets+1];
int CurrentConnections;
static int CurrentSockets=0;
int TCPPort = 10110;
int UDPPort = 10110;
SOCKET tcpsock;
SOCKET udpsock;
void Poll();
int Init();
int Socket_Accept(SOCKET SocketId);
int DataSocket_Disconnect(struct SocketConnectionInfo * sockptr);
int DataSocket_Read(struct SocketConnectionInfo * sockptr, SOCKET sock);
#ifndef WIN32
#include <pthread.h>
pthread_t _beginthread(void(*start_address)(), unsigned stack_size, VOID * arglist)
{
pthread_t thread;
if (pthread_create(&thread, NULL, (void * (*)(void *))start_address, (void*) arglist) != 0)
perror("New Thread");
else
pthread_detach(thread);
return thread;
}
int Sleep(int ms)
{
usleep(ms * 1000);
return 0;
}
#endif
int main(int argc, char * argv[])
{
if (Init() == 0)
return 0;
while (1)
{
Sleep(1000);
Poll();
}
return 0;
}
VOID Poll()
{
struct SocketConnectionInfo * sockptr;
// Look for incoming connects
fd_set readfd, writefd, exceptfd;
struct timeval timeout;
int retval;
int n;
int Active = 0;
SOCKET maxsock;
// Look for connects
timeout.tv_sec = 0;
timeout.tv_usec = 0; // poll
FD_ZERO(&readfd);
FD_SET(tcpsock, &readfd);
retval = select((int)tcpsock + 1, &readfd, NULL, NULL, &timeout);
if (retval == -1)
{
perror("listen select");
}
if (retval)
if (FD_ISSET((int)tcpsock, &readfd))
Socket_Accept(tcpsock);
// Look for UDP Data
timeout.tv_sec = 0;
timeout.tv_usec = 0; // poll
FD_ZERO(&readfd);
FD_SET(udpsock, &readfd);
retval = select((int)udpsock + 1, &readfd, NULL, NULL, &timeout);
if (retval == -1)
{
perror("udp poll select");
}
if (retval)
{
if (FD_ISSET((int)udpsock, &readfd))
{
char Message[512] = "";
struct sockaddr_in rxaddr;
int addrlen = sizeof(struct sockaddr_in);
int len, n;
struct SocketConnectionInfo * sockptr;
len = recvfrom(udpsock, Message, 512, 0, (struct sockaddr *)&rxaddr, &addrlen);
if (len > 0)
printf("%s", Message);
// Send to all connected clients
for (n = 1; n <= CurrentSockets; n++)
{
sockptr = &Sockets[n];
if (sockptr->SocketActive)
{
send(sockptr->socket, Message, len, 0);
}
}
}
}
// look for data on any active sockets
maxsock = 0;
FD_ZERO(&readfd);
FD_ZERO(&writefd);
FD_ZERO(&exceptfd);
// Check for data on active streams
for (n = 1; n <= MaxSockets; n++)
{
sockptr=&Sockets[n];
if (sockptr->SocketActive)
{
SOCKET sock = sockptr->socket;
FD_SET(sock, &readfd);
FD_SET(sock, &exceptfd);
Active++;
if (sock > maxsock)
maxsock = sock;
}
}
if (Active)
{
retval = select((int)maxsock + 1, &readfd, &writefd, &exceptfd, &timeout);
if (retval == -1)
{
perror("data select");
}
else
{
if (retval)
{
// see who has data
for (n = 1; n <= MaxSockets; n++)
{
sockptr=&Sockets[n];
if (sockptr->SocketActive)
{
SOCKET sock = sockptr->socket;
if (FD_ISSET(sock, &exceptfd))
DataSocket_Disconnect(sockptr);
if (FD_ISSET(sock, &readfd))
DataSocket_Read(sockptr, sock);
}
}
}
}
}
}
SOCKADDR_IN local_sin;
SOCKADDR_IN sinx;
SOCKADDR_IN * psin;
int Init()
{
char opt = TRUE;
#ifdef WIN32
WSADATA WsaData; // receives data from WSAStartup
WSAStartup(MAKEWORD(2, 0), &WsaData);
#endif
if (TCPPort == 0)
return 0;
// Create listening socket
tcpsock = socket( AF_INET, SOCK_STREAM, 0);
if (tcpsock == INVALID_SOCKET)
{
printf("socket() failed error %d\r\n", errno);
return 0;
}
setsockopt (tcpsock, SOL_SOCKET, SO_REUSEADDR, &opt, 1);
psin=&local_sin;
psin->sin_family = AF_INET;
psin->sin_addr.s_addr = INADDR_ANY;
psin->sin_port = htons(TCPPort); /* Convert to network ordering */
if (bind(tcpsock, (struct sockaddr *)&local_sin, sizeof(local_sin)) == SOCKET_ERROR)
{
printf("bind(sock) failed Port %d Error %d\r\n", TCPPort, errno);
closesocket(tcpsock);
return 0;
}
udpsock = socket(AF_INET,SOCK_DGRAM,0);
sinx.sin_family = AF_INET;
sinx.sin_addr.s_addr = INADDR_ANY;
sinx.sin_port = htons(UDPPort);
if (bind(udpsock, (struct sockaddr *) &sinx, sizeof(sinx)) != 0 )
{
// Bind Failed
int err = errno;
printf("Bind Failed for UDP port %d - error code = %d\r\n", UDPPort, err);
return 0;
}
if (listen(tcpsock, 5) < 0)
{
printf("listen(tcpsock) failed Error %d\r\n", errno);
return 0;
}
_beginthread(Poll,0,0);
return 1;
}
int Socket_Accept(SOCKET SocketId)
{
int n,addrlen;
struct SocketConnectionInfo * sockptr;
SOCKET sock;
unsigned char work[4];
// Find a free Socket
for (n = 1; n <= MaxSockets; n++)
{
sockptr=&Sockets[n];
if (sockptr->SocketActive == FALSE)
{
addrlen=sizeof(struct sockaddr);
memset(sockptr, 0, sizeof(struct SocketConnectionInfo));
sock = accept(SocketId, (struct sockaddr *)&sockptr->sin, &addrlen);
if (sock == INVALID_SOCKET)
{
printf("accept() failed Error %d\r", errno);
return FALSE;
}
sockptr->socket = sock;
sockptr->SocketActive = TRUE;
sockptr->Number = n;
if (CurrentSockets < n) CurrentSockets = n; //Record max used to save searching all entries
memcpy(work, &sockptr->sin.sin_addr.s_addr, 4);
printf("Connected Session %d from %d.%d.%d.%d\r\n", n, work[0], work[1], work[2], work[3]);
return 0;
}
}
// Should accept, then immediately close
return 0;
}
int DataSocket_Read(struct SocketConnectionInfo * sockptr, SOCKET sock)
{
int i;
char Message[512] = "";
i = recv(sock, Message, 512, 0);
if (i == SOCKET_ERROR || i == 0)
{
// Failed or closed - clear connection
DataSocket_Disconnect(sockptr);
return 0;
}
printf(Message);
return 0;
}
int DataSocket_Disconnect(struct SocketConnectionInfo * sockptr)
{
closesocket(sockptr->socket);
sockptr->SocketActive = FALSE;
printf("Session %d Disconnected\r\n", sockptr->Number);
return 0;
}