mirror of
https://github.com/kidfromjupiter/nearby.git
synced 2026-09-16 15:36:12 -04:00
removed ipc client
This commit is contained in:
@@ -1,145 +0,0 @@
|
||||
#include "sharing/linux/tui/ipc_client.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <cstring>
|
||||
#include <utility>
|
||||
|
||||
namespace nearby::sharing::linux_tui {
|
||||
|
||||
IpcClient::IpcClient(std::string socket_path)
|
||||
: socket_path_(std::move(socket_path)) {}
|
||||
|
||||
IpcClient::~IpcClient() {
|
||||
Stop();
|
||||
}
|
||||
|
||||
bool IpcClient::Start(EventHandler event_handler) {
|
||||
Stop();
|
||||
event_handler_ = std::move(event_handler);
|
||||
|
||||
socket_fd_ = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
if (socket_fd_ < 0) {
|
||||
Emit({{"event", "ipc_disconnected"},
|
||||
{"message", "failed to create socket"}});
|
||||
return false;
|
||||
}
|
||||
|
||||
sockaddr_un addr{};
|
||||
addr.sun_family = AF_UNIX;
|
||||
strncpy(addr.sun_path, socket_path_.c_str(), sizeof(addr.sun_path) - 1);
|
||||
|
||||
if (connect(socket_fd_, reinterpret_cast<sockaddr*>(&addr), sizeof(addr)) <
|
||||
0) {
|
||||
close(socket_fd_);
|
||||
socket_fd_ = -1;
|
||||
Emit({{"event", "ipc_disconnected"},
|
||||
{"message", "failed to connect to daemon"}});
|
||||
return false;
|
||||
}
|
||||
|
||||
running_.store(true);
|
||||
connected_.store(true);
|
||||
read_thread_ = std::thread([this] { ReadLoop(); });
|
||||
Emit({{"event", "ipc_connected"}});
|
||||
return true;
|
||||
}
|
||||
|
||||
void IpcClient::Stop() {
|
||||
running_.store(false);
|
||||
connected_.store(false);
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(write_mutex_);
|
||||
if (socket_fd_ >= 0) {
|
||||
shutdown(socket_fd_, SHUT_RDWR);
|
||||
close(socket_fd_);
|
||||
socket_fd_ = -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (read_thread_.joinable()) {
|
||||
read_thread_.join();
|
||||
}
|
||||
}
|
||||
|
||||
bool IpcClient::Send(const nlohmann::json& message) {
|
||||
return SendLine(message.dump());
|
||||
}
|
||||
|
||||
void IpcClient::ReadLoop() {
|
||||
std::string buffer;
|
||||
char chunk[1024]{};
|
||||
|
||||
while (running_.load()) {
|
||||
ssize_t received = recv(socket_fd_, chunk, sizeof(chunk), 0);
|
||||
if (received > 0) {
|
||||
buffer.append(chunk, static_cast<size_t>(received));
|
||||
size_t newline = std::string::npos;
|
||||
while ((newline = buffer.find('\n')) != std::string::npos) {
|
||||
std::string line = buffer.substr(0, newline);
|
||||
buffer.erase(0, newline + 1);
|
||||
if (line.empty()) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
Emit(nlohmann::json::parse(line));
|
||||
} catch (const nlohmann::json::exception& error) {
|
||||
Emit({{"event", "ipc_error"},
|
||||
{"message",
|
||||
std::string("malformed daemon JSON: ") + error.what()}});
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (received < 0 && errno == EINTR) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
connected_.store(false);
|
||||
if (running_.load()) {
|
||||
Emit({{"event", "ipc_disconnected"}, {"message", "daemon disconnected"}});
|
||||
}
|
||||
}
|
||||
|
||||
void IpcClient::Emit(nlohmann::json event) {
|
||||
if (event_handler_) {
|
||||
event_handler_(event);
|
||||
}
|
||||
}
|
||||
|
||||
bool IpcClient::SendLine(std::string_view line) {
|
||||
std::lock_guard<std::mutex> lock(write_mutex_);
|
||||
if (socket_fd_ < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string data(line);
|
||||
if (data.empty() || data.back() != '\n') {
|
||||
data.push_back('\n');
|
||||
}
|
||||
|
||||
size_t total_sent = 0;
|
||||
while (total_sent < data.size()) {
|
||||
ssize_t sent = send(socket_fd_, data.data() + total_sent,
|
||||
data.size() - total_sent, MSG_NOSIGNAL);
|
||||
if (sent > 0) {
|
||||
total_sent += static_cast<size_t>(sent);
|
||||
continue;
|
||||
}
|
||||
if (sent < 0 && errno == EINTR) {
|
||||
continue;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace nearby::sharing::linux_tui
|
||||
@@ -1,43 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <atomic>
|
||||
#include <functional>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <thread>
|
||||
|
||||
#include "nlohmann/json.hpp"
|
||||
|
||||
namespace nearby::sharing::linux_tui {
|
||||
|
||||
class IpcClient {
|
||||
public:
|
||||
using EventHandler = std::function<void(const nlohmann::json& event)>;
|
||||
|
||||
explicit IpcClient(std::string socket_path = "/tmp/nearby_sharing_sock");
|
||||
~IpcClient();
|
||||
|
||||
IpcClient(const IpcClient&) = delete;
|
||||
IpcClient& operator=(const IpcClient&) = delete;
|
||||
|
||||
bool Start(EventHandler event_handler);
|
||||
void Stop();
|
||||
bool Send(const nlohmann::json& message);
|
||||
bool connected() const { return connected_.load(); }
|
||||
|
||||
private:
|
||||
void ReadLoop();
|
||||
void Emit(nlohmann::json event);
|
||||
bool SendLine(std::string_view line);
|
||||
|
||||
std::string socket_path_;
|
||||
EventHandler event_handler_;
|
||||
std::thread read_thread_;
|
||||
mutable std::mutex write_mutex_;
|
||||
std::atomic<bool> running_{false};
|
||||
std::atomic<bool> connected_{false};
|
||||
int socket_fd_ = -1;
|
||||
};
|
||||
|
||||
} // namespace nearby::sharing::linux_tui
|
||||
@@ -1,135 +0,0 @@
|
||||
#include "sharing/linux/tui/ipc_client.h"
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <condition_variable>
|
||||
#include <chrono>
|
||||
#include <cstring>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "nlohmann/json.hpp"
|
||||
|
||||
namespace nearby::sharing::linux_tui {
|
||||
namespace {
|
||||
|
||||
std::string TestSocketPath() {
|
||||
return "/tmp/nearby_tui_ipc_client_test_" + std::to_string(getpid());
|
||||
}
|
||||
|
||||
int CreateServerSocket(const std::string& socket_path) {
|
||||
int fd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
EXPECT_GE(fd, 0);
|
||||
|
||||
unlink(socket_path.c_str());
|
||||
|
||||
sockaddr_un addr{};
|
||||
addr.sun_family = AF_UNIX;
|
||||
strncpy(addr.sun_path, socket_path.c_str(), sizeof(addr.sun_path) - 1);
|
||||
|
||||
EXPECT_EQ(bind(fd, reinterpret_cast<sockaddr*>(&addr), sizeof(addr)), 0);
|
||||
EXPECT_EQ(listen(fd, 1), 0);
|
||||
return fd;
|
||||
}
|
||||
|
||||
std::string ReadLine(int fd) {
|
||||
std::string line;
|
||||
char byte = '\0';
|
||||
while (recv(fd, &byte, 1, 0) == 1) {
|
||||
if (byte == '\n') {
|
||||
return line;
|
||||
}
|
||||
line.push_back(byte);
|
||||
}
|
||||
return line;
|
||||
}
|
||||
|
||||
void SendAll(int fd, const std::string& data) {
|
||||
size_t sent_total = 0;
|
||||
while (sent_total < data.size()) {
|
||||
ssize_t sent = send(fd, data.data() + sent_total, data.size() - sent_total,
|
||||
MSG_NOSIGNAL);
|
||||
ASSERT_GT(sent, 0);
|
||||
sent_total += static_cast<size_t>(sent);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
TEST(IpcClientTest, SendsJsonCommandWithNewline) {
|
||||
std::string socket_path = TestSocketPath();
|
||||
int server_fd = CreateServerSocket(socket_path);
|
||||
std::string received;
|
||||
|
||||
std::thread server_thread([&] {
|
||||
int client_fd = accept(server_fd, nullptr, nullptr);
|
||||
ASSERT_GE(client_fd, 0);
|
||||
received = ReadLine(client_fd);
|
||||
close(client_fd);
|
||||
});
|
||||
|
||||
IpcClient client(socket_path);
|
||||
ASSERT_TRUE(client.Start([](const nlohmann::json&) {}));
|
||||
EXPECT_TRUE(client.Send({{"command", "start_receive"}}));
|
||||
client.Stop();
|
||||
|
||||
server_thread.join();
|
||||
close(server_fd);
|
||||
unlink(socket_path.c_str());
|
||||
|
||||
nlohmann::json command = nlohmann::json::parse(received);
|
||||
EXPECT_EQ(command["command"], "start_receive");
|
||||
}
|
||||
|
||||
TEST(IpcClientTest, ParsesSplitJsonEvents) {
|
||||
std::string socket_path = TestSocketPath();
|
||||
int server_fd = CreateServerSocket(socket_path);
|
||||
|
||||
std::mutex mutex;
|
||||
std::condition_variable cv;
|
||||
std::vector<nlohmann::json> events;
|
||||
|
||||
std::thread server_thread([&] {
|
||||
int client_fd = accept(server_fd, nullptr, nullptr);
|
||||
ASSERT_GE(client_fd, 0);
|
||||
SendAll(client_fd,
|
||||
R"({"event":"target_discovered","share_target":{"id":1}})"
|
||||
"\n"
|
||||
R"({"event":"incoming)");
|
||||
SendAll(client_fd, R"(_transfer","share_target":{"id":2},"transfer":{}})"
|
||||
"\n");
|
||||
close(client_fd);
|
||||
});
|
||||
|
||||
IpcClient client(socket_path);
|
||||
ASSERT_TRUE(client.Start([&](const nlohmann::json& event) {
|
||||
if (event.value("event", std::string()).rfind("ipc_", 0) == 0) {
|
||||
return;
|
||||
}
|
||||
std::lock_guard<std::mutex> lock(mutex);
|
||||
events.push_back(event);
|
||||
cv.notify_one();
|
||||
}));
|
||||
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
cv.wait_for(lock, std::chrono::seconds(2),
|
||||
[&] { return events.size() >= 2; });
|
||||
}
|
||||
client.Stop();
|
||||
|
||||
server_thread.join();
|
||||
close(server_fd);
|
||||
unlink(socket_path.c_str());
|
||||
|
||||
ASSERT_GE(events.size(), 2u);
|
||||
EXPECT_EQ(events[0]["event"], "target_discovered");
|
||||
EXPECT_EQ(events[1]["event"], "incoming_transfer");
|
||||
}
|
||||
|
||||
} // namespace nearby::sharing::linux_tui
|
||||
Reference in New Issue
Block a user