netty: do UDP and TCP tests

This commit replaces echo_udp with the netty_udp test. TCP can be tested
via netty_tcp.
This commit is contained in:
Christian Helmuth 2017-04-27 14:59:39 +02:00
parent 4ab2b85437
commit e3d8b6098f
14 changed files with 620 additions and 654 deletions

View File

@ -1,124 +0,0 @@
assert_spec x86
set build_components {
core init
drivers/timer drivers/nic lib/vfs/lxip
server/vfs server/dynamic_rom
test/echo_udp
}
source ${genode_dir}/repos/base/run/platform_drv.inc
append_platform_drv_build_components
build $build_components
create_boot_directory
append config {
<config verbose="yes">
<parent-provides>
<service name="CPU"/>
<service name="IO_MEM"/>
<service name="IO_PORT"/>
<service name="IRQ"/>
<service name="LOG"/>
<service name="PD"/>
<service name="RAM"/>
<service name="RM"/>
<service name="ROM"/>
</parent-provides>
<default-route>
<any-service> <parent/> <any-child/> </any-service>
</default-route>
<start name="timer">
<resource name="RAM" quantum="1M"/>
<provides> <service name="Timer"/> </provides>
</start>
<start name="nic_drv">
<binary name="} [nic_drv_binary] {"/>
<resource name="RAM" quantum="4M"/>
<provides> <service name="Nic"/> </provides>
</start>
<start name="dynamic_rom">
<resource name="RAM" quantum="4M"/>
<provides><service name="ROM"/> </provides>
<config verbose="yes">
<rom name="socket_fs.config">
<inline description="static">
<config ld_verbose="yes">
<vfs>
<lxip ip_addr="10.0.2.55" netmask="255.255.255.0"
gateway="10.0.2.1" nameserver="8.8.8.8"/>
</vfs>
<default-policy writeable="yes" />
</config>
</inline>
<sleep milliseconds="5000"/>
<inline description="dynamic">
<config ld_verbose="yes">
<vfs>
<lxip dhcp="yes"/>
</vfs>
<default-policy writeable="yes" />
</config>
</inline>
<sleep milliseconds="5000"/>
</rom>
</config>
</start>
<start name="socket_fs">
<binary name="vfs"/>
<resource name="RAM" quantum="32M"/>
<provides> <service name="File_system"/> </provides>
<configfile name="socket_fs.config"/>
<route>
<service name="ROM" label="socket_fs.config"> <child name="dynamic_rom"/> </service>
<any-service> <parent/> <any-child/> </any-service>
</route>
</start>
<start name="echo">
<binary name="test-echo_udp"/>
<resource name="RAM" quantum="4M"/>
<config ld_verbose="yes">
<vfs>
<dir name="dev"> <log/> <null/> </dir>
<dir name="socket"> <fs/> </dir>
</vfs>
<libc stdin="/dev/null" stdout="/dev/log" stderr="/dev/log" socket="/socket"/>
</config>
</start>
}
append_platform_drv_config
append config {
</config>
}
install_config $config
append boot_modules {
core init timer } [nic_drv_binary] { vfs dynamic_rom
ld.lib.so libc.lib.so libm.lib.so
libc_resolv.lib.so
vfs_lxip.lib.so lxip.lib.so
test-echo_udp
}
append_platform_drv_boot_modules
build_boot_image $boot_modules
puts "####################################################################"
puts "## run 'netcat --udp <target ip> 7' to connect to the echo server ##"
puts "####################################################################"
sleep 1
append qemu_args " -nographic -net nic,model=e1000 -net tap,ifname=tap0,downscript=no,script=no "
run_genode_until forever
# vi: set ft=tcl :

View File

