190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// found in the LICENSE file.
490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "remoting/host/chromoting_param_traits.h"
690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
75e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/stringprintf.h"
86e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "third_party/webrtc/modules/desktop_capture/desktop_frame.h"
990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace IPC {
1190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// static
1390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void ParamTraits<webrtc::DesktopVector>::Write(Message* m,
1490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                               const webrtc::DesktopVector& p) {
1590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  m->WriteInt(p.x());
1690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  m->WriteInt(p.y());
1790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
1890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// static
2090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)bool ParamTraits<webrtc::DesktopVector>::Read(const Message* m,
2190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                              PickleIterator* iter,
2290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                              webrtc::DesktopVector* r) {
2390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int x, y;
2490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!m->ReadInt(iter, &x) || !m->ReadInt(iter, &y))
2590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return false;
2690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  *r = webrtc::DesktopVector(x, y);
2790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return true;
2890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
2990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
3090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// static
3190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void ParamTraits<webrtc::DesktopVector>::Log(const webrtc::DesktopVector& p,
3290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                             std::string* l) {
3390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  l->append(base::StringPrintf("webrtc::DesktopVector(%d, %d)",
3490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                               p.x(), p.y()));
3590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
3690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
3790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// static
3890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void ParamTraits<webrtc::DesktopSize>::Write(Message* m,
3990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                             const webrtc::DesktopSize& p) {
4090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  m->WriteInt(p.width());
4190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  m->WriteInt(p.height());
4290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
4390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// static
4590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)bool ParamTraits<webrtc::DesktopSize>::Read(const Message* m,
4690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                            PickleIterator* iter,
4790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                            webrtc::DesktopSize* r) {
4890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int width, height;
4990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!m->ReadInt(iter, &width) || !m->ReadInt(iter, &height))
5090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return false;
5190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  *r = webrtc::DesktopSize(width, height);
5290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return true;
5390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
5490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
5590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// static
5690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void ParamTraits<webrtc::DesktopSize>::Log(const webrtc::DesktopSize& p,
5790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                           std::string* l) {
5890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  l->append(base::StringPrintf("webrtc::DesktopSize(%d, %d)",
5990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                               p.width(), p.height()));
6090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
6190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
6290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// static
6390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void ParamTraits<webrtc::DesktopRect>::Write(Message* m,
6490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                             const webrtc::DesktopRect& p) {
6590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  m->WriteInt(p.left());
6690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  m->WriteInt(p.top());
6790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  m->WriteInt(p.right());
6890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  m->WriteInt(p.bottom());
6990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
7090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
7190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// static
7290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)bool ParamTraits<webrtc::DesktopRect>::Read(const Message* m,
7390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                            PickleIterator* iter,
7490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                            webrtc::DesktopRect* r) {
7590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int left, right, top, bottom;
7690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!m->ReadInt(iter, &left) || !m->ReadInt(iter, &top) ||
7790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      !m->ReadInt(iter, &right) || !m->ReadInt(iter, &bottom)) {
7890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return false;
7990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
8090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  *r = webrtc::DesktopRect::MakeLTRB(left, top, right, bottom);
8190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return true;
8290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
8390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
8490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// static
8590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void ParamTraits<webrtc::DesktopRect>::Log(const webrtc::DesktopRect& p,
8690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                           std::string* l) {
8790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  l->append(base::StringPrintf("webrtc::DesktopRect(%d, %d, %d, %d)",
8890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                               p.left(), p.top(), p.right(), p.bottom()));
8990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
9090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
9190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// static
926e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void ParamTraits<webrtc::MouseCursor>::Write(
936e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    Message* m,
946e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    const webrtc::MouseCursor& p) {
956e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  ParamTraits<webrtc::DesktopSize>::Write(m, p.image()->size());
966e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
976e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // Data is serialized in such a way that size is exactly width * height *
986e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // |kBytesPerPixel|.
996e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  std::string data;
1006e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  uint8_t* current_row = p.image()->data();
1016e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  for (int y = 0; y < p.image()->size().height(); ++y) {
1026e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    data.append(current_row,
1036e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                current_row + p.image()->size().width() *
1046e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                    webrtc::DesktopFrame::kBytesPerPixel);
1056e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    current_row += p.image()->stride();
1066e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
1076e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  m->WriteData(reinterpret_cast<const char*>(p.image()->data()), data.size());
1086e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1096e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  ParamTraits<webrtc::DesktopVector>::Write(m, p.hotspot());
1106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
1116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// static
1136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)bool ParamTraits<webrtc::MouseCursor>::Read(
1146e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    const Message* m,
1156e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    PickleIterator* iter,
1166e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    webrtc::MouseCursor* r) {
1176e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  webrtc::DesktopSize size;
1186e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  if (!ParamTraits<webrtc::DesktopSize>::Read(m, iter, &size) ||
1196e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      size.width() <= 0 || size.width() > (SHRT_MAX / 2) ||
1206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      size.height() <= 0 || size.height() > (SHRT_MAX / 2)) {
1216e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    return false;
1226e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
1236e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1246e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  const int expected_length =
1256e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      size.width() * size.height() * webrtc::DesktopFrame::kBytesPerPixel;
1266e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1276e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  const char* data;
1286e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  int data_length;
1296e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  if (!m->ReadData(iter, &data, &data_length) ||
1306e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      data_length != expected_length) {
1316e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    return false;
1326e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
1336e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1346e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  webrtc::DesktopVector hotspot;
1356e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  if (!ParamTraits<webrtc::DesktopVector>::Read(m, iter, &hotspot))
1366e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    return false;
1376e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1386e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  webrtc::BasicDesktopFrame* image = new webrtc::BasicDesktopFrame(size);
1396e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  memcpy(image->data(), data, data_length);
1406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  r->set_image(image);
1426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  r->set_hotspot(hotspot);
1436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  return true;
1446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
1456e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1466e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// static
1476e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void ParamTraits<webrtc::MouseCursor>::Log(
1486e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    const webrtc::MouseCursor& p,
1496e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    std::string* l) {
1506e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  l->append(base::StringPrintf(
1516e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      "webrtc::DesktopRect{image(%d, %d), hotspot(%d, %d)}",
1526e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      p.image()->size().width(), p.image()->size().height(),
1536e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      p.hotspot().x(), p.hotspot().y()));
1546e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
1556e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1566e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1576e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// static
15890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void ParamTraits<remoting::ScreenResolution>::Write(
15990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    Message* m,
16090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const remoting::ScreenResolution& p) {
16190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ParamTraits<webrtc::DesktopSize>::Write(m, p.dimensions());
16290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ParamTraits<webrtc::DesktopVector>::Write(m, p.dpi());
16390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
16490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
16590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// static
16690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)bool ParamTraits<remoting::ScreenResolution>::Read(
16790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const Message* m,
16890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    PickleIterator* iter,
16990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    remoting::ScreenResolution* r) {
17090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  webrtc::DesktopSize size;
17190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  webrtc::DesktopVector dpi;
17290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!ParamTraits<webrtc::DesktopSize>::Read(m, iter, &size) ||
17390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      !ParamTraits<webrtc::DesktopVector>::Read(m, iter, &dpi)) {
17490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return false;
17590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
17690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (size.width() < 0 || size.height() < 0 ||
17790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      dpi.x() < 0 || dpi.y() < 0) {
17890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return false;
17990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
18090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  *r = remoting::ScreenResolution(size, dpi);
18190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return true;
18290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
18390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
18490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// static
18590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void ParamTraits<remoting::ScreenResolution>::Log(
18690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const remoting::ScreenResolution& p,
18790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    std::string* l) {
18890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  l->append(base::StringPrintf("webrtc::ScreenResolution(%d, %d, %d, %d)",
18990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                               p.dimensions().width(), p.dimensions().height(),
19090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                               p.dpi().x(), p.dpi().y()));
19190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
19290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
19390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}  // namespace IPC
19490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
195