1 #pragma once
2 
3 
4 #include <type_traits>
5 #include <utility>
6 #include <memory>
7 #include <string>
8 #include <uv.h>
9 #include "request.hpp"
10 #include "stream.hpp"
11 #include "util.hpp"
12 #include "loop.hpp"
13 
14 
15 namespace uvw {
16 
17 
18 namespace details {
19 
20 
21 enum class UVChmodFlags: std::underlying_type_t<uv_poll_event> {
22     READABLE = UV_READABLE,
23     WRITABLE = UV_WRITABLE
24 };
25 
26 
27 }
28 
29 
30 /**
31  * @brief The PipeHandle handle.
32  *
33  * Pipe handles provide an abstraction over local domain sockets on Unix and
34  * named pipes on Windows.
35  *
36  * To create a `PipeHandle` through a `Loop`, arguments follow:
37  *
38  * * An optional boolean value that indicates if this pipe will be used for
39  * handle passing between processes.
40  */
41 class PipeHandle final: public StreamHandle<PipeHandle, uv_pipe_t> {
42 public:
43     using Chmod = details::UVChmodFlags;
44 
PipeHandle(ConstructorAccess ca,std::shared_ptr<Loop> ref,bool pass=false)45     explicit PipeHandle(ConstructorAccess ca, std::shared_ptr<Loop> ref, bool pass = false)
46         : StreamHandle{ca, std::move(ref)}, ipc{pass}
47     {}
48 
49     /**
50      * @brief Initializes the handle.
51      * @return True in case of success, false otherwise.
52      */
init()53     bool init() {
54         return initialize(&uv_pipe_init, ipc);
55     }
56 
57     /**
58      * @brief Opens an existing file descriptor or HANDLE as a pipe.
59      *
60      * The passed file descriptor or HANDLE is not checked for its type, but
61      * it’s required that it represents a valid pipe.<br/>
62      * An ErrorEvent event is emitted in case of errors.
63      *
64      * @param file A valid file handle (either a file descriptor or a HANDLE).
65      */
open(FileHandle file)66     void open(FileHandle file) {
67         invoke(&uv_pipe_open, get(), file);
68     }
69 
70     /**
71      * @brief bind Binds the pipe to a file path (Unix) or a name (Windows).
72      *
73      * Paths on Unix get truncated typically between 92 and 108 bytes.<br/>
74      * An ErrorEvent event is emitted in case of errors.
75      *
76      * @param name A valid file path.
77      */
bind(std::string name)78     void bind(std::string name) {
79         invoke(&uv_pipe_bind, get(), name.data());
80     }
81 
82     /**
83      * @brief Connects to the Unix domain socket or the named pipe.
84      *
85      * Paths on Unix get truncated typically between 92 and 108 bytes.<br/>
86      * A ConnectEvent event is emitted when the connection has been
87      * established.<br/>
88      * An ErrorEvent event is emitted in case of errors during the connection.
89      *
90      * @param name A valid domain socket or named pipe.
91      */
connect(std::string name)92     void connect(std::string name) {
93         auto listener = [ptr = shared_from_this()](const auto &event, const auto &) {
94             ptr->publish(event);
95         };
96 
97         auto connect = loop().resource<details::ConnectReq>();
98         connect->once<ErrorEvent>(listener);
99         connect->once<ConnectEvent>(listener);
100         connect->connect(&uv_pipe_connect, get(), name.data());
101     }
102 
103     /**
104      * @brief Gets the name of the Unix domain socket or the named pipe.
105      * @return The name of the Unix domain socket or the named pipe, an empty
106      * string in case of errors.
107      */
sock() const108     std::string sock() const noexcept {
109         return details::tryRead(&uv_pipe_getsockname, get());
110     }
111 
112     /**
113      * @brief Gets the name of the Unix domain socket or the named pipe to which
114      * the handle is connected.
115      * @return The name of the Unix domain socket or the named pipe to which
116      * the handle is connected, an empty string in case of errors.
117      */
peer() const118     std::string peer() const noexcept {
119         return details::tryRead(&uv_pipe_getpeername, get());
120     }
121 
122     /**
123      * @brief Sets the number of pending pipe this instance can handle.
124      *
125      * This method can be used to set the number of pending pipe this instance
126      * handles when the pipe server is waiting for connections.<br/>
127      * Note that this setting applies to Windows only.
128      *
129      * @param count The number of accepted pending pipe.
130      */
pending(int count)131     void pending(int count) noexcept {
132         uv_pipe_pending_instances(get(), count);
133     }
134 
135     /**
136      * @brief Gets the number of pending pipe this instance can handle.
137      * @return The number of pending pipe this instance can handle.
138      */
pending()139     int pending() noexcept {
140         return uv_pipe_pending_count(get());
141     }
142 
143     /**
144      * @brief Used to receive handles over IPC pipes.
145      *
146      * Steps to be done:
147      *
148      * * Call `pending()`, if it’s greater than zero then proceed.
149      * * Initialize a handle of the given type, as returned by `receive()`.
150      * * Call `accept(pipe, handle)`.
151      *
152      * @return The type of the pending handle. Possible values are:
153      *
154      * * `HandleType::PIPE`
155      * * `HandleType::TCP`
156      * * `HandleType::UDP`
157      * * `HandleType::UNKNOWN`
158      */
receive()159     HandleType receive() noexcept {
160         HandleCategory category = uv_pipe_pending_type(get());
161         return Utilities::guessHandle(category);
162     }
163 
164     /**
165      * @brief Alters pipe permissions.
166      *
167      * It allows the pipe to be accessed from processes run by different users.
168      *
169      * Available flags are:
170      *
171      * * `PipeHandle::Chmod::READABLE`
172      * * `PipeHandle::Chmod::WRITABLE`
173      *
174      * See the official
175      * [documentation](http://docs.libuv.org/en/v1.x/pipe.html#c.uv_pipe_chmod)
176      * for further details.
177      *
178      * @param flags A valid set of flags.
179      * @return True in case of success, false otherwise.
180      */
chmod(Flags<Chmod> flags)181     bool chmod(Flags<Chmod> flags) noexcept {
182         return (0 == uv_pipe_chmod(get(), flags));
183     }
184 
185 private:
186     bool ipc;
187 };
188 
189 
190 }
191