ipc_sync_message.cc 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. // Copyright (c) 2012 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "ipc/ipc_sync_message.h"
  5. #include <stdint.h>
  6. #include "base/atomic_sequence_num.h"
  7. #include "base/check.h"
  8. #include "base/notreached.h"
  9. #include "build/build_config.h"
  10. namespace {
  11. base::AtomicSequenceNumber g_next_id;
  12. } // namespace
  13. namespace IPC {
  14. #define kSyncMessageHeaderSize 4
  15. SyncMessage::SyncMessage(int32_t routing_id,
  16. uint32_t type,
  17. PriorityValue priority,
  18. MessageReplyDeserializer* deserializer)
  19. : Message(routing_id, type, priority),
  20. deserializer_(deserializer) {
  21. set_sync();
  22. set_unblock(true);
  23. // Add synchronous message data before the message payload.
  24. SyncHeader header;
  25. header.message_id = g_next_id.GetNext();
  26. WriteSyncHeader(this, header);
  27. }
  28. SyncMessage::~SyncMessage() = default;
  29. MessageReplyDeserializer* SyncMessage::GetReplyDeserializer() {
  30. DCHECK(deserializer_.get());
  31. return deserializer_.release();
  32. }
  33. bool SyncMessage::IsMessageReplyTo(const Message& msg, int request_id) {
  34. if (!msg.is_reply())
  35. return false;
  36. return GetMessageId(msg) == request_id;
  37. }
  38. base::PickleIterator SyncMessage::GetDataIterator(const Message* msg) {
  39. base::PickleIterator iter(*msg);
  40. if (!iter.SkipBytes(kSyncMessageHeaderSize))
  41. return base::PickleIterator();
  42. else
  43. return iter;
  44. }
  45. int SyncMessage::GetMessageId(const Message& msg) {
  46. if (!msg.is_sync() && !msg.is_reply())
  47. return 0;
  48. SyncHeader header;
  49. if (!ReadSyncHeader(msg, &header))
  50. return 0;
  51. return header.message_id;
  52. }
  53. Message* SyncMessage::GenerateReply(const Message* msg) {
  54. DCHECK(msg->is_sync());
  55. Message* reply = new Message(msg->routing_id(), IPC_REPLY_ID,
  56. msg->priority());
  57. reply->set_reply();
  58. SyncHeader header;
  59. // use the same message id, but this time reply bit is set
  60. header.message_id = GetMessageId(*msg);
  61. WriteSyncHeader(reply, header);
  62. return reply;
  63. }
  64. bool SyncMessage::ReadSyncHeader(const Message& msg, SyncHeader* header) {
  65. DCHECK(msg.is_sync() || msg.is_reply());
  66. base::PickleIterator iter(msg);
  67. bool result = iter.ReadInt(&header->message_id);
  68. if (!result) {
  69. NOTREACHED();
  70. return false;
  71. }
  72. return true;
  73. }
  74. bool SyncMessage::WriteSyncHeader(Message* msg, const SyncHeader& header) {
  75. DCHECK(msg->is_sync() || msg->is_reply());
  76. DCHECK(msg->payload_size() == 0);
  77. msg->WriteInt(header.message_id);
  78. // Note: if you add anything here, you need to update kSyncMessageHeaderSize.
  79. DCHECK(kSyncMessageHeaderSize == msg->payload_size());
  80. return true;
  81. }
  82. bool MessageReplyDeserializer::SerializeOutputParameters(const Message& msg) {
  83. return SerializeOutputParameters(msg, SyncMessage::GetDataIterator(&msg));
  84. }
  85. } // namespace IPC