Skip to content

Commit

Permalink
Merge pull request #40 from tewinget/conn-state-callbacks
Browse files Browse the repository at this point in the history
Connection established and closed callbacks
  • Loading branch information
tewinget committed Sep 18, 2023
2 parents 329a6ba + 0099dba commit 2c6b877
Show file tree
Hide file tree
Showing 17 changed files with 426 additions and 295 deletions.
4 changes: 2 additions & 2 deletions .drone.jsonnet
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ local generic_build(jobs, build_type, lto, werror, cmake_extra, local_mirror, te
+ (if tests then [
'cd build',
'../utils/gen-certs.sh',
(if gdb then '../utils/ci/drone-gdb.sh ' else '') + './tests/alltests --no-ipv6 --colour-mode ansi',
(if gdb then '../utils/ci/drone-gdb.sh ' else '') + './tests/alltests --log-level debug --no-ipv6 --colour-mode ansi',
'cd ..',
] else []);

Expand Down Expand Up @@ -172,7 +172,7 @@ local windows_cross_pipeline(name,
'-DBUILD_TESTS=' + (if tests then 'ON ' else 'OFF ') +
ci_dep_mirror(local_mirror),
'make -j' + jobs + ' VERBOSE=1',
//'wine-stable tests/alltests.exe --colour-mode ansi', // doesn't work yet :(
//'wine-stable tests/alltests.exe --log-level debug --colour-mode ansi', // doesn't work yet :(
] + extra_cmds,
},
],
Expand Down
1 change: 1 addition & 0 deletions include/quic.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "quic/crypto.hpp"
#include "quic/datagram.hpp"
#include "quic/endpoint.hpp"
#include "quic/error.hpp"
#include "quic/format.hpp"
#include "quic/gnutls_crypto.hpp"
#include "quic/messages.hpp"
Expand Down
6 changes: 2 additions & 4 deletions include/quic/connection.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ namespace oxen::quic
virtual int last_cleared() const = 0;
virtual int datagram_bufsize() const = 0;

virtual void close_connection() = 0;
virtual void close_connection(uint64_t error_code = 0) = 0;

virtual ~connection_interface() = default;

Expand Down Expand Up @@ -165,7 +165,6 @@ namespace oxen::quic
void set_closing() { closing = true; }
bool is_draining() const { return draining; }
void set_draining() { draining = true; }
void call_close_cb();
stream_data_callback get_default_data_callback() const;

const ConnectionID& scid() const override { return _source_cid; }
Expand All @@ -191,7 +190,7 @@ namespace oxen::quic

void send_datagram(bstring_view data, std::shared_ptr<void> keep_alive = nullptr) override;

void close_connection() override;
void close_connection(uint64_t error_code = 0) override;

private:
// private Constructor (publicly construct via `make_conn` instead, so that we can properly
Expand All @@ -210,7 +209,6 @@ namespace oxen::quic
const ConnectionID _source_cid;
ConnectionID _dest_cid;
Path _path;
std::function<void(Connection&)> on_closing; // clear immediately after use
const int _max_streams{DEFAULT_MAX_BIDI_STREAMS};
const bool _datagrams_enabled{false};
const bool _packet_splitting{false};
Expand Down
16 changes: 14 additions & 2 deletions include/quic/endpoint.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,21 @@ extern "C"

