Tidied GDB Connection class and made it adhere to the RAII approach
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
#include "Connection.hpp"
|
#include "Connection.hpp"
|
||||||
|
|
||||||
#include <sys/socket.h>
|
#include <arpa/inet.h>
|
||||||
#include <sys/epoll.h>
|
#include <sys/epoll.h>
|
||||||
#include <cerrno>
|
#include <cerrno>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
@@ -19,34 +19,36 @@ namespace Bloom::DebugServers::Gdb
|
|||||||
|
|
||||||
using ResponsePackets::ResponsePacket;
|
using ResponsePackets::ResponsePacket;
|
||||||
|
|
||||||
void Connection::accept(int serverSocketFileDescriptor) {
|
Connection::Connection(int serverSocketFileDescriptor, EventNotifier& interruptEventNotifier)
|
||||||
int socketAddressLength = sizeof(this->socketAddress);
|
: interruptEventNotifier(interruptEventNotifier)
|
||||||
|
{
|
||||||
this->socketFileDescriptor = ::accept(
|
this->accept(serverSocketFileDescriptor);
|
||||||
serverSocketFileDescriptor,
|
|
||||||
reinterpret_cast<sockaddr*>(&(this->socketAddress)),
|
|
||||||
reinterpret_cast<socklen_t*>(&socketAddressLength)
|
|
||||||
);
|
|
||||||
|
|
||||||
if (this->socketFileDescriptor == -1) {
|
|
||||||
throw Exception("Failed to accept GDB Remote Serial Protocol connection");
|
|
||||||
}
|
|
||||||
|
|
||||||
::fcntl(
|
::fcntl(
|
||||||
this->socketFileDescriptor,
|
this->socketFileDescriptor.value(),
|
||||||
F_SETFL,
|
F_SETFL,
|
||||||
::fcntl(this->socketFileDescriptor, F_GETFL, 0) | O_NONBLOCK
|
::fcntl(this->socketFileDescriptor.value(), F_GETFL, 0) | O_NONBLOCK
|
||||||
);
|
);
|
||||||
|
|
||||||
this->epollInstance.addEntry(this->socketFileDescriptor, static_cast<std::uint16_t>(EpollEvent::READ_READY));
|
this->epollInstance.addEntry(
|
||||||
|
this->socketFileDescriptor.value(),
|
||||||
|
static_cast<std::uint16_t>(EpollEvent::READ_READY)
|
||||||
|
);
|
||||||
this->enableReadInterrupts();
|
this->enableReadInterrupts();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Connection::close() noexcept {
|
Connection::~Connection() {
|
||||||
if (this->socketFileDescriptor > 0) {
|
this->close();
|
||||||
::close(this->socketFileDescriptor);
|
}
|
||||||
this->socketFileDescriptor = 0;
|
|
||||||
|
std::string Connection::getIpAddress() const {
|
||||||
|
std::array<char, INET_ADDRSTRLEN> ipAddress = {};
|
||||||
|
|
||||||
|
if (::inet_ntop(AF_INET, &(socketAddress.sin_addr), ipAddress.data(), INET_ADDRSTRLEN) == nullptr) {
|
||||||
|
throw Exception("Failed to convert client IP address to text form.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return std::string(ipAddress.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<RawPacketType> Connection::readRawPackets() {
|
std::vector<RawPacketType> Connection::readRawPackets() {
|
||||||
@@ -145,6 +147,29 @@ namespace Bloom::DebugServers::Gdb
|
|||||||
} while (this->readSingleByte(false).value_or(0) != '+');
|
} while (this->readSingleByte(false).value_or(0) != '+');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Connection::accept(int serverSocketFileDescriptor) {
|
||||||
|
int socketAddressLength = sizeof(this->socketAddress);
|
||||||
|
|
||||||
|
const auto socketFileDescriptor = ::accept(
|
||||||
|
serverSocketFileDescriptor,
|
||||||
|
reinterpret_cast<sockaddr*>(&(this->socketAddress)),
|
||||||
|
reinterpret_cast<socklen_t*>(&socketAddressLength)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (socketFileDescriptor < 0) {
|
||||||
|
throw Exception("Failed to accept GDB Remote Serial Protocol connection");
|
||||||
|
}
|
||||||
|
|
||||||
|
this->socketFileDescriptor = socketFileDescriptor;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Connection::close() noexcept {
|
||||||
|
if (this->socketFileDescriptor.value_or(-1) >= 0) {
|
||||||
|
::close(this->socketFileDescriptor.value());
|
||||||
|
this->socketFileDescriptor = std::nullopt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<unsigned char> Connection::read(
|
std::vector<unsigned char> Connection::read(
|
||||||
size_t bytes,
|
size_t bytes,
|
||||||
bool interruptible,
|
bool interruptible,
|
||||||
@@ -183,7 +208,7 @@ namespace Bloom::DebugServers::Gdb
|
|||||||
size_t bytesToRead = (bytes > bufferSize || bytes == 0) ? bufferSize : bytes;
|
size_t bytesToRead = (bytes > bufferSize || bytes == 0) ? bufferSize : bytes;
|
||||||
while (
|
while (
|
||||||
bytesToRead > 0
|
bytesToRead > 0
|
||||||
&& (bytesRead = ::read(this->socketFileDescriptor, buffer.data(), bytesToRead)) > 0
|
&& (bytesRead = ::read(this->socketFileDescriptor.value(), buffer.data(), bytesToRead)) > 0
|
||||||
) {
|
) {
|
||||||
output.insert(output.end(), buffer.begin(), buffer.begin() + bytesRead);
|
output.insert(output.end(), buffer.begin(), buffer.begin() + bytesRead);
|
||||||
|
|
||||||
@@ -215,7 +240,7 @@ namespace Bloom::DebugServers::Gdb
|
|||||||
|
|
||||||
void Connection::write(const std::vector<unsigned char>& buffer) {
|
void Connection::write(const std::vector<unsigned char>& buffer) {
|
||||||
Logger::debug("Writing packet: " + std::string(buffer.begin(), buffer.end()));
|
Logger::debug("Writing packet: " + std::string(buffer.begin(), buffer.end()));
|
||||||
if (::write(this->socketFileDescriptor, buffer.data(), buffer.size()) == -1) {
|
if (::write(this->socketFileDescriptor.value(), buffer.data(), buffer.size()) == -1) {
|
||||||
if (errno == EPIPE || errno == ECONNRESET) {
|
if (errno == EPIPE || errno == ECONNRESET) {
|
||||||
// Connection was closed
|
// Connection was closed
|
||||||
throw ClientDisconnected();
|
throw ClientDisconnected();
|
||||||
|
|||||||
@@ -1,13 +1,12 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <queue>
|
#include <queue>
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <arpa/inet.h>
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
|
||||||
#include "src/Helpers/EventNotifier.hpp"
|
#include "src/Helpers/EventNotifier.hpp"
|
||||||
@@ -24,47 +23,30 @@ namespace Bloom::DebugServers::Gdb
|
|||||||
class Connection
|
class Connection
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit Connection(EventNotifier& interruptEventNotifier)
|
explicit Connection(int serverSocketFileDescriptor, EventNotifier& interruptEventNotifier);
|
||||||
: interruptEventNotifier(interruptEventNotifier)
|
|
||||||
{};
|
|
||||||
|
|
||||||
Connection() = delete;
|
Connection() = delete;
|
||||||
Connection(const Connection&) = delete;
|
Connection(const Connection&) = delete;
|
||||||
|
Connection& operator = (Connection&) = delete;
|
||||||
|
Connection& operator = (Connection&&) = delete;
|
||||||
|
|
||||||
Connection(Connection&& other) noexcept
|
Connection(Connection&& other) noexcept
|
||||||
: interruptEventNotifier(other.interruptEventNotifier)
|
: interruptEventNotifier(other.interruptEventNotifier)
|
||||||
, socketFileDescriptor(other.socketFileDescriptor)
|
, socketFileDescriptor(other.socketFileDescriptor)
|
||||||
, epollInstance(std::move(other.epollInstance))
|
, epollInstance(std::move(other.epollInstance))
|
||||||
, readInterruptEnabled(other.readInterruptEnabled)
|
, readInterruptEnabled(other.readInterruptEnabled)
|
||||||
{
|
{
|
||||||
other.socketFileDescriptor = -1;
|
other.socketFileDescriptor = std::nullopt;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
~Connection();
|
||||||
* Accepts a connection on serverSocketFileDescriptor.
|
|
||||||
*
|
|
||||||
* @param serverSocketFileDescriptor
|
|
||||||
*/
|
|
||||||
void accept(int serverSocketFileDescriptor);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Closes the connection with the client.
|
|
||||||
*/
|
|
||||||
void close() noexcept;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Obtains the human readable IP address of the connected client.
|
* Obtains the human readable IP address of the connected client.
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
std::string getIpAddress() {
|
[[nodiscard]] std::string getIpAddress() const;
|
||||||
std::array<char, INET_ADDRSTRLEN> ipAddress = {};
|
|
||||||
|
|
||||||
if (::inet_ntop(AF_INET, &(socketAddress.sin_addr), ipAddress.data(), INET_ADDRSTRLEN) == nullptr) {
|
|
||||||
throw Exceptions::Exception("Failed to convert client IP address to text form.");
|
|
||||||
}
|
|
||||||
|
|
||||||
return std::string(ipAddress.data());
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Waits for incoming data from the client and returns the raw GDB packets.
|
* Waits for incoming data from the client and returns the raw GDB packets.
|
||||||
@@ -85,7 +67,7 @@ namespace Bloom::DebugServers::Gdb
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int socketFileDescriptor = -1;
|
std::optional<int> socketFileDescriptor;
|
||||||
|
|
||||||
EpollInstance epollInstance = EpollInstance();
|
EpollInstance epollInstance = EpollInstance();
|
||||||
|
|
||||||
@@ -99,6 +81,18 @@ namespace Bloom::DebugServers::Gdb
|
|||||||
EventNotifier& interruptEventNotifier;
|
EventNotifier& interruptEventNotifier;
|
||||||
bool readInterruptEnabled = false;
|
bool readInterruptEnabled = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accepts a connection on serverSocketFileDescriptor.
|
||||||
|
*
|
||||||
|
* @param serverSocketFileDescriptor
|
||||||
|
*/
|
||||||
|
void accept(int serverSocketFileDescriptor);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closes the connection with the client.
|
||||||
|
*/
|
||||||
|
void close() noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads data from the client into a raw buffer.
|
* Reads data from the client into a raw buffer.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -10,6 +10,6 @@ namespace Bloom::DebugServers::Gdb
|
|||||||
{}
|
{}
|
||||||
|
|
||||||
void DebugSession::terminate() {
|
void DebugSession::terminate() {
|
||||||
this->connection.close();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -134,7 +134,6 @@ namespace Bloom::DebugServers::Gdb
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
connection->accept(this->serverSocketFileDescriptor);
|
|
||||||
Logger::info("Accepted GDP RSP connection from " + connection->getIpAddress());
|
Logger::info("Accepted GDP RSP connection from " + connection->getIpAddress());
|
||||||
|
|
||||||
this->activeDebugSession.emplace(
|
this->activeDebugSession.emplace(
|
||||||
@@ -206,7 +205,7 @@ namespace Bloom::DebugServers::Gdb
|
|||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::make_optional<Connection>(*(this->interruptEventNotifier));
|
return std::make_optional<Connection>(this->serverSocketFileDescriptor, *(this->interruptEventNotifier));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<CommandPacket> GdbRspDebugServer::waitForCommandPacket() {
|
std::unique_ptr<CommandPacket> GdbRspDebugServer::waitForCommandPacket() {
|
||||||
|
|||||||
Reference in New Issue
Block a user