Changes to integrate bitdht into libretroshare.

Mainly re-organising tcponudp... 
	tests->test area
	network->trash (uses libbitdht classes).
	new udp interfaces (udppeer + udpstunner)

Changes include:
	* p3bitdht: added "addReceiver() call, and more debugging. 
	* p3bitdht: added DO_IDLE flag so searches are continous.
	* p3bitdht/pqiassist: matched up Assist interface.
	* fixed pqiNetListener interface.
	* rsinit/p3connmgr: setup udp init
	* tcpstream: switched to new udp receiver.
	* added "blogs" switch in libretroshare.pro (was stopping compiling ;)
	* added "bitdht" switch in libretroshare.pro 



git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@3323 b45a01b8-16f6-495d-af2f-9b41ad6348cc
This commit is contained in:
drbob 2010-07-31 18:14:10 +00:00
parent c1b624832f
commit fcdd7ee113
34 changed files with 627 additions and 1770 deletions

View file

@ -1,60 +0,0 @@
RS_TOP_DIR = ..
##### Define any flags that are needed for this section #######
###############################################################
###############################################################
include $(RS_TOP_DIR)/scripts/config.mk
###############################################################
BIOOBJ = bss_tou.o
RSOBJ = tou_net.o udplayer.o udpsorter.o udptestfn.o extaddrfinder.o
RSOBJ += tcppacket.o tcpstream.o tou.o $(BIOOBJ)
EXECS = librs udpsock_test udpsort_test udp_server
#test_tou pair_tou reset_tou internal_tou largefile_tou
TESTOBJ = udpsock_test.o udpsort_test.o udp_server.o test_tou.o
TESTOBJ += pair_tou.o reset_tou.o largefile_tou.o
#internal_tou.o
TESTS = udpsock_test udpsort_test udp_server test_tou
TESTS += pair_tou reset_tou largefile_tou
#internal_tou
all: librs tests
udpsock_test : $(OBJ) udpsock_test.o
$(CC) $(CFLAGS) -o udpsock_test udpsock_test.o $(OBJ) $(LIBS)
udpsort_test : $(OBJ) udpsort_test.o
$(CC) $(CFLAGS) -o udpsort_test udpsort_test.o $(OBJ) $(LIBS)
udp_server: $(OBJ) udp_server.o
$(CC) $(CFLAGS) -o udp_server udp_server.o $(OBJ) $(LIBS)
test_tou : $(OBJ) test_tou.o
$(CC) $(CFLAGS) -o test_tou test_tou.o $(OBJ) $(LIBS)
pair_tou : $(OBJ) pair_tou.o
$(CC) $(CFLAGS) -o pair_tou pair_tou.o $(OBJ) $(LIBS)
reset_tou : $(OBJ) reset_tou.o
$(CC) $(CFLAGS) -o reset_tou reset_tou.o $(OBJ) $(LIBS)
internal_tou : $(OBJ) internal_tou.o
$(CC) $(CFLAGS) -o internal_tou internal_tou.o $(OBJ) $(LIBS)
largefile_tou : $(OBJ) largefile_tou.o
$(CC) $(CFLAGS) -o largefile_tou largefile_tou.o $(OBJ) $(LIBS)
# Extra Rule for BIOFLAGS
.c.o:
$(BIOCC) $(BIOCFLAGS) -c $<
###############################################################
include $(RS_TOP_DIR)/scripts/rules.mk
###############################################################

View file

@ -1,632 +0,0 @@
/*
* "$Id: internal_tou.cc,v 1.2 2007-02-18 21:46:50 rmf24 Exp $"
*
* TCP-on-UDP (tou) network interface for RetroShare.
*
* Copyright 2004-2006 by Robert Fernie.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 2 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "retroshare@lunamutt.com".
*
*/
/**********************************************************
* There appears (was) to be an elusive bug in the tou internals.
* most likely to be in the packing and unpacking of the
* data queues.
*
* This test is designed to load the queues up and then
* transfer the data, repeatly with different size packets.
*
* to do this effectively we need to access the TcpStream
* objects, instead of the tou.h interface.
*
*/
#include <iostream>
// for printing sockaddr
#include "udplayer.h"
#include "tcpstream.h"
#include "tou.h"
#include "tou_net.h"
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
/* This is a simple test to ensure that the tou behaviour
* is almost identical to a standard tcp socket.
*
* In this version we open 2 sockets, and attempt to
* communicate with ourselves....
*
*/
int setup_socket(struct sockaddr_in addr);
int connect_socket_pair(int fd1, int fd2,
struct sockaddr_in addr1, struct sockaddr_in addr2);
int send_data_via_pair(int sockfd1, int sockfd2, char *data, int size);
void usage(char *name)
{
std::cerr << "Usage: " << name;
std::cerr << " [-pco] <laddr> <lport> ";
std::cerr << " <raddr> <rport> ";
std::cerr << std::endl;
exit(1);
return;
}
int main(int argc, char **argv)
{
int c;
bool isProxy = false;
bool toConnect = false;
bool stayOpen = false;
int i,j;
while(-1 != (c = getopt(argc, argv, "pco")))
{
switch (c)
{
case 'p':
isProxy = true;
break;
case 'c':
toConnect = true;
break;
case 'o':
stayOpen = true;
break;
default:
usage(argv[0]);
break;
}
}
if (argc-optind < 4)
{
usage(argv[0]);
return 1;
}
// tounet_init();
/* setup the local/remote addresses.
*/
struct sockaddr_in laddr;
struct sockaddr_in raddr;
laddr.sin_family = AF_INET;
raddr.sin_family = AF_INET;
if ((!tounet_inet_aton(argv[optind], &(laddr.sin_addr))) ||
(!tounet_inet_aton(argv[optind+2], &(raddr.sin_addr))))
{
std::cerr << "Invalid addresses!" << std::endl;
usage(argv[0]);
}
unsigned short laddr_port = atoi(argv[optind+1]);
unsigned short raddr_port = atoi(argv[optind+3]);
laddr.sin_port = htons(laddr_port);
raddr.sin_port = htons(raddr_port);
/* so create the Udp/Tcp components */
//UdpLayer udp1(laddr);
//UdpLayer udp2(raddr);
LossyUdpLayer udp1(laddr, 0.10);
LossyUdpLayer udp2(raddr, 0.10);
/* check that they are okay */
if ((!udp1.okay()) || (!udp2.okay()))
{
std::cerr << "Trouble opening udp ports!";
std::cerr << std::endl;
return 1;
}
TcpStream tcp1(&udp1);
TcpStream tcp2(&udp2);
udp1.setRemoteAddr(raddr);
udp2.setRemoteAddr(laddr);
tcp1.connect(); // start the connection.
/* now connect them */
while ((!tcp1.isConnected()) || (!tcp2.isConnected()))
{
usleep(10000); /* 10 ms */
tcp1.tick();
tcp2.tick();
}
std::cerr << "Connection Established!" << std::endl;
for(i = 0; i < 10; i++)
{
int size = 1024000;
char rnddata1[size];
char rnddata2[size];
for(j = 0; j < size; j++)
{
rnddata1[j] = (unsigned char) (255.0 *
rand() / (RAND_MAX + 1.0));
rnddata2[j] = (unsigned char) (255.0 *
rand() / (RAND_MAX + 1.0));
}
/* for each iteration, we want to
* (1) fill up the outgoing buffers with stuff
*/
int sent1 = 0;
int sent2 = 0;
int fill1, fill2;
int MaxSend = 1000000;
while((fill1 = tcp1.write_allowed()) && (sent1 < MaxSend))
{
/* fill with a random little bit more */
int psize = (int) ((i + 1.0) * 255.0 *
rand() / (RAND_MAX + 1.0));
/* don't overload */
if (psize > fill1)
{
std::cerr << "LAST FILL1" << std::endl;
psize = fill1;
}
int ret = tcp1.write(&(rnddata1[sent1]), psize);
if (ret)
{
sent1 += ret;
std::cerr << "Filled tcp1 with " << ret << " more bytes, total:";
std::cerr << sent1 << " was allowed: " << fill1;
std::cerr << std::endl;
}
//tcp1.status(std::cerr);
}
std::cerr << "Tcp1 full with " << sent1 << " bytes ";
std::cerr << std::endl;
while((fill2 = tcp2.write_allowed()) && (sent2 < MaxSend))
{
/* fill with a random little bit more */
/* slightly larger sizes */
int psize = (int) ((i + 1.0) * 1255.0 *
rand() / (RAND_MAX + 1.0));
/* don't overload */
if (psize > fill2)
{
std::cerr << "LAST FILL2" << std::endl;
psize = fill2;
}
int ret = tcp2.write(&(rnddata2[sent2]), psize);
if (ret)
{
sent2 += ret;
std::cerr << "Filled tcp2 with " << ret << " more bytes, total:";
std::cerr << sent2 << " was allowed: " << fill2;
std::cerr << std::endl;
}
//tcp2.status(std::cerr);
}
std::cerr << "Tcp2 full with " << sent2 << " bytes ";
std::cerr << std::endl;
/* for every second iteration, fill up the read buffer before starting */
if (i % 2 == 0)
{
for(j = 0; j < 100; j++)
{
tcp1.tick();
tcp2.tick();
}
}
/* now we read/tick and empty */
int read1 = 0;
int read2 = 0;
while(read1 < sent2)
{
tcp1.tick();
tcp2.tick();
/* fill with a random little bit more */
/* This one has a small read, while tcp2 has a large read */
int psize = (int) ((i + 1.0) * 100.0 *
rand() / (RAND_MAX + 1.0));
/* limit to what we have! */
if (psize > sent2 - read1)
{
std::cerr << "LAST READ1" << std::endl;
psize = sent2 - read1;
}
char rbuf[psize];
int rsize = psize;
int ret = tcp1.read(rbuf, rsize);
if (0 < ret)
{
/* check the data */
for(j = 0; j < ret; j++)
{
if (rnddata2[read1 + j] != rbuf[j])
{
std::cerr << "Error Data Mismatch @ read1:" << read1;
std::cerr << " + j:" << j << " rsize: " << rsize;
std::cerr << " Index: " << read1 + j;
std::cerr << std::endl;
int badoffset = read1 + j;
for(int k = -10; k < 10; k++)
{
printf("Orig: %02x, Trans: %02x\n",
(unsigned char) rnddata2[badoffset+k],
(unsigned char) rbuf[j + k]);
}
exit(1);
}
}
read1 += ret;
}
else
{
std::cerr << "Read Error: " << ret << std::endl;
}
std::cerr << "Requested " << psize << ", got " << ret << " bytes" << std::endl;
std::cerr << "Read " << read1 << " of " << sent2 << " bytes" << std::endl;
}
sleep(2);
while(read2 < sent1)
{
tcp1.tick();
tcp2.tick();
/* fill with a random little bit more */
int psize = (int) ((i + 1.0) * 10000.0 *
rand() / (RAND_MAX + 1.0));
/* limit to what we have! */
if (psize > sent1 - read2)
{
std::cerr << "LAST READ2" << std::endl;
psize = sent1 - read2;
}
char rbuf[psize];
int rsize = psize;
int ret = tcp2.read(rbuf, rsize);
if (0 < ret)
{
/* check the data */
for(j = 0; j < ret; j++)
{
if (rnddata1[read2 + j] != rbuf[j])
{
std::cerr << "Error Data Mismatch @ read2:" << read2;
std::cerr << " + j:" << j << " rsize: " << rsize;
std::cerr << " Index: " << read2 + j;
std::cerr << std::endl;
exit(1);
}
}
read2 += ret;
}
else
{
std::cerr << "Read Error: " << ret << std::endl;
}
std::cerr << "Requested " << psize << ", got " << ret << " bytes" << std::endl;
std::cerr << "Read " << read2 << " of " << sent1 << " bytes" << std::endl;
}
std::cerr << "Iteration " << i + 1 << " finished correctly!" << std::endl;
sleep(5);
}
return 1;
}
int setup_socket(struct sockaddr_in addr)
{
int sockfd = tou_socket(PF_INET, SOCK_STREAM, 0);
if (sockfd <= 0)
{
std::cerr << "Failed to open socket!: ";
std::cerr << "Socket Error:" << tou_errno(sockfd) << std::endl;
return -1;
}
std::cerr << "Socket Created: " << sockfd << std::endl;
int err = tou_bind(sockfd, (struct sockaddr *) &addr, sizeof(addr));
if (err < 0)
{
std::cerr << "Error: Cannot bind socket: ";
std::cerr << err << std::endl;
return -1;
}
std::cerr << "Socket1 Bound to: " << addr << std::endl;
return sockfd;
}
int connect_socket_pair(int fd1, int fd2,
struct sockaddr_in addr1, struct sockaddr_in addr2)
{
std::cerr << "Socket2 Listening " << std::endl;
/* listen */
int err = tou_listenfor(fd2, (struct sockaddr *) &addr1, sizeof(addr1));
int err_num;
if (err < 0)
{
err_num = tou_errno(fd2);
if (err_num != EINPROGRESS)
{
std::cerr << "Cannot Listen!: " << err_num << std::endl;
return -1;
}
}
std::cerr << "Socket1 Connecting to: " << addr2 << std::endl;
err = tou_connect(fd1, (struct sockaddr *) &addr2, sizeof(addr2));
if (err < 0)
{
err_num = tou_errno(fd1);
if (err_num != EINPROGRESS)
{
std::cerr << "Cannot Connect!: " << err_num << std::endl;
return -1;
}
}
bool sock1Connected = false;
bool sock2Connected = false;
while((!sock1Connected) || (!sock2Connected))
{
sleep(1);
/* sock1 */
if((!sock1Connected) && (0 == (err = tou_connected(fd1))))
{
std::cerr << "Waiting for Connect (Sock1)!" << std::endl;
}
if ((!sock1Connected) && (err < 0))
{
std::cerr << "Connect Failed" << std::endl;
return 1;
}
else if (!sock1Connected)
{
// else connected!
sock1Connected = true;
}
/* accept - sock2 */
struct sockaddr_in inaddr;
socklen_t addrlen = sizeof(inaddr);
int nsock = -1;
if ((!sock2Connected) && (0 > (nsock = tou_accept(fd2,
(struct sockaddr *) &inaddr, &addrlen))))
{
errno = tou_errno(fd2);
if (errno != EAGAIN)
{
std::cerr << "Cannot Connect!: " << errno << std::endl;
return 1;
}
else
{
std::cerr << "Waiting for Connect (Sock2)!" << std::endl;
}
}
else if (nsock > 0)
{
/* connected */
sock2Connected = true;
fd2 = nsock;
std::cerr << "Socket Accepted from: " << inaddr << std::endl;
}
}
std::cerr << "Socket Connected" << std::endl;
return 1;
}
/* This transmits into sockfd1, and check to see that we recv
* it back from sockfd2
*/
int send_data_via_pair(int sockfd1, int sockfd2, char *data, int size)
{
/* what we recvd */
char *recvd = (char *) malloc(size * 2);
int recvdsize = 0;
int sent = 0;
int sendsize = 0;
int ts_start = time(NULL);
int minsends = 100; /* min of 100 sends to complete all data */
/* ensure we don't end up sending nothing */
if (minsends * 10 > size)
{
minsends = size / 10;
}
bool doneWrite = false;
bool doneRead = false;
while((!doneWrite) || (!doneRead))
{
/* have a little break */
//usleep(10000); /* 0.01 sec */
//usleep(250000); /* 0.25 sec */
usleep(500000); /* 0.50 sec */
/* decide how much to send */
sendsize = (int) (((float) (size / minsends)) *
(rand() / (RAND_MAX + 1.0)));
/* limit send */
if (sent + sendsize > size)
{
sendsize = size - sent;
}
/* if we've finished */
if (sent == size)
{
/* eof */
std::cerr << "Write Done!" << std::endl;
doneWrite = true;
sendsize = 0;
}
/* now we write */
if ((sendsize > 0)&&(-1==tou_write(sockfd1,&(data[sent]),sendsize)))
{
std::cerr << "Write Error: " << tou_errno(sockfd1) << std::endl;
if (tou_errno(sockfd1) != EAGAIN)
{
std::cerr << "FATAL ERROR ending transfer" << std::endl;
doneRead = true;
doneWrite = true;
}
}
else
{
sent += sendsize;
}
int ret = 0;
int readsize = (int) (((float) (size / minsends)) *
(rand() / (RAND_MAX + 1.0)));
if (readsize > size - recvdsize)
readsize = size - recvdsize;
if (0 < (ret = tou_read(sockfd2, &(recvd[recvdsize]), readsize)))
{
std::cerr << "TF(" << ret << ")" << std::endl;
recvdsize += ret;
}
else if (ret == 0)
{
doneRead = true;
std::cerr << "Read Done! (ret:0)" << std::endl;
}
else
{
std::cerr << "Read Error: " << tou_errno(sockfd2) << std::endl;
std::cerr << "Read " << recvdsize << "/" << size;
std::cerr << " attempted: " << readsize << std::endl;
if (tou_errno(sockfd2) != EAGAIN)
{
std::cerr << "FATAL ERROR ending transfer" << std::endl;
doneRead = true;
doneWrite = true;
}
}
if (recvdsize == size)
{
doneRead = true;
std::cerr << "Read Done!" << std::endl;
}
}
/* we have transmitted it all, so
* check the data
*/
int i;
int diffCount = 0;
for(i = 0; i < size; i++)
{
if (recvd[i] != data[i])
{
diffCount++;
if (diffCount < 10)
{
std::cerr << "Error Byte:" << i << " is different";
std::cerr << std::endl;
}
}
}
if (diffCount)
{
std::cerr << "Errors (" << diffCount << "/" << size << ") in tranmission ... Exiting!";
std::cerr << std::endl;
exit(1);
}
int ts_end = time(NULL);
double rough_rate = size / (double) (ts_end - ts_start);
std::cerr << "Successful Data Tranmission: " << size << " in " << ts_end-ts_start << " secs";
std::cerr << std::endl;
std::cerr << "Approximate Rate: " << rough_rate / 1000.0 << " kbytes/sec";
std::cerr << std::endl;
return 1;
}

View file

