#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#ifdef WIN32
#include <winsock.h>
#define _CRT_SECURE_NO_WARNINGS
#else
#include <netinet/in.h>
#include <sys/socket.h>
#endif
typedef struct medpeer
{
char *frompeer;
char *topeer;
int tolen;
char *data;
struct sockaddr_in sock;
unsigned long time;
void *nextpeer;
} medpeer;
int sock;
struct sockaddr_in saddr_local;
medpeer *peers = NULL;
int error(int err)
{
switch (err)
{
case 1:
printf("Unable to bind to specified port.\n");
}
return err;
}
int parse_cmdline(int argc, char *argv[])
{
char *IP = NULL, *sport = NULL;
int port = 8000;
if (argc>1)
{
sport = (char *)strchr(argv[1], ':');
if (sport)
{
IP = argv[1];
*sport = 0;
sport++;
}
else
{
IP = NULL;
sport = argv[1];
}
port = atol(sport);
}
saddr_local.sin_family = AF_INET;
if (IP)
{
saddr_local.sin_addr.s_addr = inet_addr(IP);
if (saddr_local.sin_addr.s_addr == INADDR_NONE)
{
return error(-1);
}
}
else
saddr_local.sin_addr.s_addr = INADDR_ANY;
saddr_local.sin_port = htons((unsigned short)port);
return 0;
}
int init_socket()
{
sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (sock == -1)
return 1;
if (bind(sock, (struct sockaddr *) &saddr_local, sizeof(saddr_local)) < 0)
return 1;
return 0;
}
int start_mediation()
{
int len = 0;
char buff[32768];
time_t t;
struct sockaddr_in saddr_from;
int addrlen = sizeof(struct sockaddr_in);
medpeer *prev, *p;
int count;
char *frompeer, *topeer, *data;
int found;
int jlen;
char *jdata;
while (1)
{
len = recvfrom(sock, buff, 32768, 0, (struct sockaddr *) &saddr_from, &addrlen);
/* let's perform cleanup */
t = time(NULL);
prev = NULL;
p = peers;
count = 0;
while (p)
{
count++;
if (t - p->time > 15)
{
if (prev)
prev->nextpeer = p->nextpeer;
else
{
peers = (medpeer *)p->nextpeer;
}
printf("* Removing %s\n", p->frompeer);
free(p->frompeer);
free(p->topeer);
free(p);
count = 0;
p = peers;
prev = NULL;
continue;
}
prev = p;
p = (medpeer *)p->nextpeer;
}
printf("* Total %d peers listed\n", count);
if (len)
{
frompeer = buff;
topeer = strchr(buff, '\n');
if (topeer && topeer > buff)
{
if (*(topeer-1) == '\r')
*(topeer-1) = 0;
*topeer++ = 0;
data = strchr(topeer, '\n');
if (data && data > topeer)
{
if (*(data-1) == '\r')
*(data-1) = 0;
*data++ = 0;
printf("%s -> %s\n", frompeer, topeer);
/* do we have this peer? */
found = 0;
p = peers;
jlen = strlen(topeer);
jdata = strchr(topeer, '*');
if (jdata)
{
if (jdata-topeer>0 && jdata-topeer<jlen)
jlen = jdata-topeer;
}
while (p)
{
if (!strcmp(p->frompeer, frompeer) && !strncmp(p->topeer, topeer, jlen))
{
memcpy(&p->sock, &saddr_from, sizeof(saddr_from));
p->time = (unsigned long)time(NULL);
found = 1;
break;
}
p = (medpeer *)p->nextpeer;
}
if (!found)
{
/* add this peer */
p = (medpeer *)malloc(sizeof(medpeer));
p->frompeer = (char *)malloc(len);
memcpy(p->frompeer, buff, len);
p->topeer = (char *)malloc(strlen(topeer)+1);
p->tolen = jlen;
strcpy(p->topeer, topeer);
p->data = p->frompeer + (data - frompeer);
memcpy(&p->sock, &saddr_from, sizeof(saddr_from));
p->time = (unsigned long)time(NULL);
p->nextpeer = peers;
peers = p;
printf("* Adding %s\n", p->frompeer);
}
if (p) /* this MUST be valid, but doesn't hurt to check */
{
medpeer *other = peers;
while (other)
{
if (!strncmp(topeer, other->frompeer, jlen) && !strncmp(frompeer, other->topeer, other->tolen))
{
// replace 'topeer'
if (strncmp(frompeer, other->topeer, other->tolen))
{
free(other->topeer);
other->topeer = (char *)malloc(strlen(frompeer)+1);
strcpy(other->topeer, frompeer);
other->tolen = strlen(frompeer);
}
unsigned char *ad= (unsigned char *)&other->sock.sin_addr;
printf("Reply to %s, IP %u.%u.%u.%u, port %d\n", frompeer, ad[0], ad[1], ad[2], ad[3], htons(other->sock.sin_port));
buff[0] = buff[1] = 0;
sprintf(buff+2, "%u.%u.%u.%u\r\n%d\r\n%s", ad[0], ad[1], ad[2], ad[3], htons(other->sock.sin_port), other->data);
sendto(sock, buff, strlen(buff+2)+2, 0, (struct sockaddr *) &saddr_from, sizeof(saddr_from));
break;
}
other = (medpeer *)other->nextpeer;
}
}
}
}
}
}
return 1;
}
int main(int argc, char *argv[])
{
#ifdef WIN32
WSADATA wsaData;
WSAStartup(MAKEWORD(2,0), &wsaData);
#endif
if (parse_cmdline(argc, argv))
return error(2);
if (init_socket())
return error(1);
start_mediation();
#ifdef WIN32
WSACleanup();
#endif
return 0;
}