summaryrefslogtreecommitdiffstats
path: root/security/sandbox/chromium/sandbox/win/src/sharedmem_ipc_client.h
diff options
context:
space:
mode:
Diffstat (limited to 'security/sandbox/chromium/sandbox/win/src/sharedmem_ipc_client.h')
-rw-r--r--security/sandbox/chromium/sandbox/win/src/sharedmem_ipc_client.h140
1 files changed, 140 insertions, 0 deletions
diff --git a/security/sandbox/chromium/sandbox/win/src/sharedmem_ipc_client.h b/security/sandbox/chromium/sandbox/win/src/sharedmem_ipc_client.h
new file mode 100644
index 0000000000..73f739dece
--- /dev/null
+++ b/security/sandbox/chromium/sandbox/win/src/sharedmem_ipc_client.h
@@ -0,0 +1,140 @@
+// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SANDBOX_SRC_SHAREDMEM_IPC_CLIENT_H__
+#define SANDBOX_SRC_SHAREDMEM_IPC_CLIENT_H__
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "sandbox/win/src/crosscall_params.h"
+#include "sandbox/win/src/ipc_tags.h"
+#include "sandbox/win/src/sandbox.h"
+
+// IPC transport implementation that uses shared memory.
+// This is the client side
+//
+// The shared memory is divided on blocks called channels, and potentially
+// it can perform as many concurrent IPC calls as channels. The IPC over
+// each channel is strictly synchronous for the client.
+//
+// Each channel as a channel control section associated with. Each control
+// section has two kernel events (known as ping and pong) and a integer
+// variable that maintains a state
+//
+// this is the state diagram of a channel:
+//
+// locked in service
+// kFreeChannel---------->BusyChannel-------------->kAckChannel
+// ^ |
+// |_________________________________________________|
+// answer ready
+//
+// The protocol is as follows:
+// 1) client finds a free channel: state = kFreeChannel
+// 2) does an atomic compare-and-swap, now state = BusyChannel
+// 3) client writes the data into the channel buffer
+// 4) client signals the ping event and waits (blocks) on the pong event
+// 5) eventually the server signals the pong event
+// 6) the client awakes and reads the answer from the same channel
+// 7) the client updates its InOut parameters with the new data from the
+// shared memory section.
+// 8) the client atomically sets the state = kFreeChannel
+//
+// In the shared memory the layout is as follows:
+//
+// [ channel count ]
+// [ channel control 0]
+// [ channel control 1]
+// [ channel control N]
+// [ channel buffer 0 ] 1024 bytes
+// [ channel buffer 1 ] 1024 bytes
+// [ channel buffer N ] 1024 bytes
+//
+// By default each channel buffer is 1024 bytes
+namespace sandbox {
+
+// the possible channel states as described above
+enum ChannelState {
+ // channel is free
+ kFreeChannel = 1,
+ // IPC in progress client side
+ kBusyChannel,
+ // IPC in progress server side
+ kAckChannel,
+ // not used right now
+ kReadyChannel,
+ // IPC abandoned by client side
+ kAbandonedChannel
+};
+
+// The next two constants control the time outs for the IPC.
+const DWORD kIPCWaitTimeOut1 = 1000; // Milliseconds.
+const DWORD kIPCWaitTimeOut2 = 50; // Milliseconds.
+
+// the channel control structure
+struct ChannelControl {
+ // points to be beginning of the channel buffer, where data goes
+ size_t channel_base;
+ // maintains the state from the ChannelState enumeration
+ volatile LONG state;
+ // the ping event is signaled by the client when the IPC data is ready on
+ // the buffer
+ HANDLE ping_event;
+ // the client waits on the pong event for the IPC answer back
+ HANDLE pong_event;
+ // the IPC unique identifier
+ IpcTag ipc_tag;
+};
+
+struct IPCControl {
+ // total number of channels available, some might be busy at a given time
+ size_t channels_count;
+ // handle to a shared mutex to detect when the server is dead
+ HANDLE server_alive;
+ // array of channel control structures
+ ChannelControl channels[1];
+};
+
+// the actual shared memory IPC implementation class. This object is designed
+// to be lightweight so it can be constructed on-site (at the calling place)
+// wherever an IPC call is needed.
+class SharedMemIPCClient {
+ public:
+ // Creates the IPC client.
+ // as parameter it takes the base address of the shared memory
+ explicit SharedMemIPCClient(void* shared_mem);
+
+ // locks a free channel and returns the channel buffer memory base. This call
+ // blocks until there is a free channel
+ void* GetBuffer();
+
+ // releases the lock on the channel, for other to use. call this if you have
+ // called GetBuffer and you want to abort but have not called yet DoCall()
+ void FreeBuffer(void* buffer);
+
+ // Performs the actual IPC call.
+ // params: The blob of packed input parameters.
+ // answer: upon IPC completion, it contains the server answer to the IPC.
+ // If the return value is not SBOX_ERROR_CHANNEL_ERROR, the caller has to free
+ // the channel.
+ // returns ALL_OK if the IPC mechanism successfully delivered. You still need
+ // to check on the answer structure to see the actual IPC result.
+ ResultCode DoCall(CrossCallParams* params, CrossCallReturn* answer);
+
+ private:
+ // Returns the index of the first free channel. It sets 'severe_failure'
+ // to true if there is an unrecoverable error that does not allow to
+ // find a channel.
+ size_t LockFreeChannel(bool* severe_failure);
+ // Return the channel index given the address of the buffer.
+ size_t ChannelIndexFromBuffer(const void* buffer);
+ IPCControl* control_;
+ // point to the first channel base
+ char* first_base_;
+};
+
+} // namespace sandbox
+
+#endif // SANDBOX_SRC_SHAREDMEM_IPC_CLIENT_H__