Added support for simulating simultaneous connect (via the -s option).
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@19365 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
bed835af1e
commit
b38e841106
@ -69,6 +69,7 @@ struct net_socket *gServerSocket, *gClientSocket;
|
||||
static struct context sClientContext, sServerContext;
|
||||
|
||||
static vint32 sPacketNumber = 1;
|
||||
static double sRandomDrop = 0.0;
|
||||
static set<uint32> sDropList;
|
||||
static bigtime_t sRoundTripTime = 0;
|
||||
static bool sIncreasingRoundTrip = false;
|
||||
@ -77,6 +78,7 @@ static bool sTCPDump = true;
|
||||
static bigtime_t sStartTime;
|
||||
static double sRandomReorder = 0.0;
|
||||
static set<uint32> sReorderList;
|
||||
static bool sSimultaneousConnect = false;
|
||||
|
||||
static struct net_domain sDomain = {
|
||||
"ipv4",
|
||||
@ -94,6 +96,20 @@ is_server(const sockaddr* addr)
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
is_syn(net_buffer* buffer)
|
||||
{
|
||||
NetBufferHeader<tcp_header> bufferHeader(buffer);
|
||||
if (bufferHeader.Status() < B_OK)
|
||||
return bufferHeader.Status();
|
||||
|
||||
tcp_header &header = bufferHeader.Data();
|
||||
bufferHeader.Detach();
|
||||
|
||||
return (header.flags & TCP_FLAG_SYNCHRONIZE) != 0;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - stack
|
||||
|
||||
|
||||
@ -580,10 +596,10 @@ get_route(struct net_domain *_domain, const struct sockaddr *address)
|
||||
{
|
||||
if (is_server(address)) {
|
||||
// to the server
|
||||
return &sClientContext.route;
|
||||
return &sServerContext.route;
|
||||
}
|
||||
|
||||
return &sServerContext.route;
|
||||
return &sClientContext.route;
|
||||
}
|
||||
|
||||
|
||||
@ -747,7 +763,8 @@ domain_receive_data(net_buffer *buffer)
|
||||
uint32 packetNumber = atomic_add(&sPacketNumber, 1);
|
||||
|
||||
bool drop = false;
|
||||
if (sDropList.find(packetNumber) != sDropList.end())
|
||||
if (sDropList.find(packetNumber) != sDropList.end()
|
||||
|| (sRandomDrop > 0.0 && (1.0 * rand() / RAND_MAX) > sRandomDrop))
|
||||
drop = true;
|
||||
|
||||
if (!drop && (sRoundTripTime > 0 || sRandomRoundTrip || sIncreasingRoundTrip)) {
|
||||
@ -937,6 +954,21 @@ receiving_thread(void* _data)
|
||||
if (buffer == NULL)
|
||||
break;
|
||||
|
||||
if (sSimultaneousConnect && context->server && is_syn(buffer)) {
|
||||
// delay getting the SYN request, and connect as well
|
||||
sockaddr_in address;
|
||||
memset(&address, 0, sizeof(address));
|
||||
address.sin_family = AF_INET;
|
||||
address.sin_port = htons(1023);
|
||||
address.sin_addr.s_addr = htonl(0xc0a80001);
|
||||
|
||||
status_t status = socket_connect(gServerSocket, (struct sockaddr *)&address,
|
||||
sizeof(struct sockaddr));
|
||||
if (status < B_OK)
|
||||
fprintf(stderr, "tcp_tester: simultaneous connect failed: %s\n", strerror(status));
|
||||
|
||||
sSimultaneousConnect = false;
|
||||
}
|
||||
if (sRandomReorder > 0.0 || sReorderList.find(sPacketNumber) != sReorderList.end()
|
||||
&& reorderBuffer == NULL
|
||||
&& (1.0 * rand() / RAND_MAX) > sRandomReorder) {
|
||||
@ -980,6 +1012,37 @@ server_thread(void*)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
setup_server()
|
||||
{
|
||||
sockaddr_in address;
|
||||
memset(&address, 0, sizeof(address));
|
||||
address.sin_family = AF_INET;
|
||||
address.sin_port = htons(1024);
|
||||
address.sin_addr.s_addr = INADDR_ANY;
|
||||
|
||||
status_t status = socket_bind(gServerSocket, (struct sockaddr *)&address,
|
||||
sizeof(struct sockaddr));
|
||||
if (status < B_OK) {
|
||||
fprintf(stderr, "tcp_tester: cannot bind server: %s\n", strerror(status));
|
||||
exit(1);
|
||||
}
|
||||
status = socket_listen(gServerSocket, 40);
|
||||
if (status < B_OK) {
|
||||
fprintf(stderr, "tcp_tester: server cannot listen: %s\n", strerror(status));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
thread_id serverThread = spawn_thread(server_thread, "server", B_NORMAL_PRIORITY, NULL);
|
||||
if (serverThread < B_OK) {
|
||||
fprintf(stderr, "tcp_tester: cannot start server: %s\n", strerror(serverThread));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
resume_thread(serverThread);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
setup_context(struct context& context, bool server)
|
||||
{
|
||||
@ -1016,9 +1079,36 @@ static void do_help(int argc, char** argv);
|
||||
static void
|
||||
do_connect(int argc, char** argv)
|
||||
{
|
||||
sSimultaneousConnect = false;
|
||||
|
||||
int port = 1024;
|
||||
if (argc > 1)
|
||||
if (argc > 1) {
|
||||
if (!strcmp(argv[1], "-s"))
|
||||
sSimultaneousConnect = true;
|
||||
else if (isdigit(argv[1][0]))
|
||||
port = atoi(argv[1]);
|
||||
else {
|
||||
fprintf(stderr, "usage: connect [-s|<port-number>]\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (sSimultaneousConnect) {
|
||||
// bind to a port first, so the other end can find us
|
||||
sockaddr_in address;
|
||||
memset(&address, 0, sizeof(address));
|
||||
address.sin_family = AF_INET;
|
||||
address.sin_port = htons(1023);
|
||||
address.sin_addr.s_addr = htonl(0xc0a80001);
|
||||
|
||||
status_t status = socket_bind(gClientSocket, (struct sockaddr *)&address,
|
||||
sizeof(struct sockaddr));
|
||||
if (status < B_OK) {
|
||||
fprintf(stderr, "Could not bind to port 1023: %s\n", strerror(status));
|
||||
sSimultaneousConnect = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
sStartTime = system_time();
|
||||
|
||||
@ -1026,6 +1116,9 @@ do_connect(int argc, char** argv)
|
||||
memset(&address, 0, sizeof(address));
|
||||
address.sin_family = AF_INET;
|
||||
address.sin_port = htons(port);
|
||||
if (sSimultaneousConnect)
|
||||
address.sin_addr.s_addr = htonl(0xc0a80001);
|
||||
else
|
||||
address.sin_addr.s_addr = INADDR_ANY;
|
||||
|
||||
status_t status = socket_connect(gClientSocket, (struct sockaddr *)&address,
|
||||
@ -1101,6 +1194,17 @@ do_drop(int argc, char** argv)
|
||||
// flush drop list
|
||||
sDropList.clear();
|
||||
puts("drop list cleared.");
|
||||
} else if (!strcmp(argv[1], "-r")) {
|
||||
if (argc < 3) {
|
||||
fprintf(stderr, "No drop probability specified.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
sRandomDrop = atof(argv[2]);
|
||||
if (sRandomDrop < 0.0)
|
||||
sRandomDrop = 0;
|
||||
else if (sRandomDrop > 1.0)
|
||||
sRandomDrop = 1.0;
|
||||
} else if (isdigit(argv[1][0])) {
|
||||
// add to drop list
|
||||
for (int i = 1; i < argc; i++) {
|
||||
@ -1115,9 +1219,11 @@ do_drop(int argc, char** argv)
|
||||
} else {
|
||||
// print usage
|
||||
puts("usage: drop <packet-number> [...]\n"
|
||||
" or: drop -r <probability>\n\n"
|
||||
" or: drop [-f]\n\n"
|
||||
"Specifiying -f flushes the drop list; if you called drop without\n"
|
||||
"any arguments, the current drop list is dumped.");
|
||||
"Specifiying -f flushes the drop list, -r sets the probability a packet\n"
|
||||
"is dropped; if you called drop without any arguments, the current\n"
|
||||
"drop list is dumped.");
|
||||
}
|
||||
}
|
||||
|
||||
@ -1285,32 +1391,7 @@ main(int argc, char** argv)
|
||||
printf("*** Server: %p (%ld), Client: %p (%ld)\n", server,
|
||||
sServerContext.thread, client, sClientContext.thread);
|
||||
|
||||
// setup server
|
||||
|
||||
sockaddr_in address;
|
||||
memset(&address, 0, sizeof(address));
|
||||
address.sin_family = AF_INET;
|
||||
address.sin_port = htons(1024);
|
||||
address.sin_addr.s_addr = INADDR_ANY;
|
||||
|
||||
status = socket_bind(gServerSocket, (struct sockaddr *)&address, sizeof(struct sockaddr));
|
||||
if (status < B_OK) {
|
||||
fprintf(stderr, "tcp_tester: cannot bind server: %s\n", strerror(status));
|
||||
return 1;
|
||||
}
|
||||
status = socket_listen(gServerSocket, 40);
|
||||
if (status < B_OK) {
|
||||
fprintf(stderr, "tcp_tester: server cannot listen: %s\n", strerror(status));
|
||||
return 1;
|
||||
}
|
||||
|
||||
thread_id serverThread = spawn_thread(server_thread, "server", B_NORMAL_PRIORITY, NULL);
|
||||
if (serverThread < B_OK) {
|
||||
fprintf(stderr, "tcp_tester: cannot start server: %s\n", strerror(serverThread));
|
||||
return 1;
|
||||
}
|
||||
|
||||
resume_thread(serverThread);
|
||||
setup_server();
|
||||
|
||||
while (true) {
|
||||
printf("> ");
|
||||
@ -1354,8 +1435,8 @@ main(int argc, char** argv)
|
||||
free(argv);
|
||||
}
|
||||
|
||||
close_protocol(server);
|
||||
close_protocol(client);
|
||||
close_protocol(server);
|
||||
|
||||
cleanup_context(sClientContext);
|
||||
cleanup_context(sServerContext);
|
||||
|
Loading…
Reference in New Issue
Block a user