namespace oxen::quic
{
using connection_open_callback = std::function<void(connection_interface& conn)>;
using connection_closed_callback = std::function<void(connection_interface& conn, uint64_t ec)>;

class Endpoint : std::enable_shared_from_this<Endpoint>
{
private:
void handle_ep_opt(opt::enable_datagrams dc);
void handle_ep_opt(dgram_data_callback dgram_cb);
void handle_ep_opt(connection_open_callback conn_established_cb);
void handle_ep_opt(connection_closed_callback conn_closed_cb);

public:
connection_open_callback connection_open_cb;
connection_closed_callback connection_close_cb;

// Non-movable/non-copyable; you must always hold a Endpoint in a shared_ptr
Endpoint(const Endpoint&) = delete;
Endpoint& operator=(const Endpoint&) = delete;
Expand Down Expand Up @@ -169,9 +177,11 @@ namespace oxen::quic

void close_conns(std::optional<Direction> d = std::nullopt);

void close_connection(Connection& conn, int code = NGTCP2_NO_ERROR, std::string_view msg = "NO_ERROR"sv);
void drop_connection(Connection& conn);

void close_connection(ConnectionID cid, int code = NGTCP2_NO_ERROR, std::string_view msg = "NO_ERROR"sv);
void close_connection(Connection& conn, io_error ec = io_error{0}, std::string_view msg = "NO_ERROR"sv);

void close_connection(ConnectionID cid, io_error code = io_error{0}, std::string_view msg = "NO_ERROR"sv);

const Address& local() { return _local; }

Expand All @@ -192,6 +202,8 @@ namespace oxen::quic
void delete_connection(const ConnectionID& cid);
void drain_connection(Connection& conn);

void connection_established(connection_interface& conn);

int _rbufsize{4096};

private:
Expand Down
75 changes: 75 additions & 0 deletions include/quic/error.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#pragma once

#include "utils.hpp"

namespace oxen::quic
{
constexpr uint64_t LIBQUIC_ERROR_BASE = 0x6c696271756963; // "libquic"

enum class error : uint64_t {
NO_ERR = 0,

CONN_WRITE_CLOSE_FAIL = LIBQUIC_ERROR_BASE,
CONN_SEND_CLOSE_FAIL = LIBQUIC_ERROR_BASE + 1,

STREAM_EXCEPTION = LIBQUIC_ERROR_BASE + 32,
STREAM_CONNECTION_EXPIRED = LIBQUIC_ERROR_BASE + 33,

DATAGRAM_EXCEPTION = LIBQUIC_ERROR_BASE + 64
};

inline const char* quic_strerror(uint64_t e)
{
switch (static_cast<error>(e))
{
case error::NO_ERR:
return "No error";
case error::DATAGRAM_EXCEPTION:
return "Error - datagram exception";
case error::STREAM_EXCEPTION:
return "Error - stream exception";
case error::STREAM_CONNECTION_EXPIRED:
return "Error - stream connection expired";
case error::CONN_WRITE_CLOSE_FAIL:
return "Error - Failed to write connection close";
case error::CONN_SEND_CLOSE_FAIL:
return "Error - Failed to send connection close";
default:
return "Application-Specified Error";
}
}

struct io_error
{
private:
uint64_t _code{0};

public:
bool is_ngtcp2 = false;

io_error() = default;
explicit io_error(int e) : _code{static_cast<uint64_t>(e)} { is_ngtcp2 = true; }
explicit io_error(uint64_t e) : _code{e} { is_ngtcp2 = false; }
explicit io_error(error e) : _code{static_cast<uint64_t>(e)} {}

uint64_t code() const { return _code; }

int ngtcp2_code() const { return static_cast<int>(_code); }

uint64_t ngtcp2() const
{
if (not is_ngtcp2)
log::info(log_cat, "Error code {} is not an ngtcp2 error code", _code);
return _code;
}

const char* strerror() const
{
if (is_ngtcp2)
return ngtcp2_strerror(_code);
else
return quic_strerror(_code);
}
};

} // namespace oxen::quic
3 changes: 2 additions & 1 deletion include/quic/stream.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ extern "C"
#include <vector>

#include "datagram.hpp"
#include "error.hpp"
#include "types.hpp"
#include "utils.hpp"

Expand Down Expand Up @@ -59,7 +60,7 @@ namespace oxen::quic

std::shared_ptr<Stream> get_stream() override;

void close(uint64_t error_code = 0);
void close(io_error ec = io_error{});

void send(bstring_view data, std::shared_ptr<void> keep_alive = nullptr) override;

Expand Down
8 changes: 0 additions & 8 deletions include/quic/types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,6 @@

namespace oxen::quic
{
struct ngtcp2_error_code_t final
{};

// Tag value to pass into the constructor to indicate an ngtcp2 error code.
//
// (For ngtcp2, error codes are arbitrary negative values without any connection to errno).
static inline constexpr ngtcp2_error_code_t ngtcp2_error_code{};

enum class Direction { OUTBOUND = 0, INBOUND = 1 };

enum class Splitting { NONE = 0, ACTIVE = 1 };
Expand Down
7 changes: 7 additions & 0 deletions include/quic/utils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,13 @@ namespace oxen::quic
false;
#endif

struct ngtcp2_error_code_t final
{};

// Tag value to pass into the io_result/io_error constructors to indicate an ngtcp2 error code.
// (For ngtcp2, error codes are arbitrary negative values without any connection to errno).
static inline constexpr ngtcp2_error_code_t ngtcp2_error_code{};

// SI (1000) and non-SI (1024-based) modifier prefix operators. E.g.
// 50_M is 50'000'000 and 50_Mi is 52'428'800.
constexpr unsigned long long operator""_k(unsigned long long int x)
Expand Down

0 comments on commit 2c6b877

Please sign in to comment.