diff --git a/DevTools/IPCCompiler/main.cpp b/DevTools/IPCCompiler/main.cpp index 805bd60a6b0..586f93cfe90 100644 --- a/DevTools/IPCCompiler/main.cpp +++ b/DevTools/IPCCompiler/main.cpp @@ -217,6 +217,7 @@ int main(int argc, char** argv) #include #include #include +#include #include )~~~"); @@ -318,9 +319,9 @@ public: static i32 static_message_id() { return (int)MessageID::@message.name@; } virtual const char* message_name() const override { return "@endpoint.name@::@message.name@"; } - static OwnPtr<@message.name@> decode(InputMemoryStream& stream) + static OwnPtr<@message.name@> decode(InputMemoryStream& stream, int sockfd) { - IPC::Decoder decoder { stream }; + IPC::Decoder decoder { stream, sockfd }; )~~~"); for (auto& parameter : parameters) { @@ -436,7 +437,7 @@ public: static String static_name() { return "@endpoint.name@"; } virtual String name() const override { return "@endpoint.name@"; } - static OwnPtr decode_message(const ByteBuffer& buffer) + static OwnPtr decode_message(const ByteBuffer& buffer, int sockfd) { InputMemoryStream stream { buffer }; i32 message_endpoint_magic = 0; @@ -488,7 +489,7 @@ public: message_generator.append(R"~~~( case (int)Messages::@endpoint.name@::MessageID::@message.name@: - message = Messages::@endpoint.name@::@message.name@::decode(stream); + message = Messages::@endpoint.name@::@message.name@::decode(stream, sockfd); break; )~~~"); }; diff --git a/Libraries/LibIPC/Connection.h b/Libraries/LibIPC/Connection.h index 781a2d4c4f0..2b354378d1f 100644 --- a/Libraries/LibIPC/Connection.h +++ b/Libraries/LibIPC/Connection.h @@ -77,12 +77,25 @@ public: auto buffer = message.encode(); // Prepend the message size. - uint32_t message_size = buffer.size(); - buffer.prepend(reinterpret_cast(&message_size), sizeof(message_size)); + uint32_t message_size = buffer.data.size(); + buffer.data.prepend(reinterpret_cast(&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.size()) { - auto nwritten = write(m_socket->fd(), buffer.data() + total_nwritten, buffer.size() - total_nwritten); + 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: @@ -202,9 +215,9 @@ protected: break; index += sizeof(message_size); auto remaining_bytes = ByteBuffer::wrap(bytes.data() + index, bytes.size() - index); - if (auto message = LocalEndpoint::decode_message(remaining_bytes)) { + 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)) { + } 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"); diff --git a/Libraries/LibIPC/Decoder.cpp b/Libraries/LibIPC/Decoder.cpp index c76f9a73302..35e987cc9f6 100644 --- a/Libraries/LibIPC/Decoder.cpp +++ b/Libraries/LibIPC/Decoder.cpp @@ -28,6 +28,9 @@ #include #include #include +#include +#include +#include namespace IPC { @@ -163,4 +166,21 @@ bool Decoder::decode(Dictionary& dictionary) return true; } +bool Decoder::decode(File& file) +{ +#ifdef __serenity__ + int fd = recvfd(m_sockfd); + if (fd < 0) { + dbgln("recvfd: {}", strerror(errno)); + return false; + } + file = File(fd); + return true; +#else + (void)file; + warnln("fd passing is not supported on this platform, sorry :("); + return false; +#endif +} + } diff --git a/Libraries/LibIPC/Decoder.h b/Libraries/LibIPC/Decoder.h index 0b5d39041eb..a8752f7890f 100644 --- a/Libraries/LibIPC/Decoder.h +++ b/Libraries/LibIPC/Decoder.h @@ -44,8 +44,9 @@ inline bool decode(Decoder&, T&) class Decoder { public: - explicit Decoder(InputMemoryStream& stream) + Decoder(InputMemoryStream& stream, int sockfd) : m_stream(stream) + , m_sockfd(sockfd) { } @@ -63,6 +64,7 @@ public: bool decode(ByteBuffer&); bool decode(URL&); bool decode(Dictionary&); + bool decode(File&); template bool decode(HashMap& hashmap) { @@ -124,6 +126,7 @@ public: private: InputMemoryStream& m_stream; + int m_sockfd { -1 }; }; } diff --git a/Libraries/LibIPC/Encoder.cpp b/Libraries/LibIPC/Encoder.cpp index c0eb8d670ef..240c3d927f5 100644 --- a/Libraries/LibIPC/Encoder.cpp +++ b/Libraries/LibIPC/Encoder.cpp @@ -29,6 +29,7 @@ #include #include #include +#include namespace IPC { @@ -39,77 +40,77 @@ Encoder& Encoder::operator<<(bool value) Encoder& Encoder::operator<<(u8 value) { - m_buffer.append(value); + m_buffer.data.append(value); return *this; } Encoder& Encoder::operator<<(u16 value) { - m_buffer.ensure_capacity(m_buffer.size() + 2); - m_buffer.unchecked_append((u8)value); - m_buffer.unchecked_append((u8)(value >> 8)); + 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.ensure_capacity(m_buffer.size() + 4); - m_buffer.unchecked_append((u8)value); - m_buffer.unchecked_append((u8)(value >> 8)); - m_buffer.unchecked_append((u8)(value >> 16)); - m_buffer.unchecked_append((u8)(value >> 24)); + 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.ensure_capacity(m_buffer.size() + 8); - m_buffer.unchecked_append((u8)value); - m_buffer.unchecked_append((u8)(value >> 8)); - m_buffer.unchecked_append((u8)(value >> 16)); - m_buffer.unchecked_append((u8)(value >> 24)); - m_buffer.unchecked_append((u8)(value >> 32)); - m_buffer.unchecked_append((u8)(value >> 40)); - m_buffer.unchecked_append((u8)(value >> 48)); - m_buffer.unchecked_append((u8)(value >> 56)); + 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.append((u8)value); + m_buffer.data.append((u8)value); return *this; } Encoder& Encoder::operator<<(i16 value) { - m_buffer.ensure_capacity(m_buffer.size() + 2); - m_buffer.unchecked_append((u8)value); - m_buffer.unchecked_append((u8)(value >> 8)); + 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.ensure_capacity(m_buffer.size() + 4); - m_buffer.unchecked_append((u8)value); - m_buffer.unchecked_append((u8)(value >> 8)); - m_buffer.unchecked_append((u8)(value >> 16)); - m_buffer.unchecked_append((u8)(value >> 24)); + 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.ensure_capacity(m_buffer.size() + 8); - m_buffer.unchecked_append((u8)value); - m_buffer.unchecked_append((u8)(value >> 8)); - m_buffer.unchecked_append((u8)(value >> 16)); - m_buffer.unchecked_append((u8)(value >> 24)); - m_buffer.unchecked_append((u8)(value >> 32)); - m_buffer.unchecked_append((u8)(value >> 40)); - m_buffer.unchecked_append((u8)(value >> 48)); - m_buffer.unchecked_append((u8)(value >> 56)); + 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; } @@ -130,7 +131,7 @@ Encoder& Encoder::operator<<(const char* value) Encoder& Encoder::operator<<(const StringView& value) { - m_buffer.append((const u8*)value.characters_without_null_termination(), value.length()); + m_buffer.data.append((const u8*)value.characters_without_null_termination(), value.length()); return *this; } @@ -145,7 +146,7 @@ Encoder& Encoder::operator<<(const String& value) Encoder& Encoder::operator<<(const ByteBuffer& value) { *this << static_cast(value.size()); - m_buffer.append(value.data(), value.size()); + m_buffer.data.append(value.data(), value.size()); return *this; } @@ -163,4 +164,10 @@ Encoder& Encoder::operator<<(const Dictionary& dictionary) return *this; } +Encoder& Encoder::operator<<(const File& file) +{ + m_buffer.fds.append(file.fd()); + return *this; +} + } diff --git a/Libraries/LibIPC/Encoder.h b/Libraries/LibIPC/Encoder.h index 2af6d0fbca3..da8416f5a51 100644 --- a/Libraries/LibIPC/Encoder.h +++ b/Libraries/LibIPC/Encoder.h @@ -61,6 +61,7 @@ public: Encoder& operator<<(const ByteBuffer&); Encoder& operator<<(const URL&); Encoder& operator<<(const Dictionary&); + Encoder& operator<<(const File&); template Encoder& operator<<(const HashMap& hashmap) { diff --git a/Libraries/LibIPC/File.h b/Libraries/LibIPC/File.h new file mode 100644 index 00000000000..85c1137ad69 --- /dev/null +++ b/Libraries/LibIPC/File.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2020, Sergey Bugaev + * 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 }; +}; + +} diff --git a/Libraries/LibIPC/Forward.h b/Libraries/LibIPC/Forward.h index 774aba1fdfa..105f4faa5e5 100644 --- a/Libraries/LibIPC/Forward.h +++ b/Libraries/LibIPC/Forward.h @@ -32,5 +32,6 @@ class Decoder; class Dictionary; class Encoder; class Message; +class File; } diff --git a/Libraries/LibIPC/Message.h b/Libraries/LibIPC/Message.h index 7ee7bcc51d0..495e751adc4 100644 --- a/Libraries/LibIPC/Message.h +++ b/Libraries/LibIPC/Message.h @@ -30,7 +30,10 @@ namespace IPC { -typedef Vector MessageBuffer; +struct MessageBuffer { + Vector data; + Vector fds; +}; class Message { public: