* The kernelland_emu now supports turning off debug output; tcp_tester can toggle

this option now using the "dprintf" command
* Added dump_block() function to kernelland_emu
* Added tcpdump-like output to tcp_tester for each TCP segment, lines from the
  server are red, lines from the client are black.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@19334 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2006-11-20 17:38:21 +00:00
parent 75743fcd65
commit a7470d6bd5
2 changed files with 167 additions and 24 deletions

View File

@ -29,6 +29,8 @@ static const char *gModuleDirs[] = {
NULL NULL
}; };
bool gDebugOutputEnabled = true;
struct module_name_list { struct module_name_list {
set<string> names; set<string> names;
set<string>::iterator it; set<string>::iterator it;
@ -695,7 +697,7 @@ devfs_publish_partition(const char *path, const partition_info *info)
} }
void extern "C" void
panic(const char *format, ...) panic(const char *format, ...)
{ {
va_list args; va_list args;
@ -709,10 +711,12 @@ panic(const char *format, ...)
} }
// dprintf extern "C" void
void
dprintf(const char *format,...) dprintf(const char *format,...)
{ {
if (!gDebugOutputEnabled)
return;
va_list args; va_list args;
va_start(args, format); va_start(args, format);
printf("\33[34m"); printf("\33[34m");
@ -721,9 +725,45 @@ dprintf(const char *format,...)
va_end(args); va_end(args);
} }
// user_memcpy
extern "C" extern "C" void
status_t dump_block(const char *buffer, int size, const char *prefix)
{
const int DUMPED_BLOCK_SIZE = 16;
int i;
for (i = 0; i < size;) {
int start = i;
dprintf(prefix);
for (; i < start + DUMPED_BLOCK_SIZE; i++) {
if (!(i % 4))
dprintf(" ");
if (i >= size)
dprintf(" ");
else
dprintf("%02x", *(unsigned char *)(buffer + i));
}
dprintf(" ");
for (i = start; i < start + DUMPED_BLOCK_SIZE; i++) {
if (i < size) {
char c = buffer[i];
if (c < 30)
dprintf(".");
else
dprintf("%c", c);
} else
break;
}
dprintf("\n");
}
}
extern "C" status_t
user_memcpy(void *to, const void *from, size_t size) user_memcpy(void *to, const void *from, size_t size)
{ {
char *tmp = (char *)to; char *tmp = (char *)to;
@ -735,9 +775,8 @@ user_memcpy(void *to, const void *from, size_t size)
return 0; return 0;
} }
//user_strcpy
extern "C" extern "C" int
int
user_strcpy(char *to, const char *from) user_strcpy(char *to, const char *from)
{ {
while ((*to++ = *from++) != '\0') while ((*to++ = *from++) != '\0')
@ -745,7 +784,7 @@ user_strcpy(char *to, const char *from)
return 0; return 0;
} }
// user_strlcpy
/*! \brief Copies at most (\a size - 1) characters from the string in \a from to /*! \brief Copies at most (\a size - 1) characters from the string in \a from to
the string in \a to, NULL-terminating the result. the string in \a to, NULL-terminating the result.
@ -755,8 +794,7 @@ user_strcpy(char *to, const char *from)
\return strlen(\a from). \return strlen(\a from).
*/ */
extern "C" extern "C" ssize_t
ssize_t
user_strlcpy(char *to, const char *from, size_t size) user_strlcpy(char *to, const char *from, size_t size)
{ {
int from_length = 0; int from_length = 0;
@ -777,17 +815,6 @@ user_strlcpy(char *to, const char *from, size_t size)
} }
/*! Needed for locking */
bool kernel_startup = false;
extern "C" bool
arch_int_are_interrupts_enabled(void)
{
return true;
}
// #pragma mark - Private locking functions // #pragma mark - Private locking functions

View File

