* 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:
parent
75743fcd65
commit
a7470d6bd5
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
@ -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},
|
||||||
|
Loading…
Reference in New Issue
Block a user