2011-02-11 Anders Carlsson <andersca@apple.com>
[WebKit-https.git] / Source / WebKit2 / Platform / CoreIPC / Connection.h
1 /*
2  * Copyright (C) 2010 Apple Inc. All rights reserved.
3  * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
4  * Portions Copyright (c) 2010 Motorola Mobility, Inc.  All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
16  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
17  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
19  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
25  * THE POSSIBILITY OF SUCH DAMAGE.
26  */
27
28 #ifndef Connection_h
29 #define Connection_h
30
31 #include "ArgumentDecoder.h"
32 #include "ArgumentEncoder.h"
33 #include "Arguments.h"
34 #include "MessageID.h"
35 #include "WorkQueue.h"
36 #include <wtf/HashMap.h>
37 #include <wtf/PassRefPtr.h>
38 #include <wtf/OwnPtr.h>
39 #include <wtf/Threading.h>
40
41 #if PLATFORM(MAC)
42 #include <mach/mach_port.h>
43 #elif PLATFORM(WIN)
44 #include <string>
45 #elif PLATFORM(QT)
46 class QSocketNotifier;
47 #include "PlatformProcessIdentifier.h"
48 #endif
49
50 class RunLoop;
51
52 namespace CoreIPC {
53
54 class MessageID;
55     
56 enum SyncReplyMode {
57     AutomaticReply,
58     ManualReply
59 };
60
61 enum MessageSendFlags {
62     // Whether this message should be dispatched when waiting for a sync reply.
63     // This is the default for synchronous messages.
64     DispatchMessageEvenWhenWaitingForSyncReply = 1 << 0,
65 };
66
67 #define MESSAGE_CHECK_BASE(assertion, connection) do \
68     if (!(assertion)) { \
69         ASSERT(assertion); \
70         (connection)->markCurrentlyDispatchedMessageAsInvalid(); \
71         return; \
72     } \
73 while (0)
74
75 class Connection : public ThreadSafeShared<Connection> {
76 public:
77     class MessageReceiver {
78     protected:
79         virtual ~MessageReceiver() { }
80
81     public:
82         virtual void didReceiveMessage(Connection*, MessageID, ArgumentDecoder*) = 0;
83         virtual SyncReplyMode didReceiveSyncMessage(Connection*, MessageID, ArgumentDecoder*, ArgumentEncoder*) { ASSERT_NOT_REACHED(); return AutomaticReply; }
84     };
85     
86     class Client : public MessageReceiver {
87     protected:
88         virtual ~Client() { }
89
90     public:
91         virtual void didClose(Connection*) = 0;
92         virtual void didReceiveInvalidMessage(Connection*, MessageID) = 0;
93         virtual void didFailToSendSyncMessage(Connection*) { }
94     };
95
96 #if PLATFORM(MAC)
97     typedef mach_port_t Identifier;
98 #elif PLATFORM(WIN)
99     typedef HANDLE Identifier;
100     static bool createServerAndClientIdentifiers(Identifier& serverIdentifier, Identifier& clientIdentifier);
101 #elif PLATFORM(QT)
102     typedef int Identifier;
103 #elif PLATFORM(GTK)
104     typedef int Identifier;
105 #endif
106
107     static PassRefPtr<Connection> createServerConnection(Identifier, Client*, RunLoop* clientRunLoop);
108     static PassRefPtr<Connection> createClientConnection(Identifier, Client*, RunLoop* clientRunLoop);
109     ~Connection();
110
111 #if PLATFORM(MAC)
112     void setShouldCloseConnectionOnMachExceptions();
113 #elif PLATFORM(QT)
114     void setShouldCloseConnectionOnProcessTermination(WebKit::PlatformProcessIdentifier);
115 #endif
116
117     // The set callback will be called on the connection work queue when the connection is closed, 
118     // before didCall is called on the client thread. Must be called before the connection is opened.
119     // In the future we might want a more generic way to handle sync or async messages directly
120     // on the work queue, for example if we want to handle them on some other thread we could avoid
121     // handling the message on the client thread first.
122     typedef void (*DidCloseOnConnectionWorkQueueCallback)(WorkQueue&, Connection*);
123     void setDidCloseOnConnectionWorkQueueCallback(DidCloseOnConnectionWorkQueueCallback callback);
124                                                 
125     bool open();
126     void invalidate();
127     void markCurrentlyDispatchedMessageAsInvalid();
128
129     static const unsigned long long NoTimeout = 10000000000ULL;
130
131     template<typename T> bool send(const T& message, uint64_t destinationID, unsigned messageSendFlags = 0);
132     template<typename T> bool sendSync(const T& message, const typename T::Reply& reply, uint64_t destinationID, double timeout = NoTimeout);
133     template<typename T> bool waitForAndDispatchImmediately(uint64_t destinationID, double timeout);
134
135     PassOwnPtr<ArgumentEncoder> createSyncMessageArgumentEncoder(uint64_t destinationID, uint64_t& syncRequestID);
136     bool sendMessage(MessageID, PassOwnPtr<ArgumentEncoder>, unsigned messageSendFlags = 0);
137     bool sendSyncReply(PassOwnPtr<ArgumentEncoder>);
138
139     // FIXME: These variants of senc, sendSync and waitFor are all deprecated.
140     // All clients should move to the overloads that take a message type.
141     template<typename E, typename T> bool deprecatedSend(E messageID, uint64_t destinationID, const T& arguments);
142     template<typename E, typename T, typename U> bool deprecatedSendSync(E messageID, uint64_t destinationID, const T& arguments, const U& reply, double timeout = NoTimeout);
143     template<typename E> PassOwnPtr<ArgumentDecoder> deprecatedWaitFor(E messageID, uint64_t destinationID, double timeout);
144     
145 private:
146     template<typename T> class Message {
147     public:
148         Message()
149             : m_arguments(0)
150         {
151         }
152
153         Message(MessageID messageID, PassOwnPtr<T> arguments)
154             : m_messageID(messageID)
155             , m_arguments(arguments.leakPtr())
156         {
157         }
158         
159         MessageID messageID() const { return m_messageID; }
160         uint64_t destinationID() const { return m_arguments->destinationID(); }
161
162         T* arguments() const { return m_arguments; }
163         
164         PassOwnPtr<T> releaseArguments()
165         {
166             T* arguments = m_arguments;
167             m_arguments = 0;
168
169             return arguments;
170         }
171         
172     private:
173         MessageID m_messageID;
174         T* m_arguments;
175     };
176
177 public:
178     typedef Message<ArgumentEncoder> OutgoingMessage;
179
180 private:
181     Connection(Identifier, bool isServer, Client*, RunLoop* clientRunLoop);
182     void platformInitialize(Identifier);
183     void platformInvalidate();
184     
185     bool isValid() const { return m_client; }
186     
187     PassOwnPtr<ArgumentDecoder> waitForMessage(MessageID, uint64_t destinationID, double timeout);
188     
189     PassOwnPtr<ArgumentDecoder> sendSyncMessage(MessageID, uint64_t syncRequestID, PassOwnPtr<ArgumentEncoder>, double timeout);
190     PassOwnPtr<ArgumentDecoder> waitForSyncReply(uint64_t syncRequestID, double timeout);
191
192     // Called on the connection work queue.
193     void processIncomingMessage(MessageID, PassOwnPtr<ArgumentDecoder>);
194     bool canSendOutgoingMessages() const;
195     bool platformCanSendOutgoingMessages() const;
196     void sendOutgoingMessages();
197     bool sendOutgoingMessage(MessageID, PassOwnPtr<ArgumentEncoder>);
198     void connectionDidClose();
199     
200     typedef Message<ArgumentDecoder> IncomingMessage;
201
202     // Called on the listener thread.
203     void dispatchConnectionDidClose();
204     void dispatchMessage(IncomingMessage&);
205     void dispatchMessages();
206     void dispatchSyncMessage(MessageID, ArgumentDecoder*);
207
208     // Can be called on any thread.
209     void enqueueIncomingMessage(IncomingMessage&);
210
211     Client* m_client;
212     bool m_isServer;
213     uint64_t m_syncRequestID;
214
215     DidCloseOnConnectionWorkQueueCallback m_didCloseOnConnectionWorkQueueCallback;
216
217     bool m_isConnected;
218     WorkQueue m_connectionQueue;
219     RunLoop* m_clientRunLoop;
220
221     uint32_t m_inDispatchMessageCount;
222     bool m_didReceiveInvalidMessage;
223
224     // Incoming messages.
225     Mutex m_incomingMessagesLock;
226     Vector<IncomingMessage> m_incomingMessages;
227
228     // Outgoing messages.
229     Mutex m_outgoingMessagesLock;
230     Deque<OutgoingMessage> m_outgoingMessages;
231     
232     ThreadCondition m_waitForMessageCondition;
233     Mutex m_waitForMessageMutex;
234     HashMap<std::pair<unsigned, uint64_t>, ArgumentDecoder*> m_waitForMessageMap;
235
236     // Represents a sync request for which we're waiting on a reply.
237     struct PendingSyncReply {
238         // The request ID.
239         uint64_t syncRequestID;
240
241         // The reply decoder, will be null if there was an error processing the sync
242         // message on the other side.
243         ArgumentDecoder* replyDecoder;
244
245         // Will be set to true once a reply has been received or an error occurred.
246         bool didReceiveReply;
247     
248         PendingSyncReply()
249             : syncRequestID(0)
250             , replyDecoder(0)
251             , didReceiveReply(false)
252         {
253         }
254
255         explicit PendingSyncReply(uint64_t syncRequestID)
256             : syncRequestID(syncRequestID)
257             , replyDecoder(0)
258             , didReceiveReply(0)
259         {
260         }
261
262         PassOwnPtr<ArgumentDecoder> releaseReplyDecoder()
263         {
264             OwnPtr<ArgumentDecoder> reply = adoptPtr(replyDecoder);
265             replyDecoder = 0;
266             
267             return reply.release();
268         }
269     };
270     
271     class SyncMessageState;
272     friend class SyncMessageState;
273     RefPtr<SyncMessageState> m_syncMessageState;
274
275     Mutex m_syncReplyStateMutex;
276     bool m_shouldWaitForSyncReplies;
277     Vector<PendingSyncReply> m_pendingSyncReplies;
278
279 #if PLATFORM(MAC)
280     // Called on the connection queue.
281     void receiveSourceEventHandler();
282     void initializeDeadNameSource();
283     void exceptionSourceEventHandler();
284
285     mach_port_t m_sendPort;
286     mach_port_t m_receivePort;
287
288     // If setShouldCloseConnectionOnMachExceptions has been called, this has
289     // the exception port that exceptions from the other end will be sent on.
290     mach_port_t m_exceptionPort;
291
292 #elif PLATFORM(WIN)
293     // Called on the connection queue.
294     void readEventHandler();
295     void writeEventHandler();
296
297     Vector<uint8_t> m_readBuffer;
298     OVERLAPPED m_readState;
299     OwnPtr<ArgumentEncoder> m_pendingWriteArguments;
300     OVERLAPPED m_writeState;
301     HANDLE m_connectionPipe;
302 #elif PLATFORM(QT)
303     // Called on the connection queue.
304     void readyReadHandler();
305
306     Vector<uint8_t> m_readBuffer;
307     size_t m_currentMessageSize;
308     QSocketNotifier* m_socketNotifier;
309     int m_socketDescriptor;
310 #elif PLATFORM(GTK)
311     void readEventHandler();
312     void processCompletedMessage();
313     bool messageProcessingCompleted() { return !m_currentMessageSize; }
314
315     int m_socket;
316     Vector<uint8_t> m_readBuffer;
317     size_t m_currentMessageSize;
318     size_t m_pendingBytes;
319 #endif
320 };
321
322 template<typename T> bool Connection::send(const T& message, uint64_t destinationID, unsigned messageSendFlags)
323 {
324     OwnPtr<ArgumentEncoder> argumentEncoder = ArgumentEncoder::create(destinationID);
325     argumentEncoder->encode(message);
326     
327     return sendMessage(MessageID(T::messageID), argumentEncoder.release(), messageSendFlags);
328 }
329
330 template<typename T> bool Connection::sendSync(const T& message, const typename T::Reply& reply, uint64_t destinationID, double timeout)
331 {
332     uint64_t syncRequestID = 0;
333     OwnPtr<ArgumentEncoder> argumentEncoder = createSyncMessageArgumentEncoder(destinationID, syncRequestID);
334     
335     // Encode the rest of the input arguments.
336     argumentEncoder->encode(message);
337
338     // Now send the message and wait for a reply.
339     OwnPtr<ArgumentDecoder> replyDecoder = sendSyncMessage(MessageID(T::messageID, MessageID::SyncMessage), syncRequestID, argumentEncoder.release(), timeout);
340     if (!replyDecoder)
341         return false;
342
343     // Decode the reply.
344     return replyDecoder->decode(const_cast<typename T::Reply&>(reply));
345 }
346
347 template<typename T> bool Connection::waitForAndDispatchImmediately(uint64_t destinationID, double timeout)
348 {
349     OwnPtr<ArgumentDecoder> decoder = waitForMessage(MessageID(T::messageID), destinationID, timeout);
350     if (!decoder)
351         return false;
352
353     ASSERT(decoder->destinationID() == destinationID);
354     m_client->didReceiveMessage(this, MessageID(T::messageID), decoder.get());
355     return true;
356 }
357
358 // These three member functions are all deprecated.
359
360 template<typename E, typename T, typename U>
361 inline bool Connection::deprecatedSendSync(E messageID, uint64_t destinationID, const T& arguments, const U& reply, double timeout)
362 {
363     uint64_t syncRequestID = 0;
364     OwnPtr<ArgumentEncoder> argumentEncoder = createSyncMessageArgumentEncoder(destinationID, syncRequestID);
365
366     // Encode the input arguments.
367     argumentEncoder->encode(arguments);
368     
369     // Now send the message and wait for a reply.
370     OwnPtr<ArgumentDecoder> replyDecoder = sendSyncMessage(MessageID(messageID, MessageID::SyncMessage), syncRequestID, argumentEncoder.release(), timeout);
371     if (!replyDecoder)
372         return false;
373     
374     // Decode the reply.
375     return replyDecoder->decode(const_cast<U&>(reply));
376 }
377
378 template<typename E, typename T>
379 bool Connection::deprecatedSend(E messageID, uint64_t destinationID, const T& arguments)
380 {
381     OwnPtr<ArgumentEncoder> argumentEncoder = ArgumentEncoder::create(destinationID);
382     argumentEncoder->encode(arguments);
383
384     return sendMessage(MessageID(messageID), argumentEncoder.release());
385 }
386
387 template<typename E> inline PassOwnPtr<ArgumentDecoder> Connection::deprecatedWaitFor(E messageID, uint64_t destinationID, double timeout)
388 {
389     return waitForMessage(MessageID(messageID), destinationID, timeout);
390 }
391
392 } // namespace CoreIPC
393
394 #endif // Connection_h