@ -1,502 +0,0 @@
/*
* "$Id: largefile_tou.cc,v 1.2 2007-02-18 21:46:50 rmf24 Exp $"
*
* TCP-on-UDP (tou) network interface for RetroShare.
*
* Copyright 2004-2006 by Robert Fernie.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 2 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "retroshare@lunamutt.com".
*
*/
/**********************************************************
* This test is designed to test large data blocks/files
* running to tou. Currently we see occasional errors
* every 1/2 -> 1 MB of transfer....
*
* This test will continually fill the output buffer,
* and then empty the receive one. To ensure the
* whole system gets a good workout.
*
*/
#include <iostream>
// for printing sockaddr
#include "udplayer.h"
#include "tou.h"
#include "tou_net.h"
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
int setup_socket(struct sockaddr_in addr);
int connect_socket_pair(int fd1, int fd2,
struct sockaddr_in addr1, struct sockaddr_in addr2);
int send_data_via_pair(int sockfd1, int sockfd2, char *data, int size);
void usage(char *name)
{
std::cerr << "Usage: " << name;
std::cerr << " [-pco] <laddr> <lport> ";
std::cerr << " <raddr> <rport> ";
std::cerr << std::endl;
exit(1);
return;
}
int main(int argc, char **argv)
{
int c;
bool isProxy = false;
bool toConnect = false;
bool stayOpen = false;
int i,j;
while(-1 != (c = getopt(argc, argv, "pco")))
{
switch (c)
{
case 'p':
isProxy = true;
break;
case 'c':
toConnect = true;
break;
case 'o':
stayOpen = true;
break;
default:
usage(argv[0]);
break;
}
}
if (argc-optind < 4)
{
usage(argv[0]);
return 1;
}
tounet_init();
/* setup the local/remote addresses.
*/
struct sockaddr_in laddr;
struct sockaddr_in raddr;
laddr.sin_family = AF_INET;
raddr.sin_family = AF_INET;
if ((!tounet_inet_aton(argv[optind], &(laddr.sin_addr))) ||
(!tounet_inet_aton(argv[optind+2], &(raddr.sin_addr))))
{
std::cerr << "Invalid addresses!" << std::endl;
usage(argv[0]);
}
unsigned short laddr_port = atoi(argv[optind+1]);
unsigned short raddr_port = atoi(argv[optind+3]);
for(i = 0; i < 10; i++)
{
laddr.sin_port = htons(laddr_port);
raddr.sin_port = htons(raddr_port);
//laddr.sin_port = htons(laddr_port + i);
//raddr.sin_port = htons(raddr_port + i);
std::cerr << "Interation: " << i << std::endl;
/* setup the sockets */
int sockfd1 = setup_socket(laddr);
int sockfd2 = setup_socket(raddr);
if ((sockfd1 < 0) || (sockfd2 < 0))
{
std::cerr << "Failed to setup sockets!";
std::cerr << std::endl;
return -1;
}
std::cerr << "Local Address: " << laddr;
std::cerr << " fd: " << sockfd1 << std::endl;
std::cerr << "Remote Address: " << raddr;
std::cerr << " fd: " << sockfd2 << std::endl;
/* connect */
int err = connect_socket_pair(sockfd1, sockfd2, laddr, raddr);
if (err < 0)
{
std::cerr << "Failed to connect sockets!";
std::cerr << std::endl;
return -1;
}
/* send the data */
int size = 3093237;
char rnddata[size];
int data_loops = (i+1) * (i+1);
for(int k = 0; k < data_loops; k++)
{
std::cerr << "Send Iteration: " << k+1 << " of " << data_loops << std::endl;
for(j = 0; j < size; j++)
{
rnddata[j] = (unsigned char) (255.0 *
rand() / (RAND_MAX + 1.0));
}
send_data_via_pair(sockfd1, sockfd2, rnddata, size);
std::cerr << "Send Iteration: " << k+1 << " of " << data_loops << std::endl;
sleep(2);
}
std::cerr << "Completed Successful transfer of " << size * data_loops << " bytes";
std::cerr << std::endl;
sleep(10);
std::cerr << "closing sockfd1: " << sockfd1 << std::endl;
tou_close(sockfd1);
std::cerr << "closing sockfd2: " << sockfd2 << std::endl;
tou_close(sockfd2);
}
return 1;
}
int setup_socket(struct sockaddr_in addr)
{
int sockfd = tou_socket(PF_INET, SOCK_STREAM, 0);
if (sockfd <= 0)
{
std::cerr << "Failed to open socket!: ";
std::cerr << "Socket Error:" << tou_errno(sockfd) << std::endl;
return -1;
}
std::cerr << "Socket Created: " << sockfd << std::endl;
int err = tou_bind(sockfd, (struct sockaddr *) &addr, sizeof(addr));
if (err < 0)
{
std::cerr << "Error: Cannot bind socket: ";
std::cerr << err << std::endl;
return -1;
}
std::cerr << "Socket1 Bound to: " << addr << std::endl;
return sockfd;
}
int connect_socket_pair(int fd1, int fd2,
struct sockaddr_in addr1, struct sockaddr_in addr2)
{
std::cerr << "Socket2 Listening " << std::endl;
/* listen */
int err = tou_listenfor(fd2, (struct sockaddr *) &addr1, sizeof(addr1));
int err_num;
if (err < 0)
{
err_num = tou_errno(fd2);
if (err_num != EINPROGRESS)
{
std::cerr << "Cannot Listen!: " << err_num << std::endl;
return -1;
}
}
std::cerr << "Socket1 Connecting to: " << addr2 << std::endl;
err = tou_connect(fd1, (struct sockaddr *) &addr2, sizeof(addr2), 30);
if (err < 0)
{
err_num = tou_errno(fd1);
if (err_num != EINPROGRESS)
{
std::cerr << "Cannot Connect!: " << err_num << std::endl;
return -1;
}
}
bool sock1Connected = false;
bool sock2Connected = false;
while((!sock1Connected) || (!sock2Connected))
{
sleep(1);
/* sock1 */
if((!sock1Connected) && (0 == (err = tou_connected(fd1))))
{
std::cerr << "Waiting for Connect (Sock1)!" << std::endl;
}
if ((!sock1Connected) && (err < 0))
{
std::cerr << "Connect Failed" << std::endl;
return 1;
}
else if (!sock1Connected)
{
// else connected!
sock1Connected = true;
}
/* accept - sock2 */
struct sockaddr_in inaddr;
socklen_t addrlen = sizeof(inaddr);
int nsock = -1;
if ((!sock2Connected) && (0 > (nsock = tou_accept(fd2,
(struct sockaddr *) &inaddr, &addrlen))))
{
errno = tou_errno(fd2);
if (errno != EAGAIN)
{
std::cerr << "Cannot Connect!: " << errno << std::endl;
return 1;
}
else
{
std::cerr << "Waiting for Connect (Sock2)!" << std::endl;
}
}
else if (nsock > 0)
{
/* connected */
sock2Connected = true;
fd2 = nsock;
std::cerr << "Socket Accepted from: " << inaddr << std::endl;
}
}
std::cerr << "Socket Connected" << std::endl;
return 1;
}
/* This transmits into sockfd1, and check to see that we recv
* it back from sockfd2
*/
int send_data_via_pair(int sockfd1, int sockfd2, char *data, int size)
{
/* what we recvd */
char *recvd = (char *) malloc(size * 2);
int recvdsize = 0;
int sent = 0;
int sendsize = 0;
int ts_start = time(NULL);
int minsends = 100; /* min of 100 sends to complete all data */
/* ensure we don't end up sending nothing */
if (minsends * 10 > size)
{
minsends = size / 10;
}
bool doneWrite = false;
bool doneRead = false;
int maxtransfer = (int) (size / minsends) + (int) (((float) (size / minsends)) *
(rand() / (RAND_MAX + 1.0)));
/* allow the transfer ratio read/write to vary between 0.4->1,5. */
double tf_ratio = 0.4 + 1.1 * (rand() / (RAND_MAX + 1.0));
while((!doneWrite) || (!doneRead))
{
/* have a little break */
//usleep(10000); /* 0.01 sec */
usleep(20000); /* 0.02 sec */
//usleep(250000); /* 0.25 sec */
//usleep(500000); /* 0.50 sec */
/* decide how much to send */
sendsize = (int) (((float) (maxtransfer)) *
(rand() / (RAND_MAX + 1.0)));
/* limit send */
if (sent + sendsize > size)
{
std::cerr << "Last WRITE!" << std::endl;
sendsize = size - sent;
}
/* if we've finished */
if (sent == size)
{
/* eof */
std::cerr << "Write Done!" << std::endl;
doneWrite = true;
sendsize = 0;
}
/* now we write */
if ((sendsize > 0)&&(-1==tou_write(sockfd1,&(data[sent]),sendsize)))
{
std::cerr << "Write Error: " << tou_errno(sockfd1) << std::endl;
if (tou_errno(sockfd1) != EAGAIN)
{
std::cerr << "FATAL ERROR ending transfer" << std::endl;
doneRead = true;
doneWrite = true;
}
}
else
{
sent += sendsize;
}
int ret = 0;
// read size about 1/4 of write to exercise the buffers.
int readsize = (int) (((float) (maxtransfer)) * tf_ratio *
(rand() / (RAND_MAX + 1.0)));
if (readsize > size - recvdsize)
{
std::cerr << "Last READ!" << std::endl;
readsize = size - recvdsize;
}
if (0 < (ret = tou_read(sockfd2, &(recvd[recvdsize]), readsize)))
{
std::cerr << "TF(" << ret << ")" << std::endl;
/* check the data at this point */
int i;
int diffCount = 0;
int init_err = 0;
for(i = 0; i < ret; i++)
{
if (recvd[recvdsize + i] != data[recvdsize + i])
{
if (!diffCount)
{
init_err = i;
}
diffCount++;
if (diffCount < 10)
{
std::cerr << "Error Byte:" << recvdsize + i << " is different";
std::cerr << std::endl;
}
}
}
if (diffCount)
{
std::cerr << "Errors (" << diffCount << "/" << ret << ") in read, ";
std::cerr << std::endl;
std::cerr << " At Blk Start: " << recvdsize << " offset: " << init_err;
std::cerr << " ==> At index: " << recvdsize + init_err << "... Exiting!";
std::cerr << std::endl;
exit(1);
}
else
{
std::cerr << "Checked (" << recvdsize << "+ 0 => " << ret << ") Okay" << std::endl;
}
recvdsize += ret;
}
else if (ret == 0)
{
//doneRead = true;
std::cerr << "Read Done? (ret:0)" << std::endl;
}
else
{
std::cerr << "Read Error: " << tou_errno(sockfd2) << std::endl;
std::cerr << "Read " << recvdsize << "/" << size;
std::cerr << " attempted: " << readsize << std::endl;
if (tou_errno(sockfd2) != EAGAIN)
{
std::cerr << "FATAL ERROR ending transfer" << std::endl;
doneRead = true;
doneWrite = true;
}
}
if (recvdsize == size)
{
doneRead = true;
std::cerr << "Read Done!" << std::endl;
}
}
/* we have transmitted it all, so
* check the data
*/
int i;
int diffCount = 0;
for(i = 0; i < size; i++)
{
if (recvd[i] != data[i])
{
diffCount++;
if (diffCount < 10)
{
std::cerr << "Error Byte:" << i << " is different";
std::cerr << std::endl;
}
}
}
if (diffCount)
{
std::cerr << "Errors (" << diffCount << "/" << size << ") in tranmission ... Exiting!";
std::cerr << std::endl;
exit(1);
}
int ts_end = time(NULL);
double rough_rate = size / (double) (ts_end - ts_start);
std::cerr << "Successful Data Tranmission: " << size << " in " << ts_end-ts_start << " secs";
std::cerr << std::endl;
std::cerr << "Approximate Rate: " << rough_rate / 1000.0 << " kbytes/sec";
std::cerr << std::endl;
std::cerr << "Transfer Ratio: " << tf_ratio;
std::cerr << std::endl;
free(recvd);
return 1;
}

View file

@ -1,491 +0,0 @@
/*
* "$Id: pair_tou.cc,v 1.3 2007-02-18 21:46:50 rmf24 Exp $"
*
* TCP-on-UDP (tou) network interface for RetroShare.
*
* Copyright 2004-2006 by Robert Fernie.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 2 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "retroshare@lunamutt.com".
*
*/
#include <iostream>
//#define USE_TCP_SOCKET
// for printing sockaddr
#include "udplayer.h"
#ifndef USE_TCP_SOCKET
#include "tou.h"
#endif
#include "tou_net.h"
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
/* This is a simple test to ensure that the tou behaviour
* is almost identical to a standard tcp socket.
*
* In this version we open 2 sockets, and attempt to
* communicate with ourselves....
*
*/
int Check_Socket(int fd);
void usage(char *name)
{
std::cerr << "Usage: " << name;
std::cerr << " [-pco] <laddr> <lport> ";
std::cerr << " <raddr> <rport> ";
std::cerr << std::endl;
exit(1);
return;
}
int main(int argc, char **argv)
{
int c;
bool isProxy = false;
bool toConnect = false;
bool stayOpen = false;
int totalwbytes = 0;
int totalrbytes = 0;
while(-1 != (c = getopt(argc, argv, "pco")))
{
switch (c)
{
case 'p':
isProxy = true;
break;
case 'c':
toConnect = true;
break;
case 'o':
stayOpen = true;
break;
default:
usage(argv[0]);
break;
}
}
if (argc-optind < 4)
{
usage(argv[0]);
return 1;
}
tounet_init();
/* setup the local/remote addresses.
*/
struct sockaddr_in laddr;
struct sockaddr_in raddr;
laddr.sin_family = AF_INET;
raddr.sin_family = AF_INET;
if ((!tounet_inet_aton(argv[optind], &(laddr.sin_addr))) ||
(!tounet_inet_aton(argv[optind+2], &(raddr.sin_addr))))
{
std::cerr << "Invalid addresses!" << std::endl;
usage(argv[0]);
}
laddr.sin_port = htons(atoi(argv[optind+1]));
raddr.sin_port = htons(atoi(argv[optind+3]));
std::cerr << "Local Address: " << laddr << std::endl;
std::cerr << "Remote Address: " << raddr << std::endl;
#ifdef USE_TCP_SOCKET
int sockfd = socket(PF_INET, SOCK_STREAM, 0);
int sockfd2 = socket(PF_INET, SOCK_STREAM, 0);
#else
int sockfd = tou_socket(PF_INET, SOCK_STREAM, 0);
int sockfd2 = tou_socket(PF_INET, SOCK_STREAM, 0);
#endif
if ((sockfd <= 0) || (sockfd2 <= 0))
{
std::cerr << "Failed to open socket!: ";
#ifdef USE_TCP_SOCKET
std::cerr << "Socket Error:" << errno << std::endl;
#else
std::cerr << "Socket Error:" << tou_errno(sockfd) << std::endl;
std::cerr << "Socket Error:" << tou_errno(sockfd2) << std::endl;
#endif
return -1;
}
std::cerr << "Sockets Created: " << sockfd << " & " << sockfd2 << std::endl;
/* make nonblocking */
#ifdef USE_TCP_SOCKET
int err = fcntl(sockfd,F_SETFD,O_NONBLOCK);
int err2 = fcntl(sockfd2,F_SETFD,O_NONBLOCK);
#else
int err = 0;
int err2 = 0;
#endif
if ((err < 0) || (err2 < 0))
{
std::cerr << "Error: Cannot make socket NON-Blocking: ";
std::cerr << err << std::endl;
return -1;
}
std::cerr << "Socket Non-Blocking" << std::endl;
#ifdef USE_TCP_SOCKET
err = bind(sockfd, (struct sockaddr *) &laddr, sizeof(laddr));
err2 = bind(sockfd2, (struct sockaddr *) &raddr, sizeof(raddr));
#else
err = tou_bind(sockfd, (struct sockaddr *) &laddr, sizeof(laddr));
err2 = tou_bind(sockfd2, (struct sockaddr *) &raddr, sizeof(raddr));
#endif
if ((err < 0) || (err2 < 0))
{
std::cerr << "Error: Cannot bind socket: ";
std::cerr << err << std::endl;
return -1;
}
std::cerr << "Socket1 Bound to: " << laddr << std::endl;
std::cerr << "Socket2 Bound to: " << raddr << std::endl;
// listening.
if (1) // socket2.
{
std::cerr << "Socket2 Listening " << std::endl;
/* listen */
#ifdef USE_TCP_SOCKET
err = listen(sockfd2, 1);
#else
err = tou_listenfor(sockfd2,
(struct sockaddr *) &laddr, sizeof(laddr));
#endif
}
if (1) // only one program.
{
std::cerr << "Socket1 Connecting to: " << raddr << std::endl;
#ifdef USE_TCP_SOCKET
err = connect(sockfd, (struct sockaddr *) &raddr, sizeof(raddr));
#else
err = tou_connect(sockfd, (struct sockaddr *) &raddr, sizeof(raddr), 30);
#endif
if (err < 0)
{
#ifndef USE_TCP_SOCKET
errno = tou_errno(sockfd);
#endif
if (errno != EINPROGRESS)
{
std::cerr << "Cannot Connect!: " << errno << std::endl;
return 1;
}
}
}
bool sock1Connected = false;
bool sock2Connected = false;
while((!sock1Connected) || (!sock2Connected))
{
sleep(1);
/* sock1 */
#ifdef USE_TCP_SOCKET
if((!sock1Connected) && (0 == (err = Check_Socket(sockfd))))
#else
if((!sock1Connected) && (0 == (err = tou_connected(sockfd))))
#endif
{
std::cerr << "Waiting for Connect (Sock1)!" << std::endl;
}
if ((!sock1Connected) && (err < 0))
{
std::cerr << "Connect Failed" << std::endl;
return 1;
}
else if (!sock1Connected)
{
// else connected!
sock1Connected = true;
}
/* accept - sock2 */
struct sockaddr_in inaddr;
socklen_t addrlen = sizeof(inaddr);
int nsock = -1;
#ifdef USE_TCP_SOCKET
if ((!sock2Connected) && (0 > (nsock = accept(sockfd2,
(struct sockaddr *) &inaddr, &addrlen))))
#else
if ((!sock2Connected) && (0 > (nsock = tou_accept(sockfd2,
(struct sockaddr *) &inaddr, &addrlen))))
#endif
{
#ifndef USE_TCP_SOCKET
errno = tou_errno(sockfd2);
#endif
if (errno != EAGAIN)
{
std::cerr << "Cannot Connect!: " << errno << std::endl;
return 1;
}
else
{
std::cerr << "Waiting for Connect (Sock2)!" << std::endl;
}
}
else if (nsock > 0)
{
/* connected */
sock2Connected = true;
sockfd2 = nsock;
std::cerr << "Socket Accepted from: " << inaddr << std::endl;
}
}
std::cerr << "Socket Connected" << std::endl;
/* send data */
int bufsize = 1511;
char buffer[bufsize];
char data[bufsize];
int readsize = 0;
tounet_fcntl(0, F_SETFL, O_NONBLOCK);
tounet_fcntl(1,F_SETFL,O_NONBLOCK);
bool doneWrite = false;
bool doneRead = false;
bool blockread = false;
while((!doneWrite) || (!doneRead))
{
/* read -> write_socket... */
sleep(1);
if (blockread != true)
{
readsize = read(0, buffer, bufsize);
}
if (readsize == 0)
{
/* eof */
doneWrite = true;
}
/* now we write */
#ifdef USE_TCP_SOCKET
if ((readsize > 0) && (-1 == write(sockfd, buffer, readsize)))
#else
if ((readsize > 0) && (-1 == tou_write(sockfd, buffer, readsize)))
#endif
{
//std::cerr << "Blocked Write!" << std::endl;
#ifndef USE_TCP_SOCKET
//std::cerr << "Error: " << tou_errno(sockfd) << std::endl;
#endif
blockread = true;
}
else
{
blockread = false;
totalwbytes += readsize;
}
int ret = 0;
#ifdef USE_TCP_SOCKET
if (0 < (ret = read(sockfd2, data, bufsize)))
#else
if (0 < (ret = tou_read(sockfd2, data, bufsize)))
#endif
{
std::cerr << "TF(" << ret << ")" << std::endl;
write(1, data, ret);
totalrbytes += ret;
}
else if (ret == 0)
{
doneRead = true;
}
else
{
//std::cerr << "Blocked Read!" << std::endl;
#ifndef USE_TCP_SOCKET
//std::cerr << "Error: " << tou_errno(sockfd) << std::endl;
#endif
}
}
#ifdef USE_TCP_SOCKET
close(sockfd);
close(sockfd2);
#else
/* this is blocking??? */
tou_close(sockfd);
tou_close(sockfd2);
#endif
std::cerr << "Transfer Complete: " << totalwbytes << " bytes";
std::cerr << std::endl;
return 1;
}
#ifdef USE_TCP_SOCKET
int Check_Socket(int fd)
{
std::cerr << "Check_Socket()" << std::endl;
std::cerr << "1) Checking with Select()" << std::endl;
fd_set ReadFDs, WriteFDs, ExceptFDs;
FD_ZERO(&ReadFDs);
FD_ZERO(&WriteFDs);
FD_ZERO(&ExceptFDs);
FD_SET(fd, &ReadFDs);
FD_SET(fd, &WriteFDs);
FD_SET(fd, &ExceptFDs);
struct timeval timeout;
timeout.tv_sec = 0;
timeout.tv_usec = 0;
int sr = 0;
if (0 > (sr = select(fd + 1,
&ReadFDs, &WriteFDs, &ExceptFDs, &timeout)))
{
std::cerr << "Check_Socket() Select ERROR: " << sr << std::endl;
return -1;
}
if (FD_ISSET(fd, &ExceptFDs))
{
std::cerr << "Check_Socket() Exception on socket!" << std::endl;
return -1;
}
if (FD_ISSET(fd, &WriteFDs))
{
std::cerr << "Check_Socket() Can Write!" << std::endl;
}
else
{
// not ready return 0;
std::cerr << "Check_Socket() Cannot Write!" << std::endl;
std::cerr << "Check_Socket() Socket Not Ready!" << std::endl;
return 0;
}
if (FD_ISSET(fd, &ReadFDs))
{
std::cerr << "Check_Socket() Can Read!" << std::endl;
}
else
{
std::cerr << "Check_Socket() Cannot Read!" << std::endl;
std::cerr << "Check_Socket() Socket Not Ready!" << std::endl;
return 0;
}
std::cerr << "Select() Tests indicate Socket Good!" << std::endl;
std::cerr << "2) Checking with getsockopt()" << std::endl;
int err = 1;
socklen_t optlen = 4;
if (0==getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &optlen))
{
std::cerr << "Check_Socket() getsockopt returned :" << err;
std::cerr << ", optlen:" << optlen;
std::cerr << std::endl;
if (err == 0)
{
std::cerr << "Check_Socket() getsockopt";
std::cerr << " Indicates TCP Connection Complete:";
std::cerr << std::endl;
return 1;
}
else if (err == EINPROGRESS)
{
std::cerr << "Check_Socket() getsockopt";
std::cerr << " Indicates TCP Connection INPROGRESS";
std::cerr << std::endl;
return 0;
}
else if ((err == ENETUNREACH) || (err == ETIMEDOUT))
{
std::cerr << "Check_Socket() getsockopt";
std::cerr << " Indicates TCP Connection ENETUNREACH/ETIMEDOUT";
std::cerr << std::endl;
return -1;
}
else if ((err == EHOSTUNREACH) || (err == EHOSTDOWN))
{
std::cerr << "Check_Socket() getsockopt";
std::cerr << " Indicates TCP Connection ENETUNREACH/ETIMEDOUT";
std::cerr << std::endl;
return -1;
}
else
{
std::cerr << "Check_Socket() getsockopt";
std::cerr << " Indicates Other Error: " << err;
std::cerr << std::endl;
return -1;
}
}
else
{
std::cerr << "Check_Socket() getsockopt";
std::cerr << " FAILED ";
std::cerr << std::endl;
return -1;
}
}
#else
int Check_Socket(int fd)
{
return 0;
}
#endif

