Skip to content

Commit c56dd1c

Browse files
authored
Merge pull request #1454 from fwsGonzo/dev
examples: Add LiveUpdate example
2 parents e7bee50 + 835dae4 commit c56dd1c

9 files changed

Lines changed: 278 additions & 1 deletion

File tree

examples/LiveUpdate/CMakeLists.txt

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
cmake_minimum_required(VERSION 2.8.9)
2+
3+
# IncludeOS install location
4+
if (NOT DEFINED ENV{INCLUDEOS_PREFIX})
5+
set(ENV{INCLUDEOS_PREFIX} /usr/local)
6+
endif()
7+
include($ENV{INCLUDEOS_PREFIX}/includeos/pre.service.cmake)
8+
project(service)
9+
10+
# Human-readable name of your service
11+
set(SERVICE_NAME "LiveUpdate example")
12+
13+
# Name of your service binary
14+
set(BINARY "liveupdate")
15+
16+
# Source files to be linked with OS library parts to form bootable image
17+
set(SOURCES
18+
service.cpp response.cpp
19+
)
20+
21+
# DRIVERS / PLUGINS:
22+
set(DRIVERS
23+
virtionet
24+
)
25+
26+
set(PLUGINS
27+
autoconf
28+
)
29+
30+
set(LIBRARIES
31+
libliveupdate.a
32+
)
33+
34+
# include service build script
35+
include($ENV{INCLUDEOS_PREFIX}/includeos/post.service.cmake)

examples/LiveUpdate/README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
### LiveUpdate Demo Service
2+
3+
```
4+
boot .
5+
Ctrl+Shift+T
6+
./update.sh
7+
```
8+
9+
This service should start an instance of IncludeOS that brings up a minimal web service on port 80 with static content. When running test.sh the service should be updated with itself.

examples/LiveUpdate/config.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"net" : [
3+
["10.0.0.42", "255.255.255.0", "10.0.0.1"]
4+
]
5+
}

examples/LiveUpdate/liu.hpp

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// This file is a part of the IncludeOS unikernel - www.includeos.org
2+
//
3+
// Copyright 2015 Oslo and Akershus University College of Applied Sciences
4+
// and Alfred Bratterud
5+
//
6+
// Licensed under the Apache License, Version 2.0 (the "License");
7+
// you may not use this file except in compliance with the License.
8+
// You may obtain a copy of the License at
9+
//
10+
// http://www.apache.org/licenses/LICENSE-2.0
11+
//
12+
// Unless required by applicable law or agreed to in writing, software
13+
// distributed under the License is distributed on an "AS IS" BASIS,
14+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
// See the License for the specific language governing permissions and
16+
// limitations under the License.
17+
18+
#pragma once
19+
#include <liveupdate>
20+
#include "server.hpp"
21+
22+
void setup_liveupdate_server(net::Inet<net::IP4>& inet,
23+
const uint16_t PORT,
24+
liu::LiveUpdate::storage_func func)
25+
{
26+
static liu::LiveUpdate::storage_func save_function;
27+
save_function = func;
28+
29+
// listen for live updates
30+
server(inet, PORT,
31+
[] (liu::buffer_t& buffer)
32+
{
33+
printf("* Live updating from %p (len=%u)\n",
34+
buffer.data(), (uint32_t) buffer.size());
35+
try
36+
{
37+
// run live update process
38+
liu::LiveUpdate::exec(buffer, "test", save_function);
39+
}
40+
catch (std::exception& err)
41+
{
42+
liu::LiveUpdate::restore_environment();
43+
printf("Live update failed:\n%s\n", err.what());
44+
throw;
45+
}
46+
});
47+
}

examples/LiveUpdate/response.cpp

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
#include <net/http/request.hpp>
2+
#include <net/http/response.hpp>
3+
4+
static std::string HTML_RESPONSE()
5+
{
6+
const int color = rand();
7+
8+
// Generate some HTML
9+
std::stringstream stream;
10+
stream << "<!DOCTYPE html><html><head>"
11+
<< "<link href='https://fonts.googleapis.com/css?family=Ubuntu:500,300'"
12+
<< " rel='stylesheet' type='text/css'>"
13+
<< "<title>IncludeOS Demo Service</title></head><body>"
14+
<< "<h1 style='color: #" << std::hex << ((color >> 8) | 0x020202)
15+
<< "; font-family: \"Arial\", sans-serif'>"
16+
<< "Include<span style='font-weight: lighter'>OS</span></h1>"
17+
<< "<h2>The C++ Unikernel</h2>"
18+
<< "<p>You have successfully booted an IncludeOS TCP service with simple http. "
19+
<< "For a more sophisticated example, take a look at "
20+
<< "<a href='https://github.com/hioa-cs/IncludeOS/tree/master/examples/acorn'>Acorn</a>.</p>"
21+
<< "<footer><hr/>&copy; 2017 IncludeOS </footer></body></html>";
22+
23+
return stream.str();
24+
}
25+
26+
http::Response handle_request(const http::Request& req)
27+
{
28+
printf("<Service> Request:\n%s\n", req.to_string().c_str());
29+
30+
http::Response res;
31+
32+
auto& header = res.header();
33+
34+
header.set_field(http::header::Server, "IncludeOS/0.10");
35+
36+
// GET /
37+
if(req.method() == http::GET && req.uri().to_string() == "/")
38+
{
39+
// add HTML response
40+
res.add_body(HTML_RESPONSE());
41+
42+
// set Content type and length
43+
header.set_field(http::header::Content_Type, "text/html; charset=UTF-8");
44+
header.set_field(http::header::Content_Length, std::to_string(res.body().to_string().size()));
45+
}
46+
else
47+
{
48+
// Generate 404 response
49+
res.set_status_code(http::Not_Found);
50+
}
51+
52+
header.set_field(http::header::Connection, "close");
53+
54+
return res;
55+
}

