mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-23 15:32:25 +00:00
lwip: enhance http_srv_static and http_clnt
Both, client and server now read their IP config from their Genode config. Furthermore, the client now waits 4 instead of 2 seconds before sending the first request to prevent connection fails in tests with a slow startup. The client truncates its packet dump for better readability. Ref #114
This commit is contained in:
parent
6a40c5c13d
commit
dbbda9839b
@ -68,7 +68,10 @@ append config {
|
||||
<any-service> <parent/> <any-child/> </any-service>
|
||||
</route>
|
||||
<config>
|
||||
<libc stdout="/dev/log" stderr="/dev/log">
|
||||
<libc stdout="/dev/log" stderr="/dev/log"
|
||||
ip_addr="10.0.2.55" netmask="255.255.255.0"
|
||||
gateway="10.0.2.1" http_port="80"
|
||||
>
|
||||
<vfs> <dir name="dev"> <log/> </dir> </vfs>
|
||||
</libc>
|
||||
</config>
|
||||
@ -80,7 +83,10 @@ append config {
|
||||
<any-service> <parent/> <any-child/> </any-service>
|
||||
</route>
|
||||
<config>
|
||||
<libc stdout="/dev/log" stderr="/dev/log">
|
||||
<libc
|
||||
stdout="/dev/log" stderr="/dev/log" server_ip="10.0.2.55"
|
||||
http_port="80"
|
||||
>
|
||||
<vfs> <dir name="dev"> <log/> </dir> </vfs>
|
||||
</libc>
|
||||
</config>
|
||||
@ -108,7 +114,6 @@ set boot_modules {
|
||||
|
||||
# platform-specific modules
|
||||
lappend_if [have_spec linux] boot_modules fb_sdl
|
||||
lappend_if [have_spec ps2] boot_modules ps2_drv
|
||||
|
||||
append_platform_drv_boot_modules
|
||||
|
||||
|
@ -62,7 +62,7 @@ append config {
|
||||
</route>
|
||||
</start>
|
||||
<start name="lighttpd">
|
||||
<resource name="RAM" quantum="256M" />
|
||||
<resource name="RAM" quantum="128M" />
|
||||
<config>
|
||||
<arg value="lighttpd" />
|
||||
<arg value="-f" />
|
||||
@ -121,7 +121,10 @@ mimetype.assign = (
|
||||
<any-service> <parent/> <any-child/> </any-service>
|
||||
</route>
|
||||
<config>
|
||||
<libc stdout="/dev/log" stderr="/dev/log">
|
||||
<libc
|
||||
stdout="/dev/log" stderr="/dev/log" server_ip="10.0.2.55"
|
||||
http_port="80"
|
||||
>
|
||||
<vfs> <dir name="dev"> <log/> </dir> </vfs>
|
||||
</libc>
|
||||
</config>
|
||||
@ -151,7 +154,6 @@ set boot_modules {
|
||||
|
||||
# platform-specific modules
|
||||
lappend_if [have_spec linux] boot_modules fb_sdl
|
||||
lappend_if [have_spec ps2] boot_modules ps2_drv
|
||||
|
||||
append_platform_drv_boot_modules
|
||||
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include <util/string.h>
|
||||
#include <timer_session/connection.h>
|
||||
#include <nic/packet_allocator.h>
|
||||
#include <os/config.h>
|
||||
|
||||
extern "C" {
|
||||
#include <lwip/sockets.h>
|
||||
@ -31,6 +32,42 @@ extern "C" {
|
||||
static const char *http_get_request =
|
||||
"GET / HTTP/1.0\r\nHost: localhost:80\r\n\r\n"; /* simple HTTP request header */
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
template <size_t N>
|
||||
static Genode::String<N> read_string_attribute(Genode::Xml_node node, char const *attr,
|
||||
Genode::String<N> default_value)
|
||||
{
|
||||
try {
|
||||
char buf[N];
|
||||
node.attribute(attr).value(buf, sizeof(buf));
|
||||
return Genode::String<N>(Genode::Cstring(buf));
|
||||
}
|
||||
catch (...) {
|
||||
return default_value; }
|
||||
}
|
||||
|
||||
|
||||
bool static_ip_config(uint32_t & ip, uint32_t & nm, uint32_t & gw)
|
||||
{
|
||||
enum { ADDR_STR_SZ = 16 };
|
||||
Xml_node libc_node = config()->xml_node().sub_node("libc");
|
||||
String<ADDR_STR_SZ> ip_str =
|
||||
read_string_attribute<ADDR_STR_SZ>(libc_node, "ip_addr", String<ADDR_STR_SZ>());
|
||||
String<ADDR_STR_SZ> nm_str =
|
||||
read_string_attribute<ADDR_STR_SZ>(libc_node, "netmask", String<ADDR_STR_SZ>());
|
||||
String<ADDR_STR_SZ> gw_str =
|
||||
read_string_attribute<ADDR_STR_SZ>(libc_node, "gateway", String<ADDR_STR_SZ>());
|
||||
|
||||
ip = inet_addr(ip_str.string());
|
||||
nm = inet_addr(nm_str.string());
|
||||
gw = inet_addr(gw_str.string());
|
||||
if (ip == INADDR_NONE || nm == INADDR_NONE || gw == INADDR_NONE) { return false; }
|
||||
log("static ip config: ip=", ip_str, " nm=", nm_str, " gw=", gw_str);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The client thread simply loops endless,
|
||||
@ -42,44 +79,72 @@ int main()
|
||||
enum { BUF_SIZE = Nic::Packet_allocator::DEFAULT_PACKET_SIZE * 128 };
|
||||
|
||||
static Timer::Connection _timer;
|
||||
_timer.msleep(2000);
|
||||
lwip_tcpip_init();
|
||||
|
||||
char serv_addr[] = "10.0.2.55";
|
||||
uint32_t ip = 0;
|
||||
uint32_t nm = 0;
|
||||
uint32_t gw = 0;
|
||||
bool static_ip = static_ip_config(ip, nm, gw);
|
||||
|
||||
if( lwip_nic_init(0, 0, 0, BUF_SIZE, BUF_SIZE))
|
||||
{
|
||||
Genode::error("got no IP address!");
|
||||
return 0;
|
||||
enum { ADDR_STR_SZ = 16 };
|
||||
char serv_addr[ADDR_STR_SZ] = { 0 };
|
||||
Xml_node libc_node = config()->xml_node().sub_node("libc");
|
||||
try { libc_node.attribute("server_ip").value(serv_addr, ADDR_STR_SZ); }
|
||||
catch(...) {
|
||||
error("Missing \"server_ip\" attribute.");
|
||||
throw Xml_node::Nonexistent_attribute();
|
||||
}
|
||||
|
||||
if (static_ip) {
|
||||
if (lwip_nic_init(ip, nm, gw, BUF_SIZE, BUF_SIZE)) {
|
||||
error("We got no IP address!");
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
if( lwip_nic_init(0, 0, 0, BUF_SIZE, BUF_SIZE))
|
||||
{
|
||||
error("got no IP address!");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
for(int j = 0; j != 5; ++j) {
|
||||
_timer.msleep(2000);
|
||||
|
||||
|
||||
Genode::log("Create new socket ...");
|
||||
log("Create new socket ...");
|
||||
int s = lwip_socket(AF_INET, SOCK_STREAM, 0 );
|
||||
if (s < 0) {
|
||||
Genode::error("no socket available!");
|
||||
error("no socket available!");
|
||||
continue;
|
||||
}
|
||||
|
||||
Genode::log("Connect to server ...");
|
||||
log("Connect to server ...");
|
||||
|
||||
unsigned port = 0;
|
||||
try { libc_node.attribute("http_port").value(&port); }
|
||||
catch (...) {
|
||||
error("Missing \"http_port\" attribute.");
|
||||
throw Xml_node::Nonexistent_attribute();
|
||||
}
|
||||
|
||||
struct sockaddr_in addr;
|
||||
addr.sin_port = htons(80);
|
||||
addr.sin_port = htons(port);
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_addr.s_addr = inet_addr(serv_addr);
|
||||
|
||||
if((lwip_connect(s, (struct sockaddr *)&addr, sizeof(addr))) < 0) {
|
||||
Genode::error("could not connect!");
|
||||
error("Could not connect!");
|
||||
lwip_close(s);
|
||||
continue;
|
||||
}
|
||||
|
||||
Genode::log("Send request...");
|
||||
log("Send request...");
|
||||
unsigned long bytes = lwip_send(s, (char*)http_get_request,
|
||||
Genode::strlen(http_get_request), 0);
|
||||
if ( bytes < 0 ) {
|
||||
Genode::error("couldn't send request ...");
|
||||
error("couldn't send request ...");
|
||||
lwip_close(s);
|
||||
continue;
|
||||
}
|
||||
@ -91,8 +156,7 @@ int main()
|
||||
buflen = lwip_recv(s, buf, 1024, 0);
|
||||
if(buflen > 0) {
|
||||
buf[buflen] = 0;
|
||||
Genode::log("Packet received!");
|
||||
Genode::log("Packet content:\n", Genode::Cstring(buf));
|
||||
log("Received \"", String<64>(buf), " ...\"");
|
||||
} else
|
||||
break;
|
||||
}
|
||||
|
@ -22,6 +22,8 @@
|
||||
#include <base/thread.h>
|
||||
#include <util/string.h>
|
||||
#include <nic/packet_allocator.h>
|
||||
#include <os/config.h>
|
||||
#include <base/snprintf.h>
|
||||
|
||||
/* LwIP includes */
|
||||
extern "C" {
|
||||
@ -35,8 +37,11 @@ extern "C" {
|
||||
const static char http_html_hdr[] =
|
||||
"HTTP/1.0 200 OK\r\nContent-type: text/html\r\n\r\n"; /* HTTP response header */
|
||||
|
||||
const static char http_index_html[] =
|
||||
"<html><head><title>Congrats!</title></head><body><h1>Welcome to our lwIP HTTP server!</h1><p>This is a small test page.</body></html>"; /* HTML page */
|
||||
enum { HTTP_INDEX_HTML_SZ = 1024 };
|
||||
|
||||
static char http_index_html[HTTP_INDEX_HTML_SZ]; /* HTML page */
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
/**
|
||||
@ -52,7 +57,7 @@ void http_server_serve(int conn)
|
||||
/* 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);
|
||||
Genode::log("Packet received!");
|
||||
log("Packet received!");
|
||||
|
||||
/* Ignore all receive errors */
|
||||
if (buflen > 0) {
|
||||
@ -66,7 +71,7 @@ void http_server_serve(int conn)
|
||||
buf[3] == ' ' &&
|
||||
buf[4] == '/' ) {
|
||||
|
||||
Genode::log("Will send response");
|
||||
log("Will send response");
|
||||
|
||||
/* Send http header */
|
||||
lwip_send(conn, http_html_hdr, Genode::strlen(http_html_hdr), 0);
|
||||
@ -78,50 +83,104 @@ void http_server_serve(int conn)
|
||||
}
|
||||
|
||||
|
||||
template <size_t N>
|
||||
static Genode::String<N> read_string_attribute(Genode::Xml_node node, char const *attr,
|
||||
Genode::String<N> default_value)
|
||||
{
|
||||
try {
|
||||
char buf[N];
|
||||
node.attribute(attr).value(buf, sizeof(buf));
|
||||
return Genode::String<N>(Genode::Cstring(buf));
|
||||
}
|
||||
catch (...) {
|
||||
return default_value; }
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
using namespace Genode;
|
||||
|
||||
enum { BUF_SIZE = Nic::Packet_allocator::DEFAULT_PACKET_SIZE * 128 };
|
||||
|
||||
int s;
|
||||
|
||||
lwip_tcpip_init();
|
||||
|
||||
enum { ADDR_STR_SZ = 16 };
|
||||
|
||||
uint32_t ip = 0;
|
||||
uint32_t nm = 0;
|
||||
uint32_t gw = 0;
|
||||
unsigned port = 0;
|
||||
|
||||
Xml_node libc_node = config()->xml_node().sub_node("libc");
|
||||
String<ADDR_STR_SZ> ip_addr_str =
|
||||
read_string_attribute<ADDR_STR_SZ>(libc_node, "ip_addr", String<ADDR_STR_SZ>());
|
||||
String<ADDR_STR_SZ> netmask_str =
|
||||
read_string_attribute<ADDR_STR_SZ>(libc_node, "netmask", String<ADDR_STR_SZ>());
|
||||
String<ADDR_STR_SZ> gateway_str =
|
||||
read_string_attribute<ADDR_STR_SZ>(libc_node, "gateway", String<ADDR_STR_SZ>());
|
||||
|
||||
try { libc_node.attribute("http_port").value(&port); }
|
||||
catch(...) {
|
||||
error("Missing \"http_port\" attribute.");
|
||||
throw Xml_node::Nonexistent_attribute();
|
||||
}
|
||||
|
||||
log("static network interface: ip=", ip_addr_str, " nm=", netmask_str, " gw=", gateway_str);
|
||||
|
||||
ip = inet_addr(ip_addr_str.string());
|
||||
nm = inet_addr(netmask_str.string());
|
||||
gw = inet_addr(gateway_str.string());
|
||||
|
||||
if (ip == INADDR_NONE || nm == INADDR_NONE || gw == INADDR_NONE) {
|
||||
error("Invalid network interface config.");
|
||||
throw -1;
|
||||
}
|
||||
|
||||
/* Initialize network stack */
|
||||
if (lwip_nic_init(inet_addr("10.0.2.55"), inet_addr("255.255.255.0"),
|
||||
inet_addr("10.0.2.1"), BUF_SIZE, BUF_SIZE)) {
|
||||
Genode::error("got no IP address!");
|
||||
if (lwip_nic_init(ip, nm, gw, BUF_SIZE, BUF_SIZE)) {
|
||||
error("got no IP address!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
Genode::log("Create new socket ...");
|
||||
log("Create new socket ...");
|
||||
if((s = lwip_socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
||||
Genode::error("no socket available!");
|
||||
error("no socket available!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
Genode::log("Now, I will bind ...");
|
||||
Genode::snprintf(
|
||||
http_index_html, HTTP_INDEX_HTML_SZ,
|
||||
"<html><head></head><body>"
|
||||
"<h1>HTTP server at %s:%u</h1>"
|
||||
"<p>This is a small test page.</body></html>",
|
||||
ip_addr_str.string(), port);
|
||||
|
||||
log("Now, I will bind ...");
|
||||
struct sockaddr_in in_addr;
|
||||
in_addr.sin_family = AF_INET;
|
||||
in_addr.sin_port = htons(80);
|
||||
in_addr.sin_port = htons(port);
|
||||
in_addr.sin_addr.s_addr = INADDR_ANY;
|
||||
if(lwip_bind(s, (struct sockaddr*)&in_addr, sizeof(in_addr))) {
|
||||
Genode::error("bind failed!");
|
||||
error("bind failed!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
Genode::log("Now, I will listen ...");
|
||||
log("Now, I will listen ...");
|
||||
if(lwip_listen(s, 5)) {
|
||||
Genode::error("listen failed!");
|
||||
error("listen failed!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
Genode::log("Start the server loop ...");
|
||||
log("Start the server loop ...");
|
||||
while(true) {
|
||||
struct sockaddr addr;
|
||||
socklen_t len = sizeof(addr);
|
||||
int client = lwip_accept(s, &addr, &len);
|
||||
if(client < 0) {
|
||||
Genode::warning("invalid socket from accept!");
|
||||
warning("invalid socket from accept!");
|
||||
continue;
|
||||
}
|
||||
http_server_serve(client);
|
||||
|
@ -1,5 +1,5 @@
|
||||
TARGET = test-lwip_httpsrv_static
|
||||
LIBS = lwip libc
|
||||
LIBS = lwip libc config
|
||||
SRC_CC = main.cc
|
||||
|
||||
INC_DIR += $(REP_DIR)/src/lib/lwip/include
|
||||
|
Loading…
Reference in New Issue
Block a user