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