michael@0: // Copyright (c) 2012 The Chromium Authors. All rights reserved. michael@0: // Use of this source code is governed by a BSD-style license that can be michael@0: // found in the LICENSE file. michael@0: michael@0: #ifndef SANDBOX_SRC_SHAREDMEM_IPC_SERVER_H_ michael@0: #define SANDBOX_SRC_SHAREDMEM_IPC_SERVER_H_ michael@0: michael@0: #include michael@0: michael@0: #include "base/basictypes.h" michael@0: #include "base/gtest_prod_util.h" michael@0: #include "sandbox/win/src/crosscall_params.h" michael@0: #include "sandbox/win/src/crosscall_server.h" michael@0: #include "sandbox/win/src/sharedmem_ipc_client.h" michael@0: michael@0: // IPC transport implementation that uses shared memory. michael@0: // This is the server side michael@0: // michael@0: // The server side has knowledge about the layout of the shared memory michael@0: // and the state transitions. Both are explained in sharedmem_ipc_client.h michael@0: // michael@0: // As opposed to SharedMemIPClient, the Server object should be one for the michael@0: // entire lifetime of the target process. The server is in charge of creating michael@0: // the events (ping, pong) both for the client and for the target that are used michael@0: // to signal the IPC and also in charge of setting the initial state of the michael@0: // channels. michael@0: // michael@0: // When an IPC is ready, the server relies on being called by on the michael@0: // ThreadPingEventReady callback. The IPC server then retrieves the buffer, michael@0: // marshals it into a CrossCallParam object and calls the Dispatcher, who is in michael@0: // charge of fulfilling the IPC request. michael@0: namespace sandbox { michael@0: michael@0: // the shared memory implementation of the IPC server. There should be one michael@0: // of these objects per target (IPC client) process michael@0: class SharedMemIPCServer { michael@0: public: michael@0: // Creates the IPC server. michael@0: // target_process: handle to the target process. It must be suspended. michael@0: // target_process_id: process id of the target process. michael@0: // target_job: the job object handle associated with the target process. michael@0: // thread_provider: a thread provider object. michael@0: // dispatcher: an object that can service IPC calls. michael@0: SharedMemIPCServer(HANDLE target_process, DWORD target_process_id, michael@0: HANDLE target_job, ThreadProvider* thread_provider, michael@0: Dispatcher* dispatcher); michael@0: michael@0: ~SharedMemIPCServer(); michael@0: michael@0: // Initializes the server structures, shared memory structures and michael@0: // creates the kernels events used to signal the IPC. michael@0: bool Init(void* shared_mem, uint32 shared_size, uint32 channel_size); michael@0: michael@0: private: michael@0: // Allow tests to be marked DISABLED_. Note that FLAKY_ and FAILS_ prefixes michael@0: // do not work with sandbox tests. michael@0: FRIEND_TEST_ALL_PREFIXES(IPCTest, SharedMemServerTests); michael@0: // When an event fires (IPC request). A thread from the ThreadProvider michael@0: // will call this function. The context parameter should be the same as michael@0: // provided when ThreadProvider::RegisterWait was called. michael@0: static void __stdcall ThreadPingEventReady(void* context, michael@0: unsigned char); michael@0: michael@0: // Makes the client and server events. This function is called once michael@0: // per channel. michael@0: bool MakeEvents(HANDLE* server_ping, HANDLE* server_pong, michael@0: HANDLE* client_ping, HANDLE* client_pong); michael@0: michael@0: // A copy this structure is maintained per channel. michael@0: // Note that a lot of the fields are just the same of what we have in the IPC michael@0: // object itself. It is better to have the copies since we can dispatch in the michael@0: // static method without worrying about converting back to a member function michael@0: // call or about threading issues. michael@0: struct ServerControl { michael@0: // This channel server ping event. michael@0: HANDLE ping_event; michael@0: // This channel server pong event. michael@0: HANDLE pong_event; michael@0: // The size of this channel. michael@0: uint32 channel_size; michael@0: // The pointer to the actual channel data. michael@0: char* channel_buffer; michael@0: // The pointer to the base of the shared memory. michael@0: char* shared_base; michael@0: // A pointer to this channel's client-side control structure this structure michael@0: // lives in the shared memory. michael@0: ChannelControl* channel; michael@0: // the IPC dispatcher associated with this channel. michael@0: Dispatcher* dispatcher; michael@0: // The target process information associated with this channel. michael@0: ClientInfo target_info; michael@0: }; michael@0: michael@0: // Looks for the appropriate handler for this IPC and invokes it. michael@0: static bool InvokeCallback(const ServerControl* service_context, michael@0: void* ipc_buffer, CrossCallReturn* call_result); michael@0: michael@0: // Points to the shared memory channel control which lives at michael@0: // the start of the shared section. michael@0: IPCControl* client_control_; michael@0: michael@0: // Keeps track of the server side objects that are used to answer an IPC. michael@0: typedef std::list ServerContexts; michael@0: ServerContexts server_contexts_; michael@0: michael@0: // The thread provider provides the threads that call back into this object michael@0: // when the IPC events fire. michael@0: ThreadProvider* thread_provider_; michael@0: michael@0: // The IPC object is associated with a target process. michael@0: HANDLE target_process_; michael@0: michael@0: // The target process id associated with the IPC object. michael@0: DWORD target_process_id_; michael@0: michael@0: // The target object is inside a job too. michael@0: HANDLE target_job_object_; michael@0: michael@0: // The dispatcher handles 'ready' IPC calls. michael@0: Dispatcher* call_dispatcher_; michael@0: michael@0: DISALLOW_COPY_AND_ASSIGN(SharedMemIPCServer); michael@0: }; michael@0: michael@0: } // namespace sandbox michael@0: michael@0: #endif // SANDBOX_SRC_SHAREDMEM_IPC_SERVER_H_