diff --git a/src/tests/add-ons/kernel/kernelland_emu.cpp b/src/tests/add-ons/kernel/kernelland_emu.cpp index e0a068675d..d332cad914 100644 --- a/src/tests/add-ons/kernel/kernelland_emu.cpp +++ b/src/tests/add-ons/kernel/kernelland_emu.cpp @@ -29,6 +29,8 @@ static const char *gModuleDirs[] = { NULL }; +bool gDebugOutputEnabled = true; + struct module_name_list { set names; set::iterator it; @@ -695,7 +697,7 @@ devfs_publish_partition(const char *path, const partition_info *info) } -void +extern "C" void panic(const char *format, ...) { va_list args; @@ -709,10 +711,12 @@ panic(const char *format, ...) } -// dprintf -void +extern "C" void dprintf(const char *format,...) { + if (!gDebugOutputEnabled) + return; + va_list args; va_start(args, format); printf("\33[34m"); @@ -721,9 +725,45 @@ dprintf(const char *format,...) va_end(args); } -// user_memcpy -extern "C" -status_t + +extern "C" void +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) { char *tmp = (char *)to; @@ -735,9 +775,8 @@ user_memcpy(void *to, const void *from, size_t size) return 0; } -//user_strcpy -extern "C" -int + +extern "C" int user_strcpy(char *to, const char *from) { while ((*to++ = *from++) != '\0') @@ -745,7 +784,7 @@ user_strcpy(char *to, const char *from) return 0; } -// user_strlcpy + /*! \brief Copies at most (\a size - 1) characters from the string in \a from to the string in \a to, NULL-terminating the result. @@ -755,8 +794,7 @@ user_strcpy(char *to, const char *from) \return strlen(\a from). */ -extern "C" -ssize_t +extern "C" ssize_t user_strlcpy(char *to, const char *from, size_t size) { 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 diff --git a/src/tests/kits/net/tcp_tester.cpp b/src/tests/kits/net/tcp_tester.cpp index bd8015411d..2f6d764e1d 100644 --- a/src/tests/kits/net/tcp_tester.cpp +++ b/src/tests/kits/net/tcp_tester.cpp @@ -1,6 +1,8 @@ #include "argv.h" +#include "tcp.h" #include "utility.h" +#include #include #include #include @@ -26,6 +28,8 @@ struct cmd_entry { extern "C" status_t _add_builtin_module(module_info *info); +extern bool gDebugOutputEnabled; + // from libkernelland_emu.so extern struct net_buffer_module_info gNetBufferModule; // from net_buffer.cpp @@ -42,6 +46,8 @@ extern struct net_socket_module_info gNetSocketModule; struct net_protocol_module_info *gTCPModule; struct net_socket *gServerSocket, *gClientSocket; +bool gTCPDump = true; + static struct net_domain sDomain = { "ipv4", 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 @@ -473,6 +486,8 @@ get_route(struct net_domain *_domain, const struct sockaddr *address) { static net_route route; route.interface = &gInterface; + route.mtu = 1500; + return &route; } @@ -585,7 +600,6 @@ status_t domain_send_routed_data(net_protocol *protocol, struct net_route *route, net_buffer *buffer) { - printf("send routed buffer %p!\n", buffer); return sDomain.module->receive_data(buffer); } @@ -629,6 +643,95 @@ domain_get_mtu(net_protocol *protocol, const struct sockaddr *address) status_t domain_receive_data(net_buffer *buffer) { + static uint32 packetNumber = 1; + + if (gTCPDump) { + NetBufferHeader 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(" ", ntohs(option->max_segment_size)); + length = 4; + break; + case TCP_OPTION_WINDOW_SHIFT: + printf(" ", option->window_shift); + length = 3; + break; + case TCP_OPTION_TIMESTAMP: + printf(" ", 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); } @@ -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[] = { {"connect", do_connect, "Connects the client"}, + {"dprintf", do_dprintf, "Toggles debug output"}, {"help", do_help, "prints this help text"}, {"quit", NULL, "exits the application"}, {NULL, NULL, NULL},