libos: Add os::LocalClient
This commit is contained in:
parent
4382c3686b
commit
9722e9def8
@ -15,6 +15,7 @@ set(SOURCES
|
|||||||
src/Prompt.cpp
|
src/Prompt.cpp
|
||||||
src/Security.cpp
|
src/Security.cpp
|
||||||
src/LocalServer.cpp
|
src/LocalServer.cpp
|
||||||
|
src/LocalClient.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
add_library(os ${SOURCES})
|
add_library(os ${SOURCES})
|
||||||
|
90
libos/include/os/LocalClient.h
Normal file
90
libos/include/os/LocalClient.h
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <luna/SharedPtr.h>
|
||||||
|
#include <luna/StringView.h>
|
||||||
|
|
||||||
|
namespace os
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @brief A client used to connect to a local server socket.
|
||||||
|
*/
|
||||||
|
class LocalClient : public Shareable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Create a new client object and connect it to a local server.
|
||||||
|
*
|
||||||
|
* @param path The path of the server socket to connect to.
|
||||||
|
* @param blocking Whether the client should block if no data is available and recv() is called.
|
||||||
|
* @return Result<SharedPtr<LocalClient>> An error, or a new client object.
|
||||||
|
*/
|
||||||
|
static Result<SharedPtr<LocalClient>> connect(StringView path, bool blocking);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Return the underlying socket file descriptor used by this object.
|
||||||
|
*
|
||||||
|
* @return int The file descriptor.
|
||||||
|
*/
|
||||||
|
int fd() const
|
||||||
|
{
|
||||||
|
return m_fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Read arbitrary data from the server. The call will block if there is no data and this object has not
|
||||||
|
* been created as non-blocking.
|
||||||
|
*
|
||||||
|
* @param buf The buffer to read data into.
|
||||||
|
* @param length The maximum amount of bytes to read.
|
||||||
|
* @return Result<usize> An error, or the number of bytes read.
|
||||||
|
*/
|
||||||
|
Result<usize> recv(u8* buf, usize length);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Read an object from the server. The call will block if there is no data and this object has not been
|
||||||
|
* created as non-blocking.
|
||||||
|
*
|
||||||
|
* @tparam T The type of the object.
|
||||||
|
* @param out A reference to the object to read data into.
|
||||||
|
* @return Result<void> Whether the operation succeded.
|
||||||
|
*/
|
||||||
|
template <typename T> Result<void> recv_typed(T& out)
|
||||||
|
{
|
||||||
|
TRY(recv((u8*)&out, sizeof(T)));
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Send arbitrary data to the server.
|
||||||
|
*
|
||||||
|
* @param buf The buffer to send data from.
|
||||||
|
* @param length The amount of bytes to send.
|
||||||
|
* @return Result<usize> An error, or the number of bytes actually sent.
|
||||||
|
*/
|
||||||
|
Result<usize> send(const u8* buf, usize length);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Send an object to the server.
|
||||||
|
*
|
||||||
|
* @tparam T The type of the object.
|
||||||
|
* @param out A reference to the object to send data from.
|
||||||
|
* @return Result<void> Whether the operation succeded.
|
||||||
|
*/
|
||||||
|
template <typename T> Result<void> send_typed(const T& out)
|
||||||
|
{
|
||||||
|
TRY(send((const u8*)&out, sizeof(T)));
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Disconnect from the attached server.
|
||||||
|
*
|
||||||
|
* This will make any further reads on this connection return ECONNRESET, and will make this object invalid.
|
||||||
|
*/
|
||||||
|
void disconnect();
|
||||||
|
|
||||||
|
~LocalClient();
|
||||||
|
|
||||||
|
private:
|
||||||
|
int m_fd;
|
||||||
|
};
|
||||||
|
}
|
59
libos/src/LocalClient.cpp
Normal file
59
libos/src/LocalClient.cpp
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <os/LocalClient.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/un.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
namespace os
|
||||||
|
{
|
||||||
|
Result<SharedPtr<LocalClient>> LocalClient::connect(StringView path, bool blocking)
|
||||||
|
{
|
||||||
|
auto client = TRY(make_shared<LocalClient>());
|
||||||
|
|
||||||
|
int sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||||
|
if (sockfd < 0) return err(errno);
|
||||||
|
|
||||||
|
struct sockaddr_un un;
|
||||||
|
un.sun_family = AF_UNIX;
|
||||||
|
strncpy(un.sun_path, path.chars(), sizeof(un.sun_path));
|
||||||
|
|
||||||
|
if (::connect(sockfd, (struct sockaddr*)&un, sizeof(un)) < 0)
|
||||||
|
{
|
||||||
|
close(sockfd);
|
||||||
|
return err(errno);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!blocking) { fcntl(sockfd, F_SETFL, O_NONBLOCK); }
|
||||||
|
|
||||||
|
fcntl(sockfd, F_SETFD, FD_CLOEXEC);
|
||||||
|
|
||||||
|
client->m_fd = sockfd;
|
||||||
|
return client;
|
||||||
|
}
|
||||||
|
|
||||||
|
LocalClient::~LocalClient()
|
||||||
|
{
|
||||||
|
close(m_fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result<usize> LocalClient::recv(u8* buf, usize length)
|
||||||
|
{
|
||||||
|
ssize_t nread = read(m_fd, buf, length);
|
||||||
|
if (nread < 0) return err(errno);
|
||||||
|
return nread;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result<usize> LocalClient::send(const u8* buf, usize length)
|
||||||
|
{
|
||||||
|
ssize_t nwrite = write(m_fd, buf, length);
|
||||||
|
if (nwrite < 0) return err(errno);
|
||||||
|
return nwrite;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LocalClient::disconnect()
|
||||||
|
{
|
||||||
|
close(m_fd);
|
||||||
|
m_fd = -1;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user