@ -3,17 +3,12 @@ assert_spec x86
set build_components {
core init
drivers/timer drivers/nic server/ram_fs server/vfs
test/netty
lib/vfs/lxip
}
source ${genode_dir}/repos/base/run/platform_drv.inc
append_platform_drv_build_components
build $build_components
create_boot_directory
append config {
<config verbose="yes">
<parent-provides>
@ -36,6 +31,11 @@ append config {
<resource name="RAM" quantum="1M"/>
<provides> <service name="Timer"/> </provides>
</start>
}
append_platform_drv_config
append config {
<start name="nic_drv">
<binary name="} [nic_drv_binary] {"/>
<resource name="RAM" quantum="4M"/>
@ -56,84 +56,17 @@ append config {
<default-policy root="/socket" writeable="yes" />
</config>
</start>
<start name="netty-server-80">
<binary name="test-netty"/>
<resource name="RAM" quantum="4M"/>
<config ld_verbose="yes" port="80" read_write="no" nonblock="true">
<vfs>
<dir name="dev"> <log/> </dir>
<dir name="socket"> <fs/> </dir>
<dir name="tmp"> <ram/> </dir>
</vfs>
<libc stdout="/dev/log" stderr="/dev/log" socket="/socket"/>
</config>
</start>
<!--
<start name="netty-server-8080">
<binary name="test-netty"/>
<resource name="RAM" quantum="4M"/>
<config ld_verbose="yes" mode="server" port="8080" nonblock="false">
<vfs>
<dir name="dev"> <log/> </dir>
<dir name="socket"> <fs/> </dir>
<dir name="tmp"> <ram/> </dir>
</vfs>
<libc stdout="/dev/log" stderr="/dev/log" socket="/socket"/>
</config>
</start>
-->
<!--
<start name="netty-client-A">
<binary name="test-netty"/>
<resource name="RAM" quantum="4M"/>
<config ld_verbose="yes" mode="client" ip="10.0.2.1" port="8080">
<vfs>
<dir name="dev"> <log/> </dir>
<dir name="socket"> <fs/> </dir>
<dir name="tmp"> <ram/> </dir>
</vfs>
<libc stdout="/dev/log" stderr="/dev/log" socket="/socket"/>
</config>
</start>
<start name="netty-client-B">
<binary name="test-netty"/>
<resource name="RAM" quantum="4M"/>
<config ld_verbose="yes" mode="client" ip="10.0.2.1" port="12345">
<vfs>
<dir name="dev"> <log/> </dir>
<dir name="socket"> <fs/> </dir>
<dir name="tmp"> <ram/> </dir>
</vfs>
<libc stdout="/dev/log" stderr="/dev/log" socket="/socket"/>
</config>
</start>
-->
}
append_platform_drv_config
append config {
</config>
}
install_config $config
append boot_modules {
core init timer } [nic_drv_binary] { ram_fs vfs
ld.lib.so libc.lib.so libm.lib.so
libc_resolv.lib.so stdcxx.lib.so libc_pipe.lib.so
vfs_lxip.lib.so lxip.lib.so
test-netty
}
append_platform_drv_boot_modules
build_boot_image $boot_modules
append qemu_args " -nographic -net nic,model=e1000 -net tap,ifname=tap0,downscript=no,script=no "
run_genode_until forever
# vi: set ft=tcl :

View File

@ -0,0 +1,72 @@
source ${genode_dir}/repos/libports/run/netty.inc
append build_components { test/netty/tcp }
build $build_components
create_boot_directory
append config {
<start name="netty-server-80">
<binary name="test-netty_tcp"/>
<resource name="RAM" quantum="4M"/>
<config ld_verbose="yes" port="80" read_write="no" nonblock="true">
<vfs>
<dir name="dev"> <log/> </dir>
<dir name="socket"> <fs/> </dir>
<dir name="tmp"> <ram/> </dir>
</vfs>
<libc stdout="/dev/log" stderr="/dev/log" socket="/socket"/>
</config>
</start>
<start name="netty-server-8080">
<binary name="test-netty_tcp"/>
<resource name="RAM" quantum="4M"/>
<config ld_verbose="yes" mode="server" port="8080" nonblock="false">
<vfs>
<dir name="dev"> <log/> </dir>
<dir name="socket"> <fs/> </dir>
<dir name="tmp"> <ram/> </dir>
</vfs>
<libc stdout="/dev/log" stderr="/dev/log" socket="/socket"/>
</config>
</start>
<!--
<start name="netty-client-A">
<binary name="test-netty_tcp"/>
<resource name="RAM" quantum="4M"/>
<config ld_verbose="yes" mode="client" ip="10.0.2.1" port="8080">
<vfs>
<dir name="dev"> <log/> </dir>
<dir name="socket"> <fs/> </dir>
<dir name="tmp"> <ram/> </dir>
</vfs>
<libc stdout="/dev/log" stderr="/dev/log" socket="/socket"/>
</config>
</start>
<start name="netty-client-B">
<binary name="test-netty_tcp"/>
<resource name="RAM" quantum="4M"/>
<config ld_verbose="yes" mode="client" ip="10.0.2.1" port="13002">
<vfs>
<dir name="dev"> <log/> </dir>
<dir name="socket"> <fs/> </dir>
<dir name="tmp"> <ram/> </dir>
</vfs>
<libc stdout="/dev/log" stderr="/dev/log" socket="/socket"/>
</config>
</start>
-->
</config>
}
install_config $config
append boot_modules { test-netty_tcp }
build_boot_image $boot_modules
run_genode_until forever
# vi: set ft=tcl :

View File

@ -0,0 +1,45 @@
source ${genode_dir}/repos/libports/run/netty.inc
append build_components { test/netty/udp }
build $build_components
create_boot_directory
append config {
<start name="netty-server-7">
<binary name="test-netty_udp"/>
<resource name="RAM" quantum="4M"/>
<config ld_verbose="yes" port="7" read_write="no" nonblock="true">
<vfs>
<dir name="dev"> <log/> </dir>
<dir name="socket"> <fs/> </dir>
<dir name="tmp"> <ram/> </dir>
</vfs>
<libc stdout="/dev/log" stderr="/dev/log" socket="/socket"/>
</config>
</start>
<start name="netty-server-7070">
<binary name="test-netty_udp"/>
<resource name="RAM" quantum="4M"/>
<config ld_verbose="yes" mode="server" port="7070" nonblock="false">
<vfs>
<dir name="dev"> <log/> </dir>
<dir name="socket"> <fs/> </dir>
<dir name="tmp"> <ram/> </dir>
</vfs>
<libc stdout="/dev/log" stderr="/dev/log" socket="/socket"/>
</config>
</start>
</config>
}
install_config $config
append boot_modules { test-netty_udp }
build_boot_image $boot_modules
run_genode_until forever
# vi: set ft=tcl :

View File

@ -1,141 +0,0 @@
/*
* \brief RFC862 echo server
* \author Emery Hemingway
* \date 2016-10-17
*/
/*
* Copyright (C) 2016-2017 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
/* Genode includes */
#include <base/log.h>
/* libc includes */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/fcntl.h>
#include <sys/select.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#define ECHO_PORT 7
#define MAXBUFLEN 0xFFFF
#define RECV_FLAGS 0
#define SEND_FLAGS 0
static void print(Genode::Output &output, sockaddr_in const &addr)
{
print(output, (ntohl(addr.sin_addr.s_addr) >> 24) & 0xff);
output.out_string(".");
print(output, (ntohl(addr.sin_addr.s_addr) >> 16) & 0xff);
output.out_string(".");
print(output, (ntohl(addr.sin_addr.s_addr) >> 8) & 0xff);
output.out_string(".");
print(output, (ntohl(addr.sin_addr.s_addr) >> 0) & 0xff);
output.out_string(":");
print(output, ntohs(addr.sin_port));
}
int main(void)
{
int udp_sock;
int rv = 0;
int err = 0;
ssize_t numbytes;
struct sockaddr_in their_addr;
char buf[MAXBUFLEN];
socklen_t addr_len;
struct sockaddr_in const addr = { 0, AF_INET, htons(ECHO_PORT), { INADDR_ANY } };
Genode::log("Create, bind, and close test...");
unsigned i = 0;
for (; i < 10000; i++) {
udp_sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (udp_sock < 0) {
Genode::log("create failed with error ", udp_sock);
return errno;
}
err = bind(udp_sock, (struct sockaddr*)&addr, sizeof(addr));
if (err) {
Genode::log("bind failed with error ", err);
return errno;
}
err = close(udp_sock);
if (err) {
Genode::log("close failed with error ", err);
return errno;
}
}
Genode::log("Create, bind, and close test succeeded");
Genode::log("UDP echo test...");
udp_sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (udp_sock < 0) {
Genode::log("create failed with error ", udp_sock);
return errno;
}
err = bind(udp_sock, (struct sockaddr*)&addr, sizeof(addr));
if (err) {
Genode::log("bind failed with error ", err);
return errno;
}
for (;;) {
fd_set read_fds;
FD_ZERO(&read_fds);
FD_SET(udp_sock, &read_fds);
timeval tv { 10, 0 };
int num_ready = select(udp_sock + 1, &read_fds, nullptr, nullptr, &tv);
if (num_ready == -1) {
perror("select failed");
break;
}
if (!num_ready) {
Genode::log("timeout");
continue;
}
if (!FD_ISSET(udp_sock, &read_fds)) {
Genode::log("spurious wakeup");
continue;
}
Genode::log("num_ready=", num_ready);
addr_len = sizeof their_addr;
numbytes = recvfrom(udp_sock, buf, sizeof(buf), RECV_FLAGS,
(struct sockaddr *)&their_addr, &addr_len);
if (numbytes == -1) {
rv = errno;
perror("recvfrom failed");
break;
}
Genode::log("received ", numbytes, " bytes from ", their_addr);
numbytes = sendto(udp_sock, buf, numbytes, SEND_FLAGS,
(struct sockaddr *)&their_addr, addr_len);
if (numbytes == -1) {
rv = errno;
perror("sendto failed");
break;
}
Genode::log("sent ", numbytes, " bytes to ", their_addr);
}
close(udp_sock);
return rv;
}

View File

@ -1,3 +0,0 @@
TARGET = test-echo_udp
LIBS = posix libc_resolv
SRC_CC = main.cc

View File

@ -1,311 +0,0 @@
/*
* \brief Network TCP echo test
* \author Christian Helmuth
* \date 2015-09-21
*/
/*
* Copyright (C) 2015-2017 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
/* Genode includes */
#include <base/log.h>
#include <base/thread.h>
#include <base/attached_rom_dataspace.h>
#include <base/sleep.h>
#include <libc/component.h>
#include <timer_session/connection.h>
/* Libc includes */
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
typedef Genode::String<32> String;
#define DIE(step) \
do { \
Genode::error("dying..."); \
perror(step); \
exit(1); \
} while (0)
static void print(Genode::Output &output, sockaddr_in const &addr)
{
print(output, (ntohl(addr.sin_addr.s_addr) >> 24) & 0xff);
output.out_string(".");
print(output, (ntohl(addr.sin_addr.s_addr) >> 16) & 0xff);
output.out_string(".");
print(output, (ntohl(addr.sin_addr.s_addr) >> 8) & 0xff);
output.out_string(".");
print(output, (ntohl(addr.sin_addr.s_addr) >> 0) & 0xff);
output.out_string(":");
print(output, ntohs(addr.sin_port));
}
static size_t test_nonblocking(int cd, bool const use_read_write)
{
Genode::log("test in non-blocking mode");
int ret = 0;
{
ret = fcntl(cd, F_GETFL);
if (ret == -1) DIE("fcntl");
Genode::log("F_GETFL returned ", Genode::Hex(ret), "(O_NONBLOCK=", !!(ret & O_NONBLOCK), ")");
ret = fcntl(cd, F_SETFL, ret | O_NONBLOCK);
if (ret == -1) DIE("fcntl");
ret = fcntl(cd, F_GETFL);
if (ret == -1) DIE("fcntl");
Genode::log("F_GETFL returned ", Genode::Hex(ret), "(O_NONBLOCK=", !!(ret & O_NONBLOCK), ")");
}
size_t count = 0;
static char data[64*1024];
while (true) {
ret = use_read_write
? read(cd, data, sizeof(data))
: recv(cd, data, sizeof(data), 0);
if (ret == 0) {
Genode::log("experienced EOF");
return count;
}
if (ret > 0) {
/* echo received data */
ret = use_read_write
? write(cd, data, ret)
: send(cd, data, ret, 0);
if (ret == -1) DIE(use_read_write ? "write" : "send");
count += ret;
continue;
}
if (errno != EAGAIN) DIE(use_read_write ? "read" : "recv");
Genode::log("block in select because of EAGAIN");
fd_set read_fds; FD_ZERO(&read_fds); FD_SET(cd, &read_fds);
int ret = select(cd + 1, &read_fds, nullptr, nullptr, nullptr);
if (ret == -1) DIE("select");
}
}
static size_t test_blocking(int cd, bool const use_read_write)
{
Genode::log("test in blocking mode");
size_t count = 0;
int ret = 0;
static char data[64*1024];
while (true) {
if (use_read_write) {
ret = read(cd, data, sizeof(data));
if (ret == -1) DIE("read");
} else {
ret = recv(cd, data, sizeof(data), 0);
if (ret == -1) DIE("recv");
}
/* EOF */
if (ret == 0) {
Genode::log("experienced EOF");
return count;
}
if (use_read_write) {
ret = write(cd, data, ret);
if (ret == -1) DIE("write");
} else {
ret = send(cd, data, ret, 0);
if (ret == -1) DIE("send");
}
count += ret;
}
}
static void test_getnames(int sd)
{
int err = 0;
sockaddr_in addr;
socklen_t addr_len;
memset(&addr, 0, sizeof(addr));
addr_len = sizeof(addr);
err = getsockname(sd, (sockaddr *)&addr, &addr_len);
if (err == -1) DIE("getsockname");
Genode::log("sock ", addr);
memset(&addr, 0, sizeof(addr));
addr_len = sizeof(addr);
err = getpeername(sd, (sockaddr *)&addr, &addr_len);
if (err == -1) DIE("getpeername");
Genode::log("peer ", addr);
}
static void server(Genode::Env &env, Genode::Xml_node const config)
{
int ret = 0;
Genode::log("Let's serve");
int sd = socket(AF_INET, SOCK_STREAM, 0);
Genode::log("sd=", sd);
if (sd == -1) DIE("socket");
unsigned const port = config.attribute_value("port", 8080U);
bool const use_read_write = config.attribute_value("read_write", false);
bool const nonblock = config.attribute_value("nonblock", false);
Genode::log("config: port=", port, " read_write=", use_read_write,
" nonblock=", nonblock);
sockaddr_in const addr { 0, AF_INET, htons(port), { INADDR_ANY } };
sockaddr const *paddr = reinterpret_cast<sockaddr const *>(&addr);
if (1) {
int const on = 1;
ret = setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
}
ret = bind(sd, paddr, sizeof(addr));
if (ret == -1) DIE("bind");
ret = listen(sd, SOMAXCONN);
if (ret == -1) DIE("listen");
bool const loop = true;
do {
Genode::log("accepting connections on ", port);
sockaddr_in caddr;
socklen_t scaddr = sizeof(caddr);
sockaddr *pcaddr = reinterpret_cast<sockaddr *>(&caddr);
int cd = accept(sd, pcaddr, &scaddr);
Genode::log("cd=", cd);
if (cd == -1) DIE("accept");
test_getnames(cd);
size_t const count = nonblock
? test_nonblocking(cd, use_read_write)
: test_blocking(cd, use_read_write);
Genode::log("echoed ", count, " bytes");
ret = shutdown(cd, SHUT_RDWR);
if (ret == -1) DIE("shutdown");
ret = close(cd);
if (ret == -1) DIE("close");
} while (loop);
}
static void client(Genode::Xml_node const config)
{
int ret = 0;
Genode::log("Let's connect");
int sd = socket(AF_INET, SOCK_STREAM, 0);
Genode::log("sd=", sd);
if (sd == -1) DIE("socket");
String const ip(config.attribute_value("ip", String("10.0.2.1")));
unsigned const port(config.attribute_value("port", 8080U));
Genode::log("Connecting to %s:%u", ip.string(), port);
sockaddr_in const addr { 0, AF_INET, htons(port), { inet_addr(ip.string()) } };
sockaddr const *paddr = reinterpret_cast<sockaddr const *>(&addr);
ret = connect(sd, paddr, sizeof(addr));
if (ret == -1) DIE("connect");
Genode::log("connected");
static char data[1*1024*1024];
memset(data, 'X', sizeof(data));
/* wait for go */
char go;
ret = recv(sd, &go, sizeof(go), 0);
if (ret == -1) DIE("recv");
/* EOF */
if (ret == 0) DIE("EOF");
ret = send(sd, data, sizeof(data), 0);
if (ret == -1) DIE("send");
ret = shutdown(sd, SHUT_RDWR);
if (ret == -1) DIE("shutdown");
ret = close(sd);
if (ret == -1) DIE("close");
}
struct Main
{
String mode { "server" };
Main(Genode::Env &env)
{
Libc::with_libc([&] () {
Genode::Xml_node config { "<empty/>" };
/* parse mode configuration */
try {
static Genode::Attached_rom_dataspace rom(env, "config");
config = rom.xml();
} catch (Genode::Rom_connection::Rom_connection_failed) { }
mode = config.attribute_value("mode", mode);
if (mode == "server") {
server(env, config);
} else if (mode == "client") {
client(config);
} else {
Genode::error("unknown mode '", mode.string(), "'");
exit(__LINE__);
}
});
}
};
void Libc::Component::construct(Libc::Env &env) { static Main inst(env); }

View File

@ -0,0 +1,140 @@
/*
* \brief Network echo test
* \author Christian Helmuth
* \date 2017-04-24
*/
/*
* Copyright (C) 2017 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
/* Local includes */
#include <netty.h>
void Netty::Test::nonblocking(int fd)
{
int ret = 0;
ret = fcntl(fd, F_GETFL);
if (ret == -1) DIE("fcntl");
Genode::log("F_GETFL returned ", Genode::Hex(ret), "(O_NONBLOCK=", !!(ret & O_NONBLOCK), ")");
ret = fcntl(fd, F_SETFL, ret | O_NONBLOCK);
if (ret == -1) DIE("fcntl");
ret = fcntl(fd, F_GETFL);
if (ret == -1) DIE("fcntl");
Genode::log("F_GETFL returned ", Genode::Hex(ret), "(O_NONBLOCK=", !!(ret & O_NONBLOCK), ")");
}
void Netty::Test::_server()
{
int ret = 0;
Genode::log("initialize server");
int const sd = socket();
Genode::log("sd=", sd);
if (sd == -1) DIE("socket");
unsigned const port = _config.attribute_value("port", 8080U);
bool const read_write = _config.attribute_value("read_write", false);
bool const nonblock = _config.attribute_value("nonblock", false);
Genode::log("config: port=", port, " read_write=", read_write,
" nonblock=", nonblock);
sockaddr_in const addr { 0, AF_INET, htons(port), { INADDR_ANY } };
sockaddr const *paddr = reinterpret_cast<sockaddr const *>(&addr);
if (1) {
int const on = 1;
ret = setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
}
ret = bind(sd, paddr, sizeof(addr));
if (ret == -1) DIE("bind");
server(sd, nonblock, read_write);
close(sd);
if (ret == -1) DIE("close");
}
void Netty::Test::_client()
{
int ret = 0;
Genode::log("initialize client");
int const sd = socket();
Genode::log("sd=", sd);
if (sd == -1) DIE("socket");
String const ip(_config.attribute_value("ip", String("10.0.2.1")));
unsigned const port = _config.attribute_value("port", 8080U);
bool const read_write = _config.attribute_value("read_write", false);
bool const nonblock = _config.attribute_value("nonblock", false);
Genode::log("config: ip=", ip.string(), " port=", port,
" read_write=", read_write, " nonblock=", nonblock);
sockaddr_in const addr { 0, AF_INET, htons(port), { inet_addr(ip.string()) } };
client(sd, addr, nonblock, read_write);
ret = close(sd);
if (ret == -1) DIE("close");
Genode::log("client test finished");
}
void Netty::Test::getnames(int const sd)
{
int err = 0;
sockaddr_in addr;
socklen_t addr_len;
memset(&addr, 0, sizeof(addr));
addr_len = sizeof(addr);
err = getsockname(sd, (sockaddr *)&addr, &addr_len);
if (err == -1) perror("getsockname");
Genode::log("sock ", addr);
memset(&addr, 0, sizeof(addr));
addr_len = sizeof(addr);
err = getpeername(sd, (sockaddr *)&addr, &addr_len);
if (err == -1) perror("getpeername");
Genode::log("peer ", addr);
}
void Netty::Test::run()
{
String mode { _config.attribute_value("mode", String("server")) };
Libc::with_libc([&] () {
if (mode == "server") {
_server();
} else if (mode == "client") {
_client();
} else {
Genode::error("unknown mode '", mode.string(), "'");
exit(__LINE__);
}
});
}

View File

@ -0,0 +1,93 @@
/*
* \brief Network echo test utilities
* \author Christian Helmuth
* \date 2017-04-11
*/
/*
* Copyright (C) 2017 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _NETTY_H_
#define _NETTY_H_
/* Genode includes */
#include <base/log.h>
#include <base/attached_rom_dataspace.h>
#include <libc/component.h>
#include <timer_session/connection.h>
/* Libc includes */
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define DIE(step) \
do { \
Genode::error("dying..."); \
perror(step); \
exit(1); \
} while (0)
static inline void print(Genode::Output &output, sockaddr_in const &addr)
{
Genode::print(output, (ntohl(addr.sin_addr.s_addr) >> 24) & 0xff);
output.out_string(".");
Genode::print(output, (ntohl(addr.sin_addr.s_addr) >> 16) & 0xff);
output.out_string(".");
Genode::print(output, (ntohl(addr.sin_addr.s_addr) >> 8) & 0xff);
output.out_string(".");
Genode::print(output, (ntohl(addr.sin_addr.s_addr) >> 0) & 0xff);
output.out_string(":");
Genode::print(output, ntohs(addr.sin_port));
}
namespace Netty {
typedef Genode::String<32> String;
struct Test;
}
struct Netty::Test
{
private:
Libc::Env &_env;
Genode::Attached_rom_dataspace _config_rom { _env, "config" };
Genode::Xml_node _config { _config_rom.xml() };
void _server();
void _client();
public:
Test(Libc::Env &env) : _env(env) { }
virtual ~Test() { }
void run();
void getnames(int const sd);
void nonblocking(int fd);
/* hooks for the test */
virtual int socket() = 0;
virtual void server(int sd, bool nonblock, bool read_write) = 0;
virtual void client(int sd, sockaddr_in addr, bool nonblock, bool read_write) = 0;
};
#endif /* _NETTY_H_ */

View File

@ -1,3 +0,0 @@
TARGET = test-netty
SRC_CC = main.cc
LIBS = stdcxx libc_pipe libc_resolv

View File

@ -0,0 +1,141 @@
/*
* \brief Network TCP echo test
* \author Christian Helmuth
* \date 2017-04-11
*/
/*
* Copyright (C) 2017 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
/* Local includes */
#include <netty.h>
namespace Netty { struct Tcp; }
struct Netty::Tcp : Netty::Test
{
Tcp(Libc::Env &env) : Test(env) { run(); }
int socket() override;
void server(int, bool, bool) override;
void client(int, sockaddr_in, bool, bool) override;
};
int Netty::Tcp::socket() { return ::socket(AF_INET, SOCK_STREAM, 0); }
void Netty::Tcp::server(int const sd, bool const nonblock, bool const read_write)
{
int ret = 0;
ret = listen(sd, SOMAXCONN);
if (ret == -1) DIE("listen");
while (true) {
sockaddr_in caddr;
socklen_t scaddr = sizeof(caddr);
sockaddr *pcaddr = reinterpret_cast<sockaddr *>(&caddr);
if (nonblock) {
nonblocking(sd);
Genode::log("I want EAGAIN");
int test = accept(sd, pcaddr, &scaddr);
if (test == -1 && errno == EAGAIN)
Genode::log("I got EAGAIN");
else
Genode::error("Did not get EAGAIN but test=", test, " errno=", errno);
fd_set read_fds; FD_ZERO(&read_fds); FD_SET(sd, &read_fds);
ret = select(sd + 1, &read_fds, nullptr, nullptr, nullptr);
if (ret == -1) DIE("select");
Genode::log("okay, accept will not block");
}
Genode::log("test in ", nonblock ? "non-blocking" : "blocking", " mode");
int const cd = accept(sd, pcaddr, &scaddr);
Genode::log("cd=", cd);
if (cd == -1) DIE("accept");
getnames(cd);
size_t count = 0;
static char data[64*1024];
if (nonblock) nonblocking(cd);
while (true) {
int ret = read_write
? read(cd, data, sizeof(data))
: recv(cd, data, sizeof(data), 0);
if (ret == 0) {
Genode::log("experienced EOF");
break;
}
if (ret > 0) {
/* echo received data */
ret = read_write
? write(cd, data, ret)
: send(cd, data, ret, 0);
if (ret == -1) DIE(read_write ? "write" : "send");
count += ret;
continue;
}
if (!nonblock || errno != EAGAIN)
DIE(read_write ? "read" : "recv");
Genode::log("block in select because of EAGAIN");
fd_set read_fds; FD_ZERO(&read_fds); FD_SET(cd, &read_fds);
ret = select(cd + 1, &read_fds, nullptr, nullptr, nullptr);
if (ret == -1) DIE("select");
}
Genode::log("echoed ", count, " bytes");
ret = shutdown(cd, SHUT_RDWR);
if (ret == -1) DIE("shutdown");
ret = close(cd);
if (ret == -1) DIE("close");
}
}
void Netty::Tcp::client(int const sd, sockaddr_in const addr,
bool const nonblock, bool const read_write)
{
/* TODO nonblock, read_write */
sockaddr const *paddr = reinterpret_cast<sockaddr const *>(&addr);
int ret = 0;
ret = connect(sd, paddr, sizeof(addr));
if (ret == -1) DIE("connect");
Genode::log("connected");
static char data[16*1024];
memset(data, 'X', sizeof(data));
ret = send(sd, data, sizeof(data), 0);
if (ret == -1) DIE("send");
ret = shutdown(sd, SHUT_RDWR);
if (ret == -1) DIE("shutdown");
}
void Libc::Component::construct(Libc::Env &env) { static Netty::Tcp inst(env); }

View File

@ -0,0 +1,7 @@
TARGET = test-netty_tcp
SRC_CC = main.cc netty.cc
LIBS = libc libc_resolv
INC_DIR += $(PRG_DIR)/..
vpath netty.cc $(PRG_DIR)/..

View File

@ -0,0 +1,110 @@
/*
* \brief Network UDP echo test
* \author Christian Helmuth
* \date 2017-04-25
*/
/*
* Copyright (C) 2017 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
/* Local includes */
#include <netty.h>
namespace Netty { struct Udp; }
struct Netty::Udp : Netty::Test
{
Udp(Libc::Env &env) : Test(env) { run(); }
int socket() override;
void server(int, bool, bool) override;
void client(int, sockaddr_in, bool, bool) override;
};
int Netty::Udp::socket() { return ::socket(AF_INET, SOCK_DGRAM, 0); }
void Netty::Udp::server(int const sd, bool const nonblock, bool const read_write)
{
if (read_write)
Genode::warning("ignoring read_write attribute for UDP tests");
int ret = 0;
while (true) {
sockaddr_in caddr;
socklen_t scaddr = sizeof(caddr);
sockaddr *pcaddr = reinterpret_cast<sockaddr *>(&caddr);
static char data[64*1024];
if (nonblock) {
nonblocking(sd);
Genode::log("I want EAGAIN");
ssize_t test = recvfrom(sd, data, sizeof(data), 0, pcaddr, &scaddr);
if (test == -1 && errno == EAGAIN)
Genode::log("I got EAGAIN");
else
Genode::error("Did not get EAGAIN but test=", test, " errno=", errno);
fd_set read_fds; FD_ZERO(&read_fds); FD_SET(sd, &read_fds);
ret = select(sd + 1, &read_fds, nullptr, nullptr, nullptr);
if (ret == -1) DIE("select");
Genode::log("okay, recvfrom will not block");
}
Genode::log("test in ", nonblock ? "non-blocking" : "blocking", " mode");
ssize_t count = recvfrom(sd, data, sizeof(data), 0, pcaddr, &scaddr);
if (count == -1) DIE("recvfrom");
{
sockaddr_in addr;
socklen_t addr_len = sizeof(addr);
getsockname(sd, (sockaddr *)&addr, &addr_len);
Genode::log("sock ", addr);
Genode::log("peer ", caddr);
}
count = sendto(sd, data, count, 0, pcaddr, scaddr);
Genode::log("echoed ", count, " bytes");
}
}
void Netty::Udp::client(int const sd, sockaddr_in const addr,
bool const nonblock, bool const read_write)
{
/* TODO nonblock, read_write */
sockaddr const *paddr = reinterpret_cast<sockaddr const *>(&addr);
int ret = 0;
ret = connect(sd, paddr, sizeof(addr));
if (ret == -1) DIE("connect");
Genode::log("connected");
static char data[16*1024];
memset(data, 'X', sizeof(data));
ret = send(sd, data, sizeof(data), 0);
if (ret == -1) DIE("send");
ret = shutdown(sd, SHUT_RDWR);
if (ret == -1) DIE("shutdown");
}
void Libc::Component::construct(Libc::Env &env) { static Netty::Udp inst(env); }

View File

@ -0,0 +1,7 @@
TARGET = test-netty_udp
SRC_CC = main.cc netty.cc
LIBS = libc libc_resolv
INC_DIR += $(PRG_DIR)/..
vpath netty.cc $(PRG_DIR)/..