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