1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/ipc/glue/ProtocolUtils.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,203 @@ 1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- 1.5 + * vim: sw=2 ts=8 et : 1.6 + */ 1.7 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.8 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.9 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.10 + 1.11 +#include "base/process_util.h" 1.12 + 1.13 +#include "mozilla/ipc/MessageChannel.h" 1.14 +#include "mozilla/ipc/ProtocolUtils.h" 1.15 +#include "mozilla/ipc/Transport.h" 1.16 + 1.17 +using namespace base; 1.18 +using namespace IPC; 1.19 + 1.20 +namespace mozilla { 1.21 +namespace ipc { 1.22 + 1.23 +IToplevelProtocol::~IToplevelProtocol() 1.24 +{ 1.25 + mOpenActors.clear(); 1.26 +} 1.27 + 1.28 +void IToplevelProtocol::AddOpenedActor(IToplevelProtocol* aActor) 1.29 +{ 1.30 +#ifdef DEBUG 1.31 + for (const IToplevelProtocol* actor = mOpenActors.getFirst(); 1.32 + actor; 1.33 + actor = actor->getNext()) { 1.34 + NS_ASSERTION(actor != aActor, 1.35 + "Open the same protocol for more than one time"); 1.36 + } 1.37 +#endif 1.38 + 1.39 + mOpenActors.insertBack(aActor); 1.40 +} 1.41 + 1.42 +IToplevelProtocol* 1.43 +IToplevelProtocol::CloneToplevel(const InfallibleTArray<ProtocolFdMapping>& aFds, 1.44 + base::ProcessHandle aPeerProcess, 1.45 + ProtocolCloneContext* aCtx) 1.46 +{ 1.47 + NS_NOTREACHED("Clone() for this protocol actor is not implemented"); 1.48 + return nullptr; 1.49 +} 1.50 + 1.51 +void 1.52 +IToplevelProtocol::CloneOpenedToplevels(IToplevelProtocol* aTemplate, 1.53 + const InfallibleTArray<ProtocolFdMapping>& aFds, 1.54 + base::ProcessHandle aPeerProcess, 1.55 + ProtocolCloneContext* aCtx) 1.56 +{ 1.57 + for (IToplevelProtocol* actor = aTemplate->GetFirstOpenedActors(); 1.58 + actor; 1.59 + actor = actor->getNext()) { 1.60 + IToplevelProtocol* newactor = actor->CloneToplevel(aFds, aPeerProcess, aCtx); 1.61 + AddOpenedActor(newactor); 1.62 + } 1.63 +} 1.64 + 1.65 +class ChannelOpened : public IPC::Message 1.66 +{ 1.67 +public: 1.68 + ChannelOpened(TransportDescriptor aDescriptor, 1.69 + ProcessId aOtherProcess, 1.70 + ProtocolId aProtocol) 1.71 + : IPC::Message(MSG_ROUTING_CONTROL, // these only go to top-level actors 1.72 + CHANNEL_OPENED_MESSAGE_TYPE, 1.73 + PRIORITY_NORMAL) 1.74 + { 1.75 + IPC::WriteParam(this, aDescriptor); 1.76 + IPC::WriteParam(this, aOtherProcess); 1.77 + IPC::WriteParam(this, static_cast<uint32_t>(aProtocol)); 1.78 + } 1.79 + 1.80 + static bool Read(const IPC::Message& aMsg, 1.81 + TransportDescriptor* aDescriptor, 1.82 + ProcessId* aOtherProcess, 1.83 + ProtocolId* aProtocol) 1.84 + { 1.85 + void* iter = nullptr; 1.86 + if (!IPC::ReadParam(&aMsg, &iter, aDescriptor) || 1.87 + !IPC::ReadParam(&aMsg, &iter, aOtherProcess) || 1.88 + !IPC::ReadParam(&aMsg, &iter, reinterpret_cast<uint32_t*>(aProtocol))) { 1.89 + return false; 1.90 + } 1.91 + aMsg.EndRead(iter); 1.92 + return true; 1.93 + } 1.94 +}; 1.95 + 1.96 +bool 1.97 +Bridge(const PrivateIPDLInterface&, 1.98 + MessageChannel* aParentChannel, ProcessHandle aParentProcess, 1.99 + MessageChannel* aChildChannel, ProcessHandle aChildProcess, 1.100 + ProtocolId aProtocol, ProtocolId aChildProtocol) 1.101 +{ 1.102 + ProcessId parentId = GetProcId(aParentProcess); 1.103 + ProcessId childId = GetProcId(aChildProcess); 1.104 + if (!parentId || !childId) { 1.105 + return false; 1.106 + } 1.107 + 1.108 + TransportDescriptor parentSide, childSide; 1.109 + if (!CreateTransport(aParentProcess, aChildProcess, 1.110 + &parentSide, &childSide)) { 1.111 + return false; 1.112 + } 1.113 + 1.114 + if (!aParentChannel->Send(new ChannelOpened(parentSide, 1.115 + childId, 1.116 + aProtocol)) || 1.117 + !aChildChannel->Send(new ChannelOpened(childSide, 1.118 + parentId, 1.119 + aChildProtocol))) { 1.120 + CloseDescriptor(parentSide); 1.121 + CloseDescriptor(childSide); 1.122 + return false; 1.123 + } 1.124 + return true; 1.125 +} 1.126 + 1.127 +bool 1.128 +Open(const PrivateIPDLInterface&, 1.129 + MessageChannel* aOpenerChannel, ProcessHandle aOtherProcess, 1.130 + Transport::Mode aOpenerMode, 1.131 + ProtocolId aProtocol, ProtocolId aChildProtocol) 1.132 +{ 1.133 + bool isParent = (Transport::MODE_SERVER == aOpenerMode); 1.134 + ProcessHandle thisHandle = GetCurrentProcessHandle(); 1.135 + ProcessHandle parentHandle = isParent ? thisHandle : aOtherProcess; 1.136 + ProcessHandle childHandle = !isParent ? thisHandle : aOtherProcess; 1.137 + ProcessId parentId = GetProcId(parentHandle); 1.138 + ProcessId childId = GetProcId(childHandle); 1.139 + if (!parentId || !childId) { 1.140 + return false; 1.141 + } 1.142 + 1.143 + TransportDescriptor parentSide, childSide; 1.144 + if (!CreateTransport(parentHandle, childHandle, 1.145 + &parentSide, &childSide)) { 1.146 + return false; 1.147 + } 1.148 + 1.149 + Message* parentMsg = new ChannelOpened(parentSide, childId, aProtocol); 1.150 + Message* childMsg = new ChannelOpened(childSide, parentId, aChildProtocol); 1.151 + nsAutoPtr<Message> messageForUs(isParent ? parentMsg : childMsg); 1.152 + nsAutoPtr<Message> messageForOtherSide(!isParent ? parentMsg : childMsg); 1.153 + if (!aOpenerChannel->Echo(messageForUs.forget()) || 1.154 + !aOpenerChannel->Send(messageForOtherSide.forget())) { 1.155 + CloseDescriptor(parentSide); 1.156 + CloseDescriptor(childSide); 1.157 + return false; 1.158 + } 1.159 + return true; 1.160 +} 1.161 + 1.162 +bool 1.163 +UnpackChannelOpened(const PrivateIPDLInterface&, 1.164 + const Message& aMsg, 1.165 + TransportDescriptor* aTransport, 1.166 + ProcessId* aOtherProcess, 1.167 + ProtocolId* aProtocol) 1.168 +{ 1.169 + return ChannelOpened::Read(aMsg, aTransport, aOtherProcess, aProtocol); 1.170 +} 1.171 + 1.172 +void 1.173 +ProtocolErrorBreakpoint(const char* aMsg) 1.174 +{ 1.175 + // Bugs that generate these error messages can be tough to 1.176 + // reproduce. Log always in the hope that someone finds the error 1.177 + // message. 1.178 + printf_stderr("IPDL protocol error: %s\n", aMsg); 1.179 +} 1.180 + 1.181 +void 1.182 +FatalError(const char* aProtocolName, const char* aMsg, 1.183 + ProcessHandle aHandle, bool aIsParent) 1.184 +{ 1.185 + ProtocolErrorBreakpoint(aMsg); 1.186 + 1.187 + nsAutoCString formattedMessage("IPDL error ["); 1.188 + formattedMessage.AppendASCII(aProtocolName); 1.189 + formattedMessage.AppendLiteral("]: \""); 1.190 + formattedMessage.AppendASCII(aMsg); 1.191 + if (aIsParent) { 1.192 + formattedMessage.AppendLiteral("\". Killing child side as a result."); 1.193 + NS_ERROR(formattedMessage.get()); 1.194 + 1.195 + if (aHandle != kInvalidProcessHandle && 1.196 + !base::KillProcess(aHandle, base::PROCESS_END_KILLED_BY_USER, false)) { 1.197 + NS_ERROR("May have failed to kill child!"); 1.198 + } 1.199 + } else { 1.200 + formattedMessage.AppendLiteral("\". abort()ing as a result."); 1.201 + NS_RUNTIMEABORT(formattedMessage.get()); 1.202 + } 1.203 +} 1.204 + 1.205 +} // namespace ipc 1.206 +} // namespace mozilla