* Made it work and build again after recent network stack changes.

* Implement "close" command that actively closes the server socket, or does
  an simultaneous close. Even though this triggers an "endless conversation"
  between two time-wait endpoints on Haiku, it works fine in the shell.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@25225 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2008-04-28 15:48:49 +00:00
parent cb2afe5cc7
commit c927bf5c49

View File

@ -1,5 +1,5 @@
/*
* Copyright 2006-2007, Haiku, Inc. All Rights Reserved.
* Copyright 2006-2008, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
@ -7,6 +7,9 @@
*/
#define _KERNEL_DEBUG_H
// avoid including the private kernel debug.h header
#include "argv.h"
#include "tcp.h"
#include "utility.h"
@ -93,6 +96,8 @@ static bigtime_t sStartTime;
static double sRandomReorder = 0.0;
static set<uint32> sReorderList;
static bool sSimultaneousConnect = false;
static bool sSimultaneousClose = false;
static bool sServerActiveClose = false;
static struct net_domain sDomain = {
"ipv4",
@ -103,23 +108,36 @@ static struct net_domain sDomain = {
};
bool
static bool
is_server(const sockaddr* addr)
{
return ((sockaddr_in*)addr)->sin_port == htons(1024);
}
bool
is_syn(net_buffer* buffer)
static uint8
tcp_segment_flags(net_buffer* buffer)
{
NetBufferHeaderReader<tcp_header> bufferHeader(buffer);
if (bufferHeader.Status() < B_OK)
return bufferHeader.Status();
tcp_header &header = bufferHeader.Data();
return header.flags;
}
return (header.flags & TCP_FLAG_SYNCHRONIZE) != 0;
static bool
is_syn(net_buffer* buffer)
{
return (tcp_segment_flags(buffer) & TCP_FLAG_SYNCHRONIZE) != 0;
}
static bool
is_fin(net_buffer* buffer)
{
return (tcp_segment_flags(buffer) & TCP_FLAG_FINISH) != 0;
}
@ -155,6 +173,12 @@ delete_object_cache(object_cache *cache)
}
extern "C" void
scheduler_enqueue_in_run_queue(struct thread *thread)
{
}
// #pragma mark - stack
@ -193,33 +217,53 @@ register_domain_receiving_protocol(int family, int type, const char *moduleName)
}
static bool
dummy_is_syscall(void)
{
return false;
}
static bool
dummy_is_restarted_syscall(void)
{
return false;
}
static void
dummy_store_syscall_restart_timeout(bigtime_t timeout)
{
}
static net_stack_module_info gNetStackModule = {
{
NET_STACK_MODULE_NAME,
0,
std_ops
},
NULL, //register_domain,
NULL, //unregister_domain,
NULL, // register_domain,
NULL, // unregister_domain,
get_domain,
register_domain_protocols,
register_domain_datalink_protocols,
register_domain_receiving_protocol,
NULL, //get_domain_receiving_protocol,
NULL, //put_domain_receiving_protocol,
NULL, // get_domain_receiving_protocol,
NULL, // put_domain_receiving_protocol,
NULL, //register_device_deframer,
NULL, //unregister_device_deframer,
NULL, //register_domain_device_handler,
NULL, //register_device_handler,
NULL, //unregister_device_handler,
NULL, //register_device_monitor,
NULL, //unregister_device_monitor,
NULL, //device_link_changed,
NULL, //device_removed,
NULL, //device_enqueue_buffer,
NULL, // register_device_deframer,
NULL, // unregister_device_deframer,
NULL, // register_domain_device_handler,
NULL, // register_device_handler,
NULL, // unregister_device_handler,
NULL, // register_device_monitor,
NULL, // unregister_device_monitor,
NULL, // device_link_changed,
NULL, // device_removed,
NULL, // device_enqueue_buffer,
notify_socket,
@ -236,6 +280,11 @@ static net_stack_module_info gNetStackModule = {
set_timer,
cancel_timer,
is_timer_active,
dummy_is_syscall,
dummy_is_restarted_syscall,
dummy_store_syscall_restart_timeout,
NULL, // restore_syscall_restart_timeout
};
@ -621,23 +670,23 @@ net_socket_module_info gNetSocketModule = {
0,
std_ops
},
NULL, //socket_open,
NULL, //socket_close,
NULL, //socket_free,
NULL, // open,
NULL, // close,
NULL, // free,
NULL, //socket_readv,
NULL, //socket_writev,
NULL, //socket_control,
NULL, // readv,
NULL, // writev,
NULL, // control,
NULL, //socket_read_avail,
NULL, //socket_send_avail,
NULL, // read_avail,
NULL, // send_avail,
NULL, //socket_send_data,
NULL, //socket_receive_data,
NULL, // send_data,
NULL, // receive_data,
NULL, //get_option,
NULL, //set_option,
NULL, //socket_get_next_stat,
NULL, // get_option,
NULL, // set_option,
NULL, // get_next_stat,
// connections
socket_spawn_pending,
@ -648,22 +697,23 @@ net_socket_module_info gNetSocketModule = {
socket_connected,
// notifications
NULL, //socket_request_notification,
NULL, //socket_cancel_notification,
NULL, // request_notification,
NULL, // cancel_notification,
socket_notify,
// standard socket API
NULL, //socket_accept,
NULL, //socket_bind,
NULL, //socket_connect,
NULL, //socket_getpeername,
NULL, //socket_getsockname,
NULL, //socket_getsockopt,
NULL, //socket_listen,
NULL, //socket_recv,
NULL, //socket_send,
NULL, //socket_setsockopt,
NULL, //socket_shutdown,
NULL, // accept,
NULL, // bind,
NULL, // connect,
NULL, // getpeername,
NULL, // getsockname,
NULL, // getsockopt,
NULL, // listen,
NULL, // receive,
NULL, // send,
NULL, // setsockopt,
NULL, // shutdown,
NULL, // socketpair
};
@ -1046,6 +1096,8 @@ net_protocol_module_info gDomainModule = {
0,
std_ops
},
NET_PROTOCOL_ATOMIC_MESSAGES,
NULL, // init
NULL, // uninit
domain_open,
@ -1071,6 +1123,8 @@ net_protocol_module_info gDomainModule = {
NULL, // deliver_data
domain_error,
domain_error_reply,
NULL, // attach_ancillary_data
NULL, // process_ancillary_data
};
@ -1094,7 +1148,8 @@ receiving_thread(void* _data)
while (true) {
context->lock.Lock();
net_buffer* buffer = (net_buffer*)list_remove_head_item(&context->list);
net_buffer* buffer = (net_buffer*)list_remove_head_item(
&context->list);
context->lock.Unlock();
if (buffer == NULL)
@ -1108,13 +1163,17 @@ receiving_thread(void* _data)
address.sin_port = htons(1023);
address.sin_addr.s_addr = htonl(0xc0a80001);
status_t status = socket_connect(gServerSocket, (struct sockaddr *)&address,
sizeof(struct sockaddr));
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 (sSimultaneousClose && !context->server && is_fin(buffer)) {
close_protocol(gClientSocket->first_protocol);
sSimultaneousClose = false;
}
if ((sRandomReorder > 0.0
|| sReorderList.find(sPacketNumber) != sReorderList.end())
&& reorderBuffer == NULL
@ -1159,6 +1218,12 @@ server_thread(void*)
while ((bytesRead = socket_recv(connectionSocket, buffer,
sizeof(buffer), 0)) > 0) {
printf("server: received %ld bytes\n", bytesRead);
if (sServerActiveClose) {
printf("server: active close\n");
close_protocol(connectionSocket->first_protocol);
return 0;
}
}
if (bytesRead < 0)
printf("server: receiving failed: %s\n", strerror(bytesRead));
@ -1183,7 +1248,7 @@ setup_server()
address.sin_port = htons(1024);
address.sin_addr.s_addr = INADDR_ANY;
status_t status = socket_bind(gServerSocket, (struct sockaddr *)&address,
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));
@ -1337,6 +1402,32 @@ do_send(int argc, char** argv)
}
static void
do_close(int argc, char** argv)
{
sSimultaneousClose = false;
sServerActiveClose = true;
if (argc > 1) {
if (!strcmp(argv[1], "-s"))
sSimultaneousClose = true;
else {
fprintf(stderr, "usage: close [-s]\n");
return;
}
}
gClientSocket->send.timeout = 0;
char buffer[32767] = {'q'};
ssize_t bytesWritten = socket_send(gClientSocket, buffer, sizeof(buffer), 0);
if (bytesWritten < B_OK) {
fprintf(stderr, "failed sending buffer: %s\n", strerror(bytesWritten));
return;
}
}
static void
do_drop(int argc, char** argv)
{
@ -1493,6 +1584,7 @@ do_dprintf(int argc, char** argv)
static cmd_entry sBuiltinCommands[] = {
{"connect", do_connect, "Connects the client"},
{"send", do_send, "Sends data from the client to the server"},
{"close", do_close, "Performs an active or simultaneous close"},
{"dprintf", do_dprintf, "Toggles debug output"},
{"drop", do_drop, "Lets you drop packets during transfer"},
{"reorder", do_reorder, "Lets you reorder packets during transfer"},
@ -1514,6 +1606,9 @@ do_help(int argc, char** argv)
}
// #pragma mark -
int
main(int argc, char** argv)
{
@ -1524,10 +1619,10 @@ main(int argc, char** argv)
return 1;
}
_add_builtin_module((module_info *)&gNetStackModule);
_add_builtin_module((module_info *)&gNetBufferModule);
_add_builtin_module((module_info *)&gNetSocketModule);
_add_builtin_module((module_info *)&gNetDatalinkModule);
_add_builtin_module((module_info*)&gNetStackModule);
_add_builtin_module((module_info*)&gNetBufferModule);
_add_builtin_module((module_info*)&gNetSocketModule);
_add_builtin_module((module_info*)&gNetDatalinkModule);
_add_builtin_module(modules[0]);
if (_get_builtin_dependencies() < B_OK) {
fprintf(stderr, "tcp_tester: Could not initialize modules: %s\n",