@ -1,6 +1,8 @@
#include "argv.h" #include "argv.h"
#include "tcp.h"
#include "utility.h" #include "utility.h"
#include <NetBufferUtilities.h>
#include <net_buffer.h> #include <net_buffer.h>
#include <net_datalink.h> #include <net_datalink.h>
#include <net_protocol.h> #include <net_protocol.h>
@ -26,6 +28,8 @@ struct cmd_entry {
extern "C" status_t _add_builtin_module(module_info *info); extern "C" status_t _add_builtin_module(module_info *info);
extern bool gDebugOutputEnabled;
// from libkernelland_emu.so
extern struct net_buffer_module_info gNetBufferModule; extern struct net_buffer_module_info gNetBufferModule;
// from net_buffer.cpp // from net_buffer.cpp
@ -42,6 +46,8 @@ extern struct net_socket_module_info gNetSocketModule;
struct net_protocol_module_info *gTCPModule; struct net_protocol_module_info *gTCPModule;
struct net_socket *gServerSocket, *gClientSocket; struct net_socket *gServerSocket, *gClientSocket;
bool gTCPDump = true;
static struct net_domain sDomain = { static struct net_domain sDomain = {
"ipv4", "ipv4",
AF_INET, AF_INET,
@ -51,6 +57,13 @@ static struct net_domain sDomain = {
}; };
bool
is_server(sockaddr *addr)
{
return ((sockaddr_in *)addr)->sin_port == htons(1024);
}
// #pragma mark - stack // #pragma mark - stack
@ -473,6 +486,8 @@ get_route(struct net_domain *_domain, const struct sockaddr *address)
{ {
static net_route route; static net_route route;
route.interface = &gInterface; route.interface = &gInterface;
route.mtu = 1500;
return &route; return &route;
} }
@ -585,7 +600,6 @@ status_t
domain_send_routed_data(net_protocol *protocol, struct net_route *route, domain_send_routed_data(net_protocol *protocol, struct net_route *route,
net_buffer *buffer) net_buffer *buffer)
{ {
printf("send routed buffer %p!\n", buffer);
return sDomain.module->receive_data(buffer); return sDomain.module->receive_data(buffer);
} }
@ -629,6 +643,95 @@ domain_get_mtu(net_protocol *protocol, const struct sockaddr *address)
status_t status_t
domain_receive_data(net_buffer *buffer) domain_receive_data(net_buffer *buffer)
{ {
static uint32 packetNumber = 1;
if (gTCPDump) {
NetBufferHeader<tcp_header> bufferHeader(buffer);
if (bufferHeader.Status() < B_OK)
return bufferHeader.Status();
tcp_header &header = bufferHeader.Data();
printf("% 3ld ", packetNumber++);
if (is_server((sockaddr *)&buffer->source))
printf("\33[31mserver > client: ");
else
printf("client > server: ");
int32 length = buffer->size - header.HeaderLength();
if ((header.flags & TCP_FLAG_PUSH) != 0)
putchar('P');
if ((header.flags & TCP_FLAG_SYNCHRONIZE) != 0)
putchar('S');
if ((header.flags & TCP_FLAG_FINISH) != 0)
putchar('F');
if ((header.flags & TCP_FLAG_RESET) != 0)
putchar('R');
if ((header.flags
& (TCP_FLAG_SYNCHRONIZE | TCP_FLAG_FINISH | TCP_FLAG_PUSH | TCP_FLAG_RESET)) == 0)
putchar('.');
printf(" %lu:%lu (%lu)", header.Sequence(), header.Sequence() + length, length);
if ((header.flags & TCP_FLAG_ACKNOWLEDGE) != 0)
printf(" ack %lu", header.Acknowledge());
printf(" win %u", header.AdvertisedWindow());
if (header.HeaderLength() > sizeof(tcp_header)) {
int32 size = header.HeaderLength() - sizeof(tcp_header);
tcp_option *option;
uint8 optionsBuffer[1024];
if (gBufferModule->direct_access(buffer, sizeof(tcp_header),
size, (void **)&option) != B_OK) {
if (size > 1024) {
printf("options too large to take into account (%ld bytes)\n", size);
size = 1024;
}
gBufferModule->read(buffer, sizeof(tcp_header), optionsBuffer, size);
option = (tcp_option *)optionsBuffer;
}
while (size > 0) {
uint32 length = 1;
switch (option->kind) {
case TCP_OPTION_END:
case TCP_OPTION_NOP:
break;
case TCP_OPTION_MAX_SEGMENT_SIZE:
printf(" <mss %u>", ntohs(option->max_segment_size));
length = 4;
break;
case TCP_OPTION_WINDOW_SHIFT:
printf(" <ws %u>", option->window_shift);
length = 3;
break;
case TCP_OPTION_TIMESTAMP:
printf(" <ts %lu:%lu>", option->timestamp, option->timestamp_reply);
length = 10;
break;
default:
length = option->length;
// make sure we don't end up in an endless loop
if (length == 0)
size = 0;
break;
}
size -= length;
option = (tcp_option *)((uint8 *)option + length);
}
}
printf("\33[0m\n");
bufferHeader.Detach();
}
return gTCPModule->receive_data(buffer); return gTCPModule->receive_data(buffer);
} }
@ -727,8 +830,21 @@ do_connect(int argc, char** argv)
} }
static void
do_dprintf(int argc, char** argv)
{
if (argc > 1)
gDebugOutputEnabled = !strcmp(argv[1], "on");
else
gDebugOutputEnabled = !gDebugOutputEnabled;
printf("debug output turned %s.\n", gDebugOutputEnabled ? "on" : "off");
}
static cmd_entry sBuiltinCommands[] = { static cmd_entry sBuiltinCommands[] = {
{"connect", do_connect, "Connects the client"}, {"connect", do_connect, "Connects the client"},
{"dprintf", do_dprintf, "Toggles debug output"},
{"help", do_help, "prints this help text"}, {"help", do_help, "prints this help text"},
{"quit", NULL, "exits the application"}, {"quit", NULL, "exits the application"},
{NULL, NULL, NULL}, {NULL, NULL, NULL},