1645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// Copyright 2015 The Chromium Authors. All rights reserved.
2645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// Use of this source code is governed by a BSD-style license that can be
3645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// found in the LICENSE file.
4645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
5645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#ifndef MOJO_EDK_SYSTEM_MESSAGE_PIPE_DISPATCHER_H_
6645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#define MOJO_EDK_SYSTEM_MESSAGE_PIPE_DISPATCHER_H_
7645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
8645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include <stdint.h>
9645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
10645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include <memory>
11645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include <queue>
12645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
13645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "base/macros.h"
14645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "mojo/edk/system/atomic_flag.h"
15645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "mojo/edk/system/awakable_list.h"
16645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "mojo/edk/system/dispatcher.h"
17645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "mojo/edk/system/message_for_transit.h"
18645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "mojo/edk/system/ports/port_ref.h"
19645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
20645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chaveznamespace mojo {
21645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chaveznamespace edk {
22645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
23645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezclass NodeController;
24645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezclass PortsMessage;
25645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
26645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezclass MessagePipeDispatcher : public Dispatcher {
27645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public:
28645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  // Constructs a MessagePipeDispatcher permanently tied to a specific port.
29645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  // |connected| must indicate the state of the port at construction time; if
30645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  // the port is initialized with a peer, |connected| must be true. Otherwise it
31645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  // must be false.
32645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  //
33645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  // A MessagePipeDispatcher may not be transferred while in a disconnected
34645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  // state, and one can never return to a disconnected once connected.
35645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  //
36645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  // |pipe_id| is a unique identifier which can be used to track pipe endpoints
37645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  // as they're passed around. |endpoint| is either 0 or 1 and again is only
38645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  // used for tracking pipes (one side is always 0, the other is always 1.)
39645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  MessagePipeDispatcher(NodeController* node_controller,
40645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez                        const ports::PortRef& port,
41645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez                        uint64_t pipe_id,
42645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez                        int endpoint);
43645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
44645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  // Fuses this pipe with |other|. Returns |true| on success or |false| on
45645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  // failure. Regardless of the return value, both dispatchers are closed by
46645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  // this call.
47645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  bool Fuse(MessagePipeDispatcher* other);
48645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
49645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  // Dispatcher:
50645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  Type GetType() const override;
51645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  MojoResult Close() override;
52645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  MojoResult Watch(MojoHandleSignals signals,
53645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez                   const Watcher::WatchCallback& callback,
54645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez                   uintptr_t context) override;
55645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  MojoResult CancelWatch(uintptr_t context) override;
56645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  MojoResult WriteMessage(std::unique_ptr<MessageForTransit> message,
57645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez                          MojoWriteMessageFlags flags) override;
58645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  MojoResult ReadMessage(std::unique_ptr<MessageForTransit>* message,
59645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez                         uint32_t* num_bytes,
60645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez                         MojoHandle* handles,
61645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez                         uint32_t* num_handles,
62645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez                         MojoReadMessageFlags flags,
63645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez                         bool read_any_size) override;
64645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  HandleSignalsState GetHandleSignalsState() const override;
65645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  MojoResult AddAwakable(Awakable* awakable,
66645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez                         MojoHandleSignals signals,
67645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez                         uintptr_t context,
68645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez                         HandleSignalsState* signals_state) override;
69645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  void RemoveAwakable(Awakable* awakable,
70645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez                      HandleSignalsState* signals_state) override;
71645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  void StartSerialize(uint32_t* num_bytes,
72645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez                      uint32_t* num_ports,
73645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez                      uint32_t* num_handles) override;
74645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  bool EndSerialize(void* destination,
75645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez                    ports::PortName* ports,
76645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez                    PlatformHandle* handles) override;
77645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  bool BeginTransit() override;
78645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  void CompleteTransitAndClose() override;
79645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  void CancelTransit() override;
80645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
81645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  static scoped_refptr<Dispatcher> Deserialize(
82645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      const void* data,
83645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      size_t num_bytes,
84645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      const ports::PortName* ports,
85645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      size_t num_ports,
86645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      PlatformHandle* handles,
87645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      size_t num_handles);
88645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
89645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez private:
90645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  class PortObserverThunk;
91645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  friend class PortObserverThunk;
92645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
93645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  ~MessagePipeDispatcher() override;
94645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
95645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  MojoResult CloseNoLock();
96645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  HandleSignalsState GetHandleSignalsStateNoLock() const;
97645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  void OnPortStatusChanged();
98645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
99645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  // These are safe to access from any thread without locking.
100645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  NodeController* const node_controller_;
101645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  const ports::PortRef port_;
102645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  const uint64_t pipe_id_;
103645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  const int endpoint_;
104645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
105645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  // Guards access to all the fields below.
106645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  mutable base::Lock signal_lock_;
107645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
108645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  // This is not the same is |port_transferred_|. It's only held true between
109645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  // BeginTransit() and Complete/CancelTransit().
110645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  AtomicFlag in_transit_;
111645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
112645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  bool port_transferred_ = false;
113645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  AtomicFlag port_closed_;
114645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  AwakableList awakables_;
115645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
116645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  DISALLOW_COPY_AND_ASSIGN(MessagePipeDispatcher);
117645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez};
118645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
119645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez}  // namespace edk
120645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez}  // namespace mojo
121645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
122645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#endif  // MOJO_EDK_SYSTEM_MESSAGE_PIPE_DISPATCHER_H_
123