1// Copyright 2015 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
5#ifndef MOJO_EDK_SYSTEM_MESSAGE_PIPE_DISPATCHER_H_
6#define MOJO_EDK_SYSTEM_MESSAGE_PIPE_DISPATCHER_H_
7
8#include <stdint.h>
9
10#include <memory>
11#include <queue>
12
13#include "base/macros.h"
14#include "mojo/edk/system/atomic_flag.h"
15#include "mojo/edk/system/awakable_list.h"
16#include "mojo/edk/system/dispatcher.h"
17#include "mojo/edk/system/message_for_transit.h"
18#include "mojo/edk/system/ports/port_ref.h"
19
20namespace mojo {
21namespace edk {
22
23class NodeController;
24class PortsMessage;
25
26class MessagePipeDispatcher : public Dispatcher {
27 public:
28  // Constructs a MessagePipeDispatcher permanently tied to a specific port.
29  // |connected| must indicate the state of the port at construction time; if
30  // the port is initialized with a peer, |connected| must be true. Otherwise it
31  // must be false.
32  //
33  // A MessagePipeDispatcher may not be transferred while in a disconnected
34  // state, and one can never return to a disconnected once connected.
35  //
36  // |pipe_id| is a unique identifier which can be used to track pipe endpoints
37  // as they're passed around. |endpoint| is either 0 or 1 and again is only
38  // used for tracking pipes (one side is always 0, the other is always 1.)
39  MessagePipeDispatcher(NodeController* node_controller,
40                        const ports::PortRef& port,
41                        uint64_t pipe_id,
42                        int endpoint);
43
44  // Fuses this pipe with |other|. Returns |true| on success or |false| on
45  // failure. Regardless of the return value, both dispatchers are closed by
46  // this call.
47  bool Fuse(MessagePipeDispatcher* other);
48
49  // Dispatcher:
50  Type GetType() const override;
51  MojoResult Close() override;
52  MojoResult Watch(MojoHandleSignals signals,
53                   const Watcher::WatchCallback& callback,
54                   uintptr_t context) override;
55  MojoResult CancelWatch(uintptr_t context) override;
56  MojoResult WriteMessage(std::unique_ptr<MessageForTransit> message,
57                          MojoWriteMessageFlags flags) override;
58  MojoResult ReadMessage(std::unique_ptr<MessageForTransit>* message,
59                         uint32_t* num_bytes,
60                         MojoHandle* handles,
61                         uint32_t* num_handles,
62                         MojoReadMessageFlags flags,
63                         bool read_any_size) override;
64  HandleSignalsState GetHandleSignalsState() const override;
65  MojoResult AddAwakable(Awakable* awakable,
66                         MojoHandleSignals signals,
67                         uintptr_t context,
68                         HandleSignalsState* signals_state) override;
69  void RemoveAwakable(Awakable* awakable,
70                      HandleSignalsState* signals_state) override;
71  void StartSerialize(uint32_t* num_bytes,
72                      uint32_t* num_ports,
73                      uint32_t* num_handles) override;
74  bool EndSerialize(void* destination,
75                    ports::PortName* ports,
76                    PlatformHandle* handles) override;
77  bool BeginTransit() override;
78  void CompleteTransitAndClose() override;
79  void CancelTransit() override;
80
81  static scoped_refptr<Dispatcher> Deserialize(
82      const void* data,
83      size_t num_bytes,
84      const ports::PortName* ports,
85      size_t num_ports,
86      PlatformHandle* handles,
87      size_t num_handles);
88
89 private:
90  class PortObserverThunk;
91  friend class PortObserverThunk;
92
93  ~MessagePipeDispatcher() override;
94
95  MojoResult CloseNoLock();
96  HandleSignalsState GetHandleSignalsStateNoLock() const;
97  void OnPortStatusChanged();
98
99  // These are safe to access from any thread without locking.
100  NodeController* const node_controller_;
101  const ports::PortRef port_;
102  const uint64_t pipe_id_;
103  const int endpoint_;
104
105  // Guards access to all the fields below.
106  mutable base::Lock signal_lock_;
107
108  // This is not the same is |port_transferred_|. It's only held true between
109  // BeginTransit() and Complete/CancelTransit().
110  AtomicFlag in_transit_;
111
112  bool port_transferred_ = false;
113  AtomicFlag port_closed_;
114  AwakableList awakables_;
115
116  DISALLOW_COPY_AND_ASSIGN(MessagePipeDispatcher);
117};
118
119}  // namespace edk
120}  // namespace mojo
121
122#endif  // MOJO_EDK_SYSTEM_MESSAGE_PIPE_DISPATCHER_H_
123