mirror of
https://github.com/RetroShare/RetroShare.git
synced 2025-05-10 18:15:18 -04:00
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:
parent
c1b624832f
commit
fcdd7ee113
34 changed files with 627 additions and 1770 deletions
60
libretroshare/src/tests/tcponudp/Makefile
Normal file
60
libretroshare/src/tests/tcponudp/Makefile
Normal file
|
@ -0,0 +1,60 @@
|
|||
|
||||
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
|
||||
###############################################################
|
||||
|
632
libretroshare/src/tests/tcponudp/internal_tou.cc
Normal file
632
libretroshare/src/tests/tcponudp/internal_tou.cc
Normal file
|
@ -0,0 +1,632 @@
|
|||
/*
|
||||
* "$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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
502
libretroshare/src/tests/tcponudp/largefile_tou.cc
Normal file
502
libretroshare/src/tests/tcponudp/largefile_tou.cc
Normal file
|
@ -0,0 +1,502 @@
|
|||
/*
|
||||
* "$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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
491
libretroshare/src/tests/tcponudp/pair_tou.cc
Normal file
491
libretroshare/src/tests/tcponudp/pair_tou.cc
Normal file
|
@ -0,0 +1,491 @@
|
|||
/*
|
||||
* "$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
|
453
libretroshare/src/tests/tcponudp/reset_tou.cc
Normal file
453
libretroshare/src/tests/tcponudp/reset_tou.cc
Normal file
|
@ -0,0 +1,453 @@
|
|||
/*
|
||||
* "$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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
500
libretroshare/src/tests/tcponudp/test_tou.cc
Normal file
500
libretroshare/src/tests/tcponudp/test_tou.cc
Normal file
|
@ -0,0 +1,500 @@
|
|||
/*
|
||||
* "$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
|
289
libretroshare/src/tests/tcponudp/udp_server.cc
Normal file
289
libretroshare/src/tests/tcponudp/udp_server.cc
Normal file
|
@ -0,0 +1,289 @@
|
|||
/*
|
||||
* "$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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
91
libretroshare/src/tests/tcponudp/udpsock_test.cc
Normal file
91
libretroshare/src/tests/tcponudp/udpsock_test.cc
Normal file
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* 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;
|
||||
}
|
||||
|
||||
|
||||
|
91
libretroshare/src/tests/tcponudp/udpsort_test.cc
Normal file
91
libretroshare/src/tests/tcponudp/udpsort_test.cc
Normal file
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* 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;
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue