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