Some minor improvements

This commit is contained in:
WolverinDEV
2020-04-16 13:12:00 +02:00
parent 90c9fad28b
commit d7fa67b0aa
14 changed files with 115 additions and 92 deletions
@@ -36,6 +36,8 @@ void ProtocolHandler::reset() {
{ /* initialize pow handler */
this->pow.state = pow_state::COOKIE_SET;
this->pow.retry_count = 0;
this->pow.last_buffer = pipes::buffer{};
this->pow.last_resend = system_clock::time_point{};
this->pow.last_response = system_clock::time_point{};
@@ -98,6 +98,7 @@ namespace tc {
uint8_t disconnect_id = 0;
struct {
size_t retry_count{0};
pow_state::value state;
uint64_t client_ts3_build_timestamp = 173265950 /* TS3 */; /* needs to be lower than 173265950 for old stuff, else new protocol */
@@ -49,6 +49,14 @@ void ProtocolHandler::handlePacketInit(const std::shared_ptr<ts::protocol::Serve
if(packet_state == pow_state::COMMAND_RESET) {
log_trace(category::connection, tr("[POW] Received reset"));
this->pow.retry_count++;
if(this->pow.retry_count > 8) {
log_trace(category::connection, tr("[POW] Retied puzzle too many times. Aborting connect."));
this->handle->call_connect_result.call(this->handle->errors.register_error(tr("failed to solve connect puzzle")), true);
this->handle->close_connection();
return;
}
this->pow.state = pow_state::COOKIE_SET; /* next expected packet state */
this->pow_send_cookie_get();
return;
@@ -130,7 +138,7 @@ void ProtocolHandler::handlePacketInit(const std::shared_ptr<ts::protocol::Serve
auto offset = 4 + 1 + 2 * 64 + 04 + 100;
memset(&response_buffer[offset], 0, 64);
mp_to_unsigned_bin(&result, (u_char*) &response_buffer[offset]);
mp_to_unsigned_bin(&result, (u_char*) &response_buffer[offset + 64 - mp_unsigned_bin_size(&result)]);
memcpy(&response_buffer[301], command.data(), command.size());
@@ -60,7 +60,7 @@ bool UDPSocket::initialize() {
this->event_write = event_new(this->io_base, this->file_descriptor, EV_WRITE, &UDPSocket::_callback_write, this);
event_add(this->event_read, nullptr);
this->_io_thread = thread(&UDPSocket::_io_execute, this);
this->_io_thread = thread(&UDPSocket::_io_execute, this, this->io_base);
#ifdef WIN32
//TODO set thread name
#else
@@ -71,38 +71,42 @@ bool UDPSocket::initialize() {
}
void UDPSocket::finalize() {
const auto is_event_thread = this_thread::get_id() == this->_io_thread.get_id();
if(this->file_descriptor == 0)
return;
unique_lock lock(this->io_lock);
auto event_read = this->event_read, event_write = this->event_write;
auto io_base = this->io_base;
this->io_base = nullptr;
this->event_read = nullptr;
this->event_write = nullptr;
auto event_read = std::exchange(this->event_read, nullptr);
auto event_write = std::exchange(this->event_write, nullptr);
auto io_base = std::exchange(this->io_base, nullptr);
lock.unlock();
assert(this_thread::get_id() != this->_io_thread.get_id());
if(event_read) event_del_block(event_read);
if(event_write) event_del_block(event_write);
if(io_base) {
timeval seconds{1, 0};
event_base_loopexit(io_base, &seconds);
event_base_loopexit(io_base, nullptr);
}
if(this->_io_thread.joinable())
this->_io_thread.join();
if(is_event_thread) {
if(event_read) event_del_block(event_read);
if(event_write) event_del_block(event_write);
} else {
if(event_read) event_del_noblock(event_read);
if(event_write) event_del_noblock(event_write);
}
if(io_base)
event_base_free(io_base);
event_base_loopexit(io_base, nullptr);
if(is_event_thread) {
event_base_loopexit(io_base, nullptr);
this->_io_thread.detach();
} else {
event_base_loopexit(io_base, nullptr);
if(this->_io_thread.joinable())
this->_io_thread.join();
}
#ifdef WIN32
if(::closesocket(this->file_descriptor) != 0) {
const auto close_result = ::closesocket(this->file_descriptor);
#else
if(::close(this->file_descriptor) != 0) {
const auto close_result = ::close(this->file_descriptor);
#endif
if(close_result != 0) {
if(errno != EBADF)
logger::warn(category::socket, tr("Failed to close file descriptor ({}/{})"), to_string(errno), strerror(errno));
}
@@ -117,15 +121,16 @@ void UDPSocket::_callback_read(evutil_socket_t fd, short, void *_ptr_socket) {
((UDPSocket*) _ptr_socket)->callback_read(fd);
}
void UDPSocket::_io_execute(void *_ptr_socket) {
((UDPSocket*) _ptr_socket)->io_execute();
void UDPSocket::_io_execute(void *_ptr_socket, void* _ptr_event_base) {
((UDPSocket*) _ptr_socket)->io_execute(_ptr_event_base);
}
void UDPSocket::io_execute() {
while(this->io_base) {
event_base_loop(this->io_base, EVLOOP_NO_EXIT_ON_EMPTY);
}
void UDPSocket::io_execute(void* ptr_event_base) {
auto base = (event_base*) ptr_event_base;
event_base_loop(base, EVLOOP_NO_EXIT_ON_EMPTY);
/* this pointer might be dangling here! */
logger::trace(category::socket, tr("Socket IO loop exited"));
event_base_free(base);
}
void UDPSocket::callback_read(evutil_socket_t fd) {
sockaddr source_address{};
@@ -135,41 +140,36 @@ void UDPSocket::callback_read(evutil_socket_t fd) {
size_t buffer_length = 1600; /* IPv6 MTU is ~1.5k */
char buffer[1600];
size_t read_count = 0;
while(true) { //TODO: Some kind of timeout
source_address_length = sizeof(sockaddr);
read_length = recvfrom(fd, (char*) buffer, (int) buffer_length, MSG_DONTWAIT, &source_address, &source_address_length);
if(read_length <= 0) {
if(read_length == 0 && read_count > 0)
break;
int error;
source_address_length = sizeof(sockaddr);
read_length = recvfrom(fd, (char*) buffer, (int) buffer_length, MSG_DONTWAIT, &source_address, &source_address_length);
if(read_length <= 0) {
int error;
#ifdef WIN32
error = WSAGetLastError();
if(error == WSAEWOULDBLOCK)
break;
error = WSAGetLastError();
if(error == WSAEWOULDBLOCK)
return;
#else
error = errno;
if(errno == EAGAIN)
break;
error = errno;
if(errno == EAGAIN)
return;
#endif
logger::warn(category::socket, tr("Failed to receive data: {}"), error);
if(auto callback{this->on_fatal_error}; callback)
callback(1, error);
logger::warn(category::socket, tr("Failed to receive data: {}"), error);
{
std::lock_guard lock{this->io_lock};
if(this->event_read)
event_del_noblock(this->event_read);
}
{
std::lock_guard lock{this->io_lock};
if(this->event_read)
event_del_noblock(this->event_read);
}
break; /* this should never happen! */
}
//logger::trace(category::socket, tr("Read {} bytes"), read_length);
read_count++;
if(this->on_data)
this->on_data(pipes::buffer_view{buffer, (size_t) read_length});
if(auto callback{this->on_fatal_error}; callback)
callback(1, error);
/* this pointer might be dangling now because we got deleted while handling this data */
return;
}
//logger::trace(category::socket, tr("Read {} bytes"), read_length);
if(this->on_data)
this->on_data(pipes::buffer_view{buffer, (size_t) read_length});
/* this pointer might be dangling now because we got deleted while handling this data */
}
void UDPSocket::callback_write(evutil_socket_t fd) {
@@ -34,11 +34,11 @@ namespace tc::connection {
const std::thread& io_thread() { return this->_io_thread; }
private:
static void _io_execute(void *_ptr_socket);
static void _io_execute(void *_ptr_socket, void *_ptr_event_base);
static void _callback_read(evutil_socket_t, short, void*);
static void _callback_write(evutil_socket_t, short, void*);
void io_execute();
void io_execute(void*);
void callback_read(evutil_socket_t);
void callback_write(evutil_socket_t);