Demonstrates how to use sockets and the TLS layer.This example is a most-trivial HTTPS client that requests "/" on the passed host and outputs what the server sends verbatim.
#include <iostream>
#include <type_traits>
namespace {
{
logger()
{
}
std::cerr <<
"Log: " << int(t) <<
" " <<
fz::to_string(msg) <<
"\n";
}
};
}
{
public:
, trust_store_(pool_)
{
s_ = std::make_unique<fz::socket>(pool_, this);
if (res) {
event_loop_.stop();
return;
}
tls_ = std::make_unique<fz::tls_layer>(event_loop_, this, *s_, &trust_store_, log_);
log_.log(fz::logmsg::error, "Could not start handshake");
event_loop_.stop();
return;
}
snd_.append("GET / HTTP/1.1\r\nConnection: close\r\nUser-Agent: lfz (socket demo)\r\nHost: ");
snd_.append(host);
snd_.append("\r\n\r\n");
}
virtual ~handler()
{
}
bool success_{};
private:
{
fz::dispatch<fz::socket_event>(ev, this, &handler::on_socket_event);
}
if (error) {
switch (type) {
log_.log(fz::logmsg::error, "Connection failed: %s", desc);
break;
log_.log(fz::logmsg::error, "Reading failed: %s", desc);
break;
log_.log(fz::logmsg::error, "Connection failed %s", desc);
break;
default:
log_.log(fz::logmsg::error, "Unknown error: %s", desc);
break;
}
event_loop_.stop();
return;
}
while (!snd_.empty()) {
int w = tls_->write(snd_.get(), snd_.size(), error);
if (w > 0) {
snd_.consume(w);
}
else {
if (w < 0) {
if (error == EAGAIN) {
return;
}
}
event_loop_.stop();
return;
}
}
log_.log(
fz::logmsg::status,
"Sent request");
}
char buf[1024];
while (true) {
int r = tls_->read(buf, 1024, error);
if (r > 0) {
std::cout << std::string_view(buf, r);
continue;
}
if (!r) {
log_.log(fz::logmsg::status, "Got eof");
success_ = true;
}
else {
if (error == EAGAIN) {
return;
}
}
event_loop_.stop();
return;
}
}
}
logger log_;
std::unique_ptr<fz::socket> s_;
std::unique_ptr<fz::tls_layer> tls_;
};
int main(int argc , char * argv[])
{
if (argc <= 1) {
std::cerr << "Need to pass hostname\n";
return 1;
}
std::string host = argv[1];
handler h(l, host);
return h.success_ ? 0 : 1;
}
The buffer class is a simple buffer where data can be appended at the end and consumed at the front....
Definition: buffer.hpp:27
Common base class for all events.
Definition: event.hpp:23
Simple handler for asynchronous event processing.
Definition: event_handler.hpp:55
void remove_handler()
Deactivates handler, removes all pending events and stops all timers for this handler.
virtual void operator()(event_base const &)=0
Called by the event loop in the worker thread with the event to process.
A threaded event loop that supports sending events and timers.
Definition: event_loop.hpp:34
void run()
Starts the loop in the caller's thread.
Abstract interface for logging strings.
Definition: logger.hpp:51
virtual void do_log(logmsg::type t, std::wstring &&msg)=0
The one thing you need to override.
All classes sending socket events should derive from this.
Definition: socket.hpp:85
A dumb thread-pool for asynchronous tasks.
Definition: thread_pool.hpp:64
Opaque class to load the system trust store asynchronously.
Definition: tls_system_trust_store.hpp:30
Declares the event_handler class.
type
Definition: logger.hpp:16
The namespace used by libfilezilla.
Definition: apply.hpp:17
native_string socket_error_description(int error)
Gets a human-readable, translated description of the error.
std::string to_string(std::wstring_view const &in)
Converts from std::wstring into std::string in system encoding.
socket_event_flag
The type of a socket event.
Definition: socket.hpp:35
native_string to_native(std::string_view const &in)
Converts std::string to native_string.
Socket classes for networking.
Declares thread_pool and async_task.
A Transport Layer Security (TLS) layer.
System trust store for TLS certificates.
Various utility functions.