/src/serenity/Userland/Libraries/LibIPC/Decoder.cpp
Line | Count | Source |
1 | | /* |
2 | | * Copyright (c) 2020, Andreas Kling <kling@serenityos.org> |
3 | | * Copyright (c) 2023, Tim Flynn <trflynn89@serenityos.org> |
4 | | * |
5 | | * SPDX-License-Identifier: BSD-2-Clause |
6 | | */ |
7 | | |
8 | | #include <AK/JsonValue.h> |
9 | | #include <AK/NumericLimits.h> |
10 | | #include <LibCore/AnonymousBuffer.h> |
11 | | #include <LibCore/DateTime.h> |
12 | | #include <LibCore/Proxy.h> |
13 | | #include <LibCore/Socket.h> |
14 | | #include <LibIPC/Decoder.h> |
15 | | #include <LibIPC/File.h> |
16 | | #include <LibURL/URL.h> |
17 | | #include <fcntl.h> |
18 | | |
19 | | namespace IPC { |
20 | | |
21 | | ErrorOr<size_t> Decoder::decode_size() |
22 | 0 | { |
23 | 0 | return static_cast<size_t>(TRY(decode<u32>())); |
24 | 0 | } |
25 | | |
26 | | template<> |
27 | | ErrorOr<String> decode(Decoder& decoder) |
28 | 0 | { |
29 | 0 | auto length = TRY(decoder.decode_size()); |
30 | 0 | return String::from_stream(decoder.stream(), length); |
31 | 0 | } |
32 | | |
33 | | template<> |
34 | | ErrorOr<ByteString> decode(Decoder& decoder) |
35 | 0 | { |
36 | 0 | auto length = TRY(decoder.decode_size()); |
37 | 0 | if (length == 0) |
38 | 0 | return ByteString::empty(); |
39 | | |
40 | 0 | return ByteString::create_and_overwrite(length, [&](Bytes bytes) -> ErrorOr<void> { |
41 | 0 | TRY(decoder.decode_into(bytes)); |
42 | 0 | return {}; |
43 | 0 | }); |
44 | 0 | } |
45 | | |
46 | | template<> |
47 | | ErrorOr<ByteBuffer> decode(Decoder& decoder) |
48 | 0 | { |
49 | 0 | auto length = TRY(decoder.decode_size()); |
50 | 0 | if (length == 0) |
51 | 0 | return ByteBuffer {}; |
52 | | |
53 | 0 | auto buffer = TRY(ByteBuffer::create_uninitialized(length)); |
54 | 0 | auto bytes = buffer.bytes(); |
55 | |
|
56 | 0 | TRY(decoder.decode_into(bytes)); |
57 | 0 | return buffer; |
58 | 0 | } |
59 | | |
60 | | template<> |
61 | | ErrorOr<JsonValue> decode(Decoder& decoder) |
62 | 0 | { |
63 | 0 | auto json = TRY(decoder.decode<ByteString>()); |
64 | 0 | return JsonValue::from_string(json); |
65 | 0 | } |
66 | | |
67 | | template<> |
68 | | ErrorOr<Duration> decode(Decoder& decoder) |
69 | 0 | { |
70 | 0 | auto nanoseconds = TRY(decoder.decode<i64>()); |
71 | 0 | return AK::Duration::from_nanoseconds(nanoseconds); |
72 | 0 | } |
73 | | |
74 | | template<> |
75 | | ErrorOr<UnixDateTime> decode(Decoder& decoder) |
76 | 0 | { |
77 | 0 | auto nanoseconds = TRY(decoder.decode<i64>()); |
78 | 0 | return AK::UnixDateTime::from_nanoseconds_since_epoch(nanoseconds); |
79 | 0 | } |
80 | | |
81 | | template<> |
82 | | ErrorOr<URL::URL> decode(Decoder& decoder) |
83 | 0 | { |
84 | 0 | auto url_string = TRY(decoder.decode<ByteString>()); |
85 | 0 | URL::URL url { url_string }; |
86 | |
|
87 | 0 | bool has_blob_url = TRY(decoder.decode<bool>()); |
88 | 0 | if (!has_blob_url) |
89 | 0 | return url; |
90 | | |
91 | 0 | url.set_blob_url_entry(URL::BlobURLEntry { |
92 | 0 | .type = TRY(decoder.decode<String>()), |
93 | 0 | .byte_buffer = TRY(decoder.decode<ByteBuffer>()), |
94 | 0 | .environment_origin = TRY(decoder.decode<URL::Origin>()), |
95 | 0 | }); |
96 | |
|
97 | 0 | return url; |
98 | 0 | } |
99 | | |
100 | | template<> |
101 | | ErrorOr<URL::Origin> decode(Decoder& decoder) |
102 | 0 | { |
103 | 0 | auto scheme = TRY(decoder.decode<ByteString>()); |
104 | 0 | auto host = TRY(decoder.decode<URL::Host>()); |
105 | 0 | auto port = TRY(decoder.decode<Optional<u16>>()); |
106 | |
|
107 | 0 | return URL::Origin { move(scheme), move(host), port }; |
108 | 0 | } |
109 | | |
110 | | template<> |
111 | | ErrorOr<File> decode(Decoder& decoder) |
112 | 0 | { |
113 | 0 | auto file = TRY(decoder.files().try_dequeue()); |
114 | 0 | auto fd = file.fd(); |
115 | |
|
116 | 0 | auto fd_flags = TRY(Core::System::fcntl(fd, F_GETFD)); |
117 | 0 | TRY(Core::System::fcntl(fd, F_SETFD, fd_flags | FD_CLOEXEC)); |
118 | 0 | return file; |
119 | 0 | } |
120 | | |
121 | | template<> |
122 | | ErrorOr<Empty> decode(Decoder&) |
123 | 0 | { |
124 | 0 | return Empty {}; |
125 | 0 | } |
126 | | |
127 | | template<> |
128 | | ErrorOr<Core::AnonymousBuffer> decode(Decoder& decoder) |
129 | 0 | { |
130 | 0 | if (auto valid = TRY(decoder.decode<bool>()); !valid) |
131 | 0 | return Core::AnonymousBuffer {}; |
132 | | |
133 | 0 | auto size = TRY(decoder.decode_size()); |
134 | 0 | auto anon_file = TRY(decoder.decode<IPC::File>()); |
135 | |
|
136 | 0 | return Core::AnonymousBuffer::create_from_anon_fd(anon_file.take_fd(), size); |
137 | 0 | } |
138 | | |
139 | | template<> |
140 | | ErrorOr<Core::DateTime> decode(Decoder& decoder) |
141 | 0 | { |
142 | 0 | auto timestamp = TRY(decoder.decode<i64>()); |
143 | 0 | return Core::DateTime::from_timestamp(static_cast<time_t>(timestamp)); |
144 | 0 | } |
145 | | |
146 | | template<> |
147 | | ErrorOr<Core::ProxyData> decode(Decoder& decoder) |
148 | 0 | { |
149 | 0 | auto type = TRY(decoder.decode<Core::ProxyData::Type>()); |
150 | 0 | auto host_ipv4 = TRY(decoder.decode<u32>()); |
151 | 0 | auto port = TRY(decoder.decode<int>()); |
152 | |
|
153 | 0 | return Core::ProxyData { type, host_ipv4, port }; |
154 | 0 | } |
155 | | |
156 | | } |