examples/LiveUpdate/server.hpp

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/**
2+
* Master thesis
3+
* by Alf-Andre Walla 2016-2017
4+
*
5+
**/
6+
#pragma once
7+
#include <stdexcept>
8+
9+
static inline
10+
void server(net::Inet<net::IP4>& inet,
11+
const uint16_t port,
12+
delegate<void(liu::buffer_t&)> callback)
13+
{
14+
auto& server = inet.tcp().listen(port);
15+
server.on_connect(
16+
net::tcp::Connection::ConnectCallback::make_packed(
17+
[callback, port] (auto conn)
18+
{
19+
auto* buffer = new liu::buffer_t;
20+
buffer->reserve(3*1024*1024);
21+
printf("Receiving blob on port %u\n", port);
22+
23+
// retrieve binary
24+
conn->on_read(9000,
25+
[conn, buffer] (net::tcp::buffer_t buf, size_t n)
26+
{
27+
buffer->insert(buffer->end(), buf.get(), buf.get() + n);
28+
})
29+
.on_disconnect(
30+
net::tcp::Connection::DisconnectCallback::make_packed(
31+
[buffer, callback] (auto conn, auto) {
32+
printf("* Blob size: %u b stored at %p\n",
33+
(uint32_t) buffer->size(), buffer->data());
34+
callback(*buffer);
35+
delete buffer;
36+
conn->close();
37+
}));
38+
}));
39+
}

examples/LiveUpdate/service.cpp

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
// This file is a part of the IncludeOS unikernel - www.includeos.org
2+
//
3+
// Copyright 2015 Oslo and Akershus University College of Applied Sciences
4+
// and Alfred Bratterud
5+
//
6+
// Licensed under the Apache License, Version 2.0 (the "License");
7+
// you may not use this file except in compliance with the License.
8+
// You may obtain a copy of the License at
9+
//
10+
// http://www.apache.org/licenses/LICENSE-2.0
11+
//
12+
// Unless required by applicable law or agreed to in writing, software
13+
// distributed under the License is distributed on an "AS IS" BASIS,
14+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
// See the License for the specific language governing permissions and
16+
// limitations under the License.
17+
18+
#include <cmath> // rand()
19+
#include <sstream>
20+
21+
#include <os>
22+
#include <net/inet4>
23+
#include <timers>
24+
#include <net/http/request.hpp>
25+
#include <net/http/response.hpp>
26+
#include "liu.hpp"
27+
28+
using namespace std::chrono;
29+
http::Response handle_request(const http::Request& req);
30+
31+
void Service::start()
32+
{
33+
// Get the first IP stack
34+
auto& inet = net::Super_stack::get<net::IP4>(0);
35+
36+
// Print some useful netstats every 30 secs
37+
Timers::periodic(5s, 30s,
38+
[&inet] (uint32_t) {
39+
printf("<Service> TCP STATUS:\n%s\n", inet.tcp().status().c_str());
40+
});
41+
42+
// Set up a TCP server on port 80
43+
auto& server = inet.tcp().listen(80);
44+
45+
// Add a TCP connection handler - here a hardcoded HTTP-service
46+
server.on_connect(
47+
[] (auto conn)
48+
{
49+
printf("<Service> @on_connect: Connection %s successfully established.\n",
50+
conn->remote().to_string().c_str());
51+
// read async with a buffer size of 1024 bytes
52+
// define what to do when data is read
53+
conn->on_read(1024,
54+
[conn] (auto buf, size_t n)
55+
{
56+
printf("<Service> @on_read: %lu bytes received.\n", n);
57+
try
58+
{
59+
std::string data{(const char*)buf.get(), n};
60+
// try to parse the request
61+
http::Request req{data};
62+
63+
// handle the request, getting a matching response
64+
auto res = handle_request(req);
65+
66+
printf("<Service> Responding with %u %s.\n",
67+
res.status_code(), http::code_description(res.status_code()).to_string().c_str());
68+
69+
conn->write(res);
70+
}
71+
catch(const std::exception& e)
72+
{
73+
printf("<Service> Unable to parse request:\n%s\n", e.what());
74+
}
75+
});
76+
});
77+
78+
if (liu::LiveUpdate::is_resumable() == false)
79+
{
80+
setup_liveupdate_server(inet, 666, nullptr);
81+
}
82+
else {
83+
printf("System live updated!\n");
84+
}
85+
}

examples/LiveUpdate/update.sh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#!/bin/bash
2+
dd if=build/liveupdate > /dev/tcp/10.0.0.42/666

lib/LiveUpdate/update.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ inline bool validate_header(const Class* hdr)
8686

8787
void LiveUpdate::exec(const buffer_t& blob, std::string key, storage_func func)
8888
{
89-
register_serialization_callback(key, func);
89+
if (func != nullptr) register_serialization_callback(key, func);
9090
LiveUpdate::exec(blob);
9191
}
9292

0 commit comments

Comments
 (0)