Chrome IPC Internals – Part IV

In this part, we will see how to use IPC::ChannelProxy for sending and receiving messages using chrome IPC mechanism.

From the source code (\ipc\ipc_channel_proxy.h)
// IPC::ChannelProxy
// This class is a helper class that is useful when you wish to run an IPC
// channel on a background thread.  It provides you with the option of either
// handling IPC messages on that background thread or having them dispatched to
// your main thread (the thread on which the IPC::ChannelProxy is created).

In the Main thread, we create an additional thread for handling IPC parsing. IPC::ChannelProxy handles the communication between the Main thread and the IPC thread. Main thread can continue to do its other work. The interfaces of both IPC::ChannelProxy and IPC::Channel are almost same.

IPCMessageChannelProxy.h

#pragma once

#define IPC_MESSAGE_START TestMsgStart

// Generic message class that is an int followed by a wstring.
IPC_MESSAGE_CONTROL2(MsgClassIS, int, std::wstring)

// Generic message class that is a wstring followed by an int.
IPC_MESSAGE_CONTROL2(MsgClassSI, std::wstring, int)

// Used to generate an ID for a message that should not exist.
IPC_MESSAGE_CONTROL0(MsgUnhandled)

IPCServerChannelProxy.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/message_loop_proxy_impl.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 <IPCMessage.h>
#define hello
#include <IPCMessageChannelProxy.h>

/* Listener */
class MyChannelListener : public IPC::Listener {
public:
  virtual bool OnMessageReceived(const IPC::Message& message) {
    IPC_BEGIN_MESSAGE_MAP(MyChannelListener, message)
        IPC_MESSAGE_HANDLER(MsgClassIS, classIS)
        IPC_MESSAGE_HANDLER(MsgClassSI, classSI)
    IPC_END_MESSAGE_MAP()
    return true;
  }

  virtual void OnChannelError() {
    // There is a race when closing the channel so the last message may be lost.
    MessageLoop::current()->Quit();
  }
 
  void classIS(int myint, std::wstring mystring) {
    std::cout << “classIS(): Received==> Int:” << myint << ” String:” << mystring << std::endl;
  }
       
  void classSI(std::wstring mystring,int myint) {
    std::cout << “classSI(): Received==> String:” << mystring << ” Int:” << myint << std::endl;
  }

  void Init(IPC::Sender* s) {
    sender_ = s;
  }

private:
  IPC::Sender* sender_;
};

/* Main */
void main()
{
    MyChannelListener                 serverListener;
    scoped_ptr<MessageLoopForUI>      message_loop_(new MessageLoopForUI());
    scoped_ptr<base::Thread>          thread_(new base::Thread(“New_Thread”));
    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::ChannelProxy clientChannel(kFuzzerChannel, IPC::Channel::MODE_SERVER, &serverListener,thread_->message_loop_proxy());   
    std::cout << ::GetCurrentThreadId() << “: Main Thread: Connected to IPC channel ” << kFuzzerChannel << std::endl;
   
    std::cout << “Initializing listener” << std::endl;
    serverListener.Init(&clientChannel);
   
    std::cout << “Starting the MessageLoop” << std::endl;
    MessageLoop::current()->Run();
}

IPCClientChannelProxy.cc

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

#include “base/basictypes.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”

const char kFuzzerChannel[] = “channelName”;

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

#include <IPCMessageChannelProxy.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;
            return true;
        }
       
        virtual void OnChannelConnected(int32 peer_pid)
        {
            std::cout << “Listener::OnChannelConnected(): Channel Connected” << std::endl;
           
            IPC::Message* msg = NULL;
            int value = 43;
            msg = new MsgClassIS(value, L”expect 43″);
            if(! other_->Send(msg)){
                std::cout << “Error in sending MsgClassIS” << std::endl;
                return;
            }
            std::cout << “Sent MsgClassIS” << std::endl;
           
            msg = new MsgClassSI(L”expect 44″, ++value);
            if(! other_->Send(msg)){
                std::cout << “Error in sending MsgClassSI” << std::endl;
                return;
            }
            std::cout << “Sent MsgClassSI” << std::endl;
        }
       
        virtual void OnChannelError()
        {
            std::cout << “Listener::OnChannelConnected(): Channel Error” << std::endl;
            exit(0);
        }
       
    protected:
        IPC::Sender* other_;
};

/* Main */
void main()
{
    SimpleListener serverListener;
    MessageLoopForIO main_message_loop;
   
    std::cout << “Server: Creating IPC channel ” << kFuzzerChannel << std::endl;
    IPC::Channel serverChannel(kFuzzerChannel, IPC::Channel::MODE_CLIENT, &serverListener);

    std::cout << “Server: Connecting to IPC channel ” << kFuzzerChannel << std::endl;
    if(! serverChannel.Connect()){
        std::cout << “Server: Error in connecting to the channel ” << kFuzzerChannel << std::endl;
        return;
    }
    std::cout << “Server: Connected to IPC channel ” << kFuzzerChannel << std::endl;
   
    std::cout << “Initializing listener” << std::endl;
    serverListener.Init(&serverChannel);

    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.

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