ipc/glue/ProtocolUtils.h

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
michael@0 2 * vim: sw=4 ts=4 et :
michael@0 3 */
michael@0 4 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 5 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 7
michael@0 8 #ifndef mozilla_ipc_ProtocolUtils_h
michael@0 9 #define mozilla_ipc_ProtocolUtils_h 1
michael@0 10
michael@0 11 #include "base/process.h"
michael@0 12 #include "base/process_util.h"
michael@0 13 #include "chrome/common/ipc_message_utils.h"
michael@0 14
michael@0 15 #include "prenv.h"
michael@0 16
michael@0 17 #include "IPCMessageStart.h"
michael@0 18 #include "mozilla/Attributes.h"
michael@0 19 #include "mozilla/ipc/FileDescriptor.h"
michael@0 20 #include "mozilla/ipc/Shmem.h"
michael@0 21 #include "mozilla/ipc/Transport.h"
michael@0 22 #include "mozilla/ipc/MessageLink.h"
michael@0 23 #include "mozilla/LinkedList.h"
michael@0 24
michael@0 25 #if defined(ANDROID) && defined(DEBUG)
michael@0 26 #include <android/log.h>
michael@0 27 #endif
michael@0 28
michael@0 29 // WARNING: this takes into account the private, special-message-type
michael@0 30 // enum in ipc_channel.h. They need to be kept in sync.
michael@0 31 namespace {
michael@0 32 // XXX the max message ID is actually kuint32max now ... when this
michael@0 33 // changed, the assumptions of the special message IDs changed in that
michael@0 34 // they're not carving out messages from likely-unallocated space, but
michael@0 35 // rather carving out messages from the end of space allocated to
michael@0 36 // protocol 0. Oops! We can get away with this until protocol 0
michael@0 37 // starts approaching its 65,536th message.
michael@0 38 enum {
michael@0 39 CHANNEL_OPENED_MESSAGE_TYPE = kuint16max - 5,
michael@0 40 SHMEM_DESTROYED_MESSAGE_TYPE = kuint16max - 4,
michael@0 41 SHMEM_CREATED_MESSAGE_TYPE = kuint16max - 3,
michael@0 42 GOODBYE_MESSAGE_TYPE = kuint16max - 2
michael@0 43
michael@0 44 // kuint16max - 1 is used by ipc_channel.h.
michael@0 45 };
michael@0 46 }
michael@0 47
michael@0 48 namespace mozilla {
michael@0 49 namespace dom {
michael@0 50 class ContentParent;
michael@0 51 }
michael@0 52
michael@0 53 namespace net {
michael@0 54 class NeckoParent;
michael@0 55 }
michael@0 56
michael@0 57 namespace ipc {
michael@0 58
michael@0 59 #ifdef XP_WIN
michael@0 60 const base::ProcessHandle kInvalidProcessHandle = INVALID_HANDLE_VALUE;
michael@0 61 #else
michael@0 62 const base::ProcessHandle kInvalidProcessHandle = -1;
michael@0 63 #endif
michael@0 64
michael@0 65 class ProtocolFdMapping;
michael@0 66 class ProtocolCloneContext;
michael@0 67
michael@0 68 // Used to pass references to protocol actors across the wire.
michael@0 69 // Actors created on the parent-side have a positive ID, and actors
michael@0 70 // allocated on the child side have a negative ID.
michael@0 71 struct ActorHandle
michael@0 72 {
michael@0 73 int mId;
michael@0 74 };
michael@0 75
michael@0 76 // Used internally to represent a "trigger" that might cause a state
michael@0 77 // transition. Triggers are normalized across parent+child to Send
michael@0 78 // and Recv (instead of child-in, child-out, parent-in, parent-out) so
michael@0 79 // that they can share the same state machine implementation. To
michael@0 80 // further normalize, |Send| is used for 'call', |Recv| for 'answer'.
michael@0 81 struct Trigger
michael@0 82 {
michael@0 83 enum Action { Send, Recv };
michael@0 84
michael@0 85 Trigger(Action action, int32_t msg) :
michael@0 86 mAction(action),
michael@0 87 mMsg(msg)
michael@0 88 {}
michael@0 89
michael@0 90 Action mAction;
michael@0 91 int32_t mMsg;
michael@0 92 };
michael@0 93
michael@0 94 class ProtocolCloneContext
michael@0 95 {
michael@0 96 typedef mozilla::dom::ContentParent ContentParent;
michael@0 97 typedef mozilla::net::NeckoParent NeckoParent;
michael@0 98
michael@0 99 ContentParent* mContentParent;
michael@0 100 NeckoParent* mNeckoParent;
michael@0 101
michael@0 102 public:
michael@0 103 ProtocolCloneContext()
michael@0 104 : mContentParent(nullptr)
michael@0 105 , mNeckoParent(nullptr)
michael@0 106 {}
michael@0 107
michael@0 108 void SetContentParent(ContentParent* aContentParent)
michael@0 109 {
michael@0 110 mContentParent = aContentParent;
michael@0 111 }
michael@0 112
michael@0 113 ContentParent* GetContentParent() { return mContentParent; }
michael@0 114
michael@0 115 void SetNeckoParent(NeckoParent* aNeckoParent)
michael@0 116 {
michael@0 117 mNeckoParent = aNeckoParent;
michael@0 118 }
michael@0 119
michael@0 120 NeckoParent* GetNeckoParent() { return mNeckoParent; }
michael@0 121 };
michael@0 122
michael@0 123 template<class ListenerT>
michael@0 124 class /*NS_INTERFACE_CLASS*/ IProtocolManager
michael@0 125 {
michael@0 126 public:
michael@0 127 enum ActorDestroyReason {
michael@0 128 FailedConstructor,
michael@0 129 Deletion,
michael@0 130 AncestorDeletion,
michael@0 131 NormalShutdown,
michael@0 132 AbnormalShutdown
michael@0 133 };
michael@0 134
michael@0 135 typedef base::ProcessHandle ProcessHandle;
michael@0 136
michael@0 137 virtual int32_t Register(ListenerT*) = 0;
michael@0 138 virtual int32_t RegisterID(ListenerT*, int32_t) = 0;
michael@0 139 virtual ListenerT* Lookup(int32_t) = 0;
michael@0 140 virtual void Unregister(int32_t) = 0;
michael@0 141 virtual void RemoveManagee(int32_t, ListenerT*) = 0;
michael@0 142
michael@0 143 virtual Shmem::SharedMemory* CreateSharedMemory(
michael@0 144 size_t, SharedMemory::SharedMemoryType, bool, int32_t*) = 0;
michael@0 145 virtual bool AdoptSharedMemory(Shmem::SharedMemory*, int32_t*) = 0;
michael@0 146 virtual Shmem::SharedMemory* LookupSharedMemory(int32_t) = 0;
michael@0 147 virtual bool IsTrackingSharedMemory(Shmem::SharedMemory*) = 0;
michael@0 148 virtual bool DestroySharedMemory(Shmem&) = 0;
michael@0 149
michael@0 150 // XXX odd ducks, acknowledged
michael@0 151 virtual ProcessHandle OtherProcess() const = 0;
michael@0 152 virtual MessageChannel* GetIPCChannel() = 0;
michael@0 153
michael@0 154 // The implementation of function is generated by code generator.
michael@0 155 virtual void CloneManagees(ListenerT* aSource,
michael@0 156 ProtocolCloneContext* aCtx) = 0;
michael@0 157 };
michael@0 158
michael@0 159 typedef IPCMessageStart ProtocolId;
michael@0 160
michael@0 161 /**
michael@0 162 * All RPC protocols should implement this interface.
michael@0 163 */
michael@0 164 class IProtocol : protected MessageListener
michael@0 165 {
michael@0 166 public:
michael@0 167 /**
michael@0 168 * This function is used to clone this protocol actor.
michael@0 169 *
michael@0 170 * see IProtocol::CloneProtocol()
michael@0 171 */
michael@0 172 virtual IProtocol*
michael@0 173 CloneProtocol(MessageChannel* aChannel,
michael@0 174 ProtocolCloneContext* aCtx) = 0;
michael@0 175 };
michael@0 176
michael@0 177 /**
michael@0 178 * All top-level protocols should inherit this class.
michael@0 179 *
michael@0 180 * IToplevelProtocol tracks all top-level protocol actors created from
michael@0 181 * this protocol actor.
michael@0 182 */
michael@0 183 class IToplevelProtocol : public LinkedListElement<IToplevelProtocol>
michael@0 184 {
michael@0 185 protected:
michael@0 186 IToplevelProtocol(ProtocolId aProtoId)
michael@0 187 : mProtocolId(aProtoId)
michael@0 188 , mTrans(nullptr)
michael@0 189 {
michael@0 190 }
michael@0 191
michael@0 192 ~IToplevelProtocol();
michael@0 193
michael@0 194 /**
michael@0 195 * Add an actor to the list of actors that have been opened by this
michael@0 196 * protocol.
michael@0 197 */
michael@0 198 void AddOpenedActor(IToplevelProtocol* aActor);
michael@0 199
michael@0 200 public:
michael@0 201 void SetTransport(Transport* aTrans)
michael@0 202 {
michael@0 203 mTrans = aTrans;
michael@0 204 }
michael@0 205
michael@0 206 Transport* GetTransport() const { return mTrans; }
michael@0 207
michael@0 208 ProtocolId GetProtocolId() const { return mProtocolId; }
michael@0 209
michael@0 210 /**
michael@0 211 * Return first of actors of top level protocols opened by this one.
michael@0 212 */
michael@0 213 IToplevelProtocol* GetFirstOpenedActors()
michael@0 214 {
michael@0 215 return mOpenActors.getFirst();
michael@0 216 }
michael@0 217 const IToplevelProtocol* GetFirstOpenedActors() const
michael@0 218 {
michael@0 219 return mOpenActors.getFirst();
michael@0 220 }
michael@0 221
michael@0 222 virtual IToplevelProtocol*
michael@0 223 CloneToplevel(const InfallibleTArray<ProtocolFdMapping>& aFds,
michael@0 224 base::ProcessHandle aPeerProcess,
michael@0 225 ProtocolCloneContext* aCtx);
michael@0 226
michael@0 227 void CloneOpenedToplevels(IToplevelProtocol* aTemplate,
michael@0 228 const InfallibleTArray<ProtocolFdMapping>& aFds,
michael@0 229 base::ProcessHandle aPeerProcess,
michael@0 230 ProtocolCloneContext* aCtx);
michael@0 231
michael@0 232 private:
michael@0 233 LinkedList<IToplevelProtocol> mOpenActors; // All protocol actors opened by this.
michael@0 234
michael@0 235 ProtocolId mProtocolId;
michael@0 236 Transport* mTrans;
michael@0 237 };
michael@0 238
michael@0 239
michael@0 240 inline bool
michael@0 241 LoggingEnabled()
michael@0 242 {
michael@0 243 #if defined(DEBUG)
michael@0 244 return !!PR_GetEnv("MOZ_IPC_MESSAGE_LOG");
michael@0 245 #else
michael@0 246 return false;
michael@0 247 #endif
michael@0 248 }
michael@0 249
michael@0 250 MOZ_NEVER_INLINE void
michael@0 251 ProtocolErrorBreakpoint(const char* aMsg);
michael@0 252
michael@0 253 MOZ_NEVER_INLINE void
michael@0 254 FatalError(const char* aProtocolName, const char* aMsg,
michael@0 255 base::ProcessHandle aHandle, bool aIsParent);
michael@0 256
michael@0 257 struct PrivateIPDLInterface {};
michael@0 258
michael@0 259 bool
michael@0 260 Bridge(const PrivateIPDLInterface&,
michael@0 261 MessageChannel*, base::ProcessHandle, MessageChannel*, base::ProcessHandle,
michael@0 262 ProtocolId, ProtocolId);
michael@0 263
michael@0 264 bool
michael@0 265 Open(const PrivateIPDLInterface&,
michael@0 266 MessageChannel*, base::ProcessHandle, Transport::Mode,
michael@0 267 ProtocolId, ProtocolId);
michael@0 268
michael@0 269 bool
michael@0 270 UnpackChannelOpened(const PrivateIPDLInterface&,
michael@0 271 const IPC::Message&,
michael@0 272 TransportDescriptor*, base::ProcessId*, ProtocolId*);
michael@0 273
michael@0 274 } // namespace ipc
michael@0 275 } // namespace mozilla
michael@0 276
michael@0 277
michael@0 278 namespace IPC {
michael@0 279
michael@0 280 template <>
michael@0 281 struct ParamTraits<mozilla::ipc::ActorHandle>
michael@0 282 {
michael@0 283 typedef mozilla::ipc::ActorHandle paramType;
michael@0 284
michael@0 285 static void Write(Message* aMsg, const paramType& aParam)
michael@0 286 {
michael@0 287 IPC::WriteParam(aMsg, aParam.mId);
michael@0 288 }
michael@0 289
michael@0 290 static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
michael@0 291 {
michael@0 292 int id;
michael@0 293 if (IPC::ReadParam(aMsg, aIter, &id)) {
michael@0 294 aResult->mId = id;
michael@0 295 return true;
michael@0 296 }
michael@0 297 return false;
michael@0 298 }
michael@0 299
michael@0 300 static void Log(const paramType& aParam, std::wstring* aLog)
michael@0 301 {
michael@0 302 aLog->append(StringPrintf(L"(%d)", aParam.mId));
michael@0 303 }
michael@0 304 };
michael@0 305
michael@0 306 } // namespace IPC
michael@0 307
michael@0 308
michael@0 309 #endif // mozilla_ipc_ProtocolUtils_h

mercurial