View file

@ -1,453 +0,0 @@
/*
* "$Id: reset_tou.cc,v 1.4 2007-02-18 21:46:50 rmf24 Exp $"
*
* TCP-on-UDP (tou) network interface for RetroShare.
*
* Copyright 2004-2006 by Robert Fernie.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 2 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "retroshare@lunamutt.com".
*
*/
/**********************************************************
* This test is designed to ensure that tou networking
* can be reset, and restarted.
*
*/
#include <iostream>
// for printing sockaddr
#include "udplayer.h"
#include "tou.h"
#include "tou_net.h"
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
/* This is a simple test to ensure that the tou behaviour
* is almost identical to a standard tcp socket.
*
* In this version we open 2 sockets, and attempt to
* communicate with ourselves....
*
*/
int setup_socket(struct sockaddr_in addr);
int connect_socket_pair(int fd1, int fd2,
struct sockaddr_in addr1, struct sockaddr_in addr2);
int send_data_via_pair(int sockfd1, int sockfd2, char *data, int size);
void usage(char *name)
{
std::cerr << "Usage: " << name;
std::cerr << " [-pco] <laddr> <lport> ";
std::cerr << " <raddr> <rport> ";
std::cerr << std::endl;
exit(1);
return;
}
int main(int argc, char **argv)
{
int c;
bool isProxy = false;
bool toConnect = false;
bool stayOpen = false;
int i,j;
while(-1 != (c = getopt(argc, argv, "pco")))
{
switch (c)
{
case 'p':
isProxy = true;
break;
case 'c':
toConnect = true;
break;
case 'o':
stayOpen = true;
break;
default:
usage(argv[0]);
break;
}
}
if (argc-optind < 4)
{
usage(argv[0]);
return 1;
}
tounet_init();
/* setup the local/remote addresses.
*/
struct sockaddr_in laddr;
struct sockaddr_in raddr;
laddr.sin_family = AF_INET;
raddr.sin_family = AF_INET;
if ((!tounet_inet_aton(argv[optind], &(laddr.sin_addr))) ||
(!tounet_inet_aton(argv[optind+2], &(raddr.sin_addr))))
{
std::cerr << "Invalid addresses!" << std::endl;
usage(argv[0]);
}
unsigned short laddr_port = atoi(argv[optind+1]);
unsigned short raddr_port = atoi(argv[optind+3]);
for(i = 0; i < 10; i++)
{
laddr.sin_port = htons(laddr_port);
raddr.sin_port = htons(raddr_port);
//laddr.sin_port = htons(laddr_port + i);
//raddr.sin_port = htons(raddr_port + i);
std::cerr << "Interation: " << i << std::endl;
/* setup the sockets */
int sockfd1 = setup_socket(laddr);
int sockfd2 = setup_socket(raddr);
if ((sockfd1 < 0) || (sockfd2 < 0))
{
std::cerr << "Failed to setup sockets!";
std::cerr << std::endl;
return -1;
}
std::cerr << "Local Address: " << laddr;
std::cerr << " fd: " << sockfd1 << std::endl;
std::cerr << "Remote Address: " << raddr;
std::cerr << " fd: " << sockfd2 << std::endl;
/* connect */
int err = connect_socket_pair(sockfd1, sockfd2, laddr, raddr);
if (err < 0)
{
std::cerr << "Failed to connect sockets!";
std::cerr << std::endl;
return -1;
}
/* send the data */
int size = 102400;
char rnddata[size];
int data_loops = (i+1) * (i+1);
for(int k = 0; k < data_loops; k++)
{
std::cerr << "Send Iteration: " << k+1 << " of " << data_loops << std::endl;
for(j = 0; j < size; j++)
{
rnddata[j] = (unsigned char) (255.0 *
rand() / (RAND_MAX + 1.0));
}
send_data_via_pair(sockfd1, sockfd2, rnddata, size);
std::cerr << "Send Iteration: " << k+1 << " of " << data_loops << std::endl;
sleep(2);
}
std::cerr << "Completed Successful transfer of " << size * data_loops << " bytes";
std::cerr << std::endl;
sleep(10);
std::cerr << "closing sockfd1: " << sockfd1 << std::endl;
tou_close(sockfd1);
std::cerr << "closing sockfd2: " << sockfd2 << std::endl;
tou_close(sockfd2);
}
return 1;
}
int setup_socket(struct sockaddr_in addr)
{
int sockfd = tou_socket(PF_INET, SOCK_STREAM, 0);
if (sockfd <= 0)
{
std::cerr << "Failed to open socket!: ";
std::cerr << "Socket Error:" << tou_errno(sockfd) << std::endl;
return -1;
}
std::cerr << "Socket Created: " << sockfd << std::endl;
int err = tou_bind(sockfd, (struct sockaddr *) &addr, sizeof(addr));
if (err < 0)
{
std::cerr << "Error: Cannot bind socket: ";
std::cerr << err << std::endl;
return -1;
}
std::cerr << "Socket1 Bound to: " << addr << std::endl;
return sockfd;
}
int connect_socket_pair(int fd1, int fd2,
struct sockaddr_in addr1, struct sockaddr_in addr2)
{
std::cerr << "Socket2 Listening " << std::endl;
/* listen */
int err = tou_listenfor(fd2, (struct sockaddr *) &addr1, sizeof(addr1));
int err_num;
if (err < 0)
{
err_num = tou_errno(fd2);
if (err_num != EINPROGRESS)
{
std::cerr << "Cannot Listen!: " << err_num << std::endl;
return -1;
}
}
std::cerr << "Socket1 Connecting to: " << addr2 << std::endl;
err = tou_connect(fd1, (struct sockaddr *) &addr2, sizeof(addr2), 30);
if (err < 0)
{
err_num = tou_errno(fd1);
if (err_num != EINPROGRESS)
{
std::cerr << "Cannot Connect!: " << err_num << std::endl;
return -1;
}
}
bool sock1Connected = false;
bool sock2Connected = false;
while((!sock1Connected) || (!sock2Connected))
{
sleep(1);
/* sock1 */
if((!sock1Connected) && (0 == (err = tou_connected(fd1))))
{
std::cerr << "Waiting for Connect (Sock1)!" << std::endl;
}
if ((!sock1Connected) && (err < 0))
{
std::cerr << "Connect Failed" << std::endl;
return 1;
}
else if (!sock1Connected)
{
// else connected!
sock1Connected = true;
}
/* accept - sock2 */
struct sockaddr_in inaddr;
socklen_t addrlen = sizeof(inaddr);
int nsock = -1;
if ((!sock2Connected) && (0 > (nsock = tou_accept(fd2,
(struct sockaddr *) &inaddr, &addrlen))))
{
errno = tou_errno(fd2);
if (errno != EAGAIN)
{
std::cerr << "Cannot Connect!: " << errno << std::endl;
return 1;
}
else
{
std::cerr << "Waiting for Connect (Sock2)!" << std::endl;
}
}
else if (nsock > 0)
{
/* connected */
sock2Connected = true;
fd2 = nsock;
std::cerr << "Socket Accepted from: " << inaddr << std::endl;
}
}
std::cerr << "Socket Connected" << std::endl;
return 1;
}
/* This transmits into sockfd1, and check to see that we recv
* it back from sockfd2
*/
int send_data_via_pair(int sockfd1, int sockfd2, char *data, int size)
{
/* what we recvd */
char *recvd = (char *) malloc(size * 2);
int recvdsize = 0;
int sent = 0;
int sendsize = 0;
int ts_start = time(NULL);
int minsends = 100; /* min of 100 sends to complete all data */
/* ensure we don't end up sending nothing */
if (minsends * 10 > size)
{
minsends = size / 10;
}
bool doneWrite = false;
bool doneRead = false;
while((!doneWrite) || (!doneRead))
{
/* have a little break */
//usleep(10000); /* 0.01 sec */
//usleep(250000); /* 0.25 sec */
usleep(500000); /* 0.50 sec */
/* decide how much to send */
sendsize = (int) (((float) (size / minsends)) *
(rand() / (RAND_MAX + 1.0)));
/* limit send */
if (sent + sendsize > size)
{
sendsize = size - sent;
}
/* if we've finished */
if (sent == size)
{
/* eof */
std::cerr << "Write Done!" << std::endl;
doneWrite = true;
sendsize = 0;
}
/* now we write */
if ((sendsize > 0)&&(-1==tou_write(sockfd1,&(data[sent]),sendsize)))
{
std::cerr << "Write Error: " << tou_errno(sockfd1) << std::endl;
if (tou_errno(sockfd1) != EAGAIN)
{
std::cerr << "FATAL ERROR ending transfer" << std::endl;
doneRead = true;
doneWrite = true;
}
}
else
{
sent += sendsize;
}
int ret = 0;
int readsize = (int) (((float) (size / minsends)) *
(rand() / (RAND_MAX + 1.0)));
if (readsize > size - recvdsize)
readsize = size - recvdsize;
if (0 < (ret = tou_read(sockfd2, &(recvd[recvdsize]), readsize)))
{
std::cerr << "TF(" << ret << ")" << std::endl;
recvdsize += ret;
}
else if (ret == 0)
{
doneRead = true;
std::cerr << "Read Done! (ret:0)" << std::endl;
}
else
{
std::cerr << "Read Error: " << tou_errno(sockfd2) << std::endl;
std::cerr << "Read " << recvdsize << "/" << size;
std::cerr << " attempted: " << readsize << std::endl;
if (tou_errno(sockfd2) != EAGAIN)
{
std::cerr << "FATAL ERROR ending transfer" << std::endl;
doneRead = true;
doneWrite = true;
}
}
if (recvdsize == size)
{
doneRead = true;
std::cerr << "Read Done!" << std::endl;
}
}
/* we have transmitted it all, so
* check the data
*/
int i;
int diffCount = 0;
for(i = 0; i < size; i++)
{
if (recvd[i] != data[i])
{
diffCount++;
if (diffCount < 10)
{
std::cerr << "Error Byte:" << i << " is different";
std::cerr << std::endl;
}
}
}
if (diffCount)
{
std::cerr << "Errors (" << diffCount << "/" << size << ") in tranmission ... Exiting!";
std::cerr << std::endl;
exit(1);
}
int ts_end = time(NULL);
double rough_rate = size / (double) (ts_end - ts_start);
std::cerr << "Successful Data Tranmission: " << size << " in " << ts_end-ts_start << " secs";
std::cerr << std::endl;
std::cerr << "Approximate Rate: " << rough_rate / 1000.0 << " kbytes/sec";
std::cerr << std::endl;
return 1;
}

View file

@ -0,0 +1,70 @@
#ifndef RS_UDP_STACK_RECEIVER_H
#define RS_UDP_STACK_RECEIVER_H
/*
* tcponudp/rsudpstack.h
*
* libretroshare.
*
* Copyright 2010 by Robert Fernie
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 3 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "retroshare@lunamutt.com".
*
*/
/*******************************************************/
#ifdef RS_USE_BITDHT
#include "udp/udpstack.h"
#else
class UdpStack
{
public:
UdpStack(struct sockaddr_in &local) { return; }
/* from pqiNetListener */
virtual bool resetAddress(struct sockaddr_in &local) { return false; }
};
#endif
/*******************************************************/
#include "pqi/pqimonitor.h"
#include <iostream>
class rsUdpStack: public UdpStack, public pqiNetListener
{
public:
rsUdpStack(struct sockaddr_in &local)
:UdpStack(local) { return; }
/* from pqiNetListener */
virtual bool resetListener(struct sockaddr_in &local)
{
std::cerr << "rsUdpStack::resetListener(" << local << ")";
std::cerr << std::endl;
return resetAddress(local);
}
};
#endif

View file

@ -32,7 +32,7 @@
* #include <arpa/inet.h>
*/
#include "tou_net.h" /* for winsock.h -> htons etc */
#include "util/rsnet.h" /* for winsock.h -> htons etc */
#include <stdlib.h>
#include <string.h>

View file

@ -71,7 +71,7 @@ static const double RTT_ALPHA = 0.875;
// platform independent fractional timestamp.
static double getCurrentTS();
TcpStream::TcpStream(UdpSorter *lyr)
TcpStream::TcpStream(UdpPeerReceiver *lyr)
:inSize(0), outSizeRead(0), outSizeNet(0),
state(TCP_CLOSED),
inStreamActive(false),

View file

@ -36,7 +36,7 @@
*/
#include "tcppacket.h"
#include "udpsorter.h"
#include "udppeer.h"
#define MAX_SEG 1500
#define TCP_MAX_SEQ UINT_MAX
@ -73,7 +73,7 @@ class TcpStream: public UdpPeer
public:
/* Top-Level exposed */
TcpStream(UdpSorter *lyr);
TcpStream(UdpPeerReceiver *udp);
virtual ~TcpStream() { return; }
/* user interface */
@ -230,8 +230,8 @@ uint32 int_rbytes();
struct sockaddr_in peeraddr;
bool peerKnown;
/* UdpSorter (has own Mutex!) */
UdpSorter *udp;
/* UdpPeerReceiver (has own Mutex!) */
UdpPeerReceiver *udp;
};

View file

