security/sandbox/win/src/sharedmem_ipc_client.h

changeset 0
6474c204b198
     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__

mercurial