Home | History | Annotate | Download | only in src
      1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #ifndef SANDBOX_SRC_SHAREDMEM_IPC_CLIENT_H__
      6 #define SANDBOX_SRC_SHAREDMEM_IPC_CLIENT_H__
      7 
      8 #include "sandbox/win/src/crosscall_params.h"
      9 #include "sandbox/win/src/sandbox.h"
     10 
     11 // IPC transport implementation that uses shared memory.
     12 // This is the client side
     13 //
     14 // The shared memory is divided on blocks called channels, and potentially
     15 // it can perform as many concurrent IPC calls as channels. The IPC over
     16 // each channel is strictly synchronous for the client.
     17 //
     18 // Each channel as a channel control section associated with. Each control
     19 // section has two kernel events (known as ping and pong) and a integer
     20 // variable that maintains a state
     21 //
     22 // this is the state diagram of a channel:
     23 //
     24 //                   locked                in service
     25 //     kFreeChannel---------->BusyChannel-------------->kAckChannel
     26 //          ^                                                 |
     27 //          |_________________________________________________|
     28 //                             answer ready
     29 //
     30 // The protocol is as follows:
     31 //   1) client finds a free channel: state = kFreeChannel
     32 //   2) does an atomic compare-and-swap, now state = BusyChannel
     33 //   3) client writes the data into the channel buffer
     34 //   4) client signals the ping event and waits (blocks) on the pong event
     35 //   5) eventually the server signals the pong event
     36 //   6) the client awakes and reads the answer from the same channel
     37 //   7) the client updates its InOut parameters with the new data from the
     38 //      shared memory section.
     39 //   8) the client atomically sets the state = kFreeChannel
     40 //
     41 //  In the shared memory the layout is as follows:
     42 //
     43 //    [ channel count    ]
     44 //    [ channel control 0]
     45 //    [ channel control 1]
     46 //    [ channel control N]
     47 //    [ channel buffer 0 ] 1024 bytes
     48 //    [ channel buffer 1 ] 1024 bytes
     49 //    [ channel buffer N ] 1024 bytes
     50 //
     51 // By default each channel buffer is 1024 bytes
     52 namespace sandbox {
     53 
     54 // the possible channel states as described above
     55 enum ChannelState {
     56   // channel is free
     57   kFreeChannel = 1,
     58   // IPC in progress client side
     59   kBusyChannel,
     60   // IPC in progress server side
     61   kAckChannel,
     62   // not used right now
     63   kReadyChannel,
     64   // IPC abandoned by client side
     65   kAbandonnedChannel
     66 };
     67 
     68 // The next two constants control the time outs for the IPC.
     69 const DWORD kIPCWaitTimeOut1 = 1000;   // Milliseconds.
     70 const DWORD kIPCWaitTimeOut2 =   50;   // Milliseconds.
     71 
     72 // the channel control structure
     73 struct ChannelControl {
     74   // points to be beginning of the channel buffer, where data goes
     75   size_t channel_base;
     76   // maintains the state from the ChannelState enumeration
     77   volatile LONG state;
     78   // the ping event is signaled by the client when the IPC data is ready on
     79   // the buffer
     80   HANDLE ping_event;
     81   // the client waits on the pong event for the IPC answer back
     82   HANDLE pong_event;
     83   // the IPC unique identifier
     84   uint32 ipc_tag;
     85 };
     86 
     87 struct IPCControl {
     88   // total number of channels available, some might be busy at a given time
     89   size_t channels_count;
     90   // handle to a shared mutex to detect when the server is dead
     91   HANDLE server_alive;
     92   // array of channel control structures
     93   ChannelControl channels[1];
     94 };
     95 
     96 // the actual shared memory IPC implementation class. This object is designed
     97 // to be lightweight so it can be constructed on-site (at the calling place)
     98 // wherever an IPC call is needed.
     99 class SharedMemIPCClient {
    100  public:
    101   // Creates the IPC client.
    102   // as parameter it takes the base address of the shared memory
    103   explicit SharedMemIPCClient(void* shared_mem);
    104 
    105   // locks a free channel and returns the channel buffer memory base. This call
    106   // blocks until there is a free channel
    107   void* GetBuffer();
    108 
    109   // releases the lock on the channel, for other to use. call this if you have
    110   // called GetBuffer and you want to abort but have not called yet DoCall()
    111   void FreeBuffer(void* buffer);
    112 
    113   // Performs the actual IPC call.
    114   // params: The blob of packed input parameters.
    115   // answer: upon IPC completion, it contains the server answer to the IPC.
    116   // If the return value is not SBOX_ERROR_CHANNEL_ERROR, the caller has to free
    117   // the channel.
    118   // returns ALL_OK if the IPC mechanism successfully delivered. You still need
    119   // to check on the answer structure to see the actual IPC result.
    120   ResultCode DoCall(CrossCallParams* params, CrossCallReturn* answer);
    121 
    122  private:
    123   // Returns the index of the first free channel. It sets 'severe_failure'
    124   // to true if there is an unrecoverable error that does not allow to
    125   // find a channel.
    126   size_t LockFreeChannel(bool* severe_failure);
    127   // Return the channel index given the address of the buffer.
    128   size_t ChannelIndexFromBuffer(const void* buffer);
    129   IPCControl* control_;
    130   // point to the first channel base
    131   char* first_base_;
    132 };
    133 
    134 }  // namespace sandbox
    135 
    136 #endif  // SANDBOX_SRC_SHAREDMEM_IPC_CLIENT_H__
    137