@ -1,500 +0,0 @@
/*
* "$Id: test_tou.cc,v 1.3 2007-02-18 21:46:50 rmf24 Exp $"
*
* TCP-on-UDP (tou) network interface for RetroShare.
*
* Copyright 2004-2006 by Robert Fernie.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 2 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "retroshare@lunamutt.com".
*
*/
#include <iostream>
//#define USE_TCP_SOCKET
// for printing sockaddr
#include "udplayer.h"
#ifndef USE_TCP_SOCKET
#include "tou.h"
#endif
/* shouldn't do this - but for convenience
* using tou_net.h for universal fns
* generally this should be only internal to libtou.h
*
* This includes the whole networking interface
*/
#include "tou_net.h"
/* These three includes appear to work in both W & L.
* and they shouldn't!!!! maybe cygwin is allowing it...
* will only use them for tou test fns.
*
* they appear to provide getopt + read/write in windows.
*/
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
/* This is a simple test to ensure that the tou behaviour
* is almost identical to a standard tcp socket.
*
*/
int Check_Socket(int fd);
void usage(char *name)
{
std::cerr << "Usage: " << name;
std::cerr << " [-pco] <laddr> <lport> ";
std::cerr << " <raddr> <rport> ";
std::cerr << std::endl;
exit(1);
return;
}
int main(int argc, char **argv)
{
int c;
bool isProxy = false;
bool toConnect = false;
bool stayOpen = false;
int totalwbytes = 0;
int totalrbytes = 0;
while(-1 != (c = getopt(argc, argv, "pco")))
{
switch (c)
{
case 'p':
isProxy = true;
break;
case 'c':
toConnect = true;
break;
case 'o':
stayOpen = true;
break;
default:
usage(argv[0]);
break;
}
}
if (argc-optind < 4)
{
usage(argv[0]);
return 1;
}
tounet_init();
/* setup the local/remote addresses.
*/
struct sockaddr_in laddr;
struct sockaddr_in raddr;
laddr.sin_family = AF_INET;
raddr.sin_family = AF_INET;
if ((!tounet_inet_aton(argv[optind], &(laddr.sin_addr))) ||
(!tounet_inet_aton(argv[optind+2], &(raddr.sin_addr))))
{
std::cerr << "Invalid addresses!" << std::endl;
usage(argv[0]);
}
laddr.sin_port = htons(atoi(argv[optind+1]));
raddr.sin_port = htons(atoi(argv[optind+3]));
std::cerr << "Local Address: " << laddr << std::endl;
std::cerr << "Remote Address: " << raddr << std::endl;
#ifdef USE_TCP_SOCKET
int sockfd = socket(PF_INET, SOCK_STREAM, 0);
#else
int sockfd = tou_socket(PF_INET, SOCK_STREAM, 0);
#endif
if (sockfd < 0)
{
std::cerr << "Failed to open socket!: ";
#ifdef USE_TCP_SOCKET
std::cerr << "Socket Error:" << errno << std::endl;
#else
std::cerr << "Socket Error:" << tou_errno(sockfd) << std::endl;
#endif
return -1;
}
std::cerr << "Socket Created" << std::endl;
/* make nonblocking */
#ifdef USE_TCP_SOCKET
int err = tounet_fcntl(sockfd,F_SETFL,O_NONBLOCK);
#else
int err = 0;
#endif
if (err < 0)
{
std::cerr << "Error: Cannot make socket NON-Blocking: ";
std::cerr << err << std::endl;
return -1;
}
std::cerr << "Socket Non-Blocking" << std::endl;
#ifdef USE_TCP_SOCKET
err = bind(sockfd, (struct sockaddr *) &laddr, sizeof(laddr));
#else
err = tou_bind(sockfd, (struct sockaddr *) &laddr, sizeof(laddr));
#endif
if (err < 0)
{
std::cerr << "Error: Cannot bind socket: ";
std::cerr << err << std::endl;
return -1;
}
std::cerr << "Socket Bound to: " << laddr << std::endl;
if (toConnect)
{
std::cerr << "Socket Connecting to: " << raddr << std::endl;
#ifdef USE_TCP_SOCKET
err = connect(sockfd, (struct sockaddr *) &raddr, sizeof(raddr));
#else
err = tou_connect(sockfd, (struct sockaddr *) &raddr, sizeof(raddr), 30);
#endif
if (err < 0)
{
#ifndef USE_TCP_SOCKET
errno = tou_errno(sockfd);
#endif
if (errno != EINPROGRESS)
{
std::cerr << "Cannot Connect!" << std::endl;
return 1;
}
#ifdef USE_TCP_SOCKET
while(0 == (err = Check_Socket(sockfd)))
#else
while(0 == (err = tou_connected(sockfd)))
#endif
{
std::cerr << "Waiting for Connect!" << std::endl;
sleep(1);
}
if (err < 0)
{
std::cerr << "Connect Failed" << std::endl;
return 1;
}
// else connected!
}
}
else
{
std::cerr << "Socket Listening " << std::endl;
/* listen */
#ifdef USE_TCP_SOCKET
err = listen(sockfd, 1);
#else
//err = tou_listen(sockfd, 1);
err = tou_listenfor(sockfd,
(struct sockaddr *) &raddr, sizeof(raddr));
#endif
/* accept */
struct sockaddr_in inaddr;
socklen_t addrlen = sizeof(inaddr);
int nsock;
#ifdef USE_TCP_SOCKET
while(0 > (nsock = accept(sockfd,
(struct sockaddr *) &inaddr, &addrlen)))
#else
while(0 > (nsock = tou_accept(sockfd,
(struct sockaddr *) &inaddr, &addrlen)))
#endif
{
#ifndef USE_TCP_SOCKET
errno = tou_errno(sockfd);
#endif
if (errno != EAGAIN)
{
std::cerr << "Cannot Connect!" << std::endl;
return 1;
}
sleep(1);
}
/* changed sockfd */
sockfd = nsock;
std::cerr << "Socket Accepted from: " << inaddr << std::endl;
}
std::cerr << "Socket Connected" << std::endl;
if (toConnect)
{
/* send data */
int bufsize = 15011;
char buffer[bufsize];
int readsize = 0;
tounet_fcntl(0, F_SETFL, O_NONBLOCK);
bool done = false;
bool blockread = false;
while(!done)
{
sleep(1);
//usleep(10000);
//usleep(1000);
if (blockread != true)
{
readsize = read(0, buffer, bufsize);
}
if (readsize == 0)
{
/* eof */
done = true;
}
else if ((readsize == -1) && ( EAGAIN == errno ))
{
continue;
}
/* now we write */
#ifdef USE_TCP_SOCKET
if (-1 == write(sockfd, buffer, readsize))
#else
if (-1 == tou_write(sockfd, buffer, readsize))
#endif
{
//std::cerr << "Blocked Write!" << std::endl;
#ifndef USE_TCP_SOCKET
//std::cerr << "Error: " << tou_errno(sockfd) << std::endl;
#endif
blockread = true;
}
else
{
blockread = false;
totalwbytes += readsize;
}
}
#ifdef USE_TCP_SOCKET
close(sockfd);
#else
/* this is blocking??? */
tou_close(sockfd);
#endif
std::cerr << "Transfer Complete: " << totalwbytes << " bytes";
std::cerr << std::endl;
return 1;
}
/* recv data */
int bufsize = 1523;
char data[bufsize];
tounet_fcntl(1,F_SETFL,O_NONBLOCK);
while(1)
{
sleep(1);
//usleep(10000);
//usleep(1000);
int writesize = bufsize;
int ret;
#ifdef USE_TCP_SOCKET
if (0 < (ret = read(sockfd, data, writesize)))
#else
if (0 < (ret = tou_read(sockfd, data, writesize)))
#endif
{
std::cerr << "TF(" << ret << ")" << std::endl;
write(1, data, ret);
totalrbytes += ret;
}
else if (ret == 0)
{
break;
}
else
{
//std::cerr << "Blocked Read!" << std::endl;
#ifndef USE_TCP_SOCKET
//std::cerr << "Error: " << tou_errno(sockfd) << std::endl;
#endif
}
}
#ifdef USE_TCP_SOCKET
close(sockfd);
#else
tou_close(sockfd);
#endif
std::cerr << "Transfer complete :" << totalrbytes;
std::cerr << " bytes" << std::endl;
close(1);
return 1;
}
#ifdef USE_TCP_SOCKET
int Check_Socket(int fd)
{
std::cerr << "Check_Socket()" << std::endl;
std::cerr << "1) Checking with Select()" << std::endl;
fd_set ReadFDs, WriteFDs, ExceptFDs;
FD_ZERO(&ReadFDs);
FD_ZERO(&WriteFDs);
FD_ZERO(&ExceptFDs);
FD_SET(fd, &ReadFDs);
FD_SET(fd, &WriteFDs);
FD_SET(fd, &ExceptFDs);
struct timeval timeout;
timeout.tv_sec = 0;
timeout.tv_usec = 0;
int sr = 0;
if (0 > (sr = select(fd + 1,
&ReadFDs, &WriteFDs, &ExceptFDs, &timeout)))
{
std::cerr << "Check_Socket() Select ERROR: " << sr << std::endl;
return -1;
}
if (FD_ISSET(fd, &ExceptFDs))
{
std::cerr << "Check_Socket() Exception on socket!" << std::endl;
return -1;
}
if (FD_ISSET(fd, &WriteFDs))
{
std::cerr << "Check_Socket() Can Write!" << std::endl;
}
else
{
// not ready return 0;
std::cerr << "Check_Socket() Cannot Write!" << std::endl;
std::cerr << "Check_Socket() Socket Not Ready!" << std::endl;
return 0;
}
if (FD_ISSET(fd, &ReadFDs))
{
std::cerr << "Check_Socket() Can Read!" << std::endl;
}
else
{
std::cerr << "Check_Socket() Cannot Read!" << std::endl;
std::cerr << "Check_Socket() Socket Not Ready!" << std::endl;
return 0;
}
std::cerr << "Select() Tests indicate Socket Good!" << std::endl;
std::cerr << "2) Checking with getsockopt()" << std::endl;
int err = 1;
socklen_t optlen = 4;
if (0==getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &optlen))
{
std::cerr << "Check_Socket() getsockopt returned :" << err;
std::cerr << ", optlen:" << optlen;
std::cerr << std::endl;
if (err == 0)
{
std::cerr << "Check_Socket() getsockopt";
std::cerr << " Indicates TCP Connection Complete:";
std::cerr << std::endl;
return 1;
}
else if (err == EINPROGRESS)
{
std::cerr << "Check_Socket() getsockopt";
std::cerr << " Indicates TCP Connection INPROGRESS";
std::cerr << std::endl;
return 0;
}
else if ((err == ENETUNREACH) || (err == ETIMEDOUT))
{
std::cerr << "Check_Socket() getsockopt";
std::cerr << " Indicates TCP Connection ENETUNREACH/ETIMEDOUT";
std::cerr << std::endl;
return -1;
}
else if ((err == EHOSTUNREACH) || (err == EHOSTDOWN))
{
std::cerr << "Check_Socket() getsockopt";
std::cerr << " Indicates TCP Connection ENETUNREACH/ETIMEDOUT";
std::cerr << std::endl;
return -1;
}
else
{
std::cerr << "Check_Socket() getsockopt";
std::cerr << " Indicates Other Error: " << err;
std::cerr << std::endl;
return -1;
}
}
else
{
std::cerr << "Check_Socket() getsockopt";
std::cerr << " FAILED ";
std::cerr << std::endl;
return -1;
}
}
#else
int Check_Socket(int fd)
{
return 0;
}
#endif

View file

@ -33,7 +33,7 @@ static const int kInitStreamTable = 5;
#include <stdlib.h>
#include <string.h>
#include "udplayer.h"
#include "udp/udpstack.h"
#include "tcpstream.h"
#include <vector>
#include <iostream>
@ -55,115 +55,34 @@ typedef struct TcpOnUdp_t TcpOnUdp;
static std::vector<TcpOnUdp *> tou_streams;
static int tou_inited = 0;
static UdpSorter *udps = NULL;
#include "udp/udpstack.h"
#include "tcponudp/udppeer.h"
static UdpStack *udpstack = NULL;
static UdpPeerReceiver *udps = NULL;
static int tou_tick_all();
/* tou_init - opens the udp port (universal bind) */
int tou_init(const struct sockaddr *my_addr, socklen_t addrlen)
int tou_init(UdpStack *stack)
{
if (tou_inited)
{
struct sockaddr_in *addr = (struct sockaddr_in *) my_addr;
udps->resetAddress(*addr);
if (!(udps->okay()))
{
std::cerr << "tou_init() FATAL ERROR: Cannot reset Udp Socket to: "
<< rs_inet_ntoa(addr->sin_addr) << ":" << ntohs(addr->sin_port);
std::cerr << std::endl;
return 0;
}
return 1;
}
tou_streams.resize(kInitStreamTable);
udps = new UdpSorter( *((struct sockaddr_in *) my_addr));
/* check the bind succeeded */
if (!(udps->okay()))
{
delete (udps);
udps = NULL;
return -1;
}
udpstack = stack;
udps = new UdpPeerReceiver(stack);
stack->addReceiver(udps);
tou_inited = 1;
return 1;
}
/* tou_stunpeer supply tou with stun peers. */
int tou_stunpeer(const struct sockaddr *my_addr, socklen_t addrlen,
const char *id)
{
if (!tou_inited)
return -1;
udps->addStunPeer(*(struct sockaddr_in *) my_addr, id);
return 0;
}
int tou_stunkeepalive(int required)
{
if (!tou_inited)
return -1;
udps->setStunKeepAlive(required);
return 1;
}
int tou_getstunpeer(int i, struct sockaddr *remote_addr, socklen_t *raddrlen,
struct sockaddr *ext_addr, socklen_t *eaddrlen,
uint32_t *failCount, time_t *lastSend)
{
if (!tou_inited)
return -1;
std::string id;
bool ret = udps->getStunPeer(i, id,
*((struct sockaddr_in *) remote_addr),
*((struct sockaddr_in *) ext_addr),
*failCount, *lastSend);
return ret;
}
int tou_needstunpeers()
{
if (!tou_inited)
return -1;
if (udps->needStunPeers())
return 1;
return 0;
}
int tou_tick_stunkeepalive()
{
if (!tou_inited)
return -1;
udps->tick();
return 1;
}
int tou_extaddr(struct sockaddr *ext_addr, socklen_t *addrlen, uint8_t *stable)
{
if (!tou_inited)
return -1;
if (udps->externalAddr(*(struct sockaddr_in *) ext_addr, *stable))
{
return 1;
}
return 0;
}
/* open - which does nothing */
int tou_socket(int /*domain*/, int /*type*/, int /*protocol*/)

View file

