1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
5  * You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 // Original author: ekr@rtfm.com
8 
9 #ifndef transportlayer_h__
10 #define transportlayer_h__
11 
12 #include "sigslot.h"
13 
14 #include "mozilla/DebugOnly.h"
15 #include "mozilla/RefPtr.h"
16 #include "nsCOMPtr.h"
17 #include "nsIEventTarget.h"
18 
19 #include "m_cpp_utils.h"
20 
21 namespace mozilla {
22 
23 class TransportFlow;
24 
25 typedef int TransportResult;
26 
27 enum { TE_WOULDBLOCK = -1, TE_ERROR = -2, TE_INTERNAL = -3 };
28 
29 #define TRANSPORT_LAYER_ID(name)                         \
30   const std::string id() const override { return name; } \
31   static std::string ID() { return name; }
32 
33 // Abstract base class for network transport layers.
34 class TransportLayer : public sigslot::has_slots<> {
35  public:
36   // The state of the transport flow
37   // We can't use "ERROR" because Windows has a macro named "ERROR"
38   enum State { TS_NONE, TS_INIT, TS_CONNECTING, TS_OPEN, TS_CLOSED, TS_ERROR };
39 
40   // Is this a stream or datagram flow
TransportLayer()41   TransportLayer() : state_(TS_NONE), flow_id_(), downward_(nullptr) {}
42 
~TransportLayer()43   virtual ~TransportLayer() {}
44 
45   // Called to initialize
46   nsresult Init();  // Called by Insert() to set up -- do not override
InitInternal()47   virtual nsresult InitInternal() { return NS_OK; }  // Called by Init
48 
49   // Called when inserted into a flow
50   virtual void Inserted(TransportFlow *flow, TransportLayer *downward);
51 
52   // Downward interface
downward()53   TransportLayer *downward() { return downward_; }
54 
55   // Get the state
state()56   State state() const { return state_; }
57   // Must be implemented by derived classes
58   virtual TransportResult SendPacket(const unsigned char *data, size_t len) = 0;
59 
60   // Get the thread.
GetThread()61   const nsCOMPtr<nsIEventTarget> GetThread() const { return target_; }
62 
63   // Event definitions that one can register for
64   // State has changed
65   sigslot::signal2<TransportLayer *, State> SignalStateChange;
66   // Data received on the flow
67   sigslot::signal3<TransportLayer *, const unsigned char *, size_t>
68       SignalPacketReceived;
69 
70   // Return the layer id for this layer
71   virtual const std::string id() const = 0;
72 
73   // The id of the flow
flow_id()74   const std::string &flow_id() const { return flow_id_; }
75 
76  protected:
WasInserted()77   virtual void WasInserted() {}
78   virtual void SetState(State state, const char *file, unsigned line);
79   // Check if we are on the right thread
CheckThread()80   void CheckThread() const { MOZ_ASSERT(CheckThreadInt(), "Wrong thread"); }
81 
82   State state_;
83   std::string flow_id_;
84   TransportLayer *downward_;  // The next layer in the stack
85   nsCOMPtr<nsIEventTarget> target_;
86 
87  private:
88   DISALLOW_COPY_ASSIGN(TransportLayer);
89 
CheckThreadInt()90   bool CheckThreadInt() const {
91     bool on;
92 
93     if (!target_)  // OK if no thread set.
94       return true;
95 
96     NS_ENSURE_SUCCESS(target_->IsOnCurrentThread(&on), false);
97     NS_ENSURE_TRUE(on, false);
98 
99     return true;
100   }
101 };
102 
103 #define LAYER_INFO                 \
104   "Flow[" << flow_id() << "(none)" \
105           << "]; Layer[" << id() << "]: "
106 #define TL_SET_STATE(x) SetState((x), __FILE__, __LINE__)
107 
108 }  // namespace mozilla
109 #endif
110