You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
206 lines
4.3 KiB
206 lines
4.3 KiB
1 year ago
|
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||
|
file Copyright.txt or https://cmake.org/licensing for details. */
|
||
|
#include "cmDebuggerPosixPipeConnection.h"
|
||
|
|
||
|
#include <cerrno>
|
||
|
#include <cstring>
|
||
|
#include <stdexcept>
|
||
|
#include <utility>
|
||
|
|
||
|
#include <unistd.h>
|
||
|
|
||
|
#include <sys/socket.h>
|
||
|
|
||
|
namespace cmDebugger {
|
||
|
|
||
|
#ifndef _WIN32
|
||
|
|
||
|
cmDebuggerPipeConnection_POSIX::cmDebuggerPipeConnection_POSIX(
|
||
|
std::string name)
|
||
|
: PipeName(std::move(name))
|
||
|
{
|
||
|
addr.sun_path[0] = '\0';
|
||
|
}
|
||
|
|
||
|
cmDebuggerPipeConnection_POSIX::~cmDebuggerPipeConnection_POSIX()
|
||
|
{
|
||
|
if (isOpen()) {
|
||
|
close();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bool cmDebuggerPipeConnection_POSIX::StartListening(std::string& errorMessage)
|
||
|
{
|
||
|
listen_fd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||
|
if (listen_fd < 0) {
|
||
|
errorMessage = "Failed to create socket: ";
|
||
|
errorMessage += strerror(errno);
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
addr.sun_family = AF_UNIX;
|
||
|
strncpy(addr.sun_path, PipeName.c_str(), sizeof(addr.sun_path));
|
||
|
addr.sun_path[sizeof(addr.sun_path) - 1] = '\0';
|
||
|
if (bind(listen_fd, (sockaddr*)&addr, sizeof(addr)) == -1) {
|
||
|
errorMessage = "Failed to bind name '";
|
||
|
errorMessage += addr.sun_path;
|
||
|
errorMessage += "' to socket: ";
|
||
|
errorMessage += strerror(errno);
|
||
|
close_listen();
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
if (listen(listen_fd, 1) == -1) {
|
||
|
errorMessage = "Failed to listen on socket: ";
|
||
|
errorMessage += strerror(errno);
|
||
|
close_listen();
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
StartedListening.set_value();
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
std::shared_ptr<dap::Reader> cmDebuggerPipeConnection_POSIX::GetReader()
|
||
|
{
|
||
|
return std::static_pointer_cast<dap::Reader>(shared_from_this());
|
||
|
}
|
||
|
|
||
|
std::shared_ptr<dap::Writer> cmDebuggerPipeConnection_POSIX::GetWriter()
|
||
|
{
|
||
|
return std::static_pointer_cast<dap::Writer>(shared_from_this());
|
||
|
}
|
||
|
|
||
|
bool cmDebuggerPipeConnection_POSIX::isOpen()
|
||
|
{
|
||
|
return rw_pipe >= 0;
|
||
|
}
|
||
|
|
||
|
void cmDebuggerPipeConnection_POSIX::close()
|
||
|
{
|
||
|
close_listen();
|
||
|
::close(rw_pipe);
|
||
|
rw_pipe = -1;
|
||
|
}
|
||
|
|
||
|
void cmDebuggerPipeConnection_POSIX::close_listen()
|
||
|
{
|
||
|
if (strlen(addr.sun_path) > 0) {
|
||
|
unlink(addr.sun_path);
|
||
|
addr.sun_path[0] = '\0';
|
||
|
}
|
||
|
::close(listen_fd);
|
||
|
listen_fd = -1;
|
||
|
}
|
||
|
|
||
|
void cmDebuggerPipeConnection_POSIX::WaitForConnection()
|
||
|
{
|
||
|
sockaddr_un laddr;
|
||
|
socklen_t len = sizeof(laddr);
|
||
|
rw_pipe = accept(listen_fd, (sockaddr*)&laddr, &len);
|
||
|
if (rw_pipe < 0) {
|
||
|
close();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
close_listen(); // no longer need the listen resources
|
||
|
}
|
||
|
|
||
|
size_t cmDebuggerPipeConnection_POSIX::read(void* buffer, size_t n)
|
||
|
{
|
||
|
size_t result = 0;
|
||
|
if (rw_pipe >= 0) {
|
||
|
result = ::read(rw_pipe, buffer, n);
|
||
|
if (result == 0) {
|
||
|
close();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
bool cmDebuggerPipeConnection_POSIX::write(void const* buffer, size_t n)
|
||
|
{
|
||
|
bool result = false;
|
||
|
if (rw_pipe >= 0) {
|
||
|
result = ::write(rw_pipe, buffer, n) >= 0;
|
||
|
if (!result) {
|
||
|
close();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
cmDebuggerPipeClient_POSIX::cmDebuggerPipeClient_POSIX(std::string name)
|
||
|
: PipeName(std::move(name))
|
||
|
{
|
||
|
}
|
||
|
|
||
|
cmDebuggerPipeClient_POSIX::~cmDebuggerPipeClient_POSIX()
|
||
|
{
|
||
|
close();
|
||
|
}
|
||
|
|
||
|
void cmDebuggerPipeClient_POSIX::WaitForConnection()
|
||
|
{
|
||
|
rw_pipe = socket(AF_UNIX, SOCK_STREAM, 0);
|
||
|
if (rw_pipe < 0) {
|
||
|
throw std::runtime_error(std::string("Failed to create socket: ") +
|
||
|
strerror(errno));
|
||
|
}
|
||
|
|
||
|
sockaddr_un addr;
|
||
|
addr.sun_family = AF_UNIX;
|
||
|
strncpy(addr.sun_path, PipeName.c_str(), sizeof(addr.sun_path));
|
||
|
addr.sun_path[sizeof(addr.sun_path) - 1] = '\0';
|
||
|
if (connect(rw_pipe, (sockaddr*)&addr, sizeof(addr)) == -1) {
|
||
|
close();
|
||
|
throw std::runtime_error(
|
||
|
std::string("Failed to connect path to socket: ") + strerror(errno));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bool cmDebuggerPipeClient_POSIX::isOpen()
|
||
|
{
|
||
|
return rw_pipe >= 0;
|
||
|
}
|
||
|
|
||
|
void cmDebuggerPipeClient_POSIX::close()
|
||
|
{
|
||
|
if (isOpen()) {
|
||
|
::close(rw_pipe);
|
||
|
rw_pipe = -1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
size_t cmDebuggerPipeClient_POSIX::read(void* buffer, size_t n)
|
||
|
{
|
||
|
int count = 0;
|
||
|
if (isOpen()) {
|
||
|
count = static_cast<int>(::read(rw_pipe, buffer, n));
|
||
|
if (count == 0) {
|
||
|
close();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return count;
|
||
|
}
|
||
|
|
||
|
bool cmDebuggerPipeClient_POSIX::write(void const* buffer, size_t n)
|
||
|
{
|
||
|
int count = 0;
|
||
|
if (isOpen()) {
|
||
|
count = static_cast<int>(::write(rw_pipe, buffer, n));
|
||
|
if (count < 0) {
|
||
|
close();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return count > 0;
|
||
|
}
|
||
|
|
||
|
#endif // !_WIN32
|
||
|
|
||
|
} // namespace cmDebugger
|