@ -53,39 +53,18 @@
/* standard C interface (as Unix-like as possible)
* for the tou (Tcp On Udp) library
*/
/*
* Init:
* (1) need UdpStack item, which has our address already.
*/
class UdpStack;
int tou_init(UdpStack *stack);
#ifdef __cplusplus
extern "C" {
#endif
/* The modification to a single UDP socket means
* that the structure of the TOU interface must be changed.
*
* Init:
* (1) choose our local address. (a universal bind)
* int tou_init(const struct sockaddr *my_addr);
* (2) query if we have determined our external address.
* int tou_extaddr(struct sockaddr *ext_addr, socklen_t *addrlen);
* (3) offer more stunpeers, for external address determination.
* int tou_stunpeer(const struct sockaddr *ext_addr, socklen_t addrlen, const char *id);
* (4) repeat (2)+(3) until a valid extaddr is returned.
* (5) if stunkeepalive is required, then periodically send out
* stun packets to maintain external firewall port.
*
*/
int tou_init(const struct sockaddr *my_addr, socklen_t addrlen);
int tou_extaddr(struct sockaddr *ext_addr, socklen_t *addrlen, uint8_t *stable);
int tou_stunpeer(const struct sockaddr *ext_addr, socklen_t addrlen, const char *id);
int tou_stunkeepalive(int required);
int tou_tick_stunkeepalive();
int tou_getstunpeer(int i, struct sockaddr *remote_addr, socklen_t *raddrlen,
struct sockaddr *ext_addr, socklen_t *eaddrlen,
uint32_t *failCount, time_t *lastSend);
int tou_needstunpeers();
/* Connections are as similar to UNIX as possible
* (1) create a socket: tou_socket() this reserves a socket id.
* (2) connect: active: tou_connect() or passive: tou_listenfor().

View file

@ -1,75 +0,0 @@
/*
* "$Id: tou_errno.h,v 1.3 2007-02-18 21:46:50 rmf24 Exp $"
*
* TCP-on-UDP (tou) network interface for RetroShare.
*
* Copyright 2004-2006 by Robert Fernie.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 2 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "retroshare@lunamutt.com".
*
*/
#ifndef TOU_ERRNO_HEADER
#define TOU_ERRNO_HEADER
/* C Interface */
#ifdef __cplusplus
extern "C" {
#endif
/*******
* This defines the unix errno's for windows, these are
* needed to determine error types, these are defined
* to be the same as the unix ones.
*/
/********************************** WINDOWS/UNIX SPECIFIC PART ******************/
#ifdef WINDOWS_SYS
#define EAGAIN 11
#define EWOULDBLOCK EAGAIN
#define EUSERS 87
#define ENOTSOCK 88
#define EOPNOTSUPP 95
#define EADDRINUSE 98
#define EADDRNOTAVAIL 99
#define ENETDOWN 100
#define ENETUNREACH 101
#define ECONNRESET 104
#define ETIMEDOUT 110
#define ECONNREFUSED 111
#define EHOSTDOWN 112
#define EHOSTUNREACH 113
#define EALREADY 114
#define EINPROGRESS 115
#endif
/********************************** WINDOWS/UNIX SPECIFIC PART ******************/
#ifdef __cplusplus
} /* C Interface */
#endif
#endif /* TOU_ERRNO_HEADER */

View file

@ -1,346 +0,0 @@
/*
* "$Id: tou_net.cc,v 1.3 2007-02-18 21:46:50 rmf24 Exp $"
*
* TCP-on-UDP (tou) network interface for RetroShare.
*
* Copyright 2004-2006 by Robert Fernie.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 2 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "retroshare@lunamutt.com".
*
*/
#include "tou_net.h"
/********************************** WINDOWS/UNIX SPECIFIC PART ******************/
#ifndef WINDOWS_SYS
/* Unix Version is easy -> just call the unix fn
*/
#include <unistd.h> /* for close definition */
/* the universal interface */
int tounet_init() { return 0; }
int tounet_errno() { return errno; }
/* check if we can modify the TTL on a UDP packet */
int tounet_checkTTL(int fd) { return 1;}
int tounet_inet_aton(const char *name, struct in_addr *addr)
{
return inet_aton(name, addr);
}
int tounet_close(int fd) { return close(fd); }
int tounet_socket(int domain, int type, int protocol)
{
return socket(domain, type, protocol);
}
int tounet_bind(int sockfd, const struct sockaddr *my_addr, socklen_t addrlen)
{
return bind(sockfd,my_addr,addrlen);
}
int tounet_fcntl(int fd, int cmd, long arg)
{
return fcntl(fd, cmd, arg);
}
int tounet_setsockopt(int s, int level, int optname,
const void *optval, socklen_t optlen)
{
return setsockopt(s, level, optname, optval, optlen);
}
ssize_t tounet_recvfrom(int s, void *buf, size_t len, int flags,
struct sockaddr *from, socklen_t *fromlen)
{
return recvfrom(s, buf, len, flags, from, fromlen);
}
ssize_t tounet_sendto(int s, const void *buf, size_t len, int flags,
const struct sockaddr *to, socklen_t tolen)
{
return sendto(s, buf, len, flags, to, tolen);
}
/********************************** WINDOWS/UNIX SPECIFIC PART ******************/
#else /* WINDOWS OS */
#include <iostream>
/* error handling */
int tounet_int_errno;
int tounet_errno()
{
return tounet_int_errno;
}
int tounet_init()
{
std::cerr << "tounet_init()" << std::endl;
tounet_int_errno = 0;
// Windows Networking Init.
WORD wVerReq = MAKEWORD(2,2);
WSADATA wsaData;
if (0 != WSAStartup(wVerReq, &wsaData))
{
std::cerr << "Failed to Startup Windows Networking";
std::cerr << std::endl;
}
else
{
std::cerr << "Started Windows Networking";
std::cerr << std::endl;
}
return 0;
}
/* check if we can modify the TTL on a UDP packet */
int tounet_checkTTL(int fd)
{
std::cerr << "tounet_checkTTL()" << std::endl;
int optlen = 4;
char optval[optlen];
int ret = getsockopt(fd, IPPROTO_IP, IP_TTL, optval, &optlen);
//int ret = getsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL, optval, &optlen);
if (ret == SOCKET_ERROR)
{
ret = -1;
tounet_int_errno = tounet_w2u_errno(WSAGetLastError());
std::cerr << "tounet_checkTTL() Failed!";
std::cerr << std::endl;
}
else
{
std::cerr << "tounet_checkTTL() :";
std::cerr << (int) optval[0] << ":";
std::cerr << (int) optval[1] << ":";
std::cerr << (int) optval[2] << ":";
std::cerr << (int) optval[3] << ": RET: ";
std::cerr << ret << ":";
std::cerr << std::endl;
}
return ret;
}
int tounet_close(int fd)
{
std::cerr << "tounet_close()" << std::endl;
return closesocket(fd);
}
int tounet_socket(int domain, int type, int protocol)
{
int osock = socket(domain, type, protocol);
std::cerr << "tounet_socket()" << std::endl;
if ((unsigned) osock == INVALID_SOCKET)
{
// Invalidate socket Unix style.
osock = -1;
tounet_int_errno = tounet_w2u_errno(WSAGetLastError());
}
tounet_checkTTL(osock);
return osock;
}
int tounet_bind(int sockfd, const struct sockaddr *my_addr, socklen_t addrlen)
{
std::cerr << "tounet_bind()" << std::endl;
int ret = bind(sockfd,my_addr,addrlen);
if (ret != 0)
{
/* store unix-style error
*/
ret = -1;
tounet_int_errno = tounet_w2u_errno(WSAGetLastError());
}
return ret;
}
int tounet_fcntl(int fd, int cmd, long arg)
{
int ret;
unsigned long int on = 1;
std::cerr << "tounet_fcntl()" << std::endl;
/* can only do NONBLOCK at the moment */
if ((cmd != F_SETFL) || (arg != O_NONBLOCK))
{
std::cerr << "tounet_fcntl() limited to fcntl(fd, F_SETFL, O_NONBLOCK)";
std::cerr << std::endl;
tounet_int_errno = EOPNOTSUPP;
return -1;
}
ret = ioctlsocket(fd, FIONBIO, &on);
if (ret != 0)
{
/* store unix-style error
*/
ret = -1;
tounet_int_errno = tounet_w2u_errno(WSAGetLastError());
}
return ret;
}
int tounet_setsockopt(int s, int level, int optname,
const void *optval, socklen_t optlen)
{
std::cerr << "tounet_setsockopt() val:" << *((int *) optval) << std::endl;
std::cerr << "tounet_setsockopt() len:" << optlen << std::endl;
if ((level != IPPROTO_IP) || (optname != IP_TTL))
{
std::cerr << "tounet_setsockopt() limited to ";
std::cerr << "setsockopt(fd, IPPROTO_IP, IP_TTL, ....)";
std::cerr << std::endl;
tounet_int_errno = EOPNOTSUPP;
return -1;
}
int ret = setsockopt(s, level, optname, (const char *) optval, optlen);
//int ret = setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL, (const char *) optval, optlen);
if (ret == SOCKET_ERROR)
{
ret = -1;
tounet_int_errno = tounet_w2u_errno(WSAGetLastError());
}
tounet_checkTTL(s);
return ret;
}
ssize_t tounet_recvfrom(int s, void *buf, size_t len, int flags,
struct sockaddr *from, socklen_t *fromlen)
{
std::cerr << "tounet_recvfrom()" << std::endl;
int ret = recvfrom(s, (char *) buf, len, flags, from, fromlen);
if (ret == SOCKET_ERROR)
{
ret = -1;
tounet_int_errno = tounet_w2u_errno(WSAGetLastError());
}
return ret;
}
ssize_t tounet_sendto(int s, const void *buf, size_t len, int flags,
const struct sockaddr *to, socklen_t tolen)
{
std::cerr << "tounet_sendto()" << std::endl;
int ret = sendto(s, (const char *) buf, len, flags, to, tolen);
if (ret == SOCKET_ERROR)
{
ret = -1;
tounet_int_errno = tounet_w2u_errno(WSAGetLastError());
}
return ret;
}
int tounet_w2u_errno(int err)
{
/* switch */
std::cerr << "tou_net_w2u_errno(" << err << ")" << std::endl;
switch(err)
{
case WSAEINPROGRESS:
return EINPROGRESS;
break;
case WSAEWOULDBLOCK:
return EINPROGRESS;
break;
case WSAENETUNREACH:
return ENETUNREACH;
break;
case WSAETIMEDOUT:
return ETIMEDOUT;
break;
case WSAEHOSTDOWN:
return EHOSTDOWN;
break;
case WSAECONNREFUSED:
return ECONNREFUSED;
break;
case WSAEADDRINUSE:
return EADDRINUSE;
break;
case WSAEUSERS:
return EUSERS;
break;
/* This one is returned for UDP recvfrom, when nothing there
* but not a real error... translate into EINPROGRESS
*/
case WSAECONNRESET:
std::cerr << "tou_net_w2u_errno(" << err << ")";
std::cerr << " = WSAECONNRESET ---> EINPROGRESS";
std::cerr << std::endl;
return EINPROGRESS;
break;
/***
*
case WSAECONNRESET:
return ECONNRESET;
break;
*
***/
default:
std::cerr << "tou_net_w2u_errno(" << err << ") Unknown";
std::cerr << std::endl;
break;
}
return ECONNREFUSED; /* sensible default? */
}
int tounet_inet_aton(const char *name, struct in_addr *addr)
{
return (((*addr).s_addr = inet_addr(name)) != INADDR_NONE);
}
void sleep(int sec)
{
Sleep(sec * 1000);
}
void usleep(int usec)
{
Sleep(usec / 1000);
}
#endif
/********************************** WINDOWS/UNIX SPECIFIC PART ******************/

View file

@ -1,131 +0,0 @@
/*
* "$Id: tou_net.h,v 1.3 2007-02-18 21:46:50 rmf24 Exp $"
*
* TCP-on-UDP (tou) network interface for RetroShare.
*
* Copyright 2004-2006 by Robert Fernie.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 2 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "retroshare@lunamutt.com".
*
*/
#ifndef TOU_UNIVERSAL_NETWORK_HEADER
#define TOU_UNIVERSAL_NETWORK_HEADER
/* Some Types need to be defined before the interface can be declared
*/
#include "util/rsnet.h"
/* C Interface */
#ifdef __cplusplus
extern "C" {
#endif
/*******
* This defines a (unix-like) universal networking layer
* that should function on both windows and unix. (C - interface)
*
* This is of course only a subset of the full interface.
* functions required are:
*
* int tounet_close(int fd);
* int tounet_socket(int domain, int type, int protocol);
* int tounet_bind(int sockfd, const struct sockaddr *my_addr,
* socklen_t addrlen);
* int tounet_fcntl(int fd, int cmd, long arg);
* int tounet_setsockopt(int s, int level, int optname,
* const void *optval, socklen_t optlen);
* ssize_t tounet_recvfrom(int s, void *buf, size_t len, int flags,
* struct sockaddr *from, socklen_t *fromlen);
* ssize_t tounet_sendto(int s, const void *buf, size_t len, int flags,
* const struct sockaddr *to, socklen_t tolen);
*
* There are some non-standard ones as well:
* int tounet_errno(); for internal networking errors
* int tounet_init(); required for windows
* int tounet_checkTTL(); a check if we can modify the ttl
*/
/* the universal interface */
int tounet_errno(); /* for internal networking errors */
int tounet_init(); /* required for windows */
int tounet_close(int fd);
int tounet_socket(int domain, int type, int protocol);
int tounet_bind(int sockfd, const struct sockaddr *my_addr, socklen_t addrlen);
int tounet_fcntl(int fd, int cmd, long arg);
int tounet_setsockopt(int s, int level, int optname,
const void *optval, socklen_t optlen);
ssize_t tounet_recvfrom(int s, void *buf, size_t len, int flags,
struct sockaddr *from, socklen_t *fromlen);
ssize_t tounet_sendto(int s, const void *buf, size_t len, int flags,
const struct sockaddr *to, socklen_t tolen);
/* address filling */
int tounet_inet_aton(const char *name, struct in_addr *addr);
/* check if we can modify the TTL on a UDP packet */
int tounet_checkTTL(int fd);
/* Extra stuff to declare for windows error handling (mimics unix errno)
*/
/********************************** WINDOWS/UNIX SPECIFIC PART ******************/
#ifdef WINDOWS_SYS
// Some Network functions that are missing from windows.
//in_addr_t inet_netof(struct in_addr addr);
//in_addr_t inet_network(char *inet_name);
//int inet_aton(const char *name, struct in_addr *addr);
// definitions for fcntl (NON_BLOCK) (random?)
#define F_SETFL 0x1010
#define O_NONBLOCK 0x0100
// definitions for setsockopt (TTL) (random?)
//#define IPPROTO_IP 0x0011
//#define IP_TTL 0x0110
/* define the Unix Error Codes that we use...
* NB. we should make the same, but not necessary
*/
#include "tou_errno.h"
int tounet_w2u_errno(int error);
/* also put the sleep commands in here (where else to go)
* ms uses millisecs.
* void Sleep(int ms);
*/
void sleep(int sec);
//void usleep(int usec);
#endif
/********************************** WINDOWS/UNIX SPECIFIC PART ******************/
#ifdef __cplusplus
} /* C Interface */
#endif
#endif /* TOU_UNIVERSAL_NETWORK_HEADER */

View file

@ -1,289 +0,0 @@
/*
* "$Id: udp_server.cc,v 1.4 2007-02-18 21:46:50 rmf24 Exp $"
*
* TCP-on-UDP (tou) network interface for RetroShare.
*
* Copyright 2004-2006 by Robert Fernie.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 2 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "retroshare@lunamutt.com".
*
*/
#include "udplayer.h"
#include "tcpstream.h"
#include <iostream>
/* unix only
#include <netinet/in.h>
#include <arpa/inet.h>
*/
#include "tou_net.h"
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
void usage(char *name)
{
std::cerr << "Usage: " << name;
std::cerr << " [-pco] <laddr> <lport> ";
std::cerr << " <raddr> <rport> ";
std::cerr << std::endl;
exit(1);
return;
}
int main(int argc, char **argv)
{
int c;
bool isProxy = false;
bool toConnect = false;
bool stayOpen = false;
while(-1 != (c = getopt(argc, argv, "f:pco")))
{
switch (c)
{
case 'p':
isProxy = true;
break;
case 'c':
toConnect = true;
break;
case 'o':
stayOpen = true;
break;
case 'f':
/* this can only work when the define below exists in tcpstream */
#ifdef DEBUG_TCP_STREAM_EXTRA
setupBinaryCheck(std::string(optarg));
#else
std::cerr << "Binary Check no Enabled!" << std::endl;
#endif
break;
default:
usage(argv[0]);
break;
}
}
if (argc-optind < 4)
{
usage(argv[0]);
return 1;
}
/* setup the local/remote addresses.
*/
tounet_init();
struct sockaddr_in laddr;
struct sockaddr_in raddr;
laddr.sin_family = AF_INET;
raddr.sin_family = AF_INET;
if ((!tounet_inet_aton(argv[optind], &(laddr.sin_addr))) ||
(!tounet_inet_aton(argv[optind+2], &(raddr.sin_addr))))
{
std::cerr << "Invalid addresses!" << std::endl;
usage(argv[0]);
}
laddr.sin_port = htons(atoi(argv[optind+1]));
raddr.sin_port = htons(atoi(argv[optind+3]));
std::cerr << "Local Address: " << laddr << std::endl;
std::cerr << "Remote Address: " << raddr << std::endl;
UdpSorter udps(laddr);
if (!udps.okay())
{
std::cerr << "UdpSorter not Okay (Cannot Open Local Address): " << laddr << std::endl;
exit(1);
}
TcpStream tcp(&udps);
udps.addUdpPeer(&tcp, raddr);
if (toConnect)
{
tcp.connect(raddr, 30);
}
else
{
tcp.listenfor(raddr);
}
while(!tcp.isConnected())
{
sleep(1);
std::cerr << "Waiting for TCP to Connect!" << std::endl;
udps.status(std::cerr);
tcp.status(std::cerr);
tcp.tick();
}
std::cerr << "TCP Connected***************************" << std::endl;
udps.status(std::cerr);
tcp.status(std::cerr);
std::cerr << "TCP Connected***************************" << std::endl;
int count = 1;
if (toConnect)
{
/* send data */
int bufsize = 51;
char buffer[bufsize];
int readsize = 0;
tounet_fcntl(0, F_SETFL, O_NONBLOCK);
bool done = false;
bool blockread = false;
while(!done)
{
//sleep(1);
usleep(100000);
//usleep(1000);
if (blockread != true)
{
readsize = read(0, buffer, bufsize);
}
if (readsize == 0)
{
/* eof */
done = true;
}
else if ((readsize == -1) && ( EAGAIN == errno ))
{
continue;
}
/* now we write */
if (-1 == tcp.write(buffer, readsize))
blockread = true;
else
blockread = false;
tcp.tick();
if (count++ % 10 == 0)
{
std::cerr << "******************************************" << std::endl;
tcp.status(std::cerr);
}
}
tcp.closeWrite();
while(!tcp.widle())
{
//sleep(1);
usleep(100000);
//usleep(1000);
tcp.tick();
if (count++ % 10 == 0)
{
std::cerr << "Waiting for Idle()" << std::endl;
std::cerr << "******************************************" << std::endl;
tcp.status(std::cerr);
}
}
std::cerr << "Transfer Complete: " << tcp.wbytes() << " bytes";
std::cerr << std::endl;
return 1;
}
/* recv data */
int bufsize = 1523;
char data[bufsize];
tounet_fcntl(1,F_SETFL,O_NONBLOCK);
while(1)
{
//sleep(1);
usleep(100000);
//usleep(1000);
//int writesize = bufsize;
int ret;
if (0 < (ret = tcp.read(data, bufsize)))
{
std::cerr << "TF(" << ret << ")" << std::endl;
write(1, data, ret);
}
else if (ret == 0)
{
/* completed transfer */
std::cerr << "Transfer complete :" << tcp.rbytes();
std::cerr << " bytes" << std::endl;
break;
}
tcp.tick();
if (count++ % 10 == 0)
{
std::cerr << "******************************************" << std::endl;
tcp.status(std::cerr);
}
if ((!stayOpen) && tcp.ridle())
{
std::cerr << "Transfer Idle after " << tcp.rbytes();
std::cerr << " bytes" << std::endl;
close(1);
break;
}
}
tcp.closeWrite();
/* tick for a bit */
while((stayOpen) || (!tcp.ridle()))
{
tcp.tick();
//sleep(1);
usleep(100000);
//usleep(1000);
if (count++ % 10 == 0)
{
std::cerr << "Waiting for Idle()" << std::endl;
std::cerr << "******************************************" << std::endl;
tcp.status(std::cerr);
}
}
if ((!stayOpen) && tcp.ridle())
{
//std::cerr << "Transfer complete :" << tcp.rbytes();
//std::cerr << " bytes" << std::endl;
close(1);
return 1;
}
return 1;
}

View file

@ -1,501 +0,0 @@
/*
* "$Id: udplayer.cc,v 1.8 2007-02-18 21:46:50 rmf24 Exp $"
*
* TCP-on-UDP (tou) network interface for RetroShare.
*
* Copyright 2004-2006 by Robert Fernie.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 2 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "retroshare@lunamutt.com".
*
*/
#include "udplayer.h"
#include <iostream>
#include <sstream>
#include <iomanip>
#include <string.h>
#include <stdlib.h>
/*
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
*/
/***
* #define DEBUG_UDP_LAYER 1
***/
static const int UDP_DEF_TTL = 64;
/* NB: This #define makes the listener open 0.0.0.0:X port instead
* of a specific port - this might help retroshare work on PCs with
* multiple interfaces or unique network setups.
* #define OPEN_UNIVERSAL_PORT 1
*
* This is also defined in pqissllistener (for TCP port).
*/
#define OPEN_UNIVERSAL_PORT 1
class udpPacket
{
public:
udpPacket(struct sockaddr_in *addr, void *dta, int dlen)
:raddr(*addr), len(dlen)
{
data = malloc(len);
memcpy(data, dta, len);
}
~udpPacket()
{
if (data)
{
free(data);
data = NULL;
len = 0;
}
}
struct sockaddr_in raddr;
void *data;
int len;
};
bool operator==(const struct sockaddr_in &addr, const struct sockaddr_in &addr2)
{
if (addr.sin_family != addr2.sin_family)
return false;
if (addr.sin_addr.s_addr != addr2.sin_addr.s_addr)
return false;
if (addr.sin_port != addr2.sin_port)
return false;
return true;
}
bool operator<(const struct sockaddr_in &addr, const struct sockaddr_in &addr2)
{
if (addr.sin_family != addr2.sin_family)
return (addr.sin_family < addr2.sin_family);
if (addr.sin_addr.s_addr != addr2.sin_addr.s_addr)
return (addr.sin_addr.s_addr < addr2.sin_addr.s_addr);
if (addr.sin_port != addr2.sin_port)
return (addr.sin_port < addr2.sin_port);
return false;
}
std::string printPkt(void *d, int size)
{
std::ostringstream out;
out << "Packet:" << "**********************";
for(int i = 0; i < size; i++)
{
if (i % 16 == 0)
out << std::endl;
out << std::hex << std::setw(2) << (unsigned int) ((unsigned char *) d)[i] << " ";
}
out << std::endl << "**********************";
out << std::endl;
return out.str();
}
std::string printPktOffset(unsigned int offset, void *d, unsigned int size)
{
std::ostringstream out;
out << "Packet:" << "**********************";
out << std::endl;
out << "Offset: " << std::hex << offset << " -> " << offset + size;
out << std::endl;
out << "Packet:" << "**********************";
unsigned int j = offset % 16;
if (j != 0)
{
out << std::endl;
out << std::hex << std::setw(6) << (unsigned int) offset - j;
out << ": ";
for(unsigned int i = 0; i < j; i++)
{
out << "xx ";
}
}
for(unsigned int i = offset; i < offset + size; i++)
{
if (i % 16 == 0)
{
out << std::endl;
out << std::hex << std::setw(6) << (unsigned int) i;
out << ": ";
}
out << std::hex << std::setw(2) << (unsigned int) ((unsigned char *) d)[i-offset] << " ";
}
out << std::endl << "**********************";
out << std::endl;
return out.str();
}
UdpLayer::UdpLayer(UdpReceiver *udpr, struct sockaddr_in &local)
:recv(udpr), laddr(local), errorState(0), ttl(UDP_DEF_TTL)
{
openSocket();
return;
}
int UdpLayer::status(std::ostream &out)
{
out << "UdpLayer::status()" << std::endl;
out << "localaddr: " << laddr << std::endl;
out << "sockfd: " << sockfd << std::endl;
out << std::endl;
return 1;
}
int UdpLayer::reset(struct sockaddr_in &local)
{
#ifdef DEBUG_UDP_LAYER
std::cerr << "UdpLayer::reset()" << std::endl;
#endif
/* stop the old thread */
{
RsStackMutex stack(sockMtx); /********** LOCK MUTEX *********/
#ifdef DEBUG_UDP_LAYER
std::cerr << "UdpLayer::reset() setting stopThread flag" << std::endl;
#endif
stopThread = true;
}
#ifdef DEBUG_UDP_LAYER
std::cerr << "UdpLayer::reset() joining" << std::endl;
#endif
join();
#ifdef DEBUG_UDP_LAYER
std::cerr << "UdpLayer::reset() closing socket" << std::endl;
#endif
close();
#ifdef DEBUG_UDP_LAYER
std::cerr << "UdpLayer::reset() resetting variables" << std::endl;
#endif
laddr = local;
errorState = 0;
ttl = UDP_DEF_TTL;
#ifdef DEBUG_UDP_LAYER
std::cerr << "UdpLayer::reset() opening socket" << std::endl;
#endif
openSocket();
return 1 ;
}
int UdpLayer::close()
{
/* close socket if open */
sockMtx.lock(); /********** LOCK MUTEX *********/
if (sockfd > 0)
{
tounet_close(sockfd);
}
sockMtx.unlock(); /******** UNLOCK MUTEX *********/
return 1;
}
void UdpLayer::run()
{
return recv_loop();
}
/* higher level interface */
void UdpLayer::recv_loop()
{
int maxsize = 16000;
void *inbuf = malloc(maxsize);
int status;
struct timeval timeout;
while(m_bRun)
{
/* select on the socket TODO */
fd_set rset;
for(;;)
{
/* check if we need to stop */
bool toStop = false;
{
RsStackMutex stack(sockMtx); /********** LOCK MUTEX *********/
toStop = stopThread;
}
if (toStop)
{
std::cerr << "UdpLayer::recv_loop() stopping thread" << std::endl;
stop();
}
FD_ZERO(&rset);
FD_SET(sockfd, &rset);
timeout.tv_sec = 0;
timeout.tv_usec = 500000; /* 500 ms timeout */
status = select(sockfd+1, &rset, NULL, NULL, &timeout);
if (status > 0)
{
break; /* data available, go read it */
}
else if (status < 0)
{
#ifdef DEBUG_UDP_LAYER
std::cerr << "UdpLayer::recv_loop() Error: " << tounet_errno() << std::endl;
#endif
}
};
int nsize = maxsize;
struct sockaddr_in from;
if (0 < receiveUdpPacket(inbuf, &nsize, from))
{
#ifdef DEBUG_UDP_LAYER
std::cerr << "UdpLayer::readPkt() from : " << from << std::endl;
std::cerr << printPkt(inbuf, nsize);
#endif
// send to reciever.
recv -> recvPkt(inbuf, nsize, from);
}
else
{
#ifdef DEBUG_UDP_LAYER
std::cerr << "UdpLayer::readPkt() not ready" << from;
std::cerr << std::endl;
#endif
}
}
return;
}
int UdpLayer::sendPkt(void *data, int size, sockaddr_in &to, int ttl)
{
/* if ttl is different -> set it */
if (ttl != getTTL())
{
setTTL(ttl);
}
/* and send! */
#ifdef DEBUG_UDP_LAYER
std::cerr << "UdpLayer::sendPkt() to: " << to << std::endl;
std::cerr << printPkt(data, size);
#endif
sendUdpPacket(data, size, to);
return size;
}
/* setup connections */
int UdpLayer::openSocket()
{
sockMtx.lock(); /********** LOCK MUTEX *********/
/* make a socket */
sockfd = tounet_socket(PF_INET, SOCK_DGRAM, 0);
#ifdef DEBUG_UDP_LAYER
std::cerr << "UpdStreamer::openSocket()" << std::endl;
#endif
/* bind to address */
#ifdef OPEN_UNIVERSAL_PORT
struct sockaddr_in tmpaddr = laddr;
tmpaddr.sin_addr.s_addr = 0;
if (0 != tounet_bind(sockfd, (struct sockaddr *) (&tmpaddr), sizeof(tmpaddr)))
#else
if (0 != tounet_bind(sockfd, (struct sockaddr *) (&laddr), sizeof(laddr)))
#endif
{
#ifdef DEBUG_UDP_LAYER
std::cerr << "Socket Failed to Bind to : " << laddr << std::endl;
std::cerr << "Error: " << tounet_errno() << std::endl;
#endif
errorState = EADDRINUSE;
//exit(1);
sockMtx.unlock(); /******** UNLOCK MUTEX *********/
return -1;
}
if (-1 == tounet_fcntl(sockfd, F_SETFL, O_NONBLOCK))
{
#ifdef DEBUG_UDP_LAYER
std::cerr << "Failed to Make Non-Blocking" << std::endl;
#endif
}
errorState = 0;
#ifdef DEBUG_UDP_LAYER
std::cerr << "Socket Bound to : " << laddr << std::endl;
#endif
sockMtx.unlock(); /******** UNLOCK MUTEX *********/
#ifdef DEBUG_UDP_LAYER
std::cerr << "Setting TTL to " << UDP_DEF_TTL << std::endl;
#endif
setTTL(UDP_DEF_TTL);
// start up our thread.
{
RsStackMutex stack(sockMtx); /********** LOCK MUTEX *********/
stopThread = false;
}
start();
return 1;
}
int UdpLayer::setTTL(int t)
{
sockMtx.lock(); /********** LOCK MUTEX *********/
int err = tounet_setsockopt(sockfd, IPPROTO_IP, IP_TTL, &t, sizeof(int));
ttl = t;
sockMtx.unlock(); /******** UNLOCK MUTEX *********/
#ifdef DEBUG_UDP_LAYER
std::cerr << "UdpLayer::setTTL(" << t << ") returned: " << err;
std::cerr << std::endl;
#endif
return err;
}
int UdpLayer::getTTL()
{
sockMtx.lock(); /********** LOCK MUTEX *********/
int t = ttl;
sockMtx.unlock(); /******** UNLOCK MUTEX *********/
return t;
}
/* monitoring / updates */
int UdpLayer::okay()
{
sockMtx.lock(); /********** LOCK MUTEX *********/
bool nonFatalError = ((errorState == 0) ||
(errorState == EAGAIN) ||
(errorState == EINPROGRESS));
sockMtx.unlock(); /******** UNLOCK MUTEX *********/
#ifdef DEBUG_UDP_LAYER
if (!nonFatalError)
{
std::cerr << "UdpLayer::NOT okay(): Error: " << errorState << std::endl;
}
#endif
return nonFatalError;
}
int UdpLayer::tick()
{
#ifdef DEBUG_UDP_LAYER
std::cerr << "UdpLayer::tick()" << std::endl;
#endif
return 1;
}
/******************* Internals *************************************/
int UdpLayer::receiveUdpPacket(void *data, int *size, struct sockaddr_in &from)
{
struct sockaddr_in fromaddr;
socklen_t fromsize = sizeof(fromaddr);
int insize = *size;
sockMtx.lock(); /********** LOCK MUTEX *********/
insize = tounet_recvfrom(sockfd,data,insize,0,
(struct sockaddr*)&fromaddr,&fromsize);
sockMtx.unlock(); /******** UNLOCK MUTEX *********/
if (0 < insize)
{
#ifdef DEBUG_UDP_LAYER
std::cerr << "receiveUdpPacket() from: " << fromaddr;
std::cerr << " Size: " << insize;
std::cerr << std::endl;
#endif
*size = insize;
from = fromaddr;
return insize;
}
return -1;
}
int UdpLayer::sendUdpPacket(const void *data, int size, struct sockaddr_in &to)
{
/* send out */
#ifdef DEBUG_UDP_LAYER
std::cerr << "UdpLayer::sendUdpPacket(): size: " << size;
std::cerr << " To: " << to << std::endl;
#endif
struct sockaddr_in toaddr = to;
sockMtx.lock(); /********** LOCK MUTEX *********/
tounet_sendto(sockfd, data, size, 0,
(struct sockaddr *) &(toaddr),
sizeof(toaddr));
sockMtx.unlock(); /******** UNLOCK MUTEX *********/
return 1;
}

View file

@ -1,187 +0,0 @@
/*
* "$Id: udplayer.h,v 1.5 2007-02-18 21:46:50 rmf24 Exp $"
*
* TCP-on-UDP (tou) network interface for RetroShare.
*
* Copyright 2004-2006 by Robert Fernie.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 2 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "retroshare@lunamutt.com".
*
*/
#ifndef TOU_UDP_LAYER_H
#define TOU_UDP_LAYER_H
/*
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
*/
#include "util/rsthreads.h"
/* universal networking functions */
#include "tou_net.h"
#include <iosfwd>
#include <list>
#include <deque>
bool operator==(const struct sockaddr_in &addr, const struct sockaddr_in &addr2);
bool operator<(const struct sockaddr_in &addr, const struct sockaddr_in &addr2);
std::string printPkt(void *d, int size);
std::string printPktOffset(unsigned int offset, void *d, unsigned int size);
/* UdpLayer ..... is the bottom layer which
* just sends and receives Udp packets.
*/
class UdpReceiver
{
public:
virtual void recvPkt(void *data, int size, struct sockaddr_in &from) = 0;
};
class UdpLayer: public RsThread
{
public:
UdpLayer(UdpReceiver *recv, struct sockaddr_in &local);
virtual ~UdpLayer() { return; }
int reset(struct sockaddr_in &local); /* calls join, close, openSocket */
int status(std::ostream &out);
/* setup connections */
int close();
int openSocket();
/* RsThread functions */
virtual void run(); /* called once the thread is started */
void recv_loop(); /* uses callback to UdpReceiver */
/* Higher Level Interface */
//int readPkt(void *data, int *size, struct sockaddr_in &from);
int sendPkt(void *data, int size, struct sockaddr_in &to, int ttl);
/* monitoring / updates */
int okay();
int tick();
/* data */
/* internals */
protected:
virtual int receiveUdpPacket(void *data, int *size, struct sockaddr_in &from);
virtual int sendUdpPacket(const void *data, int size, struct sockaddr_in &to);
int setTTL(int t);
int getTTL();
/* low level */
private:
UdpReceiver *recv;
struct sockaddr_in laddr; /* local addr */
int errorState;
int sockfd;
int ttl;
bool stopThread;
RsMutex sockMtx;
};
#include <iostream>
#include <stdlib.h>
class LossyUdpLayer: public UdpLayer
{
public:
LossyUdpLayer(UdpReceiver *udpr, struct sockaddr_in &local, double frac)
:UdpLayer(udpr, local), lossFraction(frac)
{
return;
}
virtual ~LossyUdpLayer() { return; }
protected:
virtual int receiveUdpPacket(void *data, int *size, struct sockaddr_in &from)
{
double prob = (1.0 * (rand() / (RAND_MAX + 1.0)));
if (prob < lossFraction)
{
/* but discard */
if (0 < UdpLayer::receiveUdpPacket(data, size, from))
{
std::cerr << "LossyUdpLayer::receiveUdpPacket() Dropping packet!";
std::cerr << std::endl;
std::cerr << printPkt(data, *size);
std::cerr << std::endl;
std::cerr << "LossyUdpLayer::receiveUdpPacket() Packet Dropped!";
std::cerr << std::endl;
}
size = 0;
return -1;
}
// otherwise read normally;
return UdpLayer::receiveUdpPacket(data, size, from);
}
virtual int sendUdpPacket(const void *data, int size, struct sockaddr_in &to)
{
double prob = (1.0 * (rand() / (RAND_MAX + 1.0)));
if (prob < lossFraction)
{
/* discard */
std::cerr << "LossyUdpLayer::sendUdpPacket() Dropping packet!";
std::cerr << std::endl;
std::cerr << printPkt((void *) data, size);
std::cerr << std::endl;
std::cerr << "LossyUdpLayer::sendUdpPacket() Packet Dropped!";
std::cerr << std::endl;
return size;
}
// otherwise read normally;
return UdpLayer::sendUdpPacket(data, size, to);
}
double lossFraction;
};
#endif

View file

@ -0,0 +1,144 @@
/*
* tcponudp/udppeer.cc
*
* libretroshare.
*
* Copyright 2010 by Robert Fernie
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 3 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "retroshare@lunamutt.com".
*
*/
#include "udppeer.h"
#include <iostream>
/*
* #define DEBUG_UDP_PEER 1
*/
UdpPeerReceiver::UdpPeerReceiver(UdpPublisher *pub)
:UdpSubReceiver(pub)
{
return;
}
/* higher level interface */
int UdpPeerReceiver::recvPkt(void *data, int size, struct sockaddr_in &from)
{
/* print packet information */
#ifdef DEBUG_UDP_PEER
std::cerr << "UdpPeerReceiver::recvPkt(" << size << ") from: " << from;
std::cerr << std::endl;
#endif
RsStackMutex stack(peerMtx); /********** LOCK MUTEX *********/
/* look for a peer */
std::map<struct sockaddr_in, UdpPeer *>::iterator it;
it = streams.find(from);
if (it == streams.end())
{
/* peer unknown */
#ifdef DEBUG_UDP_PEER
std::cerr << "UdpPeerReceiver::recvPkt() Peer Unknown!";
std::cerr << std::endl;
#endif
return 0;
}
else
{
/* forward to them */
#ifdef DEBUG_UDP_PEER
std::cerr << "UdpPeerReceiver::recvPkt() Sending to UdpPeer: ";
std::cerr << it->first;
std::cerr << std::endl;
#endif
(it->second)->recvPkt(data, size);
return 1;
}
/* done */
}
int UdpPeerReceiver::status(std::ostream &out)
{
RsStackMutex stack(peerMtx); /********** LOCK MUTEX *********/
out << "UdpPeerReceiver::status()" << std::endl;
out << "UdpPeerReceiver::peers:" << std::endl;
std::map<struct sockaddr_in, UdpPeer *>::iterator it;
for(it = streams.begin(); it != streams.end(); it++)
{
out << "\t" << it->first << std::endl;
}
out << std::endl;
return 1;
}
/* add a TCPonUDP stream */
int UdpPeerReceiver::addUdpPeer(UdpPeer *peer, const struct sockaddr_in &raddr)
{
RsStackMutex stack(peerMtx); /********** LOCK MUTEX *********/
/* check for duplicate */
std::map<struct sockaddr_in, UdpPeer *>::iterator it;
it = streams.find(raddr);
bool ok = (it == streams.end());
if (!ok)
{
#ifdef DEBUG_UDP_PEER
std::cerr << "UdpPeerReceiver::addUdpPeer() Peer already exists!" << std::endl;
std::cerr << "UdpPeerReceiver::addUdpPeer() ERROR" << std::endl;
#endif
}
else
{
streams[raddr] = peer;
}
return ok;
}
int UdpPeerReceiver::removeUdpPeer(UdpPeer *peer)
{
RsStackMutex stack(peerMtx); /********** LOCK MUTEX *********/
/* check for duplicate */
std::map<struct sockaddr_in, UdpPeer *>::iterator it;
for(it = streams.begin(); it != streams.end(); it++)
{
if (it->second == peer)
{
#ifdef DEBUG_UDP_PEER
std::cerr << "UdpPeerReceiver::removeUdpPeer() SUCCESS" << std::endl;
#endif
streams.erase(it);
return 1;
}
}
#ifdef DEBUG_UDP_PEER
std::cerr << "UdpPeerReceiver::removeUdpPeer() ERROR" << std::endl;
#endif
return 0;
}

View file

@ -0,0 +1,71 @@
#ifndef RS_UDP_PEER_RECV_H
#define RS_UDP_PEER_RECV_H
/*
* tcponudp/udppeer.h
*
* libretroshare.
*
* Copyright 2010 by Robert Fernie
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 3 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "retroshare@lunamutt.com".
*
*/
#include <netinet/in.h>
#include "util/rsthreads.h"
#include <iosfwd>
#include <list>
#include <deque>
#include "tcponudp/rsudpstack.h"
class UdpPeer
{
public:
virtual ~UdpPeer() { return; }
virtual void recvPkt(void *data, int size) = 0;
};
class UdpPeerReceiver: public UdpSubReceiver
{
public:
UdpPeerReceiver(UdpPublisher *pub);
virtual ~UdpPeerReceiver() { return; }
/* add a TCPonUDP stream */
int addUdpPeer(UdpPeer *peer, const struct sockaddr_in &raddr);
int removeUdpPeer(UdpPeer *peer);
/* callback for recved data (overloaded from UdpReceiver) */
virtual int recvPkt(void *data, int size, struct sockaddr_in &from);
int status(std::ostream &out);
private:
RsMutex peerMtx; /* for all class data (below) */
std::map<struct sockaddr_in, UdpPeer *> streams;
};
#endif

View file

@ -1,91 +0,0 @@
/*
* libretroshare/src/tcponudp: udpsock_test.cc
*
* TCP-on-UDP (tou) network interface for RetroShare.
*
* Copyright 2007-2008 by Robert Fernie.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 2 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "retroshare@lunamutt.com".
*
*/
#include "udptestfn.h"
#include "udplayer.h"
#define MAX_PEERS 16
int main(int argc, char **argv)
{
/* get local and remote addresses */
struct sockaddr_in local;
struct sockaddr_in peers[MAX_PEERS];
int numpeers = 0;
int i,j;
local.sin_family = AF_INET;
inet_aton("127.0.0.1", &(local.sin_addr));
local.sin_port = htons(8767);
for(i = 0; i < MAX_PEERS; i++)
{
peers[i].sin_family = AF_INET;
inet_aton("127.0.0.1", &(peers[i].sin_addr));
peers[i].sin_port = htons(8768);
}
if (argc < 3)
{
std::cerr << "Usage: " << argv[0] << " <l-port> [<p-port1 ..]";
std::cerr << std::endl;
exit(1);
}
local.sin_port = htons(atoi(argv[1]));
std::cerr << argv[0] << " Local Port: " << ntohs(local.sin_port);
std::cerr << std::endl;
for(i = 2; i < argc; i++)
{
numpeers++;
peers[i-2].sin_port = htons(atoi(argv[i]));
std::cerr << "\tPeer Port: " << ntohs(peers[i-2].sin_port);
std::cerr << std::endl;
}
/* create a udp layer */
UdpRecvTest recv;
UdpLayer udpl(&recv, local);
udpl.start();
int size = 12;
void *data = malloc(size);
int ttl = 64;
/* push packets to the peer */
for(i = 0; i < 60; i++)
{
sleep(1);
for(j = 0; j < numpeers; j++)
{
udpl.sendPkt(data, size, peers[j], ttl);
}
}
return 1;
}

View file

@ -1,91 +0,0 @@
/*
* libretroshare/src/tcponudp: udpsort_test.cc
*
* TCP-on-UDP (tou) network interface for RetroShare.
*
* Copyright 2007-2008 by Robert Fernie.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 2 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "retroshare@lunamutt.com".
*
*/
#include "udptestfn.h"
#include "udpsorter.h"
#define MAX_PEERS 16
int main(int argc, char **argv)
{
/* get local and remote addresses */
struct sockaddr_in local;
struct sockaddr_in peers[MAX_PEERS];
int numpeers = 0;
int i,j;
local.sin_family = AF_INET;
inet_aton("127.0.0.1", &(local.sin_addr));
local.sin_port = htons(8767);
for(i = 0; i < MAX_PEERS; i++)
{
peers[i].sin_family = AF_INET;
inet_aton("127.0.0.1", &(peers[i].sin_addr));
peers[i].sin_port = htons(8768);
}
if (argc < 3)
{
std::cerr << "Usage: " << argv[0] << " <l-port> [<p-port1 ..]";
std::cerr << std::endl;
exit(1);
}
local.sin_port = htons(atoi(argv[1]));
std::cerr << argv[0] << " Local Port: " << ntohs(local.sin_port);
std::cerr << std::endl;
UdpSorter udps(local);
for(i = 2; i < argc; i++)
{
numpeers++;
peers[i-2].sin_port = htons(atoi(argv[i]));
std::cerr << "\tPeer Port: " << ntohs(peers[i-2].sin_port);
std::cerr << std::endl;
UdpPeerTest *pt = new UdpPeerTest(peers[i-2]);
udps.addUdpPeer(pt, peers[i-2]);
}
int size = 12;
void *data = malloc(size);
int ttl = 64;
/* push packets to the peer */
for(i = 0; i < 60; i++)
{
sleep(1);
for(j = 0; j < numpeers; j++)
{
udps.sendPkt(data, size, peers[j], ttl);
}
}
return 1;
}

View file

@ -1,13 +1,13 @@
/*
* libretroshare/src/tcponudp: udpsorter.cc
* tcponudp/udpstunner.cc
*
* TCP-on-UDP (tou) network interface for RetroShare.
* libretroshare.
*
* Copyright 2007-2008 by Robert Fernie.
* Copyright 2010 by Robert Fernie
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 2 as published by the Free Software Foundation.
* License Version 3 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@ -23,246 +23,97 @@
*
*/
#include "udpsorter.h"
#include "util/rsnet.h"
#include "util/rsprint.h"
#include <stdlib.h>
#include "udpstunner.h"
#include <iostream>
#include <sstream>
#include <iomanip>
#include "util/rsdebug.h"
const int rsudpsorterzone = 28477;
static const int STUN_TTL = 64;
#define TOU_STUN_MIN_PEERS 5
/*
* #define DEBUG_UDP_SORTER 1
* #define DEBUG_UDP_STUN 1
*/
const int32_t TOU_STUN_MAX_FAIL_COUNT = 3; /* 3 tries (could be higher?) */
const int32_t TOU_STUN_MAX_SEND_RATE = 5; /* every 5 seconds */
const int32_t TOU_STUN_MAX_RECV_RATE = 25; /* every 25 seconds */
const int32_t TOU_STUN_ADDR_MAX_AGE = 120; /* 2 minutes */
UdpSorter::UdpSorter(struct sockaddr_in &local)
:udpLayer(NULL), laddr(local), eaddrKnown(false), eaddrStable(false),
UdpStunner::UdpStunner(UdpPublisher *pub)
:UdpSubReceiver(pub), eaddrKnown(false), eaddrStable(false),
mStunKeepAlive(false), mStunLastRecv(0), mStunLastSend(0)
{
sockaddr_clear(&eaddr);
openSocket();
return;
}
bool UdpSorter::resetAddress(struct sockaddr_in &local)
{
return udpLayer->reset(local);
}
/* higher level interface */
void UdpSorter::recvPkt(void *data, int size, struct sockaddr_in &from)
int UdpStunner::recvPkt(void *data, int size, struct sockaddr_in &from)
{
/* print packet information */
#ifdef DEBUG_UDP_SORTER
std::cerr << "UdpSorter::recvPkt(" << size << ") from: " << from;
#ifdef DEBUG_UDP_STUNNER
std::cerr << "UdpStunner::recvPkt(" << size << ") from: " << from;
std::cerr << std::endl;
#endif
sortMtx.lock(); /********** LOCK MUTEX *********/
mStunLastRecv = time(NULL);
/* look for a peer */
std::map<struct sockaddr_in, UdpPeer *>::iterator it;
it = streams.find(from);
RsStackMutex stack(stunMtx); /********** LOCK MUTEX *********/
/* check for STUN packet */
if (UdpStun_isStunPacket(data, size))
{
#ifdef DEBUG_UDP_SORTER
std::cerr << "UdpSorter::recvPkt() is Stun Packet";
mStunLastRecv = time(NULL);
#ifdef DEBUG_UDP_STUNNER
std::cerr << "UdpStunner::recvPkt() is Stun Packet";
std::cerr << std::endl;
#endif
/* respond */
locked_handleStunPkt(data, size, from);
}
else if (it == streams.end())
{
/* peer unknown */
#ifdef DEBUG_UDP_SORTER
std::cerr << "UdpSorter::recvPkt() Peer Unknown!";
std::cerr << std::endl;
#endif
std::ostringstream out;
out << "UdpSorter::recvPkt() ";
out << "from unknown: " << from;
rslog(RSL_WARNING,rsudpsorterzone,out.str());
}
else
{
/* forward to them */
#ifdef DEBUG_UDP_SORTER
std::cerr << "UdpSorter::recvPkt() Sending to UdpPeer: ";
std::cerr << it->first;
std::cerr << std::endl;
#endif
(it->second)->recvPkt(data, size);
}
sortMtx.unlock(); /******** UNLOCK MUTEX *********/
/* done */
return 1;
}
return 0;
}
int UdpSorter::sendPkt(void *data, int size, struct sockaddr_in &to, int ttl)
int UdpStunner::status(std::ostream &out)
{
/* print packet information */
#ifdef DEBUG_UDP_SORTER
std::cerr << "UdpSorter::sendPkt(" << size << ") ttl: " << ttl;
std::cerr << " to: " << to;
std::cerr << std::endl;
#endif
RsStackMutex stack(stunMtx); /********** LOCK MUTEX *********/
/* send to udpLayer */
return udpLayer->sendPkt(data, size, to, ttl);
}
int UdpSorter::status(std::ostream &out)
{
sortMtx.lock(); /********** LOCK MUTEX *********/
out << "UdpSorter::status()" << std::endl;
out << "localaddr: " << laddr << std::endl;
out << "UdpSorter::peers:" << std::endl;
std::map<struct sockaddr_in, UdpPeer *>::iterator it;
for(it = streams.begin(); it != streams.end(); it++)
out << "UdpStunner::status()" << std::endl;
out << "UdpStunner::potentialpeers:" << std::endl;
std::list<TouStunPeer>::iterator it;
for(it = mStunList.begin(); it != mStunList.end(); it++)
{
out << "\t" << it->first << std::endl;
out << "\t" << it->id << std::endl;
}
out << std::endl;
sortMtx.unlock(); /******** UNLOCK MUTEX *********/
udpLayer->status(out);
return 1;
}
/* setup connections */
int UdpSorter::openSocket()
int UdpStunner::tick()
{
udpLayer = new UdpLayer(this, laddr);
// start is called by udpLayer now, for consistency
// with reset!
//udpLayer->start();
return 1;
}
/* monitoring / updates */
int UdpSorter::okay()
{
return udpLayer->okay();
}
int UdpSorter::tick()
{
#ifdef DEBUG_UDP_SORTER
std::cerr << "UdpSorter::tick()" << std::endl;
#ifdef DEBUG_UDP_STUNNER
std::cerr << "UdpStunner::tick()" << std::endl;
#endif
checkStunKeepAlive();
return 1;
}
int UdpSorter::close()
{
/* TODO */
return 1;
}
/* add a TCPonUDP stream */
int UdpSorter::addUdpPeer(UdpPeer *peer, const struct sockaddr_in &raddr)
{
sortMtx.lock(); /********** LOCK MUTEX *********/
/* check for duplicate */
std::map<struct sockaddr_in, UdpPeer *>::iterator it;
it = streams.find(raddr);
bool ok = (it == streams.end());
if (!ok)
{
#ifdef DEBUG_UDP_SORTER
std::cerr << "UdpSorter::addUdpPeer() Peer already exists!" << std::endl;
std::cerr << "UdpSorter::addUdpPeer() ERROR" << std::endl;
#endif
}
else
{
streams[raddr] = peer;
}
sortMtx.unlock(); /******** UNLOCK MUTEX *********/
return ok;
}
int UdpSorter::removeUdpPeer(UdpPeer *peer)
{
RsStackMutex stack(sortMtx); /********** LOCK MUTEX *********/
/* check for duplicate */
std::map<struct sockaddr_in, UdpPeer *>::iterator it;
for(it = streams.begin(); it != streams.end(); it++)
{
if (it->second == peer)
{
#ifdef DEBUG_UDP_SORTER
std::cerr << "UdpSorter::removeUdpPeer() SUCCESS" << std::endl;
#endif
streams.erase(it);
return 1;
}
}
#ifdef DEBUG_UDP_SORTER
std::cerr << "UdpSorter::removeUdpPeer() ERROR" << std::endl;
#endif
return 0;
}
/******************************* STUN Handling ********************************/
/* respond */
bool UdpSorter::locked_handleStunPkt(void *data, int size, struct sockaddr_in &from)
bool UdpStunner::locked_handleStunPkt(void *data, int size, struct sockaddr_in &from)
{
if (size == 20) /* request */
{
#ifdef DEBUG_UDP_SORTER
std::cerr << "UdpSorter::handleStunPkt() got Request from: ";
std::cerr << rs_inet_ntoa(from.sin_addr) << ":" << ntohs(from.sin_port);
#ifdef DEBUG_UDP_STUNNER
std::cerr << "UdpStunner::handleStunPkt() got Request from: ";
std::cerr << inet_ntoa(from.sin_addr) << ":" << ntohs(from.sin_port);
std::cerr << std::endl;
#endif
{
std::ostringstream out;
out << "UdpSorter::handleStunPkt() got Request from: " << from;
rslog(RSL_WARNING,rsudpsorterzone,out.str());
}
/* generate a response */
int len;
void *pkt = UdpStun_generate_stun_reply(&from, &len);
@ -272,8 +123,8 @@ bool UdpSorter::locked_handleStunPkt(void *data, int size, struct sockaddr_in &f
int sentlen = sendPkt(pkt, len, from, STUN_TTL);
free(pkt);
#ifdef DEBUG_UDP_SORTER
std::cerr << "UdpSorter::handleStunPkt() sent Response size:" << sentlen;
#ifdef DEBUG_UDP_STUNNER
std::cerr << "UdpStunner::handleStunPkt() sent Response size:" << sentlen;
std::cerr << std::endl;
#endif
@ -281,8 +132,8 @@ bool UdpSorter::locked_handleStunPkt(void *data, int size, struct sockaddr_in &f
}
else if (size == 28)
{
#ifdef DEBUG_UDP_SORTER
std::cerr << "UdpSorter::handleStunPkt() got Response";
#ifdef DEBUG_UDP_STUNNER
std::cerr << "UdpStunner::handleStunPkt() got Response";
std::cerr << std::endl;
#endif
/* got response */
@ -290,42 +141,36 @@ bool UdpSorter::locked_handleStunPkt(void *data, int size, struct sockaddr_in &f
bool good = UdpStun_response(data, size, eAddr);
if (good)
{
#ifdef DEBUG_UDP_SORTER
std::cerr << "UdpSorter::handleStunPkt() got Ext Addr: ";
std::cerr << rs_inet_ntoa(eAddr.sin_addr) << ":" << ntohs(eAddr.sin_port);
#ifdef DEBUG_UDP_STUNNER
std::cerr << "UdpStunner::handleStunPkt() got Ext Addr: ";
std::cerr << inet_ntoa(eAddr.sin_addr) << ":" << ntohs(eAddr.sin_port);
out << " from: " << from;
std::cerr << std::endl;
#endif
{
std::ostringstream out;
out << "UdpSorter::handleStunPkt() got Response from: " << from;
out << " Ext Addr: " << eAddr;
rslog(RSL_WARNING,rsudpsorterzone,out.str());
}
locked_recvdStun(from, eAddr);
return true;
}
}
#ifdef DEBUG_UDP_SORTER
std::cerr << "UdpSorter::handleStunPkt() Bad Packet";
#ifdef DEBUG_UDP_STUNNER
std::cerr << "UdpStunner::handleStunPkt() Bad Packet";
std::cerr << std::endl;
#endif
return false;
}
bool UdpSorter::externalAddr(struct sockaddr_in &external, uint8_t &stable)
bool UdpStunner::externalAddr(struct sockaddr_in &external, uint8_t &stable)
{
RsStackMutex stack(sortMtx); /********** LOCK MUTEX *********/
RsStackMutex stack(stunMtx); /********** LOCK MUTEX *********/
if (eaddrKnown)
{
/* address timeout */
if (time(NULL) - eaddrTime > TOU_STUN_ADDR_MAX_AGE)
{
std::cerr << "UdpSorter::externalAddr() eaddr expired";
std::cerr << "UdpStunner::externalAddr() eaddr expired";
std::cerr << std::endl;
return false;
@ -338,16 +183,16 @@ bool UdpSorter::externalAddr(struct sockaddr_in &external, uint8_t &stable)
else
stable = 0;
#ifdef DEBUG_UDP_SORTER
std::cerr << "UdpSorter::externalAddr() eaddr:" << rs_inet_ntoa(external.sin_addr);
#ifdef DEBUG_UDP_STUNNER
std::cerr << "UdpStunner::externalAddr() eaddr:" << inet_ntoa(external.sin_addr);
std::cerr << ":" << ntohs(external.sin_port) << " stable: " << (int) stable;
std::cerr << std::endl;
#endif
return true;
}
#ifdef DEBUG_UDP_SORTER
std::cerr << "UdpSorter::externalAddr() eaddr unknown";
#ifdef DEBUG_UDP_STUNNER
std::cerr << "UdpStunner::externalAddr() eaddr unknown";
std::cerr << std::endl;
#endif
@ -355,21 +200,14 @@ bool UdpSorter::externalAddr(struct sockaddr_in &external, uint8_t &stable)
}
int UdpSorter::doStun(struct sockaddr_in stun_addr)
int UdpStunner::doStun(struct sockaddr_in stun_addr)
{
#ifdef DEBUG_UDP_SORTER
std::cerr << "UdpSorter::doStun()";
#ifdef DEBUG_UDP_STUNNER
std::cerr << "UdpStunner::doStun()";
std::cerr << std::endl;
#endif
/* send out a stun packet -> save in the local variable */
if (!okay())
{
#ifdef DEBUG_UDP_SORTER
std::cerr << "UdpSorter::doStun() Not Active";
std::cerr << std::endl;
#endif
}
#define MAX_STUN_SIZE 64
char stundata[MAX_STUN_SIZE];
@ -377,8 +215,8 @@ int UdpSorter::doStun(struct sockaddr_in stun_addr)
bool done = UdpStun_generate_stun_pkt(stundata, &tmplen);
if (!done)
{
#ifdef DEBUG_UDP_SORTER
std::cerr << "UdpSorter::doStun() Failed";
#ifdef DEBUG_UDP_STUNNER
std::cerr << "UdpStunner::doStun() Failed";
std::cerr << std::endl;
#endif
//pqioutput(PQL_ALERT, pqistunzone, "pqistunner::stun() Failed!");
@ -388,16 +226,17 @@ int UdpSorter::doStun(struct sockaddr_in stun_addr)
/* send it off */
int sentlen = sendPkt(stundata, tmplen, stun_addr, STUN_TTL);
sortMtx.lock(); /********** LOCK MUTEX *********/
mStunLastSend = time(NULL);
sortMtx.unlock(); /******** UNLOCK MUTEX *********/
{
RsStackMutex stack(stunMtx); /********** LOCK MUTEX *********/
mStunLastSend = time(NULL);
}
#ifdef DEBUG_UDP_SORTER
#ifdef DEBUG_UDP_STUNNER
std::ostringstream out;
out << "UdpSorter::doStun() Sent Stun Packet(" << sentlen << ") from:";
out << rs_inet_ntoa(laddr.sin_addr) << ":" << ntohs(laddr.sin_port);
out << "UdpStunner::doStun() Sent Stun Packet(" << sentlen << ") from:";
out << inet_ntoa(laddr.sin_addr) << ":" << ntohs(laddr.sin_port);
out << " to:";
out << rs_inet_ntoa(stun_addr.sin_addr) << ":" << ntohs(stun_addr.sin_port);
out << inet_ntoa(stun_addr.sin_addr) << ":" << ntohs(stun_addr.sin_port);
std::cerr << out.str() << std::endl;
@ -433,10 +272,10 @@ bool UdpStun_response(void *stun_pkt, int size, struct sockaddr_in &addr)
addr.sin_port = ((uint16_t *) stun_pkt)[11];
#ifdef DEBUG_UDP_SORTER
#ifdef DEBUG_UDP_STUNNER
std::ostringstream out;
out << "UdpSorter::response() Recvd a Stun Response, ext_addr: ";
out << rs_inet_ntoa(addr.sin_addr) << ":" << ntohs(addr.sin_port);
out << "UdpStunner::response() Recvd a Stun Response, ext_addr: ";
out << inet_ntoa(addr.sin_addr) << ":" << ntohs(addr.sin_port);
std::cerr << out.str() << std::endl;
#endif
@ -492,15 +331,15 @@ void *UdpStun_generate_stun_reply(struct sockaddr_in *stun_addr, int *len)
bool UdpStun_isStunPacket(void *data, int size)
{
#ifdef DEBUG_UDP_SORTER
std::cerr << "UdpSorter::isStunPacket() ?";
#ifdef DEBUG_UDP_STUNNER
std::cerr << "UdpStunner::isStunPacket() ?";
std::cerr << std::endl;
#endif
if (size < 20)
{
#ifdef DEBUG_UDP_SORTER
std::cerr << "UdpSorter::isStunPacket() (size < 20) -> false";
#ifdef DEBUG_UDP_STUNNER
std::cerr << "UdpStunner::isStunPacket() (size < 20) -> false";
std::cerr << std::endl;
#endif
return false;
@ -510,8 +349,8 @@ bool UdpStun_isStunPacket(void *data, int size)
uint16_t pktsize = ntohs(((uint16_t *) data)[1]);
if (size != pktsize)
{
#ifdef DEBUG_UDP_SORTER
std::cerr << "UdpSorter::isStunPacket() (size != pktsize) -> false";
#ifdef DEBUG_UDP_STUNNER
std::cerr << "UdpStunner::isStunPacket() (size != pktsize) -> false";
std::cerr << std::endl;
#endif
return false;
@ -519,8 +358,8 @@ bool UdpStun_isStunPacket(void *data, int size)
if ((size == 20) && (0x0001 == ntohs(((uint16_t *) data)[0])))
{
#ifdef DEBUG_UDP_SORTER
std::cerr << "UdpSorter::isStunPacket() (size=20 & data[0]=0x0001) -> true";
#ifdef DEBUG_UDP_STUNNER
std::cerr << "UdpStunner::isStunPacket() (size=20 & data[0]=0x0001) -> true";
std::cerr << std::endl;
#endif
/* request */
@ -529,8 +368,8 @@ bool UdpStun_isStunPacket(void *data, int size)
if ((size == 28) && (0x0101 == ntohs(((uint16_t *) data)[0])))
{
#ifdef DEBUG_UDP_SORTER
std::cerr << "UdpSorter::isStunPacket() (size=28 & data[0]=0x0101) -> true";
#ifdef DEBUG_UDP_STUNNER
std::cerr << "UdpStunner::isStunPacket() (size=28 & data[0]=0x0101) -> true";
std::cerr << std::endl;
#endif
/* response */
@ -546,32 +385,33 @@ bool UdpStun_isStunPacket(void *data, int size)
/******************************* STUN Handling ********************************/
bool UdpSorter::setStunKeepAlive(uint32_t required)
bool UdpStunner::setStunKeepAlive(uint32_t required)
{
sortMtx.lock(); /********** LOCK MUTEX *********/
RsStackMutex stack(stunMtx); /********** LOCK MUTEX *********/
mStunKeepAlive = (required != 0);
#ifdef DEBUG_UDP_SORTER
std::cerr << "UdpSorter::setStunKeepAlive() to: " << mStunKeepAlive;
#ifdef DEBUG_UDP_STUNNER
std::cerr << "UdpStunner::setStunKeepAlive() to: " << mStunKeepAlive;
std::cerr << std::endl;
#endif
sortMtx.unlock(); /******** UNLOCK MUTEX *********/
return 1;
}
bool UdpSorter::addStunPeer(const struct sockaddr_in &remote, const char *peerid)
bool UdpStunner::addStunPeer(const struct sockaddr_in &remote, const char *peerid)
{
/* add to the list */
#ifdef DEBUG_UDP_SORTER
std::cerr << "UdpSorter::addStunPeer()";
#ifdef DEBUG_UDP_STUNNER
std::cerr << "UdpStunner::addStunPeer()";
std::cerr << std::endl;
#endif
sortMtx.lock(); /********** LOCK MUTEX *********/
bool needStun = (!eaddrKnown);
sortMtx.unlock(); /******** UNLOCK MUTEX *********/
bool needStun;
{
RsStackMutex stack(stunMtx); /********** LOCK MUTEX *********/
needStun = (!eaddrKnown);
}
storeStunPeer(remote, peerid, needStun);
@ -584,15 +424,15 @@ bool UdpSorter::addStunPeer(const struct sockaddr_in &remote, const char *pee
return true;
}
bool UdpSorter::storeStunPeer(const struct sockaddr_in &remote, const char *peerid, bool sent)
bool UdpStunner::storeStunPeer(const struct sockaddr_in &remote, const char *peerid, bool sent)
{
#ifdef DEBUG_UDP_SORTER
std::cerr << "UdpSorter::storeStunPeer()";
#ifdef DEBUG_UDP_STUNNER
std::cerr << "UdpStunner::storeStunPeer()";
std::cerr << std::endl;
#endif
RsStackMutex stack(sortMtx); /********** LOCK MUTEX *********/
RsStackMutex stack(stunMtx); /********** LOCK MUTEX *********/
std::list<TouStunPeer>::iterator it;
for(it = mStunList.begin(); it != mStunList.end(); it++)
@ -600,8 +440,8 @@ bool UdpSorter::storeStunPeer(const struct sockaddr_in &remote, const char *p
if ((remote.sin_addr.s_addr == it->remote.sin_addr.s_addr) &&
(remote.sin_port == it->remote.sin_port))
{
#ifdef DEBUG_UDP_SORTER
std::cerr << "UdpSorter::storeStunPeer() Peer Already There!";
#ifdef DEBUG_UDP_STUNNER
std::cerr << "UdpStunner::storeStunPeer() Peer Already There!";
std::cerr << std::endl;
#endif
/* already there */
@ -623,8 +463,8 @@ bool UdpSorter::storeStunPeer(const struct sockaddr_in &remote, const char *p
mStunList.push_back(peer);
#ifdef DEBUG_UDP_SORTER
std::cerr << "UdpSorter::storeStunPeer() Added Peer";
#ifdef DEBUG_UDP_STUNNER
std::cerr << "UdpStunner::storeStunPeer() Added Peer";
std::cerr << std::endl;
#endif
@ -632,23 +472,23 @@ bool UdpSorter::storeStunPeer(const struct sockaddr_in &remote, const char *p
}
bool UdpSorter::checkStunKeepAlive()
bool UdpStunner::checkStunKeepAlive()
{
#ifdef DEBUG_UDP_SORTER
std::cerr << "UdpSorter::checkStunKeepAlive()";
#ifdef DEBUG_UDP_STUNNER
std::cerr << "UdpStunner::checkStunKeepAlive()";
std::cerr << std::endl;
#endif
TouStunPeer peer;
time_t now;
{
RsStackMutex stack(sortMtx); /********** LOCK MUTEX *********/
RsStackMutex stack(stunMtx); /********** LOCK MUTEX *********/
if (!mStunKeepAlive)
{
#ifdef DEBUG_UDP_SORTER
std::cerr << "UdpSorter::checkStunKeepAlive() FALSE";
#ifdef DEBUG_UDP_STUNNER
std::cerr << "UdpStunner::checkStunKeepAlive() FALSE";
std::cerr << std::endl;
#endif
return false; /* all good */
@ -660,8 +500,8 @@ bool UdpSorter::checkStunKeepAlive()
if ((now - mStunLastSend < TOU_STUN_MAX_SEND_RATE) ||
(now - mStunLastRecv < TOU_STUN_MAX_RECV_RATE))
{
#ifdef DEBUG_UDP_SORTER
std::cerr << "UdpSorter::checkStunKeepAlive() To Fast ... delaying";
#ifdef DEBUG_UDP_STUNNER
std::cerr << "UdpStunner::checkStunKeepAlive() To Fast ... delaying";
std::cerr << std::endl;
#endif
/* too fast */
@ -670,8 +510,8 @@ bool UdpSorter::checkStunKeepAlive()
if (mStunList.size() < 1)
{
#ifdef DEBUG_UDP_SORTER
std::cerr << "UdpSorter::checkStunKeepAlive() No Peers in List!";
#ifdef DEBUG_UDP_STUNNER
std::cerr << "UdpStunner::checkStunKeepAlive() No Peers in List!";
std::cerr << std::endl;
#endif
return false;
@ -685,28 +525,28 @@ bool UdpSorter::checkStunKeepAlive()
doStun(peer.remote);
{
RsStackMutex stack(sortMtx); /********** LOCK MUTEX *********/
RsStackMutex stack(stunMtx); /********** LOCK MUTEX *********/
if (peer.failCount < TOU_STUN_MAX_FAIL_COUNT)
{
peer.failCount++;
peer.lastsend = now;
mStunList.push_back(peer);
#ifdef DEBUG_UDP_SORTER
std::cerr << "UdpSorter::checkStunKeepAlive() pushing Stun peer to back of list";
#ifdef DEBUG_UDP_STUNNER
std::cerr << "UdpStunner::checkStunKeepAlive() pushing Stun peer to back of list";
std::cerr << std::endl;
#endif
}
else
{
#ifdef DEBUG_UDP_SORTER
std::cerr << "UdpSorter::checkStunKeepAlive() Discarding bad stun peer";
#ifdef DEBUG_UDP_STUNNER
std::cerr << "UdpStunner::checkStunKeepAlive() Discarding bad stun peer";
std::cerr << std::endl;
#endif
}
#ifdef DEBUG_UDP_SORTER
#ifdef DEBUG_UDP_STUNNER
locked_printStunList();
#endif
@ -717,14 +557,14 @@ bool UdpSorter::checkStunKeepAlive()
}
bool UdpSorter::locked_recvdStun(const struct sockaddr_in &remote, const struct sockaddr_in &extaddr)
bool UdpStunner::locked_recvdStun(const struct sockaddr_in &remote, const struct sockaddr_in &extaddr)
{
#ifdef DEBUG_UDP_SORTER
#ifdef DEBUG_UDP_STUNNER
std::ostringstream out;
out << "UdpSorter::locked_recvdStun() from:";
out << rs_inet_ntoa(remote.sin_addr) << ":" << ntohs(remote.sin_port);
out << "UdpStunner::locked_recvdStun() from:";
out << inet_ntoa(remote.sin_addr) << ":" << ntohs(remote.sin_port);
out << " claiming ExtAddr is:";
out << rs_inet_ntoa(extaddr.sin_addr) << ":" << ntohs(extaddr.sin_port);
out << inet_ntoa(extaddr.sin_addr) << ":" << ntohs(extaddr.sin_port);
std::cerr << out.str() << std::endl;
#endif
@ -745,7 +585,7 @@ bool UdpSorter::locked_recvdStun(const struct sockaddr_in &remote, const stru
}
}
#ifdef DEBUG_UDP_SORTER
#ifdef DEBUG_UDP_STUNNER
locked_printStunList();
#endif
@ -754,11 +594,11 @@ bool UdpSorter::locked_recvdStun(const struct sockaddr_in &remote, const stru
return found;
}
bool UdpSorter::locked_checkExternalAddress()
bool UdpStunner::locked_checkExternalAddress()
{
#ifdef DEBUG_UDP_SORTER
#ifdef DEBUG_UDP_STUNNER
std::ostringstream out;
out << "UdpSorter::locked_checkExternalAddress()";
out << "UdpStunner::locked_checkExternalAddress()";
std::cerr << out.str() << std::endl;
#endif
@ -811,8 +651,8 @@ bool UdpSorter::locked_checkExternalAddress()
eaddr = p1->eaddr;
eaddrTime = now;
#ifdef DEBUG_UDP_SORTER
std::cerr << "UdpSorter::locked_checkExternalAddress() Found State:";
#ifdef DEBUG_UDP_STUNNER
std::cerr << "UdpStunner::locked_checkExternalAddress() Found State:";
if (eaddrStable)
std::cerr << " Stable NAT translation (GOOD!) ";
else
@ -828,9 +668,9 @@ bool UdpSorter::locked_checkExternalAddress()
bool UdpSorter::locked_printStunList()
bool UdpStunner::locked_printStunList()
{
#ifdef DEBUG_UDP_SORTER
#ifdef DEBUG_UDP_STUNNER
std::ostringstream out;
time_t now = time(NULL);
@ -841,9 +681,9 @@ bool UdpSorter::locked_printStunList()
std::list<TouStunPeer>::iterator it;
for(it = mStunList.begin(); it != mStunList.end(); it++)
{
out << "id:" << RsUtil::BinToHex(it->id) << " addr: " << rs_inet_ntoa(it->remote.sin_addr);
out << "id:" << RsUtil::BinToHex(it->id) << " addr: " << inet_ntoa(it->remote.sin_addr);
out << ":" << htons(it->remote.sin_port);
out << " eaddr: " << rs_inet_ntoa(it->eaddr.sin_addr);
out << " eaddr: " << inet_ntoa(it->eaddr.sin_addr);
out << ":" << htons(it->eaddr.sin_port);
out << " failCount: " << it->failCount;
out << " lastSend: " << now - it->lastsend;
@ -857,11 +697,11 @@ bool UdpSorter::locked_printStunList()
}
bool UdpSorter::getStunPeer(int idx, std::string &id,
bool UdpStunner::getStunPeer(int idx, std::string &id,
struct sockaddr_in &remote, struct sockaddr_in &eaddr,
uint32_t &failCount, time_t &lastSend)
{
RsStackMutex stack(sortMtx); /********** LOCK MUTEX *********/
RsStackMutex stack(stunMtx); /********** LOCK MUTEX *********/
std::list<TouStunPeer>::iterator it;
int i;
@ -881,9 +721,9 @@ bool UdpSorter::getStunPeer(int idx, std::string &id,
}
bool UdpSorter::needStunPeers()
bool UdpStunner::needStunPeers()
{
RsStackMutex stack(sortMtx); /********** LOCK MUTEX *********/
RsStackMutex stack(stunMtx); /********** LOCK MUTEX *********/
return (mStunList.size() < TOU_STUN_MIN_PEERS);
}

View file

@ -1,13 +1,15 @@
#ifndef RS_UDP_STUN_H
#define RS_UDP_STUN_H
/*
* libretroshare/src/tcponudp: udpsorter.h
* tcponudp/udpstunner.h
*
* TCP-on-UDP (tou) network interface for RetroShare.
* libretroshare.
*
* Copyright 2007-2008 by Robert Fernie.
* Copyright 2010 by Robert Fernie
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 2 as published by the Free Software Foundation.
* License Version 3 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@ -23,28 +25,16 @@
*
*/
#include <netinet/in.h>
#ifndef TOU_UDP_SORTER_H
#define TOU_UDP_SORTER_H
#include "tcponudp/rsudpstack.h"
#include "util/rsthreads.h"
#include <string>
/* universal networking functions */
#include "tou_net.h"
#include <iosfwd>
#include <map>
#include "udplayer.h"
/* UdpSorter ..... filters the UDP packets.
/* UdpStun.
* Stuns peers to determine external addresses.
*/
class UdpPeer
{
public:
virtual void recvPkt(void *data, int size) = 0;
};
class TouStunPeer
{
public:
@ -72,18 +62,12 @@ class TouStunPeer
};
class UdpSorter: public UdpReceiver
class UdpStunner: public UdpSubReceiver
{
public:
UdpSorter(struct sockaddr_in &local);
virtual ~UdpSorter() { return; }
bool resetAddress(struct sockaddr_in &local);
/* add a TCPonUDP stream */
int addUdpPeer(UdpPeer *peer, const struct sockaddr_in &raddr);
int removeUdpPeer(UdpPeer *peer);
UdpStunner(UdpPublisher *pub);
virtual ~UdpStunner() { return; }
bool setStunKeepAlive(uint32_t required);
bool addStunPeer(const struct sockaddr_in &remote, const char *peerid);
@ -97,22 +81,12 @@ bool needStunPeers();
bool externalAddr(struct sockaddr_in &remote, uint8_t &stable);
/* Packet IO */
/* pass-through send packets */
int sendPkt(void *data, int size, struct sockaddr_in &to, int ttl);
/* callback for recved data (overloaded from UdpReceiver) */
virtual void recvPkt(void *data, int size, struct sockaddr_in &from);
int status(std::ostream &out);
/* setup connections */
int openSocket();
virtual int recvPkt(void *data, int size, struct sockaddr_in &from);
virtual int status(std::ostream &out);
/* monitoring / updates */
int okay();
int tick();
int close();
private:
/* STUN handling */
@ -120,7 +94,6 @@ bool locked_handleStunPkt(void *data, int size, struct sockaddr_in &from);
int doStun(struct sockaddr_in stun_addr);
/* stun keepAlive */
bool locked_printStunList();
bool locked_recvdStun(const struct sockaddr_in &remote, const struct sockaddr_in &extaddr);
@ -128,13 +101,10 @@ bool locked_checkExternalAddress();
bool storeStunPeer(const struct sockaddr_in &remote, const char *peerid, bool sent);
UdpLayer *udpLayer;
RsMutex sortMtx; /* for all class data (below) */
struct sockaddr_in laddr; /* local addr */
RsMutex stunMtx; /* for all class data (below) */
struct sockaddr_in eaddr; /* external addr */
bool eaddrKnown;
bool eaddrStable; /* if true then usable. if false -> Symmettric NAT */
time_t eaddrTime;
@ -145,10 +115,6 @@ bool storeStunPeer(const struct sockaddr_in &remote, const char *peerid, bool
std::list<TouStunPeer> mStunList; /* potentials */
std::map<struct sockaddr_in, UdpPeer *> streams;
};
/* generic stun functions */