Chrome IPC Internals – Part V

In this part, we will see how to send a message in synchronized manner. We will send a message to the server and wait for the server to respond.

IPCSyncMessage.h

#pragma once

#define IPC_MESSAGE_START TestMsgStart

// in1 must be false, out1 is true, out2 is 12
IPC_SYNC_MESSAGE_CONTROL1_2(Msg_C_1_2, bool, bool, int)

IPCSyncServer.cc

#include <iostream>
#include <string.h>

#include “base/basictypes.h”
#include “base/compiler_specific.h”
#include “base/memory/scoped_ptr.h”
#include “base/process_util.h”
#include “base/synchronization/waitable_event.h”
#include “base/threading/platform_thread.h”
#include “base/threading/thread.h”
#include “base/time.h”
#include “ipc/ipc_message.h”
#include “ipc/ipc_message_utils.h”
#include “ipc/ipc_channel.h”
#include “base/logging.h”
#include “base/threading/platform_thread.h”
#include “base/message_loop.h”
#include “base/synchronization/waitable_event.h”
#include “ipc/ipc_sync_channel.h”

const char kFuzzerChannel[] = “channelName”;

#define IPC_MESSAGE_IMPL
#include “ipc/ipc_message_macros.h”

#include <IPCSyncMessage.h>

/* Listener */
class SimpleListener : public IPC::Listener {
    public:
        SimpleListener() : other_(NULL) {}
   
        void Init(IPC::Sender* s)
        {
            other_ = s;
        }
       
        virtual bool OnMessageReceived(const IPC::Message& msg) {
            std::cout << “Listener::OnChannelConnected(): Message Received” << std::endl;
            IPC_BEGIN_MESSAGE_MAP(SimpleListener, msg)
                IPC_MESSAGE_HANDLER(Msg_C_1_2, classMsg_C_1_2)
            IPC_END_MESSAGE_MAP()
            return true;
        }

    /* CallStack at classMsg_C_1_2
    IPCSyncServer.exe!SimpleListener::classMsg_C_1_2(bool in1=true, bool * out1=0x001cf3f4, int * out2=0x001cf3f8)  Line 49    C++
    IPCSyncServer.exe!IPC::SyncMessageSchema<Tuple1<bool>,Tuple2<bool &,int &> >::DispatchWithSendParams<SimpleListener,SimpleListener,void (__thiscall SimpleListener::*)(bool,bool *,int *)>(bool ok=true, const Tuple1<bool> & send_params={…}, const IPC::Message * msg=0x00000000, SimpleListener * obj=0x001cfa7c, SimpleListener * sender=0x001cfa7c, void (bool, bool *, int *)* func=0x001cf520)  Line 851    C++
>    IPCSyncServer.exe!SimpleListener::OnMessageReceived(const IPC::Message & msg={…})  Line 42 + 0x61 bytes    C++
    IPCSyncServer.exe!IPC::ChannelProxy::Context::OnDispatchMessage(const IPC::Message & message={…})  Line 267    C++
    IPCSyncServer.exe!IPC::SyncChannel::ReceivedSyncMsgQueue::DispatchMessages(IPC::SyncChannel::SyncContext * dispatching_context=0x009d1c98)  Line 123    C++
    IPCSyncServer.exe!IPC::SyncChannel::ReceivedSyncMsgQueue::DispatchMessagesTask(IPC::SyncChannel::SyncContext * context=0x009d1c98)  Line 90 + 0xf bytes    C++
    IPCSyncServer.exe!base::internal::Invoker<2,base::internal::BindState<base::internal::RunnableAdapter<void (__thiscall IPC::SyncChannel::ReceivedSyncMsgQueue::*)(IPC::SyncChannel::SyncContext *)>,void __cdecl(IPC::SyncChannel::ReceivedSyncMsgQueue *,IPC::SyncChannel::SyncContext *),void __cdecl(IPC::SyncChannel::ReceivedSyncMsgQueue *,scoped_refptr<IPC::SyncChannel::SyncContext>)>,void __cdecl(IPC::SyncChannel::ReceivedSyncMsgQueue *,IPC::SyncChannel::SyncContext *)>::Run(base::internal::BindStateBase * base=0x009d57f0)  Line 1257    C++
    IPCSyncServer.exe!MessageLoop::RunTask(const base::PendingTask & pending_task={…})  Line 462    C++
    IPCSyncServer.exe!MessageLoop::DoWork()  Line 649    C++
    IPCSyncServer.exe!base::MessagePumpForUI::DoRunLoop()  Line 240    C++
    IPCSyncServer.exe!base::MessagePumpWin::Run(base::MessagePump::Delegate * delegate=0x009d1530)  Line 47 + 0x3e bytes    C++
    IPCSyncServer.exe!MessageLoop::RunInternal()  Line 419 + 0xa bytes    C++
    IPCSyncServer.exe!base::RunLoop::Run()  Line 46    C++
    IPCSyncServer.exe!MessageLoop::Run()  Line 300    C++
    IPCSyncServer.exe!main()  Line 103    C++
    IPCSyncServer.exe!_cinit(int initFloatingPrecision=2130567168)  Line 288 + 0x19 bytes    C
    kernel32.dll!7694339a()    
    [Frames below may be incorrect and/or missing, no symbols loaded for kernel32.dll]   
    ntdll.dll!774f9ef2()    
    ntdll.dll!774f9ec5()    
    */

        void classMsg_C_1_2(bool in1, bool *out1, int *out2)
        {
            std::cout << “Boolean received: ” << in1 << std::endl;
            *out1= false;
            *out2= 255;
            std::cout << “Out1: ” << *out1 << std::endl;
            std::cout << “Out2: ” << *out2 << std::endl;
        }
       
