mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 08:37:46 +00:00
Libraries: Move to Userland/Libraries/
This commit is contained in:
parent
dc28c07fa5
commit
13d7c09125
1857 changed files with 266 additions and 274 deletions
9
Userland/Libraries/LibIPC/CMakeLists.txt
Normal file
9
Userland/Libraries/LibIPC/CMakeLists.txt
Normal file
|
@ -0,0 +1,9 @@
|
|||
set(SOURCES
|
||||
Decoder.cpp
|
||||
Encoder.cpp
|
||||
Endpoint.cpp
|
||||
Message.cpp
|
||||
)
|
||||
|
||||
serenity_lib(LibIPC ipc)
|
||||
target_link_libraries(LibIPC LibC LibCore)
|
78
Userland/Libraries/LibIPC/ClientConnection.h
Normal file
78
Userland/Libraries/LibIPC/ClientConnection.h
Normal file
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <LibIPC/Connection.h>
|
||||
|
||||
namespace IPC {
|
||||
|
||||
template<typename T, class... Args>
|
||||
NonnullRefPtr<T> new_client_connection(Args&&... args)
|
||||
{
|
||||
return T::construct(forward<Args>(args)...) /* arghs */;
|
||||
}
|
||||
|
||||
template<typename ClientEndpoint, typename ServerEndpoint>
|
||||
class ClientConnection : public Connection<ServerEndpoint, ClientEndpoint> {
|
||||
public:
|
||||
ClientConnection(ServerEndpoint& endpoint, NonnullRefPtr<Core::LocalSocket> socket, int client_id)
|
||||
: IPC::Connection<ServerEndpoint, ClientEndpoint>(endpoint, move(socket))
|
||||
, m_client_id(client_id)
|
||||
{
|
||||
ASSERT(this->socket().is_connected());
|
||||
this->socket().on_ready_to_read = [this] { this->drain_messages_from_peer(); };
|
||||
this->initialize_peer_info();
|
||||
}
|
||||
|
||||
virtual ~ClientConnection() override
|
||||
{
|
||||
}
|
||||
|
||||
void did_misbehave()
|
||||
{
|
||||
dbg() << *this << " (id=" << m_client_id << ", pid=" << client_pid() << ") misbehaved, disconnecting.";
|
||||
this->shutdown();
|
||||
}
|
||||
|
||||
void did_misbehave(const char* message)
|
||||
{
|
||||
dbg() << *this << " (id=" << m_client_id << ", pid=" << client_pid() << ") misbehaved (" << message << "), disconnecting.";
|
||||
this->shutdown();
|
||||
}
|
||||
|
||||
int client_id() const { return m_client_id; }
|
||||
|
||||
pid_t client_pid() const { return this->peer_pid(); }
|
||||
void set_client_pid(pid_t pid) { this->set_peer_pid(pid); }
|
||||
|
||||
virtual void die() = 0;
|
||||
|
||||
private:
|
||||
int m_client_id { -1 };
|
||||
};
|
||||
|
||||
}
|
281
Userland/Libraries/LibIPC/Connection.h
Normal file
281
Userland/Libraries/LibIPC/Connection.h
Normal file
|
@ -0,0 +1,281 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AK/ByteBuffer.h>
|
||||
#include <AK/NonnullOwnPtrVector.h>
|
||||
#include <LibCore/Event.h>
|
||||
#include <LibCore/EventLoop.h>
|
||||
#include <LibCore/LocalSocket.h>
|
||||
#include <LibCore/Notifier.h>
|
||||
#include <LibCore/SyscallUtils.h>
|
||||
#include <LibCore/Timer.h>
|
||||
#include <LibIPC/Message.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
namespace IPC {
|
||||
|
||||
template<typename LocalEndpoint, typename PeerEndpoint>
|
||||
class Connection : public Core::Object {
|
||||
public:
|
||||
Connection(LocalEndpoint& local_endpoint, NonnullRefPtr<Core::LocalSocket> socket)
|
||||
: m_local_endpoint(local_endpoint)
|
||||
, m_socket(move(socket))
|
||||
, m_notifier(Core::Notifier::construct(m_socket->fd(), Core::Notifier::Read, this))
|
||||
{
|
||||
m_responsiveness_timer = Core::Timer::create_single_shot(3000, [this] { may_have_become_unresponsive(); });
|
||||
m_notifier->on_ready_to_read = [this] {
|
||||
drain_messages_from_peer();
|
||||
handle_messages();
|
||||
};
|
||||
}
|
||||
|
||||
pid_t peer_pid() const { return m_peer_pid; }
|
||||
|
||||
template<typename MessageType>
|
||||
OwnPtr<MessageType> wait_for_specific_message()
|
||||
{
|
||||
return wait_for_specific_endpoint_message<MessageType, LocalEndpoint>();
|
||||
}
|
||||
|
||||
void post_message(const Message& message)
|
||||
{
|
||||
// NOTE: If this connection is being shut down, but has not yet been destroyed,
|
||||
// the socket will be closed. Don't try to send more messages.
|
||||
if (!m_socket->is_open())
|
||||
return;
|
||||
|
||||
auto buffer = message.encode();
|
||||
// Prepend the message size.
|
||||
uint32_t message_size = buffer.data.size();
|
||||
buffer.data.prepend(reinterpret_cast<const u8*>(&message_size), sizeof(message_size));
|
||||
|
||||
#ifdef __serenity__
|
||||
for (int fd : buffer.fds) {
|
||||
auto rc = sendfd(m_socket->fd(), fd);
|
||||
if (rc < 0) {
|
||||
perror("sendfd");
|
||||
shutdown();
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (!buffer.fds.is_empty())
|
||||
warnln("fd passing is not supported on this platform, sorry :(");
|
||||
#endif
|
||||
|
||||
size_t total_nwritten = 0;
|
||||
while (total_nwritten < buffer.data.size()) {
|
||||
auto nwritten = write(m_socket->fd(), buffer.data.data() + total_nwritten, buffer.data.size() - total_nwritten);
|
||||
if (nwritten < 0) {
|
||||
switch (errno) {
|
||||
case EPIPE:
|
||||
dbg() << *this << "::post_message: Disconnected from peer";
|
||||
shutdown();
|
||||
return;
|
||||
case EAGAIN:
|
||||
dbg() << *this << "::post_message: Peer buffer overflowed";
|
||||
shutdown();
|
||||
return;
|
||||
default:
|
||||
perror("Connection::post_message write");
|
||||
shutdown();
|
||||
return;
|
||||
}
|
||||
}
|
||||
total_nwritten += nwritten;
|
||||
}
|
||||
|
||||
m_responsiveness_timer->start();
|
||||
}
|
||||
|
||||
template<typename RequestType, typename... Args>
|
||||
OwnPtr<typename RequestType::ResponseType> send_sync(Args&&... args)
|
||||
{
|
||||
post_message(RequestType(forward<Args>(args)...));
|
||||
auto response = wait_for_specific_endpoint_message<typename RequestType::ResponseType, PeerEndpoint>();
|
||||
ASSERT(response);
|
||||
return response;
|
||||
}
|
||||
|
||||
virtual void may_have_become_unresponsive() { }
|
||||
virtual void did_become_responsive() { }
|
||||
|
||||
void shutdown()
|
||||
{
|
||||
m_notifier->close();
|
||||
m_socket->close();
|
||||
die();
|
||||
}
|
||||
|
||||
virtual void die() { }
|
||||
|
||||
protected:
|
||||
Core::LocalSocket& socket() { return *m_socket; }
|
||||
void set_peer_pid(pid_t pid) { m_peer_pid = pid; }
|
||||
|
||||
template<typename MessageType, typename Endpoint>
|
||||
OwnPtr<MessageType> wait_for_specific_endpoint_message()
|
||||
{
|
||||
for (;;) {
|
||||
// Double check we don't already have the event waiting for us.
|
||||
// Otherwise we might end up blocked for a while for no reason.
|
||||
for (size_t i = 0; i < m_unprocessed_messages.size(); ++i) {
|
||||
auto& message = m_unprocessed_messages[i];
|
||||
if (message.endpoint_magic() != Endpoint::static_magic())
|
||||
continue;
|
||||
if (message.message_id() == MessageType::static_message_id())
|
||||
return m_unprocessed_messages.take(i).template release_nonnull<MessageType>();
|
||||
}
|
||||
|
||||
if (!m_socket->is_open())
|
||||
break;
|
||||
fd_set rfds;
|
||||
FD_ZERO(&rfds);
|
||||
FD_SET(m_socket->fd(), &rfds);
|
||||
int rc = Core::safe_syscall(select, m_socket->fd() + 1, &rfds, nullptr, nullptr, nullptr);
|
||||
if (rc < 0) {
|
||||
perror("select");
|
||||
}
|
||||
ASSERT(rc > 0);
|
||||
ASSERT(FD_ISSET(m_socket->fd(), &rfds));
|
||||
if (!drain_messages_from_peer())
|
||||
break;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
bool drain_messages_from_peer()
|
||||
{
|
||||
Vector<u8> bytes;
|
||||
|
||||
if (!m_unprocessed_bytes.is_empty()) {
|
||||
bytes.append(m_unprocessed_bytes.data(), m_unprocessed_bytes.size());
|
||||
m_unprocessed_bytes.clear();
|
||||
}
|
||||
|
||||
while (m_socket->is_open()) {
|
||||
u8 buffer[4096];
|
||||
ssize_t nread = recv(m_socket->fd(), buffer, sizeof(buffer), MSG_DONTWAIT);
|
||||
if (nread < 0) {
|
||||
if (errno == EAGAIN)
|
||||
break;
|
||||
perror("recv");
|
||||
exit(1);
|
||||
return false;
|
||||
}
|
||||
if (nread == 0) {
|
||||
if (bytes.is_empty()) {
|
||||
deferred_invoke([this](auto&) { die(); });
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bytes.append(buffer, nread);
|
||||
}
|
||||
|
||||
if (!bytes.is_empty()) {
|
||||
m_responsiveness_timer->stop();
|
||||
did_become_responsive();
|
||||
}
|
||||
|
||||
size_t index = 0;
|
||||
uint32_t message_size = 0;
|
||||
for (; index + sizeof(message_size) < bytes.size(); index += message_size) {
|
||||
message_size = *reinterpret_cast<uint32_t*>(bytes.data() + index);
|
||||
if (message_size == 0 || bytes.size() - index - sizeof(uint32_t) < message_size)
|
||||
break;
|
||||
index += sizeof(message_size);
|
||||
auto remaining_bytes = ReadonlyBytes { bytes.data() + index, bytes.size() - index };
|
||||
if (auto message = LocalEndpoint::decode_message(remaining_bytes, m_socket->fd())) {
|
||||
m_unprocessed_messages.append(message.release_nonnull());
|
||||
} else if (auto message = PeerEndpoint::decode_message(remaining_bytes, m_socket->fd())) {
|
||||
m_unprocessed_messages.append(message.release_nonnull());
|
||||
} else {
|
||||
dbgln("Failed to parse a message");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (index < bytes.size()) {
|
||||
// Sometimes we might receive a partial message. That's okay, just stash away
|
||||
// the unprocessed bytes and we'll prepend them to the next incoming message
|
||||
// in the next run of this function.
|
||||
auto remaining_bytes = ByteBuffer::copy(bytes.data() + index, bytes.size() - index);
|
||||
if (!m_unprocessed_bytes.is_empty()) {
|
||||
dbg() << *this << "::drain_messages_from_peer: Already have unprocessed bytes";
|
||||
shutdown();
|
||||
return false;
|
||||
}
|
||||
m_unprocessed_bytes = remaining_bytes;
|
||||
}
|
||||
|
||||
if (!m_unprocessed_messages.is_empty()) {
|
||||
deferred_invoke([this](auto&) {
|
||||
handle_messages();
|
||||
});
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void handle_messages()
|
||||
{
|
||||
auto messages = move(m_unprocessed_messages);
|
||||
for (auto& message : messages) {
|
||||
if (message.endpoint_magic() == LocalEndpoint::static_magic())
|
||||
if (auto response = m_local_endpoint.handle(message))
|
||||
post_message(*response);
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
void initialize_peer_info()
|
||||
{
|
||||
ucred creds;
|
||||
socklen_t creds_size = sizeof(creds);
|
||||
if (getsockopt(this->socket().fd(), SOL_SOCKET, SO_PEERCRED, &creds, &creds_size) < 0) {
|
||||
// FIXME: We should handle this more gracefully.
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
m_peer_pid = creds.pid;
|
||||
}
|
||||
|
||||
LocalEndpoint& m_local_endpoint;
|
||||
NonnullRefPtr<Core::LocalSocket> m_socket;
|
||||
RefPtr<Core::Timer> m_responsiveness_timer;
|
||||
|
||||
RefPtr<Core::Notifier> m_notifier;
|
||||
NonnullOwnPtrVector<Message> m_unprocessed_messages;
|
||||
ByteBuffer m_unprocessed_bytes;
|
||||
pid_t m_peer_pid { -1 };
|
||||
};
|
||||
|
||||
}
|
186
Userland/Libraries/LibIPC/Decoder.cpp
Normal file
186
Userland/Libraries/LibIPC/Decoder.cpp
Normal file
|
@ -0,0 +1,186 @@
|
|||
/*
|
||||
* Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <AK/MemoryStream.h>
|
||||
#include <AK/URL.h>
|
||||
#include <LibIPC/Decoder.h>
|
||||
#include <LibIPC/Dictionary.h>
|
||||
#include <LibIPC/File.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
namespace IPC {
|
||||
|
||||
bool Decoder::decode(bool& value)
|
||||
{
|
||||
m_stream >> value;
|
||||
return !m_stream.handle_any_error();
|
||||
}
|
||||
|
||||
bool Decoder::decode(u8& value)
|
||||
{
|
||||
m_stream >> value;
|
||||
return !m_stream.handle_any_error();
|
||||
}
|
||||
|
||||
bool Decoder::decode(u16& value)
|
||||
{
|
||||
m_stream >> value;
|
||||
return !m_stream.handle_any_error();
|
||||
}
|
||||
|
||||
bool Decoder::decode(u32& value)
|
||||
{
|
||||
m_stream >> value;
|
||||
return !m_stream.handle_any_error();
|
||||
}
|
||||
|
||||
bool Decoder::decode(u64& value)
|
||||
{
|
||||
m_stream >> value;
|
||||
return !m_stream.handle_any_error();
|
||||
}
|
||||
|
||||
bool Decoder::decode(i8& value)
|
||||
{
|
||||
m_stream >> value;
|
||||
return !m_stream.handle_any_error();
|
||||
}
|
||||
|
||||
bool Decoder::decode(i16& value)
|
||||
{
|
||||
m_stream >> value;
|
||||
return !m_stream.handle_any_error();
|
||||
}
|
||||
|
||||
bool Decoder::decode(i32& value)
|
||||
{
|
||||
m_stream >> value;
|
||||
return !m_stream.handle_any_error();
|
||||
}
|
||||
|
||||
bool Decoder::decode(i64& value)
|
||||
{
|
||||
m_stream >> value;
|
||||
return !m_stream.handle_any_error();
|
||||
}
|
||||
|
||||
bool Decoder::decode(float& value)
|
||||
{
|
||||
m_stream >> value;
|
||||
return !m_stream.handle_any_error();
|
||||
}
|
||||
|
||||
bool Decoder::decode(String& value)
|
||||
{
|
||||
i32 length = 0;
|
||||
m_stream >> length;
|
||||
if (m_stream.handle_any_error())
|
||||
return false;
|
||||
if (length < 0) {
|
||||
value = {};
|
||||
return true;
|
||||
}
|
||||
if (length == 0) {
|
||||
value = String::empty();
|
||||
return true;
|
||||
}
|
||||
char* text_buffer = nullptr;
|
||||
auto text_impl = StringImpl::create_uninitialized(static_cast<size_t>(length), text_buffer);
|
||||
m_stream >> Bytes { text_buffer, static_cast<size_t>(length) };
|
||||
value = *text_impl;
|
||||
return !m_stream.handle_any_error();
|
||||
}
|
||||
|
||||
bool Decoder::decode(ByteBuffer& value)
|
||||
{
|
||||
i32 length = 0;
|
||||
m_stream >> length;
|
||||
if (m_stream.handle_any_error())
|
||||
return false;
|
||||
if (length < 0) {
|
||||
value = {};
|
||||
return true;
|
||||
}
|
||||
if (length == 0) {
|
||||
value = ByteBuffer::create_uninitialized(0);
|
||||
return true;
|
||||
}
|
||||
value = ByteBuffer::create_uninitialized(length);
|
||||
m_stream >> value.bytes();
|
||||
return !m_stream.handle_any_error();
|
||||
}
|
||||
|
||||
bool Decoder::decode(URL& value)
|
||||
{
|
||||
String string;
|
||||
if (!decode(string))
|
||||
return false;
|
||||
value = URL(string);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Decoder::decode(Dictionary& dictionary)
|
||||
{
|
||||
u64 size = 0;
|
||||
m_stream >> size;
|
||||
if (m_stream.handle_any_error())
|
||||
return false;
|
||||
if (size >= (size_t)NumericLimits<i32>::max()) {
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
String key;
|
||||
if (!decode(key))
|
||||
return false;
|
||||
String value;
|
||||
if (!decode(value))
|
||||
return false;
|
||||
dictionary.add(move(key), move(value));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Decoder::decode([[maybe_unused]] File& file)
|
||||
{
|
||||
#ifdef __serenity__
|
||||
int fd = recvfd(m_sockfd);
|
||||
if (fd < 0) {
|
||||
dbgln("recvfd: {}", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
file = File(fd);
|
||||
return true;
|
||||
#else
|
||||
[[maybe_unused]] auto fd = m_sockfd;
|
||||
warnln("fd passing is not supported on this platform, sorry :(");
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
132
Userland/Libraries/LibIPC/Decoder.h
Normal file
132
Userland/Libraries/LibIPC/Decoder.h
Normal file
|
@ -0,0 +1,132 @@
|
|||
/*
|
||||
* Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AK/Forward.h>
|
||||
#include <AK/NumericLimits.h>
|
||||
#include <AK/StdLibExtras.h>
|
||||
#include <AK/String.h>
|
||||
#include <LibIPC/Forward.h>
|
||||
#include <LibIPC/Message.h>
|
||||
|
||||
namespace IPC {
|
||||
|
||||
template<typename T>
|
||||
inline bool decode(Decoder&, T&)
|
||||
{
|
||||
static_assert(DependentFalse<T>, "Base IPC::decoder() instantiated");
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
|
||||
class Decoder {
|
||||
public:
|
||||
Decoder(InputMemoryStream& stream, int sockfd)
|
||||
: m_stream(stream)
|
||||
, m_sockfd(sockfd)
|
||||
{
|
||||
}
|
||||
|
||||
bool decode(bool&);
|
||||
bool decode(u8&);
|
||||
bool decode(u16&);
|
||||
bool decode(u32&);
|
||||
bool decode(u64&);
|
||||
bool decode(i8&);
|
||||
bool decode(i16&);
|
||||
bool decode(i32&);
|
||||
bool decode(i64&);
|
||||
bool decode(float&);
|
||||
bool decode(String&);
|
||||
bool decode(ByteBuffer&);
|
||||
bool decode(URL&);
|
||||
bool decode(Dictionary&);
|
||||
bool decode(File&);
|
||||
template<typename K, typename V>
|
||||
bool decode(HashMap<K, V>& hashmap)
|
||||
{
|
||||
u32 size;
|
||||
if (!decode(size) || size > NumericLimits<i32>::max())
|
||||
return false;
|
||||
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
K key;
|
||||
if (!decode(key))
|
||||
return false;
|
||||
|
||||
V value;
|
||||
if (!decode(value))
|
||||
return false;
|
||||
|
||||
hashmap.set(move(key), move(value));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool decode(T& value)
|
||||
{
|
||||
return IPC::decode(*this, value);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool decode(Vector<T>& vector)
|
||||
{
|
||||
u64 size;
|
||||
if (!decode(size) || size > NumericLimits<i32>::max())
|
||||
return false;
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
T value;
|
||||
if (!decode(value))
|
||||
return false;
|
||||
vector.append(move(value));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool decode(Optional<T>& optional)
|
||||
{
|
||||
bool has_value;
|
||||
if (!decode(has_value))
|
||||
return false;
|
||||
if (!has_value) {
|
||||
optional = {};
|
||||
return true;
|
||||
}
|
||||
T value;
|
||||
if (!decode(value))
|
||||
return false;
|
||||
optional = move(value);
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
InputMemoryStream& m_stream;
|
||||
int m_sockfd { -1 };
|
||||
};
|
||||
|
||||
}
|
65
Userland/Libraries/LibIPC/Dictionary.h
Normal file
65
Userland/Libraries/LibIPC/Dictionary.h
Normal file
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AK/HashMap.h>
|
||||
#include <AK/String.h>
|
||||
|
||||
namespace IPC {
|
||||
|
||||
class Dictionary {
|
||||
public:
|
||||
Dictionary() { }
|
||||
|
||||
Dictionary(const HashMap<String, String>& initial_entries)
|
||||
: m_entries(initial_entries)
|
||||
{
|
||||
}
|
||||
|
||||
bool is_empty() const { return m_entries.is_empty(); }
|
||||
size_t size() const { return m_entries.size(); }
|
||||
|
||||
void add(String key, String value)
|
||||
{
|
||||
m_entries.set(move(key), move(value));
|
||||
}
|
||||
|
||||
template<typename Callback>
|
||||
void for_each_entry(Callback callback) const
|
||||
{
|
||||
for (auto& it : m_entries) {
|
||||
callback(it.key, it.value);
|
||||
}
|
||||
}
|
||||
|
||||
const HashMap<String, String>& entries() const { return m_entries; }
|
||||
|
||||
private:
|
||||
HashMap<String, String> m_entries;
|
||||
};
|
||||
|
||||
}
|
173
Userland/Libraries/LibIPC/Encoder.cpp
Normal file
173
Userland/Libraries/LibIPC/Encoder.cpp
Normal file
|
@ -0,0 +1,173 @@
|
|||
/*
|
||||
* Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <AK/ByteBuffer.h>
|
||||
#include <AK/String.h>
|
||||
#include <AK/URL.h>
|
||||
#include <LibIPC/Dictionary.h>
|
||||
#include <LibIPC/Encoder.h>
|
||||
#include <LibIPC/File.h>
|
||||
|
||||
namespace IPC {
|
||||
|
||||
Encoder& Encoder::operator<<(bool value)
|
||||
{
|
||||
return *this << (u8)value;
|
||||
}
|
||||
|
||||
Encoder& Encoder::operator<<(u8 value)
|
||||
{
|
||||
m_buffer.data.append(value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Encoder& Encoder::operator<<(u16 value)
|
||||
{
|
||||
m_buffer.data.ensure_capacity(m_buffer.data.size() + 2);
|
||||
m_buffer.data.unchecked_append((u8)value);
|
||||
m_buffer.data.unchecked_append((u8)(value >> 8));
|
||||
return *this;
|
||||
}
|
||||
|
||||
Encoder& Encoder::operator<<(u32 value)
|
||||
{
|
||||
m_buffer.data.ensure_capacity(m_buffer.data.size() + 4);
|
||||
m_buffer.data.unchecked_append((u8)value);
|
||||
m_buffer.data.unchecked_append((u8)(value >> 8));
|
||||
m_buffer.data.unchecked_append((u8)(value >> 16));
|
||||
m_buffer.data.unchecked_append((u8)(value >> 24));
|
||||
return *this;
|
||||
}
|
||||
|
||||
Encoder& Encoder::operator<<(u64 value)
|
||||
{
|
||||
m_buffer.data.ensure_capacity(m_buffer.data.size() + 8);
|
||||
m_buffer.data.unchecked_append((u8)value);
|
||||
m_buffer.data.unchecked_append((u8)(value >> 8));
|
||||
m_buffer.data.unchecked_append((u8)(value >> 16));
|
||||
m_buffer.data.unchecked_append((u8)(value >> 24));
|
||||
m_buffer.data.unchecked_append((u8)(value >> 32));
|
||||
m_buffer.data.unchecked_append((u8)(value >> 40));
|
||||
m_buffer.data.unchecked_append((u8)(value >> 48));
|
||||
m_buffer.data.unchecked_append((u8)(value >> 56));
|
||||
return *this;
|
||||
}
|
||||
|
||||
Encoder& Encoder::operator<<(i8 value)
|
||||
{
|
||||
m_buffer.data.append((u8)value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Encoder& Encoder::operator<<(i16 value)
|
||||
{
|
||||
m_buffer.data.ensure_capacity(m_buffer.data.size() + 2);
|
||||
m_buffer.data.unchecked_append((u8)value);
|
||||
m_buffer.data.unchecked_append((u8)(value >> 8));
|
||||
return *this;
|
||||
}
|
||||
|
||||
Encoder& Encoder::operator<<(i32 value)
|
||||
{
|
||||
m_buffer.data.ensure_capacity(m_buffer.data.size() + 4);
|
||||
m_buffer.data.unchecked_append((u8)value);
|
||||
m_buffer.data.unchecked_append((u8)(value >> 8));
|
||||
m_buffer.data.unchecked_append((u8)(value >> 16));
|
||||
m_buffer.data.unchecked_append((u8)(value >> 24));
|
||||
return *this;
|
||||
}
|
||||
|
||||
Encoder& Encoder::operator<<(i64 value)
|
||||
{
|
||||
m_buffer.data.ensure_capacity(m_buffer.data.size() + 8);
|
||||
m_buffer.data.unchecked_append((u8)value);
|
||||
m_buffer.data.unchecked_append((u8)(value >> 8));
|
||||
m_buffer.data.unchecked_append((u8)(value >> 16));
|
||||
m_buffer.data.unchecked_append((u8)(value >> 24));
|
||||
m_buffer.data.unchecked_append((u8)(value >> 32));
|
||||
m_buffer.data.unchecked_append((u8)(value >> 40));
|
||||
m_buffer.data.unchecked_append((u8)(value >> 48));
|
||||
m_buffer.data.unchecked_append((u8)(value >> 56));
|
||||
return *this;
|
||||
}
|
||||
|
||||
Encoder& Encoder::operator<<(float value)
|
||||
{
|
||||
union bits {
|
||||
float as_float;
|
||||
u32 as_u32;
|
||||
} u;
|
||||
u.as_float = value;
|
||||
return *this << u.as_u32;
|
||||
}
|
||||
|
||||
Encoder& Encoder::operator<<(const char* value)
|
||||
{
|
||||
return *this << StringView(value);
|
||||
}
|
||||
|
||||
Encoder& Encoder::operator<<(const StringView& value)
|
||||
{
|
||||
m_buffer.data.append((const u8*)value.characters_without_null_termination(), value.length());
|
||||
return *this;
|
||||
}
|
||||
|
||||
Encoder& Encoder::operator<<(const String& value)
|
||||
{
|
||||
if (value.is_null())
|
||||
return *this << (i32)-1;
|
||||
*this << static_cast<i32>(value.length());
|
||||
return *this << value.view();
|
||||
}
|
||||
|
||||
Encoder& Encoder::operator<<(const ByteBuffer& value)
|
||||
{
|
||||
*this << static_cast<i32>(value.size());
|
||||
m_buffer.data.append(value.data(), value.size());
|
||||
return *this;
|
||||
}
|
||||
|
||||
Encoder& Encoder::operator<<(const URL& value)
|
||||
{
|
||||
return *this << value.to_string();
|
||||
}
|
||||
|
||||
Encoder& Encoder::operator<<(const Dictionary& dictionary)
|
||||
{
|
||||
*this << (u64)dictionary.size();
|
||||
dictionary.for_each_entry([this](auto& key, auto& value) {
|
||||
*this << key << value;
|
||||
});
|
||||
return *this;
|
||||
}
|
||||
|
||||
Encoder& Encoder::operator<<(const File& file)
|
||||
{
|
||||
m_buffer.fds.append(file.fd());
|
||||
return *this;
|
||||
}
|
||||
|
||||
}
|
111
Userland/Libraries/LibIPC/Encoder.h
Normal file
111
Userland/Libraries/LibIPC/Encoder.h
Normal file
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <LibIPC/Forward.h>
|
||||
#include <LibIPC/Message.h>
|
||||
|
||||
namespace IPC {
|
||||
|
||||
template<typename T>
|
||||
bool encode(Encoder&, T&)
|
||||
{
|
||||
static_assert(DependentFalse<T>, "Base IPC::encode() was instantiated");
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
|
||||
class Encoder {
|
||||
public:
|
||||
explicit Encoder(MessageBuffer& buffer)
|
||||
: m_buffer(buffer)
|
||||
{
|
||||
}
|
||||
|
||||
Encoder& operator<<(bool);
|
||||
Encoder& operator<<(u8);
|
||||
Encoder& operator<<(u16);
|
||||
Encoder& operator<<(u32);
|
||||
Encoder& operator<<(u64);
|
||||
Encoder& operator<<(i8);
|
||||
Encoder& operator<<(i16);
|
||||
Encoder& operator<<(i32);
|
||||
Encoder& operator<<(i64);
|
||||
Encoder& operator<<(float);
|
||||
Encoder& operator<<(const char*);
|
||||
Encoder& operator<<(const StringView&);
|
||||
Encoder& operator<<(const String&);
|
||||
Encoder& operator<<(const ByteBuffer&);
|
||||
Encoder& operator<<(const URL&);
|
||||
Encoder& operator<<(const Dictionary&);
|
||||
Encoder& operator<<(const File&);
|
||||
template<typename K, typename V>
|
||||
Encoder& operator<<(const HashMap<K, V>& hashmap)
|
||||
{
|
||||
*this << (u32)hashmap.size();
|
||||
for (auto it : hashmap) {
|
||||
*this << it.key;
|
||||
*this << it.value;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Encoder& operator<<(const Vector<T>& vector)
|
||||
{
|
||||
*this << (u64)vector.size();
|
||||
for (auto& value : vector)
|
||||
*this << value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Encoder& operator<<(const T& value)
|
||||
{
|
||||
encode(value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Encoder& operator<<(const Optional<T>& optional)
|
||||
{
|
||||
*this << optional.has_value();
|
||||
if (optional.has_value())
|
||||
*this << optional.value();
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void encode(const T& value)
|
||||
{
|
||||
IPC::encode(*this, value);
|
||||
}
|
||||
|
||||
private:
|
||||
MessageBuffer& m_buffer;
|
||||
};
|
||||
|
||||
}
|
39
Userland/Libraries/LibIPC/Endpoint.cpp
Normal file
39
Userland/Libraries/LibIPC/Endpoint.cpp
Normal file
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <LibIPC/Endpoint.h>
|
||||
|
||||
namespace IPC {
|
||||
|
||||
Endpoint::Endpoint()
|
||||
{
|
||||
}
|
||||
|
||||
Endpoint::~Endpoint()
|
||||
{
|
||||
}
|
||||
|
||||
}
|
55
Userland/Libraries/LibIPC/Endpoint.h
Normal file
55
Userland/Libraries/LibIPC/Endpoint.h
Normal file
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AK/OwnPtr.h>
|
||||
#include <AK/String.h>
|
||||
|
||||
namespace AK {
|
||||
class BufferStream;
|
||||
}
|
||||
|
||||
namespace IPC {
|
||||
|
||||
class Message;
|
||||
|
||||
class Endpoint {
|
||||
public:
|
||||
virtual ~Endpoint();
|
||||
|
||||
virtual int magic() const = 0;
|
||||
virtual String name() const = 0;
|
||||
virtual OwnPtr<Message> handle(const Message&) = 0;
|
||||
|
||||
protected:
|
||||
Endpoint();
|
||||
|
||||
private:
|
||||
String m_name;
|
||||
};
|
||||
|
||||
}
|
49
Userland/Libraries/LibIPC/File.h
Normal file
49
Userland/Libraries/LibIPC/File.h
Normal file
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Copyright (c) 2020, Sergey Bugaev <bugaevc@serenityos.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace IPC {
|
||||
|
||||
class File {
|
||||
public:
|
||||
// Must have a default constructor, because LibIPC
|
||||
// default-constructs arguments prior to decoding them.
|
||||
File() { }
|
||||
|
||||
// Intentionally not `explicit`.
|
||||
File(int fd)
|
||||
: m_fd(fd)
|
||||
{
|
||||
}
|
||||
|
||||
int fd() const { return m_fd; }
|
||||
|
||||
private:
|
||||
int m_fd { -1 };
|
||||
};
|
||||
|
||||
}
|
37
Userland/Libraries/LibIPC/Forward.h
Normal file
37
Userland/Libraries/LibIPC/Forward.h
Normal file
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace IPC {
|
||||
|
||||
class Decoder;
|
||||
class Dictionary;
|
||||
class Encoder;
|
||||
class Message;
|
||||
class File;
|
||||
|
||||
}
|
41
Userland/Libraries/LibIPC/Message.cpp
Normal file
41
Userland/Libraries/LibIPC/Message.cpp
Normal file
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <LibIPC/Message.h>
|
||||
|
||||
namespace IPC {
|
||||
|
||||
Message::Message()
|
||||
{
|
||||
}
|
||||
|
||||
Message::~Message()
|
||||
{
|
||||
if (on_destruction)
|
||||
on_destruction();
|
||||
}
|
||||
|
||||
}
|
54
Userland/Libraries/LibIPC/Message.h
Normal file
54
Userland/Libraries/LibIPC/Message.h
Normal file
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AK/Function.h>
|
||||
#include <AK/Vector.h>
|
||||
|
||||
namespace IPC {
|
||||
|
||||
struct MessageBuffer {
|
||||
Vector<u8, 1024> data;
|
||||
Vector<int> fds;
|
||||
};
|
||||
|
||||
class Message {
|
||||
public:
|
||||
virtual ~Message();
|
||||
|
||||
virtual int endpoint_magic() const = 0;
|
||||
virtual int message_id() const = 0;
|
||||
virtual const char* message_name() const = 0;
|
||||
virtual MessageBuffer encode() const = 0;
|
||||
|
||||
Function<void()> on_destruction;
|
||||
|
||||
protected:
|
||||
Message();
|
||||
};
|
||||
|
||||
}
|
70
Userland/Libraries/LibIPC/ServerConnection.h
Normal file
70
Userland/Libraries/LibIPC/ServerConnection.h
Normal file
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <LibIPC/Connection.h>
|
||||
|
||||
namespace IPC {
|
||||
|
||||
template<typename ClientEndpoint, typename ServerEndpoint>
|
||||
class ServerConnection : public IPC::Connection<ClientEndpoint, ServerEndpoint> {
|
||||
public:
|
||||
ServerConnection(ClientEndpoint& local_endpoint, const StringView& address)
|
||||
: Connection<ClientEndpoint, ServerEndpoint>(local_endpoint, Core::LocalSocket::construct())
|
||||
{
|
||||
// We want to rate-limit our clients
|
||||
this->socket().set_blocking(true);
|
||||
|
||||
if (!this->socket().connect(Core::SocketAddress::local(address))) {
|
||||
perror("connect");
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
|
||||
ASSERT(this->socket().is_connected());
|
||||
|
||||
this->initialize_peer_info();
|
||||
}
|
||||
|
||||
virtual void handshake() = 0;
|
||||
|
||||
pid_t server_pid() const { return this->peer_pid(); }
|
||||
void set_server_pid(pid_t pid) { this->set_peer_pid(pid); }
|
||||
|
||||
void set_my_client_id(int id) { m_my_client_id = id; }
|
||||
int my_client_id() const { return m_my_client_id; }
|
||||
|
||||
virtual void die() override
|
||||
{
|
||||
// Override this function if you don't want your app to exit if it loses the connection.
|
||||
exit(0);
|
||||
}
|
||||
|
||||
private:
|
||||
int m_my_client_id { -1 };
|
||||
};
|
||||
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue