diff --git a/libports/run/http_srv_tracing.run b/libports/run/http_srv_tracing.run
new file mode 100644
index 0000000000..a5b016b5b6
--- /dev/null
+++ b/libports/run/http_srv_tracing.run
@@ -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 {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ }
+
+append_if [have_spec pci] config {
+
+
+
+ }
+
+append 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 :
diff --git a/libports/run/http_srv_tracing_nonblocking_panda.run b/libports/run/http_srv_tracing_nonblocking_panda.run
new file mode 100644
index 0000000000..aab9bd75bf
--- /dev/null
+++ b/libports/run/http_srv_tracing_nonblocking_panda.run
@@ -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 {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+}
+
+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 " "]
+
diff --git a/libports/run/http_srv_tracing_panda.run b/libports/run/http_srv_tracing_panda.run
new file mode 100644
index 0000000000..dbec42c10e
--- /dev/null
+++ b/libports/run/http_srv_tracing_panda.run
@@ -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 {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+}
+
+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 " "]
+
diff --git a/libports/src/test/lwip/http_srv_connect/Makefile b/libports/src/test/lwip/http_srv_connect/Makefile
new file mode 100644
index 0000000000..926c837588
--- /dev/null
+++ b/libports/src/test/lwip/http_srv_connect/Makefile
@@ -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
diff --git a/libports/src/test/lwip/http_srv_connect/README b/libports/src/test/lwip/http_srv_connect/README
new file mode 100644
index 0000000000..ed7e04395b
--- /dev/null
+++ b/libports/src/test/lwip/http_srv_connect/README
@@ -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.
diff --git a/libports/src/test/lwip/http_srv_connect/main.c b/libports/src/test/lwip/http_srv_connect/main.c
new file mode 100644
index 0000000000..b847faccba
--- /dev/null
+++ b/libports/src/test/lwip/http_srv_connect/main.c
@@ -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
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+/* 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] \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;
+}
diff --git a/libports/src/test/lwip/http_srv_connect/net.c b/libports/src/test/lwip/http_srv_connect/net.c
new file mode 100644
index 0000000000..52cdbe767c
--- /dev/null
+++ b/libports/src/test/lwip/http_srv_connect/net.c
@@ -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
+#include
+#include
+#include
+#include
+#include
+#include
+
+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;
+}
diff --git a/libports/src/test/lwip/http_srv_tracing/main.cc b/libports/src/test/lwip/http_srv_tracing/main.cc
new file mode 100644
index 0000000000..eeb5871e91
--- /dev/null
+++ b/libports/src/test/lwip/http_srv_tracing/main.cc
@@ -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
+#include
+#include
+
+/* LwIP includes */
+extern "C" {
+#include
+#include
+}
+
+#include
+
+namespace Fiasco {
+#include
+}
+
+
+//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
+
+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;
+}
diff --git a/libports/src/test/lwip/http_srv_tracing/target.mk b/libports/src/test/lwip/http_srv_tracing/target.mk
new file mode 100644
index 0000000000..1d05623139
--- /dev/null
+++ b/libports/src/test/lwip/http_srv_tracing/target.mk
@@ -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
diff --git a/libports/src/test/lwip/http_srv_tracing_nonblocking/main.cc b/libports/src/test/lwip/http_srv_tracing_nonblocking/main.cc
new file mode 100644
index 0000000000..bfc3099bec
--- /dev/null
+++ b/libports/src/test/lwip/http_srv_tracing_nonblocking/main.cc
@@ -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
+#include
+#include
+
+/* LwIP includes */
+extern "C" {
+#include
+#include
+}
+
+#include
+#include
+
+//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
+
+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;
+}
diff --git a/libports/src/test/lwip/http_srv_tracing_nonblocking/target.mk b/libports/src/test/lwip/http_srv_tracing_nonblocking/target.mk
new file mode 100644
index 0000000000..15528e663e
--- /dev/null
+++ b/libports/src/test/lwip/http_srv_tracing_nonblocking/target.mk
@@ -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