Line data Source code
1 : /*
2 : * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3 : * Copyright Contributors to the OpenSDN project
4 : */
5 :
6 : //
7 : // sandesh_connection.cc
8 : //
9 : // Sandesh connection management implementation
10 : //
11 :
12 : #include <io/tcp_session.h>
13 : #include <io/tcp_server.h>
14 : #include <base/logging.h>
15 : #include <sandesh/protocol/TXMLProtocol.h>
16 :
17 : #include <sandesh/sandesh_types.h>
18 : #include <sandesh/sandesh.h>
19 : #include <sandesh/sandesh_ctrl_types.h>
20 : #include <sandesh/common/vns_types.h>
21 : #include <sandesh/common/vns_constants.h>
22 : #include "sandesh_uve.h"
23 : #include "sandesh_session.h"
24 : #include "sandesh_client.h"
25 : #include "sandesh_server.h"
26 : #include "sandesh_connection.h"
27 :
28 : using namespace std;
29 : using boost::system::error_code;
30 :
31 : #define CONNECTION_LOG(_Level, _Msg) \
32 : do { \
33 : if (LoggingDisabled()) break; \
34 : log4cplus::Logger _Xlogger = Sandesh::logger(); \
35 : if (_Xlogger.isEnabledFor(log4cplus::_Level##_LOG_LEVEL)) { \
36 : log4cplus::tostringstream _Xbuf; \
37 : if (!state_machine()->generator_key().empty()) { \
38 : _Xbuf << state_machine()->generator_key() << " (" << \
39 : GetTaskInstance() << ") "; \
40 : } \
41 : if (session()) { \
42 : _Xbuf << session()->ToString() << " "; \
43 : } \
44 : _Xbuf << _Msg; \
45 : _Xlogger.forcedLog(log4cplus::_Level##_LOG_LEVEL, \
46 : _Xbuf.str()); \
47 : } \
48 : } while (false)
49 :
50 37 : SandeshConnection::SandeshConnection(const char *prefix, TcpServer *server,
51 37 : Endpoint endpoint, int task_instance, int task_id)
52 37 : : is_deleted_(false),
53 37 : server_(server),
54 37 : endpoint_(endpoint),
55 37 : admin_down_(false),
56 37 : session_(NULL),
57 37 : task_instance_(task_instance),
58 37 : task_id_(task_id),
59 37 : state_machine_(new SandeshStateMachine(prefix, this)) {
60 37 : }
61 :
62 37 : SandeshConnection::~SandeshConnection() {
63 37 : }
64 :
65 74 : void SandeshConnection::set_session(SandeshSession *session) {
66 74 : session_ = session;
67 74 : }
68 :
69 12486 : SandeshSession *SandeshConnection::session() const {
70 12486 : return session_;
71 : }
72 :
73 12449 : bool SandeshConnection::ReceiveMsg(const std::string &msg, SandeshSession *session) {
74 12449 : return state_machine_->OnSandeshMessage(session, msg);
75 : }
76 :
77 37 : bool SandeshConnection::SendSandesh(Sandesh *snh) {
78 37 : if (!session_) {
79 0 : snh->Release();
80 0 : return false;
81 : }
82 37 : ssm::SsmState state = state_machine_->get_state();
83 37 : if (state != ssm::SERVER_INIT && state != ssm::ESTABLISHED) {
84 0 : snh->Release();
85 0 : return false;
86 : }
87 : // XXX No bounded work queue
88 37 : SandeshElement element(snh);
89 37 : session_->send_queue()->Enqueue(element);
90 37 : return true;
91 : }
92 :
93 37 : void SandeshConnection::AcceptSession(SandeshSession *session) {
94 37 : session->SetReceiveMsgCb(boost::bind(&SandeshConnection::ReceiveMsg, this, _1, _2));
95 37 : session->SetConnection(this);
96 37 : state_machine_->PassiveOpen(session);
97 37 : }
98 :
99 148 : SandeshStateMachine *SandeshConnection::state_machine() const {
100 148 : return state_machine_.get();
101 : }
102 :
103 0 : void SandeshConnection::SetAdminState(bool down) {
104 0 : if (admin_down_ != down) {
105 0 : admin_down_ = down;
106 0 : state_machine_->SetAdminState(down);
107 : }
108 0 : }
109 :
110 0 : void SandeshConnection::Shutdown() {
111 0 : is_deleted_ = true;
112 0 : deleter()->Delete();
113 0 : }
114 :
115 37 : bool SandeshConnection::MayDelete() const {
116 : // XXX Do we have any dependencies?
117 37 : return true;
118 : }
119 :
120 : class SandeshServerConnection::DeleteActor : public LifetimeActor {
121 : public:
122 37 : DeleteActor(SandeshServer *server, SandeshServerConnection *parent)
123 37 : : LifetimeActor(server->lifetime_manager()),
124 37 : server_(server), parent_(parent) {
125 37 : }
126 37 : virtual bool MayDelete() const {
127 37 : return parent_->MayDelete();
128 : }
129 37 : virtual void Shutdown() {
130 37 : SandeshSession *session = NULL;
131 37 : if (parent_->state_machine()) {
132 37 : session = parent_->state_machine()->session();
133 37 : parent_->state_machine()->clear_session();
134 : }
135 37 : if (session) {
136 0 : server_->DeleteSession(session);
137 : }
138 37 : parent_->is_deleted_ = true;
139 37 : }
140 37 : virtual void Destroy() {
141 37 : parent_->Destroy();
142 37 : }
143 :
144 : private:
145 : SandeshServer *server_;
146 : SandeshServerConnection *parent_;
147 : };
148 :
149 37 : SandeshServerConnection::SandeshServerConnection(
150 37 : TcpServer *server, Endpoint endpoint, int task_instance, int task_id)
151 : : SandeshConnection("SandeshServer: ", server, endpoint, task_instance, task_id),
152 37 : deleter_(new DeleteActor(dynamic_cast<SandeshServer *>(server), this)),
153 74 : server_delete_ref_(this, dynamic_cast<SandeshServer *>(server)->deleter()) {
154 37 : }
155 :
156 74 : SandeshServerConnection::~SandeshServerConnection() {
157 74 : }
158 :
159 37 : void SandeshServerConnection::ManagedDelete() {
160 37 : deleter_->Delete();
161 37 : }
162 :
163 37 : bool SandeshServerConnection::ProcessSandeshCtrlMessage(const std::string &msg,
164 : const SandeshHeader &header, const std::string sandesh_name,
165 : const uint32_t header_offset) {
166 37 : SandeshServer *sserver = dynamic_cast<SandeshServer *>(server());
167 37 : if (!sserver) {
168 0 : CONNECTION_LOG(ERROR, __func__ << " No Server");
169 0 : return false;
170 : }
171 37 : Sandesh *ctrl_snh = SandeshSession::DecodeCtrlSandesh(msg, header, sandesh_name,
172 : header_offset);
173 37 : bool ret = sserver->ReceiveSandeshCtrlMsg(state_machine(), session(), ctrl_snh);
174 37 : ctrl_snh->Release();
175 37 : return ret;
176 : }
177 :
178 0 : bool SandeshServerConnection::ProcessResourceUpdate(bool rsc) {
179 0 : SandeshServer *sserver = dynamic_cast<SandeshServer *>(server());
180 0 : if (!sserver) {
181 0 : CONNECTION_LOG(ERROR, __func__ << " No Server");
182 0 : return false;
183 : }
184 0 : return sserver->ReceiveResourceUpdate(session(), rsc);
185 : }
186 :
187 12412 : bool SandeshServerConnection::ProcessSandeshMessage(
188 : const SandeshMessage *msg, bool resource) {
189 12412 : SandeshServer *sserver = dynamic_cast<SandeshServer *>(server());
190 12412 : if (!sserver) {
191 0 : CONNECTION_LOG(ERROR, __func__ << " No Server");
192 0 : return false;
193 : }
194 12412 : sserver->ReceiveSandeshMsg(session(), msg, resource);
195 12412 : return true;
196 : }
197 :
198 37 : void SandeshServerConnection::ProcessDisconnect(SandeshSession * sess) {
199 37 : SandeshServer *sserver = dynamic_cast<SandeshServer *>(server());
200 37 : if (!sserver) {
201 0 : CONNECTION_LOG(ERROR, __func__ << " No Server");
202 0 : return;
203 : }
204 37 : sserver->DisconnectSession(sess);
205 : }
206 :
207 0 : LifetimeManager *SandeshServerConnection::lifetime_manager() {
208 0 : SandeshServer *sserver = dynamic_cast<SandeshServer *>(server());
209 0 : if (!sserver) {
210 0 : CONNECTION_LOG(ERROR, __func__ << " No Server");
211 0 : return NULL;
212 : }
213 0 : return sserver->lifetime_manager();
214 : }
215 :
216 37 : void SandeshServerConnection::Destroy() {
217 37 : SandeshServer *sserver = dynamic_cast<SandeshServer *>(server());
218 37 : if (!sserver) {
219 0 : CONNECTION_LOG(ERROR, __func__ << " No Server");
220 0 : return;
221 : }
222 37 : int index = GetTaskInstance();
223 37 : if (index != -1) {
224 37 : sserver->FreeConnectionIndex(index);
225 : }
226 : // Deletes self - should always be the last
227 37 : sserver->RemoveConnection(this);
228 : };
229 :
230 0 : LifetimeActor *SandeshServerConnection::deleter() {
231 0 : return deleter_.get();
232 : }
|