1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/sandbox/win/src/sharedmem_ipc_client.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,136 @@ 1.4 +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. 1.5 +// Use of this source code is governed by a BSD-style license that can be 1.6 +// found in the LICENSE file. 1.7 + 1.8 +#ifndef SANDBOX_SRC_SHAREDMEM_IPC_CLIENT_H__ 1.9 +#define SANDBOX_SRC_SHAREDMEM_IPC_CLIENT_H__ 1.10 + 1.11 +#include "sandbox/win/src/crosscall_params.h" 1.12 +#include "sandbox/win/src/sandbox.h" 1.13 + 1.14 +// IPC transport implementation that uses shared memory. 1.15 +// This is the client side 1.16 +// 1.17 +// The shared memory is divided on blocks called channels, and potentially 1.18 +// it can perform as many concurrent IPC calls as channels. The IPC over 1.19 +// each channel is strictly synchronous for the client. 1.20 +// 1.21 +// Each channel as a channel control section associated with. Each control 1.22 +// section has two kernel events (known as ping and pong) and a integer 1.23 +// variable that maintains a state 1.24 +// 1.25 +// this is the state diagram of a channel: 1.26 +// 1.27 +// locked in service 1.28 +// kFreeChannel---------->BusyChannel-------------->kAckChannel 1.29 +// ^ | 1.30 +// |_________________________________________________| 1.31 +// answer ready 1.32 +// 1.33 +// The protocol is as follows: 1.34 +// 1) client finds a free channel: state = kFreeChannel 1.35 +// 2) does an atomic compare-and-swap, now state = BusyChannel 1.36 +// 3) client writes the data into the channel buffer 1.37 +// 4) client signals the ping event and waits (blocks) on the pong event 1.38 +// 5) eventually the server signals the pong event 1.39 +// 6) the client awakes and reads the answer from the same channel 1.40 +// 7) the client updates its InOut parameters with the new data from the 1.41 +// shared memory section. 1.42 +// 8) the client atomically sets the state = kFreeChannel 1.43 +// 1.44 +// In the shared memory the layout is as follows: 1.45 +// 1.46 +// [ channel count ] 1.47 +// [ channel control 0] 1.48 +// [ channel control 1] 1.49 +// [ channel control N] 1.50 +// [ channel buffer 0 ] 1024 bytes 1.51 +// [ channel buffer 1 ] 1024 bytes 1.52 +// [ channel buffer N ] 1024 bytes 1.53 +// 1.54 +// By default each channel buffer is 1024 bytes 1.55 +namespace sandbox { 1.56 + 1.57 +// the possible channel states as described above 1.58 +enum ChannelState { 1.59 + // channel is free 1.60 + kFreeChannel = 1, 1.61 + // IPC in progress client side 1.62 + kBusyChannel, 1.63 + // IPC in progress server side 1.64 + kAckChannel, 1.65 + // not used right now 1.66 + kReadyChannel, 1.67 + // IPC abandoned by client side 1.68 + kAbandonnedChannel 1.69 +}; 1.70 + 1.71 +// The next two constants control the time outs for the IPC. 1.72 +const DWORD kIPCWaitTimeOut1 = 1000; // Milliseconds. 1.73 +const DWORD kIPCWaitTimeOut2 = 50; // Milliseconds. 1.74 + 1.75 +// the channel control structure 1.76 +struct ChannelControl { 1.77 + // points to be beginning of the channel buffer, where data goes 1.78 + size_t channel_base; 1.79 + // maintains the state from the ChannelState enumeration 1.80 + volatile LONG state; 1.81 + // the ping event is signaled by the client when the IPC data is ready on 1.82 + // the buffer 1.83 + HANDLE ping_event; 1.84 + // the client waits on the pong event for the IPC answer back 1.85 + HANDLE pong_event; 1.86 + // the IPC unique identifier 1.87 + uint32 ipc_tag; 1.88 +}; 1.89 + 1.90 +struct IPCControl { 1.91 + // total number of channels available, some might be busy at a given time 1.92 + size_t channels_count; 1.93 + // handle to a shared mutex to detect when the server is dead 1.94 + HANDLE server_alive; 1.95 + // array of channel control structures 1.96 + ChannelControl channels[1]; 1.97 +}; 1.98 + 1.99 +// the actual shared memory IPC implementation class. This object is designed 1.100 +// to be lightweight so it can be constructed on-site (at the calling place) 1.101 +// wherever an IPC call is needed. 1.102 +class SharedMemIPCClient { 1.103 + public: 1.104 + // Creates the IPC client. 1.105 + // as parameter it takes the base address of the shared memory 1.106 + explicit SharedMemIPCClient(void* shared_mem); 1.107 + 1.108 + // locks a free channel and returns the channel buffer memory base. This call 1.109 + // blocks until there is a free channel 1.110 + void* GetBuffer(); 1.111 + 1.112 + // releases the lock on the channel, for other to use. call this if you have 1.113 + // called GetBuffer and you want to abort but have not called yet DoCall() 1.114 + void FreeBuffer(void* buffer); 1.115 + 1.116 + // Performs the actual IPC call. 1.117 + // params: The blob of packed input parameters. 1.118 + // answer: upon IPC completion, it contains the server answer to the IPC. 1.119 + // If the return value is not SBOX_ERROR_CHANNEL_ERROR, the caller has to free 1.120 + // the channel. 1.121 + // returns ALL_OK if the IPC mechanism successfully delivered. You still need 1.122 + // to check on the answer structure to see the actual IPC result. 1.123 + ResultCode DoCall(CrossCallParams* params, CrossCallReturn* answer); 1.124 + 1.125 + private: 1.126 + // Returns the index of the first free channel. It sets 'severe_failure' 1.127 + // to true if there is an unrecoverable error that does not allow to 1.128 + // find a channel. 1.129 + size_t LockFreeChannel(bool* severe_failure); 1.130 + // Return the channel index given the address of the buffer. 1.131 + size_t ChannelIndexFromBuffer(const void* buffer); 1.132 + IPCControl* control_; 1.133 + // point to the first channel base 1.134 + char* first_base_; 1.135 +}; 1.136 + 1.137 +} // namespace sandbox 1.138 + 1.139 +#endif // SANDBOX_SRC_SHAREDMEM_IPC_CLIENT_H__