        void Send(const IPC::Message *msg)
        {
            other_->Send((IPC::Message *)msg);
        }
       
        virtual void OnChannelConnected(int32 peer_pid)
        {
            std::cout << “Listener::OnChannelConnected(): Channel Connected” << std::endl;
        }
       
        virtual void OnChannelError()
        {
            std::cout << “Listener::OnChannelConnected(): Channel Error” << std::endl;
            exit(0);
        }
       
    protected:
        IPC::Sender* other_;
};

/* Main */
void main()
{
    SimpleListener                    serverListener;
    scoped_ptr<MessageLoopForUI>      message_loop_(new MessageLoopForUI());
    scoped_ptr<base::Thread>          thread_(new base::Thread(“New_Thread”));
    scoped_ptr<base::WaitableEvent>   wEvent_(new base::WaitableEvent(false,false));
    base::Thread::Options             options;
   
    options.message_loop_type = MessageLoop::TYPE_IO;
   
    std::cout << ::GetCurrentThreadId() << “: Main Thread: Starting IO Thread ” << std::endl;
    bool thread_result = thread_->StartWithOptions(options);
    if(!thread_result){
        std::cout << “failed” << std::endl;
        return;
    }

    std::cout << ::GetCurrentThreadId() << “: Main Thread: Creating IPC channel ” << kFuzzerChannel << std::endl;
    IPC::SyncChannel syncChannel(kFuzzerChannel, IPC::Channel::MODE_SERVER, &serverListener,thread_->message_loop_proxy(), true, wEvent_.get());
    std::cout << ::GetCurrentThreadId() << “: Main Thread: Connected to IPC channel ” << kFuzzerChannel << std::endl;
   
    std::cout << “Initializing listener” << std::endl;
    serverListener.Init(&syncChannel);
   
    std::cout << “Starting the MessageLoop” << std::endl;
    MessageLoop::current()->Run();
}
 
IPCSyncClient.cc

#include <iostream>
#include <string.h>

#include “base/basictypes.h”
#include “base/compiler_specific.h”
#include “base/memory/scoped_ptr.h”
#include “base/process_util.h”
#include “base/synchronization/waitable_event.h”
#include “base/threading/platform_thread.h”
#include “base/threading/thread.h”
#include “base/time.h”
#include “ipc/ipc_message.h”
#include “ipc/ipc_message_utils.h”
#include “ipc/ipc_channel.h”
#include “base/logging.h”
#include “base/threading/platform_thread.h”
#include “base/message_loop.h”
#include <ipc/ipc_sync_channel.h>

const char kFuzzerChannel[] = “channelName”;

#define IPC_MESSAGE_IMPL
#include “ipc/ipc_message_macros.h”

#include <IPCSyncMessage.h>

/* Listener */
class SimpleListener : public IPC::Listener {
    public:
        SimpleListener() : other_(NULL) {}
   
        void Init(IPC::Sender* s)
        {
            other_ = s;
        }
       
        virtual bool OnMessageReceived(const IPC::Message& msg) {
            std::cout << “Listener::OnMessageReceived(): Message Received” << std::endl;
            return true;
        }
       
        virtual void OnChannelConnected(int32 peer_pid)
        {
            std::cout << “Listener::OnChannelConnected(): Channel Connected” << std::endl;
           
            IPC::SyncMessage* msg = NULL;
            int out2 = 0;
            bool out1;
            msg = new Msg_C_1_2(true, &out1,&out2 );
            if(! other_->Send(msg)){
                std::cout << “Error in sending Msg_C_1_2” << std::endl;
                return;
            }
            std::cout << “Sent Msg_C_1_2 and received the response also” << std::endl;
            std::cout << “out1 is: ” << out1 << ” and out2 is:” << out2 << std::endl ;
        }
       
        virtual void OnChannelError()
        {
            std::cout << “Listener::OnChannelError(): Channel Error” << std::endl;
            exit(0);
        }
   
    protected:
        IPC::Sender* other_;
};

/* Main */
void main()
{
    SimpleListener                    clientListener;
    scoped_ptr<MessageLoopForUI>      message_loop_(new MessageLoopForUI());
    scoped_ptr<base::Thread>          thread_(new base::Thread(“New_Thread”));
    scoped_ptr<base::WaitableEvent>   wEvent_(new base::WaitableEvent(false,false));
    base::Thread::Options             options;
   
    options.message_loop_type = MessageLoop::TYPE_IO;
   
    std::cout << ::GetCurrentThreadId() << “: Main Thread: Starting IO Thread ” << std::endl;
    bool thread_result = thread_->StartWithOptions(options);
    if(!thread_result){
        std::cout << “failed” << std::endl;
        return;
    }

    std::cout << ::GetCurrentThreadId() << “: Main Thread: Creating IPC channel ” << kFuzzerChannel << std::endl;
    IPC::SyncChannel syncChannel(kFuzzerChannel, IPC::Channel::MODE_CLIENT, &clientListener,thread_->message_loop_proxy(), true, wEvent_.get());
    std::cout << ::GetCurrentThreadId() << “: Main Thread: Connected to IPC channel ” << kFuzzerChannel << std::endl;
   
    std::cout << “Initializing listener” << std::endl;
    clientListener.Init(&syncChannel);
   
    std::cout << “Starting the MessageLoop” << std::endl;
    MessageLoop::current()->Run();
}

Advertisements
This entry was posted in C/C++, Chrome, Cr-48, Internals, Windows VC++ and tagged , , , , , , . Bookmark the permalink.

2 Responses to Chrome IPC Internals – Part V

  1. dzmitrylahoda says:

    Hi,
    How do you think of possibility to reuse this IPC in pure C or Python? How IPC code is interlinked with Chromium or it can be separated as reusable library?

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s