ebb37384c337bf12f5d6de8a6b46f6f0481c78f9
[WebKit-https.git] / Source / WebKit / Platform / IPC / win / ConnectionWin.cpp
1 /*
2  * Copyright (C) 2017 Sony Interactive Entertainment Inc.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "Connection.h"
28
29 #include "DataReference.h"
30 #include <wtf/HexNumber.h>
31 #include <wtf/RandomNumber.h>
32
33 namespace IPC {
34
35 // FIXME: Rename this or use a different constant on windows.
36 static const size_t inlineMessageMaxSize = 4096;
37
38 bool Connection::createServerAndClientIdentifiers(HANDLE& serverIdentifier, HANDLE& clientIdentifier)
39 {
40     String pipeName;
41
42     do {
43         unsigned uniqueID = randomNumber() * std::numeric_limits<unsigned>::max();
44         pipeName = makeString("\\\\.\\pipe\\com.apple.WebKit.", hex(uniqueID));
45
46         serverIdentifier = ::CreateNamedPipe(pipeName.charactersWithNullTermination().data(),
47             PIPE_ACCESS_DUPLEX | FILE_FLAG_FIRST_PIPE_INSTANCE | FILE_FLAG_OVERLAPPED,
48             PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE, 1, inlineMessageMaxSize, inlineMessageMaxSize,
49             0, 0);
50     } while (!serverIdentifier && ::GetLastError() == ERROR_PIPE_BUSY);
51
52     if (!serverIdentifier)
53         return false;
54
55     clientIdentifier = ::CreateFileW(pipeName.charactersWithNullTermination().data(), GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
56     if (!clientIdentifier) {
57         ::CloseHandle(serverIdentifier);
58         return false;
59     }
60
61     DWORD mode = PIPE_READMODE_MESSAGE;
62     if (!::SetNamedPipeHandleState(clientIdentifier, &mode, 0, 0)) {
63         ::CloseHandle(serverIdentifier);
64         ::CloseHandle(clientIdentifier);
65         return false;
66     }
67
68     return true;
69 }
70
71 void Connection::platformInitialize(Identifier identifier)
72 {
73     m_connectionPipe = identifier;
74 }
75
76 void Connection::platformInvalidate()
77 {
78     if (m_connectionPipe == INVALID_HANDLE_VALUE)
79         return;
80
81     m_isConnected = false;
82
83     m_readListener.close();
84     m_writeListener.close();
85
86     ::CloseHandle(m_connectionPipe);
87     m_connectionPipe = INVALID_HANDLE_VALUE;
88 }
89
90 void Connection::readEventHandler()
91 {
92     if (m_connectionPipe == INVALID_HANDLE_VALUE)
93         return;
94
95     while (true) {
96         // Check if we got some data.
97         DWORD numberOfBytesRead = 0;
98         if (!::GetOverlappedResult(m_connectionPipe, &m_readListener.state(), &numberOfBytesRead, FALSE)) {
99             DWORD error = ::GetLastError();
100             switch (error) {
101             case ERROR_BROKEN_PIPE:
102                 connectionDidClose();
103                 return;
104             case ERROR_MORE_DATA: {
105                 // Read the rest of the message out of the pipe.
106
107                 DWORD bytesToRead = 0;
108                 if (!::PeekNamedPipe(m_connectionPipe, 0, 0, 0, 0, &bytesToRead)) {
109                     DWORD error = ::GetLastError();
110                     if (error == ERROR_BROKEN_PIPE) {
111                         connectionDidClose();
112                         return;
113                     }
114                     ASSERT_NOT_REACHED();
115                     return;
116                 }
117
118                 // ::GetOverlappedResult told us there's more data. ::PeekNamedPipe shouldn't
119                 // contradict it!
120                 ASSERT(bytesToRead);
121                 if (!bytesToRead)
122                     break;
123
124                 m_readBuffer.grow(m_readBuffer.size() + bytesToRead);
125                 if (!::ReadFile(m_connectionPipe, m_readBuffer.data() + numberOfBytesRead, bytesToRead, 0, &m_readListener.state())) {
126                     DWORD error = ::GetLastError();
127                     ASSERT_NOT_REACHED();
128                     return;
129                 }
130                 continue;
131             }
132
133             // FIXME: We should figure out why we're getting this error.
134             case ERROR_IO_INCOMPLETE:
135                 return;
136             default:
137                 ASSERT_NOT_REACHED();
138             }
139         }
140
141         if (!m_readBuffer.isEmpty()) {
142             // We have a message, let's dispatch it.
143             Vector<Attachment> attachments(0);
144             auto decoder = std::make_unique<Decoder>(m_readBuffer.data(), m_readBuffer.size(), nullptr, WTFMove(attachments));
145             processIncomingMessage(WTFMove(decoder));
146         }
147
148         // Find out the size of the next message in the pipe (if there is one) so that we can read
149         // it all in one operation. (This is just an optimization to avoid an extra pass through the
150         // loop (if we chose a buffer size that was too small) or allocating extra memory (if we
151         // chose a buffer size that was too large).)
152         DWORD bytesToRead = 0;
153         if (!::PeekNamedPipe(m_connectionPipe, 0, 0, 0, 0, &bytesToRead)) {
154             DWORD error = ::GetLastError();
155             if (error == ERROR_BROKEN_PIPE) {
156                 connectionDidClose();
157                 return;
158             }
159             ASSERT_NOT_REACHED();
160         }
161         if (!bytesToRead) {
162             // There's no message waiting in the pipe. Schedule a read of the first byte of the
163             // next message. We'll find out the message's actual size when it arrives. (If we
164             // change this to read more than a single byte for performance reasons, we'll have to
165             // deal with m_readBuffer potentially being larger than the message we read after
166             // calling ::GetOverlappedResult above.)
167             bytesToRead = 1;
168         }
169
170         m_readBuffer.resize(bytesToRead);
171
172         // Either read the next available message (which should occur synchronously), or start an
173         // asynchronous read of the next message that becomes available.
174         BOOL result = ::ReadFile(m_connectionPipe, m_readBuffer.data(), m_readBuffer.size(), 0, &m_readListener.state());
175         if (result) {
176             // There was already a message waiting in the pipe, and we read it synchronously.
177             // Process it.
178             continue;
179         }
180
181         DWORD error = ::GetLastError();
182
183         if (error == ERROR_IO_PENDING) {
184             // There are no messages in the pipe currently. readEventHandler will be called again once there is a message.
185             return;
186         }
187
188         if (error == ERROR_MORE_DATA) {
189             // Either a message is available when we didn't think one was, or the message is larger
190             // than ::PeekNamedPipe told us. The former seems far more likely. Probably the message
191             // became available between our calls to ::PeekNamedPipe and ::ReadFile above. Go back
192             // to the top of the loop to use ::GetOverlappedResult to retrieve the available data.
193             continue;
194         }
195
196         if (error == ERROR_BROKEN_PIPE)
197             return;
198
199         // FIXME: We need to handle other errors here.
200         ASSERT_NOT_REACHED();
201     }
202 }
203
204 void Connection::writeEventHandler()
205 {
206     if (m_connectionPipe == INVALID_HANDLE_VALUE)
207         return;
208
209     DWORD numberOfBytesWritten = 0;
210     if (!::GetOverlappedResult(m_connectionPipe, &m_writeListener.state(), &numberOfBytesWritten, FALSE)) {
211         DWORD error = ::GetLastError();
212
213         if (error == ERROR_IO_INCOMPLETE) {
214             // FIXME: We should figure out why we're getting this error.
215             return;
216         }
217         if (error == ERROR_BROKEN_PIPE) {
218             connectionDidClose();
219             return;
220         }
221         ASSERT_NOT_REACHED();
222     }
223
224     // The pending write has finished, so we are now done with its encoder. Clearing this member
225     // will allow us to send messages again.
226     m_pendingWriteEncoder = nullptr;
227
228     // Now that the pending write has finished, we can try to send a new message.
229     sendOutgoingMessages();
230 }
231
232 void Connection::invokeReadEventHandler()
233 {
234     m_connectionQueue->dispatch([this, protectedThis = makeRef(*this)] {
235         readEventHandler();
236     });
237 }
238
239 void Connection::invokeWriteEventHandler()
240 {
241     m_connectionQueue->dispatch([this, protectedThis = makeRef(*this)] {
242         writeEventHandler();
243     });
244 }
245
246 bool Connection::open()
247 {
248     // We connected the two ends of the pipe in createServerAndClientIdentifiers.
249     m_isConnected = true;
250
251     // Start listening for read and write state events.
252     m_readListener.open([this] {
253         invokeReadEventHandler();
254     });
255
256     m_writeListener.open([this] {
257         invokeWriteEventHandler();
258     });
259
260     // Schedule a read.
261     invokeReadEventHandler();
262     return true;
263 }
264
265 bool Connection::platformCanSendOutgoingMessages() const
266 {
267     // We only allow sending one asynchronous message at a time. If we wanted to send more than one
268     // at once, we'd have to use multiple OVERLAPPED structures and hold onto multiple pending
269     // MessageEncoders (one of each for each simultaneous asynchronous message).
270     return !m_pendingWriteEncoder;
271 }
272
273 bool Connection::sendOutgoingMessage(std::unique_ptr<Encoder> encoder)
274 {
275     ASSERT(!m_pendingWriteEncoder);
276
277     // Just bail if the handle has been closed.
278     if (m_connectionPipe == INVALID_HANDLE_VALUE)
279         return false;
280
281     // We put the message ID last.
282     *encoder << 0;
283
284     // Write the outgoing message.
285
286     if (::WriteFile(m_connectionPipe, encoder->buffer(), encoder->bufferSize(), 0, &m_writeListener.state())) {
287         // We successfully sent this message.
288         return true;
289     }
290
291     DWORD error = ::GetLastError();
292
293     if (error == ERROR_NO_DATA) {
294         // The pipe is being closed.
295         connectionDidClose();
296         return false;
297     }
298
299     if (error != ERROR_IO_PENDING) {
300         ASSERT_NOT_REACHED();
301         return false;
302     }
303
304     // The message will be sent soon. Hold onto the encoder so that it won't be destroyed
305     // before the write completes.
306     m_pendingWriteEncoder = WTFMove(encoder);
307
308     // We can only send one asynchronous message at a time (see comment in platformCanSendOutgoingMessages).
309     return false;
310 }
311
312 void Connection::willSendSyncMessage(OptionSet<SendSyncOption>)
313 {
314 }
315
316 void Connection::didReceiveSyncReply(OptionSet<SendSyncOption>)
317 {
318 }
319
320 void Connection::EventListener::open(Function<void()>&& handler)
321 {
322     m_handler = WTFMove(handler);
323
324     memset(&m_state, 0, sizeof(m_state));
325     m_state.hEvent = ::CreateEventW(0, FALSE, FALSE, 0);
326
327     BOOL result;
328     result = ::RegisterWaitForSingleObject(&m_waitHandle, m_state.hEvent, callback, this, INFINITE, WT_EXECUTEDEFAULT);
329     ASSERT(result);
330 }
331
332 void Connection::EventListener::callback(void* data, BOOLEAN timerOrWaitFired)
333 {
334     ASSERT_ARG(data, data);
335     ASSERT_ARG(timerOrWaitFired, !timerOrWaitFired);
336
337     auto* listener = static_cast<Connection::EventListener*>(data);
338     listener->m_handler();
339 }
340
341 void Connection::EventListener::close()
342 {
343     // We call ::UnregisterWaitEx directly here. Since ::UnregisterWaitEx drains all the remaining tasks here,
344     // it would cause deadlock if this function itself is executed in Windows callback functions. But this call
345     // is safe since our callbacks immediately dispatch a task to WorkQueue. And no Windows callbacks call this
346     // Connection::EventListener::close().
347     // https://msdn.microsoft.com/en-us/library/windows/desktop/ms685061(v=vs.85).aspx
348     //
349     // And do not ::CloseHandle(m_waitHandle).
350     // > Note that a wait handle cannot be used in functions that require an object handle, such as CloseHandle.
351     // https://msdn.microsoft.com/en-us/library/windows/desktop/ms685061(v=vs.85).aspx
352     ::UnregisterWaitEx(m_waitHandle, INVALID_HANDLE_VALUE);
353     m_waitHandle = INVALID_HANDLE_VALUE;
354
355     ::CloseHandle(m_state.hEvent);
356     m_state.hEvent = 0;
357
358     m_handler = Function<void()>();
359 }
360
361 } // namespace IPC