Skip to content

Commit

Permalink
Merge pull request #5 from beman-project/cppcon-2024
Browse files Browse the repository at this point in the history
adding the code created during the cppcon-2024 presentation
  • Loading branch information
dietmarkuehl authored Sep 17, 2024
2 parents d1d7605 + 91114a2 commit 1b591df
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 0 deletions.
Binary file added docs/cppcon-2024-slides.pdf
Binary file not shown.
1 change: 1 addition & 0 deletions examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ set(EXAMPLES
server
client
task
cppcon-2024
)

set(DATA
Expand Down
108 changes: 108 additions & 0 deletions examples/cppcon-2024.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
// examples/http-server.cpp -*-C++-*-
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#include <beman/net29/net.hpp>
#include <beman/execution26/execution.hpp>
#include "demo_algorithm.hpp"
#include "demo_error.hpp"
#include "demo_scope.hpp"
#include "demo_task.hpp"
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include <string_view>
#include <unordered_map>

namespace ex = beman::execution26;
namespace net = beman::net29;
using namespace std::chrono_literals;

// ----------------------------------------------------------------------------

std::unordered_map<std::string, std::string> files{
{"/", "examples/data/index.html"},
{"/favicon.ico", "examples/data/favicon.ico"},
{"/logo.png", "examples/data/logo.png"},
};

auto process(auto& stream, auto const& request) -> demo::task<>
{
std::cout << "request=" << request << "\n";
std::string method, url, version;
std::string body;
std::ostringstream out;
if (std::istringstream(request) >> method >> url >> version
&& files.contains(url))
{
std::cout << "url=" << url << "\n";
out << std::ifstream(files[url]).rdbuf();
body = out.str();
out.str({});
}

out << "HTTP/1.1 " << (body.empty()? "404 not found": "200 found") << "\r\n"
<< "Content-Length: " << body.size() << "\r\n"
<< "\r\n"
<< body;
auto response{out.str()};
co_await net::async_send(stream, net::buffer(response));
}

auto timeout(auto scheduler, auto duration, auto sender)
{
return demo::when_any(
std::move(sender),
net::resume_after(scheduler, duration)
| demo::into_error([]{ return std::error_code(demo::timeout, demo::category()); })
);
}

auto make_client_handler(auto scheduler, auto stream) -> demo::task<>
{
char buffer[16];
std::string request;
while (true)
try {
if (auto n = co_await timeout(scheduler, 2s, net::async_receive(stream, net::buffer(buffer)))) {
std::string_view data(buffer, n);
request += data;
if (request.find("\r\n\r\n") != request.npos)
{
co_await process(stream, request);
break;
}
}
else {
//std::cout << "ERROR (via expected): " << std::get<0>(n.error()).message() << "\n";
break;
}
}
catch (std::variant<std::error_code> const& ex) {
std::cout << "ERROR: " << std::get<0>(ex).message() << "\n";
break;
}


co_return;
}

auto main() -> int
{
demo::scope scope;

net::io_context context;
net::ip::tcp::endpoint endpoint(net::ip::address_v4::any(), 12345);
net::ip::tcp::acceptor acceptor(context, endpoint);

scope.spawn(std::invoke([](auto scheduler, auto& scope, auto& acceptor)->demo::task<> {
while (true)
{
auto[stream, address] = co_await net::async_accept(acceptor);
std::cout << "received client: " << address << "\n";
scope.spawn(make_client_handler(scheduler, std::move(stream)));
}
}, context.get_scheduler(), scope, acceptor));

context.run();
}

0 comments on commit 1b591df

Please sign in to comment.