Initial commit.
This commit is contained in:
commit
f215bc3742
43 changed files with 2983 additions and 0 deletions
148
Shared/Network/Connection.cpp
Normal file
148
Shared/Network/Connection.cpp
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
#include <string>
|
||||
#include <thread>
|
||||
|
||||
#include <ngtcp2/ngtcp2_crypto.h>
|
||||
#include <ngtcp2/ngtcp2_crypto_gnutls.h>
|
||||
#include <gnutls/crypto.h>
|
||||
#include <cista.h>
|
||||
|
||||
#include "Connection.h"
|
||||
|
||||
namespace Artifact {
|
||||
|
||||
Connection::Connection() {
|
||||
ngtcp2_settings_default(&settings);
|
||||
ngtcp2_transport_params_default(&transportParams);
|
||||
transportParams.initial_max_streams_bidi = 1;
|
||||
transportParams.initial_max_data = 65535;
|
||||
transportParams.initial_max_stream_data_bidi_local = 65535;
|
||||
|
||||
callbacks.encrypt = ngtcp2_crypto_encrypt_cb;
|
||||
callbacks.decrypt = ngtcp2_crypto_decrypt_cb;
|
||||
callbacks.hp_mask = ngtcp2_crypto_hp_mask_cb;
|
||||
callbacks.update_key = ngtcp2_crypto_update_key_cb;
|
||||
callbacks.delete_crypto_aead_ctx = ngtcp2_crypto_delete_crypto_aead_ctx_cb;
|
||||
callbacks.delete_crypto_cipher_ctx = ngtcp2_crypto_delete_crypto_cipher_ctx_cb;
|
||||
callbacks.get_path_challenge_data = ngtcp2_crypto_get_path_challenge_data_cb;
|
||||
callbacks.rand = [](auto dest, auto len, auto ctx) {
|
||||
gnutls_rnd(GNUTLS_RND_RANDOM, dest, len);
|
||||
};
|
||||
callbacks.get_new_connection_id = [](auto conn, auto cid, auto token, auto cidlen, auto userdata) {
|
||||
gnutls_rnd(GNUTLS_RND_RANDOM, cid, cidlen);
|
||||
gnutls_rnd(GNUTLS_RND_RANDOM, token, NGTCP2_STATELESS_RESET_TOKENLEN);
|
||||
return 0;
|
||||
};
|
||||
callbacks.version_negotiation = ngtcp2_crypto_version_negotiation_cb;
|
||||
|
||||
gnutls_rnd(GNUTLS_RND_RANDOM, dcid.data, dcid.datalen);
|
||||
gnutls_rnd(GNUTLS_RND_RANDOM, scid.data, scid.datalen);
|
||||
}
|
||||
|
||||
void readPacket(ngtcp2_pkt_info * info, void * packet) {
|
||||
|
||||
}
|
||||
|
||||
ClientConnection::ClientConnection(std::string host, std::string port) {
|
||||
struct addrinfo hints;
|
||||
struct addrinfo * local = nullptr;
|
||||
struct addrinfo * remote = nullptr;
|
||||
getaddrinfo("::", "", &hints, &local);
|
||||
getaddrinfo(host.c_str(), port.c_str(), &hints, &remote);
|
||||
ngtcp2_path path = {
|
||||
.local = {
|
||||
.addr = local->ai_addr,
|
||||
.addrlen = local->ai_addrlen
|
||||
},
|
||||
.remote = {
|
||||
.addr = remote->ai_addr,
|
||||
.addrlen = remote->ai_addrlen
|
||||
}
|
||||
};
|
||||
|
||||
if (gnutls_init(&session, GNUTLS_CLIENT) != GNUTLS_E_SUCCESS) {
|
||||
throw std::runtime_error("Failed to initialize gnutls.");
|
||||
}
|
||||
gnutls_set_default_priority(session);
|
||||
|
||||
ngtcp2_conn_client_new(&conn, &dcid, &scid, &path, NGTCP2_PROTO_VER_V1, &callbacks, &settings, &transportParams, nullptr, this);
|
||||
ngtcp2_conn_set_tls_native_handle(conn, session);
|
||||
}
|
||||
|
||||
ServerConnection::ServerConnection(ngtcp2_path path) : path(path) {
|
||||
if (gnutls_init(&session, GNUTLS_CLIENT) != GNUTLS_E_SUCCESS) {
|
||||
throw std::runtime_error("Failed to initialize gnutls.");
|
||||
}
|
||||
gnutls_set_default_priority(session);
|
||||
|
||||
ngtcp2_conn_server_new(&conn, &dcid, &scid, &path, NGTCP2_PROTO_VER_V1, &callbacks, &settings, &transportParams, nullptr, this);
|
||||
ngtcp2_conn_set_tls_native_handle(conn, session);
|
||||
}
|
||||
|
||||
ServerListener::ServerListener(std::string port) {
|
||||
struct addrinfo hints;
|
||||
struct addrinfo * local = nullptr;
|
||||
getaddrinfo("::", "", &hints, &local);
|
||||
|
||||
socketDescriptor = socket(local->ai_family, local->ai_socktype, local->ai_protocol);
|
||||
|
||||
int on = 1;
|
||||
setsockopt(socketDescriptor, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast<char *>(&on), sizeof(int));
|
||||
|
||||
if (local->ai_family == AF_INET6) {
|
||||
int off = 0;
|
||||
setsockopt(socketDescriptor, IPPROTO_IPV6, IPV6_V6ONLY, reinterpret_cast<char *>(&off), sizeof(int));
|
||||
}
|
||||
|
||||
if (bind(socketDescriptor, local->ai_addr, local->ai_addrlen)) {
|
||||
// Save our actual local address for later use.
|
||||
getsockname(socketDescriptor, reinterpret_cast<sockaddr *>(&localAddr.addr), &localAddr.addrlen);
|
||||
}
|
||||
}
|
||||
|
||||
void ServerListener::onReadable(struct ev_loop *, ev_io * watcher, int) {
|
||||
auto self = static_cast<ServerListener *>(watcher->data);
|
||||
|
||||
uint8_t buf[2048];
|
||||
ngtcp2_addr remote;
|
||||
auto len = recvfrom(self->socketDescriptor, buf, sizeof(buf), 0, remote.addr, &remote.addrlen);
|
||||
|
||||
ngtcp2_pkt_info pi{};
|
||||
ngtcp2_pkt_hd hd{};
|
||||
ngtcp2_pkt_decode_hd_long(&hd, buf, len);
|
||||
|
||||
auto it = self->connections.find(hd.dcid);
|
||||
if (it != self->connections.end()) {
|
||||
ServerConnection * conn = it->second.get();
|
||||
|
||||
ngtcp2_conn_read_pkt(conn->conn, &conn->path, &pi, buf, len, std::chrono::steady_clock::now().time_since_epoch().count());
|
||||
|
||||
conn->readPacket(&pi, buf);
|
||||
return;
|
||||
}
|
||||
|
||||
if (hd.flags & NGTCP2_PKT_FLAG_LONG_FORM && hd.type == NGTCP2_PKT_INITIAL) {
|
||||
ngtcp2_pkt_hd accept_hd{};
|
||||
if (ngtcp2_accept(&accept_hd, buf, static_cast<size_t>(len)) != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto new_conn = std::make_unique<ServerConnection>(ngtcp2_path {
|
||||
.local = self->localAddr,
|
||||
.remote = remote
|
||||
});
|
||||
|
||||
self->connections[accept_hd.dcid] = std::move(new_conn);
|
||||
}
|
||||
}
|
||||
|
||||
void ServerListener::run() {
|
||||
std::thread([this]() {
|
||||
loop = ev_loop_new(EVFLAG_AUTO);
|
||||
ev_io_init(&watcher, onReadable, socketDescriptor, EV_READ);
|
||||
watcher.data = this;
|
||||
ev_io_start(loop, &watcher);
|
||||
ev_run(loop, 0);
|
||||
}).detach();
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue