mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-01 11:36:43 +00:00
libports: add lwIP tests for Pandaboard on foc
This commit is contained in:
parent
b22920c3a7
commit
6259fcf736
117
libports/run/http_srv_tracing.run
Normal file
117
libports/run/http_srv_tracing.run
Normal file
@ -0,0 +1,117 @@
|
||||
#
|
||||
# \brief Test for using the lwIP TCP/IP stack
|
||||
# \author Norman Feske
|
||||
# \date 2011-05-22
|
||||
#
|
||||
# This test case executes a small HTTP server on Genode running on qemu. When
|
||||
# the HTTP server is up, a HTTP request to the server is performed using
|
||||
# 'lynx'. The response is validated against a known pattern.
|
||||
#
|
||||
# The test uses qemu's "-net user" option, redirecting Genode's port 80 to the
|
||||
# host's port 5555. Consequently, it cannot be executed on non-qemu test
|
||||
# environments (i.e., the test won't work with the Linux version of Genode).
|
||||
#
|
||||
# Please make sure to include a nic driver in your build configuration. E.g.,
|
||||
# on the x86 platform, you may enable the 'linux_drivers' repository.
|
||||
#
|
||||
|
||||
#
|
||||
# TODO: Add support for Linux via user-level networking (using the
|
||||
# tun/tap proxy driver at os/src/drivers/nic/linux)
|
||||
#
|
||||
if {[have_spec linux]} {
|
||||
puts "Run script does not support Linux."; exit 0 }
|
||||
|
||||
requires_installation_of lynx
|
||||
|
||||
#
|
||||
# Build
|
||||
#
|
||||
|
||||
build {
|
||||
core init
|
||||
drivers/pci drivers/timer drivers/nic
|
||||
test/lwip/http_srv_tracing
|
||||
}
|
||||
|
||||
create_boot_directory
|
||||
|
||||
#
|
||||
# Generate config
|
||||
#
|
||||
|
||||
set config {
|
||||
<config verbose="yes">
|
||||
<parent-provides>
|
||||
<service name="ROM"/>
|
||||
<service name="RAM"/>
|
||||
<service name="IRQ"/>
|
||||
<service name="IO_MEM"/>
|
||||
<service name="IO_PORT"/>
|
||||
<service name="CAP"/>
|
||||
<service name="PD"/>
|
||||
<service name="RM"/>
|
||||
<service name="CPU"/>
|
||||
<service name="LOG"/>
|
||||
<service name="SIGNAL"/>
|
||||
</parent-provides>
|
||||
<default-route>
|
||||
<any-service> <parent/> <any-child/> </any-service>
|
||||
</default-route>
|
||||
<start name="timer">
|
||||
<resource name="RAM" quantum="568K"/>
|
||||
<provides> <service name="Timer"/> </provides>
|
||||
</start>
|
||||
<start name="nic_drv">
|
||||
<resource name="RAM" quantum="2M"/>
|
||||
<provides> <service name="Nic"/> </provides>
|
||||
</start>
|
||||
<start name="test-lwip_httpsrv_tracing">
|
||||
<resource name="RAM" quantum="64M"/>
|
||||
</start> }
|
||||
|
||||
append_if [have_spec pci] config {
|
||||
<start name="pci_drv">
|
||||
<resource name="RAM" quantum="1M"/>
|
||||
<provides> <service name="PCI"/> </provides>
|
||||
</start> }
|
||||
|
||||
append config {
|
||||
</config>
|
||||
}
|
||||
|
||||
install_config $config
|
||||
|
||||
#
|
||||
# Boot modules
|
||||
#
|
||||
|
||||
# generic modules
|
||||
set boot_modules {
|
||||
core init timer
|
||||
nic_drv
|
||||
ld.lib.so libc.lib.so libc_log.lib.so lwip.lib.so
|
||||
test-lwip_httpsrv_tracing
|
||||
}
|
||||
|
||||
# platform-specific modules
|
||||
lappend_if [have_spec pci] boot_modules pci_drv
|
||||
|
||||
build_boot_image $boot_modules
|
||||
|
||||
#
|
||||
# Execute test case
|
||||
#
|
||||
|
||||
# qemu config
|
||||
append qemu_args " -m 128 -nographic -serial mon:stdio "
|
||||
|
||||
append_if [have_spec x86] qemu_args " -net nic,model=e1000 "
|
||||
append_if [have_spec lan9118] qemu_args " -net nic,model=lan9118 "
|
||||
|
||||
append qemu_args " -net user -redir tcp:5555::80 "
|
||||
|
||||
#run_genode_until {.*Sent response.*} 60
|
||||
run_genode_until forever
|
||||
|
||||
# vi: set ft=tcl :
|
75
libports/run/http_srv_tracing_nonblocking_panda.run
Normal file
75
libports/run/http_srv_tracing_nonblocking_panda.run
Normal file
@ -0,0 +1,75 @@
|
||||
# vi: set ft=tcl :
|
||||
assert_spec foc
|
||||
assert_spec platform_panda
|
||||
|
||||
#
|
||||
# Build
|
||||
#
|
||||
build {
|
||||
core
|
||||
init
|
||||
drivers/timer
|
||||
drivers/usb
|
||||
test/lwip/http_srv_tracing_nonblocking
|
||||
}
|
||||
|
||||
create_boot_directory
|
||||
|
||||
#
|
||||
# Config
|
||||
#
|
||||
set config {
|
||||
<config prio_levels="2">
|
||||
<parent-provides>
|
||||
<service name="ROM"/>
|
||||
<service name="RAM"/>
|
||||
<service name="IRQ"/>
|
||||
<service name="IO_MEM"/>
|
||||
<service name="IO_PORT"/>
|
||||
<service name="CAP"/>
|
||||
<service name="PD"/>
|
||||
<service name="RM"/>
|
||||
<service name="CPU"/>
|
||||
<service name="LOG"/>
|
||||
<service name="SIGNAL"/>
|
||||
</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="usb_drv">
|
||||
<resource name="RAM" quantum="6M"/>
|
||||
<provides>
|
||||
<service name="Input"/>
|
||||
<service name="Nic"/>
|
||||
</provides>
|
||||
<config>
|
||||
<hid/>
|
||||
<nic mac="2e:60:90:0c:4e:01" />
|
||||
</config>
|
||||
</start>
|
||||
|
||||
<start name="test-lwip_httpsrv_tracing_nob">
|
||||
<resource name="RAM" quantum="64M"/>
|
||||
</start>
|
||||
</config>}
|
||||
|
||||
install_config $config
|
||||
|
||||
#
|
||||
# Boot modules
|
||||
#
|
||||
set boot_modules {
|
||||
core
|
||||
init
|
||||
timer
|
||||
usb_drv
|
||||
test-lwip_httpsrv_tracing_nob
|
||||
ld.lib.so libc.lib.so libc_log.lib.so lwip.lib.so
|
||||
}
|
||||
|
||||
build_boot_image [join $boot_modules " "]
|
||||
|
75
libports/run/http_srv_tracing_panda.run
Normal file
75
libports/run/http_srv_tracing_panda.run
Normal file
@ -0,0 +1,75 @@
|
||||
# vi: set ft=tcl :
|
||||
assert_spec foc
|
||||
assert_spec platform_panda
|
||||
|
||||
#
|
||||
# Build
|
||||
#
|
||||
build {
|
||||
core
|
||||
init
|
||||
drivers/timer
|
||||
drivers/usb
|
||||
test/lwip/http_srv_tracing
|
||||
}
|
||||
|
||||
create_boot_directory
|
||||
|
||||
#
|
||||
# Config
|
||||
#
|
||||
set config {
|
||||
<config prio_levels="2">
|
||||
<parent-provides>
|
||||
<service name="ROM"/>
|
||||
<service name="RAM"/>
|
||||
<service name="IRQ"/>
|
||||
<service name="IO_MEM"/>
|
||||
<service name="IO_PORT"/>
|
||||
<service name="CAP"/>
|
||||
<service name="PD"/>
|
||||
<service name="RM"/>
|
||||
<service name="CPU"/>
|
||||
<service name="LOG"/>
|
||||
<service name="SIGNAL"/>
|
||||
</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="usb_drv">
|
||||
<resource name="RAM" quantum="12M"/>
|
||||
<provides>
|
||||
<service name="Input"/>
|
||||
<service name="Nic"/>
|
||||
</provides>
|
||||
<config>
|
||||
<hid/>
|
||||
<nic mac="2e:60:90:0c:4e:01" />
|
||||
</config>
|
||||
</start>
|
||||
|
||||
<start name="test-lwip_httpsrv_tracing">
|
||||
<resource name="RAM" quantum="64M"/>
|
||||
</start>
|
||||
</config>}
|
||||
|
||||
install_config $config
|
||||
|
||||
#
|
||||
# Boot modules
|
||||
#
|
||||
set boot_modules {
|
||||
core
|
||||
init
|
||||
timer
|
||||
usb_drv
|
||||
test-lwip_httpsrv_tracing
|
||||
ld.lib.so libc.lib.so libc_log.lib.so lwip.lib.so
|
||||
}
|
||||
|
||||
build_boot_image [join $boot_modules " "]
|
||||
|
23
libports/src/test/lwip/http_srv_connect/Makefile
Normal file
23
libports/src/test/lwip/http_srv_connect/Makefile
Normal file
@ -0,0 +1,23 @@
|
||||
TARGET = httpsrv_connect
|
||||
SRC = main.c net.c
|
||||
|
||||
CFLAGS = -Wall -Wextra -Wno-unused
|
||||
ifeq ($(time),1)
|
||||
CC_DEF += -DUGLY_MEASURE_TIME
|
||||
endif
|
||||
LDFLAGS = -pthread
|
||||
|
||||
OBJS = $(SRC:.c=.o)
|
||||
|
||||
.PHONY: clean
|
||||
|
||||
all: $(TARGET)
|
||||
|
||||
$(TARGET): $(OBJS)
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) $^ -o $@
|
||||
|
||||
.c.o:
|
||||
$(CC) -c $(CFLAGS) $(CC_DEF) $^ -o $@
|
||||
|
||||
clean:
|
||||
-rm -rf ./$(TARGET) ./*.o
|
2
libports/src/test/lwip/http_srv_connect/README
Normal file
2
libports/src/test/lwip/http_srv_connect/README
Normal file
@ -0,0 +1,2 @@
|
||||
This is just a simple test client for http_srv, that runs on the host
|
||||
system. Therefore it does not use the Genode buildsystem.
|
197
libports/src/test/lwip/http_srv_connect/main.c
Normal file
197
libports/src/test/lwip/http_srv_connect/main.c
Normal file
@ -0,0 +1,197 @@
|
||||
/*
|
||||
* \brief Simple http_srv client
|
||||
* \author Josef Soentgen
|
||||
* \date 2012-8-30
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
#include <netdb.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
#include <errno.h>
|
||||
|
||||
/* prototypes for net.c functions */
|
||||
extern int dial(struct addrinfo*);
|
||||
extern struct addrinfo *lookup(const char*, const char*, const char*);
|
||||
|
||||
/* pthread error handling */
|
||||
#define handle_error_en(en, msg) \
|
||||
do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0)
|
||||
|
||||
/* send request, currently hardcoded and works with httpsrv test only */
|
||||
const char req[] = "GET /";
|
||||
|
||||
/* thread arguments */
|
||||
struct args {
|
||||
struct addrinfo* ai;
|
||||
int flags;
|
||||
int count;
|
||||
int verbose;
|
||||
};
|
||||
|
||||
/* receive flag */
|
||||
enum { F_NONE, F_RECV };
|
||||
|
||||
/* pthread start function */
|
||||
void *
|
||||
run(void *arg)
|
||||
{
|
||||
char buf[1 << 20]; /* 1 MiB should be enough */
|
||||
struct args *ap = (struct args *) arg;
|
||||
int count = ap->count;
|
||||
int flags = ap->flags;
|
||||
int verbose = ap->verbose;
|
||||
int i, s, nbytes, sum_nbytes;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
s = dial(ap->ai); /* create socket and connect */
|
||||
if (s == -1)
|
||||
break;
|
||||
|
||||
/* only send/receive if flag is set { */
|
||||
if (flags & F_RECV) {
|
||||
/* first send request and second get header */
|
||||
write(s, req, sizeof(req));
|
||||
nbytes = read(s, buf, sizeof (buf));
|
||||
|
||||
/* get data */
|
||||
sum_nbytes = 0;
|
||||
#if UGLY_MEASURE_TIME
|
||||
struct timeval start, end;
|
||||
gettimeofday(&start, NULL);
|
||||
#endif
|
||||
do {
|
||||
/**
|
||||
* override buffer because we don't care about
|
||||
* the actual data.
|
||||
*/
|
||||
nbytes = read(s, buf, sizeof (buf));
|
||||
sum_nbytes += nbytes;
|
||||
|
||||
} while (nbytes > 0 && nbytes != -1);
|
||||
|
||||
if (nbytes == -1)
|
||||
perror("read");
|
||||
|
||||
#if UGLY_MEASURE_TIME
|
||||
gettimeofday(&end, NULL);
|
||||
int sec = end.tv_sec - start.tv_sec;
|
||||
int usec = end.tv_usec - start.tv_usec;
|
||||
if (usec < 0) {
|
||||
usec += 1000000;
|
||||
sec--;
|
||||
}
|
||||
|
||||
printf("time: %d ms\n",
|
||||
((sec) * 1000) + ((usec) / 1000));
|
||||
#endif
|
||||
|
||||
if (verbose)
|
||||
printf("bytes read: %d\n", sum_nbytes);
|
||||
}
|
||||
/* } */
|
||||
|
||||
close(s);
|
||||
}
|
||||
/* XXX s == -1 handling */
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
struct args a;
|
||||
struct addrinfo *ai;
|
||||
const char *proto = "tcp", *host, *port;
|
||||
int i, err, verbose = 0, flags = F_NONE, count = 1, threads = 1;
|
||||
pthread_t *thread;
|
||||
|
||||
if (argc < 3) {
|
||||
fprintf(stderr, "usage: %s [-vr] [-c count] [-t threads] "
|
||||
"[-p protocol] <host> <port>\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* argument parsing { */
|
||||
while ((i = getopt(argc, argv, "c:p:t:rv")) != -1) {
|
||||
switch (i) {
|
||||
case 'c': count = atoi(optarg); break;
|
||||
/**
|
||||
* valid values are only 'tcp' and 'udp'
|
||||
*/
|
||||
case 'p': proto = optarg; break;
|
||||
case 't': threads = atoi(optarg); break;
|
||||
/**
|
||||
* If receive is specified we will read from the socket,
|
||||
* just connect to the host otherwise.
|
||||
*/
|
||||
case 'r': flags |= F_RECV; break;
|
||||
case 'v': verbose = 1; break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
if ((argc - optind) != 2) {
|
||||
fprintf(stderr, "missing host and/or port\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
host = argv[optind++];
|
||||
port = argv[optind];
|
||||
/* } */
|
||||
|
||||
/* main { */
|
||||
thread = (pthread_t *) calloc(threads, sizeof (pthread_t));
|
||||
if (thread == NULL) {
|
||||
perror("calloc");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/* get addrinfo once and use it for all threads */
|
||||
ai = lookup(proto, host, port);
|
||||
if (ai == NULL) {
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/* fill thread argument structure */
|
||||
a.ai = ai;
|
||||
a.count = count / threads; /* XXX check if -c > -t */
|
||||
a.flags = flags;
|
||||
a.verbose = verbose;
|
||||
|
||||
printf("connect to '%s!%s!%s' roughly %d times, %d per thread\n",
|
||||
proto, host, port, count, a.count);
|
||||
|
||||
for (i = 0; i < threads; i++) {
|
||||
err = pthread_create(&thread[i], NULL, run, (void*)&a);
|
||||
if (err != 0)
|
||||
handle_error_en(err, "pthread_create");
|
||||
}
|
||||
|
||||
for (i = 0; i < threads; i++) {
|
||||
err = pthread_join(thread[i], NULL);
|
||||
if (err != 0)
|
||||
handle_error_en(err, "pthread_create");
|
||||
}
|
||||
|
||||
freeaddrinfo(ai);
|
||||
free(thread);
|
||||
|
||||
/* } */
|
||||
|
||||
return 0;
|
||||
}
|
89
libports/src/test/lwip/http_srv_connect/net.c
Normal file
89
libports/src/test/lwip/http_srv_connect/net.c
Normal file
@ -0,0 +1,89 @@
|
||||
/*
|
||||
* \brief Simple http_srv client
|
||||
* \author Josef Soentgen
|
||||
* \date 2012-8-30
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
#include <netdb.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
int
|
||||
dial(struct addrinfo *ai)
|
||||
{
|
||||
struct addrinfo *aip;
|
||||
int s, err;
|
||||
|
||||
for (aip = ai; aip != NULL; aip->ai_next) {
|
||||
s = socket(aip->ai_family, aip->ai_socktype,
|
||||
aip->ai_protocol);
|
||||
if (s == -1) {
|
||||
perror("socket");
|
||||
continue;
|
||||
}
|
||||
|
||||
err = connect(s, aip->ai_addr, aip->ai_addrlen);
|
||||
if (err != -1)
|
||||
break;
|
||||
|
||||
close(s);
|
||||
s = -1;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
struct addrinfo *
|
||||
lookup(const char *proto, const char *host, const char *port)
|
||||
{
|
||||
struct addrinfo hints, *r;
|
||||
int err, socktype, protocol;
|
||||
|
||||
if (proto == NULL) {
|
||||
fprintf(stderr, "protocol is not set\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* actually we can simply use protcol == 0 but we
|
||||
* set it explicitly anyway.
|
||||
*/
|
||||
if (strcmp(proto, "tcp") == 0) {
|
||||
socktype = SOCK_STREAM;
|
||||
protocol = IPPROTO_TCP;
|
||||
}
|
||||
else if (strcmp(proto, "udp") == 0) {
|
||||
socktype = SOCK_DGRAM;
|
||||
protocol = IPPROTO_UDP;
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "protocol '%s' invalid\n", proto);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(&hints, 0, sizeof(struct addrinfo));
|
||||
hints.ai_family = AF_INET;
|
||||
hints.ai_socktype = socktype;
|
||||
hints.ai_flags = 0;
|
||||
hints.ai_protocol = protocol;
|
||||
|
||||
err = getaddrinfo(host, port, &hints, &r);
|
||||
if (err != 0) {
|
||||
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(err));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
148
libports/src/test/lwip/http_srv_tracing/main.cc
Normal file
148
libports/src/test/lwip/http_srv_tracing/main.cc
Normal file
@ -0,0 +1,148 @@
|
||||
/*
|
||||
* \brief Minimal HTTP server lwIP demonstration
|
||||
* \author lwIP Team
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2009-10-23
|
||||
*
|
||||
* This small example shows how to use the LwIP in Genode directly.
|
||||
* If you simply want to use LwIP's socket API, you might use
|
||||
* Genode's libc together with its LwIP backend, especially useful
|
||||
* when porting legacy code.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2009-2012 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/printf.h>
|
||||
#include <base/thread.h>
|
||||
#include <util/string.h>
|
||||
|
||||
/* LwIP includes */
|
||||
extern "C" {
|
||||
#include <lwip/sockets.h>
|
||||
#include <lwip/api.h>
|
||||
}
|
||||
|
||||
#include <lwip/genode.h>
|
||||
|
||||
namespace Fiasco {
|
||||
#include <l4/sys/ktrace.h>
|
||||
}
|
||||
|
||||
|
||||
//enum { FILE_SIZE = 1UL }; /* 1 Byte */
|
||||
enum { FILE_SIZE = 3072UL }; /* 3 KiB */
|
||||
//enum { FILE_SIZE = 5120UL }; /* 5 KiB */
|
||||
//enum { FILE_SIZE = 8388608UL }; /* 8 MiB */
|
||||
//enum { FILE_SIZE = 2097152UL }; /* 2 MiB */
|
||||
//enum { FILE_SIZE = 16777216UL }; /* 16 MiB */
|
||||
//enum { FILE_SIZE = 33554432UL }; /* 32 MiB */
|
||||
|
||||
const static char http_html_hdr[] =
|
||||
"HTTP/1.0 200 OK\r\nContent-type: text/html\r\n\r\n"; /* HTTP response header */
|
||||
|
||||
static char http_file_data[FILE_SIZE];
|
||||
|
||||
|
||||
/**
|
||||
* Handle a single client's request.
|
||||
*
|
||||
* \param conn socket connected to the client
|
||||
*/
|
||||
void http_server_serve(int conn) {
|
||||
char buf[1024];
|
||||
ssize_t buflen;
|
||||
|
||||
/* Read the data from the port, blocking if nothing yet there.
|
||||
We assume the request (the part we care about) is in one packet */
|
||||
buflen = lwip_recv(conn, buf, 1024, 0);
|
||||
//PLOG("Packet received!");
|
||||
|
||||
/* Ignore all receive errors */
|
||||
if (buflen > 0) {
|
||||
|
||||
/* Is this an HTTP GET command? (only check the first 5 chars, since
|
||||
there are other formats for GET, and we're keeping it very simple)*/
|
||||
if (buflen >= 5 &&
|
||||
buf[0] == 'G' &&
|
||||
buf[1] == 'E' &&
|
||||
buf[2] == 'T' &&
|
||||
buf[3] == ' ' &&
|
||||
buf[4] == '/' ) {
|
||||
|
||||
//PLOG("Will send response");
|
||||
|
||||
/* Send http header */
|
||||
//Fiasco::fiasco_tbuf_log_3val(">> lwip_send", Genode::strlen(http_html_hdr), 0, 0);
|
||||
lwip_send(conn, http_html_hdr, Genode::strlen(http_html_hdr), 0);
|
||||
//Fiasco::fiasco_tbuf_log("<< lwip_send");
|
||||
|
||||
/*
|
||||
unsigned int val = 0xdeadbeef;
|
||||
Fiasco::fiasco_tbuf_log_3val(">> lwip_send", sizeof (unsigned int), 0, 0);
|
||||
lwip_send(conn, &val, sizeof (unsigned int), 0);
|
||||
Fiasco::fiasco_tbuf_log("<< lwip_send");
|
||||
*/
|
||||
|
||||
lwip_send(conn, http_file_data, sizeof (http_file_data), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#include <l4/sys/kdebug.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
int s;
|
||||
|
||||
lwip_tcpip_init();
|
||||
|
||||
/* Initialize network stack and do DHCP */
|
||||
if (lwip_nic_init(0, 0, 0)) {
|
||||
PERR("We got no IP address!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
PLOG("Create new socket ...");
|
||||
if((s = lwip_socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
||||
PERR("No socket available!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
PLOG("Now, I will bind ...");
|
||||
struct sockaddr_in in_addr;
|
||||
in_addr.sin_family = AF_INET;
|
||||
in_addr.sin_port = htons(80);
|
||||
in_addr.sin_addr.s_addr = INADDR_ANY;
|
||||
if(lwip_bind(s, (struct sockaddr*)&in_addr, sizeof(in_addr))) {
|
||||
PERR("bind failed!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
PLOG("Now, I will listen ...");
|
||||
if(lwip_listen(s, 5)) {
|
||||
PERR("listen failed!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
PLOG("Start the server loop ...");
|
||||
while(true) {
|
||||
struct sockaddr addr;
|
||||
socklen_t len = sizeof(addr);
|
||||
int client = lwip_accept(s, &addr, &len);
|
||||
if(client < 0) {
|
||||
PWRN("Invalid socket from accept!");
|
||||
continue;
|
||||
}
|
||||
http_server_serve(client);
|
||||
// PLOG("Sent response, closing connection");
|
||||
lwip_close(client);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
6
libports/src/test/lwip/http_srv_tracing/target.mk
Normal file
6
libports/src/test/lwip/http_srv_tracing/target.mk
Normal file
@ -0,0 +1,6 @@
|
||||
TARGET = test-lwip_httpsrv_tracing
|
||||
LIBS = cxx env lwip libc libc_log
|
||||
SRC_CC = main.cc
|
||||
REQUIRES = foc
|
||||
|
||||
INC_DIR += $(REP_DIR)/src/lib/lwip/include
|
222
libports/src/test/lwip/http_srv_tracing_nonblocking/main.cc
Normal file
222
libports/src/test/lwip/http_srv_tracing_nonblocking/main.cc
Normal file
@ -0,0 +1,222 @@
|
||||
/*
|
||||
* \brief Minimal HTTP server lwIP demonstration
|
||||
* \author lwIP Team
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2009-10-23
|
||||
*
|
||||
* This small example shows how to use the LwIP in Genode directly.
|
||||
* If you simply want to use LwIP's socket API, you might use
|
||||
* Genode's libc together with its LwIP backend, especially useful
|
||||
* when porting legacy code.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2009-2012 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/printf.h>
|
||||
#include <base/thread.h>
|
||||
#include <util/string.h>
|
||||
|
||||
/* LwIP includes */
|
||||
extern "C" {
|
||||
#include <lwip/sockets.h>
|
||||
#include <lwip/api.h>
|
||||
}
|
||||
|
||||
#include <lwip/genode.h>
|
||||
#include <errno.h>
|
||||
|
||||
//enum { FILE_SIZE = 8388608UL }; /* 8 MiB */
|
||||
//enum { FILE_SIZE = 2097152UL }; /* 2 MiB */
|
||||
//enum { FILE_SIZE = 16777216UL }; /* 16 MiB */
|
||||
//enum { FILE_SIZE = 33554432UL }; /* 32 MiB */
|
||||
enum { FILE_SIZE = 5120UL }; /* 5 KiB */
|
||||
|
||||
enum { MAX_CLIENTS = 1024 };
|
||||
enum { TRY_TO_CONNECT = 100 };
|
||||
|
||||
const static char http_html_hdr[] =
|
||||
"HTTP/1.0 200 OK\r\nContent-type: text/html\r\n\r\n"; /* HTTP response header */
|
||||
|
||||
static char http_file_data[FILE_SIZE];
|
||||
|
||||
struct clients {
|
||||
int fd;
|
||||
struct sockaddr addr;
|
||||
socklen_t len;
|
||||
};
|
||||
|
||||
static struct clients c[MAX_CLIENTS];
|
||||
|
||||
/**
|
||||
* Handle a single client's request.
|
||||
*
|
||||
* \param conn socket connected to the client
|
||||
*/
|
||||
void http_server_serve(int conn) {
|
||||
char buf[1024];
|
||||
ssize_t buflen;
|
||||
|
||||
/* Read the data from the port, blocking if nothing yet there.
|
||||
We assume the request (the part we care about) is in one packet */
|
||||
buflen = lwip_recv(conn, buf, 1024, 0);
|
||||
PLOG("Packet received!");
|
||||
|
||||
/* Ignore all receive errors */
|
||||
if (buflen > 0) {
|
||||
|
||||
/* Is this an HTTP GET command? (only check the first 5 chars, since
|
||||
there are other formats for GET, and we're keeping it very simple)*/
|
||||
if (buflen >= 5 &&
|
||||
buf[0] == 'G' &&
|
||||
buf[1] == 'E' &&
|
||||
buf[2] == 'T' &&
|
||||
buf[3] == ' ' &&
|
||||
buf[4] == '/' ) {
|
||||
|
||||
PLOG("Will send response");
|
||||
|
||||
/* Send http header */
|
||||
lwip_send(conn, http_html_hdr, Genode::strlen(http_html_hdr), 0);
|
||||
lwip_send(conn, http_file_data, FILE_SIZE, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#include <l4/sys/kdebug.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
int s, c_num;
|
||||
|
||||
fd_set rs, ws, es;
|
||||
|
||||
lwip_tcpip_init();
|
||||
|
||||
/* Initialize network stack and do DHCP */
|
||||
if (lwip_nic_init(0, 0, 0)) {
|
||||
PERR("We got no IP address!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
PLOG("Create new socket ...");
|
||||
if((s = lwip_socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
||||
PERR("No socket available!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
PLOG("Now, I will bind to port 80 ...");
|
||||
struct sockaddr_in in_addr;
|
||||
in_addr.sin_family = AF_INET;
|
||||
in_addr.sin_port = htons(80);
|
||||
in_addr.sin_addr.s_addr = INADDR_ANY;
|
||||
memset(&(in_addr.sin_zero), '\0', 8);
|
||||
|
||||
if (lwip_bind(s, (struct sockaddr*)&in_addr, sizeof(in_addr))) {
|
||||
PERR("bind failed!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
PLOG("Now, I will listen ...");
|
||||
if (lwip_listen(s, 5)) {
|
||||
PERR("listen failed!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
PLOG("Make socket non-blocking ...");
|
||||
if (lwip_fcntl(s, F_SETFL, O_NONBLOCK)) {
|
||||
PERR("fcntl() failed!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct timeval timeout;
|
||||
timeout.tv_sec = 1;
|
||||
timeout.tv_usec = 0;
|
||||
|
||||
for (int i = 0; i < MAX_CLIENTS; i++)
|
||||
c[i].fd = -1;
|
||||
|
||||
c_num = 0;
|
||||
|
||||
PLOG("Start the server loop ...");
|
||||
while(true) {
|
||||
/* clear fds */
|
||||
FD_ZERO(&rs);
|
||||
FD_ZERO(&ws);
|
||||
FD_ZERO(&es);
|
||||
|
||||
/* set fds */
|
||||
FD_SET(s, &rs);
|
||||
for (int i = 0, num = c_num; i < MAX_CLIENTS; i++) {
|
||||
if (c[i].fd != -1) {
|
||||
FD_SET(c[i].fd, &rs);
|
||||
|
||||
if (num > 0)
|
||||
num--;
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//PLOG("before select, c_num: %d", c_num);
|
||||
int ready = lwip_select(c_num + 1, &rs, &ws, &es, &timeout);
|
||||
|
||||
if (ready > 0) {
|
||||
if (FD_ISSET(s, &rs)) {
|
||||
for (int i = 0; i < TRY_TO_CONNECT; i++) {
|
||||
int *fd = &c[c_num].fd;
|
||||
struct sockaddr *addr = &c[c_num].addr;
|
||||
socklen_t *len = &c[c_num].len;
|
||||
|
||||
*fd = lwip_accept(s, addr, len);
|
||||
|
||||
if (*fd < 0) {
|
||||
/* there is currently nobody waiting */
|
||||
if (errno == EWOULDBLOCK)
|
||||
break;
|
||||
|
||||
//PWRN("Invalid socket from accept!");
|
||||
continue;
|
||||
}
|
||||
if (lwip_fcntl(*fd, F_SETFL, O_NONBLOCK)) {
|
||||
//PERR("fcntl() failed");
|
||||
lwip_close(*fd);
|
||||
continue;
|
||||
}
|
||||
|
||||
c_num++;
|
||||
//PLOG("add client %d", c_num);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0, num = c_num; i < MAX_CLIENTS; i++) {
|
||||
int *fd = &c[i].fd;
|
||||
|
||||
if (*fd != -1) {
|
||||
if (FD_ISSET(*fd, &rs)) {
|
||||
http_server_serve(*fd);
|
||||
//PLOG("Send response, closing connection");
|
||||
lwip_close(*fd);
|
||||
|
||||
c_num--;
|
||||
*fd = -1;
|
||||
|
||||
//PLOG("after close, c_num: %d", c_num);
|
||||
}
|
||||
|
||||
if (num > 0)
|
||||
num--;
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
TARGET = test-lwip_httpsrv_tracing_nob
|
||||
LIBS = cxx env lwip libc libc_log
|
||||
SRC_CC = main.cc
|
||||
REQUIRES = foc
|
||||
|
||||
INC_DIR += $(REP_DIR)/src/lib/lwip/include
|
Loading…
Reference in New Issue
Block a user