OpenSDN source code
tcp_server.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3  */
4 
5 #include "io/tcp_server.h"
6 
7 #include <errno.h>
8 
9 #include <boost/asio/connect.hpp>
10 #include <boost/asio/placeholders.hpp>
11 #include <boost/bind/bind.hpp>
12 #include <netinet/tcp.h>
13 
14 #include "base/logging.h"
15 #include "io/event_manager.h"
16 #include "io/tcp_session.h"
17 #include "io/io_log.h"
18 #include "io/io_utils.h"
19 
20 using boost::asio::ip::address;
21 using boost::asio::ip::tcp;
22 using boost::asio::placeholders::error;
23 using boost::asio::socket_base;
24 using boost::bind;
25 using boost::system::error_code;
26 using namespace boost::placeholders;
27 
28 using boost::asio::socket_base;
29 using std::ostringstream;
30 using std::string;
31 
33  : evm_(evm), socket_open_failure_(false), intf_id_(-1) {
34  refcount_ = 0;
36 }
37 
38 // TcpServer delete procedure:
39 // 1. Shutdown() to stop accepting incoming sessions.
40 // 2. Close and terminate current sessions. ASIO callbacks maybe in-flight.
41 // 3. Optionally: WaitForEmpty().
42 // 4. Destroy TcpServer.
44  assert(acceptor_ == NULL);
45  assert(session_ref_.empty());
46  assert(session_map_.empty());
47 }
48 
49 void TcpServer::SetName(Endpoint local_endpoint) {
50  ostringstream out;
51  out << local_endpoint;
52  name_ = out.str();
53 }
54 
56  acceptor_.reset();
57  name_ = "";
58 }
59 
60 bool TcpServer::Initialize(unsigned short port) {
61  intf_id_ = -1; //this initializer is only for IPv4
62  tcp::endpoint localaddr(tcp::v4(), port);
63  return InitializeInternal(localaddr);
64 }
65 
66 bool TcpServer::Initialize(unsigned short port,
67  const IpAddress &host_ip,
68  int intf_id) {
69  tcp::endpoint localaddr(host_ip, port);
70  tcp::endpoint serv_ep(host_ip, port);
71  intf_id_ = intf_id;
72  if (host_ip.is_v6()) {
73  Ip6Address ipaddr = host_ip.to_v6();
74  if (intf_id_ > 0) {
75  ipaddr.scope_id(this->intf_id_);
76  serv_ep.address(ipaddr);
77  }
78  }
79  return InitializeInternal(serv_ep);
80 }
81 
82 bool TcpServer::InitializeInternal(tcp::endpoint localaddr) {
83  acceptor_.reset(new tcp::acceptor(*evm_->io_service()));
84  if (!acceptor_) {
85  TCP_SERVER_LOG_ERROR(this, TCP_DIR_NA, "Cannot create acceptor");
86  return false;
87  }
88 
89  error_code ec;
90  if (localaddr.address().is_v4())
91  acceptor_->open(tcp::v4(), ec);
92  else
93  acceptor_->open(tcp::v6(), ec);
94 
95  if (ec) {
96  TCP_SERVER_LOG_ERROR(this, TCP_DIR_NA, "TCP open: " << ec.message());
97  ResetAcceptor();
98  return false;
99  }
100 
101  acceptor_->set_option(socket_base::reuse_address(true), ec);
102  if (ec) {
103  TCP_SERVER_LOG_ERROR(this, TCP_DIR_NA, "TCP reuse_address: "
104  << ec.message());
105  ResetAcceptor();
106  return false;
107  }
108 
109  acceptor_->bind(localaddr, ec);
110  if (ec) {
111  TCP_SERVER_LOG_ERROR(this, TCP_DIR_NA, "TCP bind(" << localaddr.address() <<
112  ":" << localaddr.port() << "): " << ec.message());
113  ResetAcceptor();
114  return false;
115  }
116 
117  tcp::endpoint local_endpoint = acceptor_->local_endpoint(ec);
118  if (ec) {
120  "Cannot retrieve acceptor local-endpont");
121  ResetAcceptor();
122  return false;
123  }
124 
125  //
126  // Server name can be set after local-endpoint information is available.
127  //
128  SetName(local_endpoint);
129 
130  acceptor_->listen(socket_base::max_connections, ec);
131  if (ec) {
132  TCP_SERVER_LOG_ERROR(this, TCP_DIR_NA, "TCP listen(" << localaddr.port() <<
133  "): " << ec.message());
134  ResetAcceptor();
135  return false;
136  }
137 
138  TCP_SERVER_LOG_DEBUG(this, TCP_DIR_NA, "Initialization complete");
139  AsyncAccept();
140 
141  return true;
142 }
143 
145  std::scoped_lock lock(mutex_);
146  error_code ec;
147 
148  if (acceptor_) {
149  acceptor_->close(ec);
150  if (ec) {
151  TCP_SERVER_LOG_ERROR(this, TCP_DIR_NA, "Error during shutdown: "
152  << ec.message());
153  }
154  ResetAcceptor();
155  }
156 }
157 
158 // Close and remove references from all sessions. The application code must
159 // make sure it no longer holds any references to these sessions.
161  SessionSet refs;
162  {
163  std::scoped_lock lock(mutex_);
164  refs.swap(session_ref_);
165  }
166 
167  for (SessionSet::iterator iter = refs.begin(), next = iter;
168  iter != refs.end(); iter = next) {
169  ++next;
170  TcpSession *session = iter->get();
171  session->Close();
172  }
173  refs.clear();
174  if (session_ref_.empty() && session_map_.empty()) {
175  cond_var_.notify_all();
176  }
177 }
178 
179 void TcpServer::UpdateSessionsDscp(uint8_t dscp) {
180  std::scoped_lock lock(mutex_);
181 
182  for (SessionSet::iterator iter = session_ref_.begin(), next = iter;
183  iter != session_ref_.end(); iter = next) {
184  ++next;
185  TcpSession *session = iter->get();
186  session->SetDscpSocketOption(dscp);
187  }
188 }
189 
191  TcpSession *session = AllocSession(false);
192  {
193  std::scoped_lock lock(mutex_);
194  session_ref_.insert(TcpSessionPtr(session));
195  }
196  return session;
197 }
198 
200  // The caller will typically close the socket before deleting the
201  // session.
202  session->Close();
203  {
204  std::scoped_lock lock(mutex_);
205  assert(session->refcount_);
206  session_ref_.erase(TcpSessionPtr(session));
207  if (session_ref_.empty() && session_map_.empty()) {
208  cond_var_.notify_all();
209  }
210  }
211 }
212 
213 //
214 // Insert into SessionMap.
215 // Assumes that caller has the mutex.
216 //
218  session_map_.insert(make_pair(remote, session));
219 }
220 
221 //
222 // Remove from SessionMap.
223 // Assumes that caller has the mutex.
224 // Return true if the session is found.
225 //
227  for (SessionMap::iterator iter = session_map_.find(remote);
228  iter != session_map_.end() && iter->first == remote; ++iter) {
229  if (iter->second == session) {
230  session_map_.erase(iter);
231  return true;
232  }
233  }
234  return false;
235 }
236 
238  std::scoped_lock lock(mutex_);
239 
240  // CloseSessions closes and removes all the sessions from the map.
241  if (session_map_.empty()) {
242  return;
243  }
244 
245  bool found = RemoveSessionFromMap(session->remote_endpoint(), session);
246  if (session_map_.empty() && session_ref_.empty()) {
247  cond_var_.notify_all();
248  }
249  assert(found);
250 }
251 
252 // This method ensures that the application code requested the session to be
253 // deleted (which may be a delayed action). It does not guarantee that the
254 // session object has actually been freed yet as ASIO callbacks can be in
255 // progress.
257  std::unique_lock<std::mutex> lock(mutex_);
258  while (!session_ref_.empty() || !session_map_.empty()) {
259  cond_var_.wait(lock);
260  }
261 }
262 
264  std::scoped_lock lock(mutex_);
265  if (acceptor_ == NULL) {
266  return;
267  }
269  acceptor_->async_accept(*accept_socket(),
271  TcpServerPtr(this), error));
272 }
273 
274 int TcpServer::GetPort() const {
275  std::scoped_lock lock(mutex_);
276  if (acceptor_.get() == NULL) {
277  return -1;
278  }
279  error_code ec;
280  tcp::endpoint ep = acceptor_->local_endpoint(ec);
281  if (ec) {
282  return -1;
283  }
284  return ep.port();
285 }
286 
288  std::scoped_lock lock(mutex_);
289  return !session_map_.empty();
290 }
291 
293  std::scoped_lock lock(mutex_);
294  error_code error;
295  if (accept_socket()->available(error) > 0) {
296  return true;
297  }
298  for (SessionMap::const_iterator iter = session_map_.begin();
299  iter != session_map_.end();
300  ++iter) {
301  if (iter->second->socket()->available(error) > 0) {
302  return true;
303  }
304  }
305  return false;
306 }
307 
309  std::scoped_lock lock(mutex_);
310  if (acceptor_.get() == NULL) {
311  return Endpoint();
312  }
313  error_code ec;
314  Endpoint local = acceptor_->local_endpoint(ec);
315  if (ec) {
316  return Endpoint();
317  }
318  return local;
319 }
320 
321 TcpSession *TcpServer::AllocSession(bool server_session) {
322  TcpSession *session;
323  if (server_session) {
324  session = AllocSession(so_accept_.get());
325 
326  // if session allocate succeeds release ownership to so_accept.
327  if (session != NULL) {
328  so_accept_.release();
329  }
330  } else {
331  Socket *socket = new Socket(*evm_->io_service());
332  session = AllocSession(socket);
333  }
334 
335  return session;
336 }
337 
339  return so_accept_.get();
340 }
341 
343  so_accept_.reset(new Socket(*evm_->io_service()));
344 }
345 
347  return true;
348 }
349 
350 //
351 // concurrency: called from the event_manager thread.
352 //
353 // accept() tcp connections. Once done, must register with boost again
354 // via AsyncAccept() in order to process future accept calls
355 //
357  const error_code& error) {
358  tcp::endpoint remote;
359  error_code ec;
360  TcpSessionPtr session;
361  bool need_close = false;
362 
363  if (error) {
364  goto done;
365  }
366 
367  remote = accept_socket()->remote_endpoint(ec);
368  if (ec) {
370  "Accept: No remote endpoint: " << ec.message());
371  goto done;
372  }
373 
374  if (acceptor_ == NULL) {
376  "Session accepted after server shutdown: "
377  << remote.address().to_string()
378  << ":" << remote.port());
379  accept_socket()->close(ec);
380  goto done;
381  }
382 
383  session.reset(AllocSession(true));
384  if (session == NULL) {
385  TCP_SERVER_LOG_DEBUG(this, TCP_DIR_IN, "Session not created");
386  goto done;
387  }
388 
389  ec = session->SetSocketOptions();
390  if (ec) {
392  "Accept: Non-blocking error: " << ec.message());
393  need_close = true;
394  goto done;
395  }
396 
397  session->SessionEstablished(remote, TcpSession::PASSIVE);
398  AcceptHandlerComplete(session);
399 
400 done:
401  if (need_close) {
402  session->CloseInternal(ec, false, false);
403  }
404  AsyncAccept();
405 }
406 
408  tcp::endpoint remote = session->remote_endpoint();
409  {
410  std::scoped_lock lock(mutex_);
411  if (AcceptSession(session.get())) {
413  "Accepted session from "
414  << remote.address().to_string()
415  << ":" << remote.port());
416  session_ref_.insert(session);
417  InsertSessionToMap(remote, session.get());
418  } else {
420  "Rejected session from "
421  << remote.address().to_string()
422  << ":" << remote.port());
423  error_code ec;
424  session->CloseInternal(ec, false, false);
425  return;
426  }
427  }
428 
429  session->Accepted();
430 }
431 
433  std::scoped_lock lock(mutex_);
434  SessionMap::const_iterator iter = session_map_.find(remote);
435  if (iter != session_map_.end()) {
436  return iter->second;
437  }
438  return NULL;
439 }
440 
442  const error_code &error) {
443  if (error) {
445  "Connect failure: " << error.message());
446  session->ConnectFailed();
447  return;
448  }
449 
450  ConnectHandlerComplete(session);
451 }
452 
454  error_code ec;
455  Endpoint remote = session->socket()->remote_endpoint(ec);
456  if (ec) {
458  "Connect getsockaddr: " << ec.message());
459  session->ConnectFailed();
460  return;
461  }
462 
463  {
464  std::scoped_lock lock(mutex_);
465  InsertSessionToMap(remote, session.get());
466  }
467 
468  // Connected verifies whether the session has been closed or is still
469  // active.
470  if (!session->Connected(remote)) {
471  std::scoped_lock lock(mutex_);
472  RemoveSessionFromMap(remote, session.get());
473  }
474 }
475 
476 void TcpServer::Connect(TcpSession *session, Endpoint remote) {
477  assert(session->refcount_);
478  Socket *socket = session->socket();
479  socket->async_connect(remote,
480  bind(&TcpServer::ConnectHandler, this, TcpServerPtr(this),
481  TcpSessionPtr(session), error));
482 }
483 
485  const string &md5_password) {
486  assert(md5_password.size() <= TCP_MD5SIG_MAXKEYLEN);
487  if (!peer_ip) {
488  TCP_SERVER_LOG_ERROR(this, TCP_DIR_NA, "Invalid peer IP");
489  return 0;
490  }
491 
492  struct sockaddr_in local_addr;
493  memset(&local_addr, 0, sizeof(local_addr));
494 
495  local_addr.sin_family = AF_INET;
496  local_addr.sin_addr.s_addr = htonl(peer_ip);
497 
498  struct tcp_md5sig md5sig;
499  memset(&md5sig, 0, sizeof (md5sig));
500 
501  memcpy(md5sig.tcpm_key, md5_password.c_str(), md5_password.size());
502  md5sig.tcpm_keylen = md5_password.size();
503  memcpy(&md5sig.tcpm_addr, &local_addr, sizeof(local_addr));
504  int retval = setsockopt(fd, IPPROTO_TCP, TCP_MD5SIG, (const char *)&md5sig,
505  sizeof(md5sig));
506  if (retval < 0) {
508  "Failure in setting md5 key on the socket " +
509  integerToString(fd) + " for peer " + integerToString(peer_ip) +
510  " with errno " + strerror(errno));
511  } else {
513  "Success in setting md5 key on the socket " +
514  integerToString(fd) + " for peer " + integerToString(peer_ip));
515  }
516  return retval;
517 }
518 
520  const string &md5_password) {
521  int retval = 0;
522  if (acceptor_) {
523  retval = SetMd5SocketOption(acceptor_->native_handle(), peer_ip,
524  md5_password);
525  }
526  return retval;
527 }
528 
529 int TcpServer::SetListenSocketDscp(uint8_t value) {
530  int retval = 0;
531  if (acceptor_) {
532  retval = SetDscpSocketOption(acceptor_->native_handle(), value);
533  }
534  return retval;
535 }
536 
538  /* The 'value' argument is expected to have DSCP value between 0 and 63 ie
539  * in the lower order 6 bits of a byte. However, setsockopt expects DSCP
540  * value in upper 6 bits of a byte. Hence left shift the value by 2 digits
541  * before passing it to setsockopt */
542  value = value << 2;
543  int retval = setsockopt(fd, IPPROTO_IP, IP_TOS,
544  reinterpret_cast<const char *>(&value), sizeof(value));
545  if (retval < 0) {
547  "Failure in setting DSCP value on the socket " +
548  integerToString(fd) + " for value " + integerToString(value) +
549  " with errno " + strerror(errno));
550  }
551  return retval;
552 }
553 
555  uint8_t dscp = 0;
556  unsigned int optlen = sizeof(dscp);
557  int retval = getsockopt(fd, IPPROTO_IP, IP_TOS,
558  reinterpret_cast<char *>(&dscp),
559  reinterpret_cast<socklen_t *>(&optlen));
560  if (retval < 0) {
562  "Failure in getting DSCP value on the socket " +
563  integerToString(fd) + " with errno " + strerror(errno));
564  }
565  return dscp;
566 }
567 
568 int TcpServer::SetSocketOptions(const SandeshConfig &sandesh_config) {
569  int retval = 0;
570  if (acceptor_ && sandesh_config.tcp_keepalive_enable) {
571  retval = SetKeepAliveSocketOption(acceptor_->native_handle(), sandesh_config);
572  }
573  return retval;
574 }
575 
576 int TcpServer::SetKeepAliveSocketOption(int fd, const SandeshConfig &sandesh_config) {
577  int tcp_keepalive_enable = 1, retval = 0;
578  int tcp_keepalive_idle_time = sandesh_config.tcp_keepalive_idle_time;
579  int tcp_keepalive_probes = sandesh_config.tcp_keepalive_probes;
580  int tcp_keepalive_interval = sandesh_config.tcp_keepalive_interval;
581  retval = setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE,
582  reinterpret_cast<const char *>(&tcp_keepalive_enable), sizeof(tcp_keepalive_enable));
583  if (retval < 0) {
585  "Failure in setting Keepalive enable on the socket " +
586  integerToString(fd) +
587  " with errno " + strerror(errno));
588  return retval;
589  }
590 
591 #ifdef TCP_KEEPIDLE
592  retval = setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE,
593  reinterpret_cast<const char *>(&tcp_keepalive_idle_time), sizeof(tcp_keepalive_idle_time));
594  if (retval < 0) {
596  "Failure in setting keepalive idle time on the socket " +
597  integerToString(fd) +
598  " with errno " + strerror(errno));
599  return retval;
600  }
601 #elif TCP_KEEPALIVE
602  retval = setsockopt(fd, IPPROTO_TCP, TCP_KEEPALIVE,
603  reinterpret_cast<const char *>(&tcp_keepalive_idle_time), sizeof(tcp_keepalive_idle_time));
604  if (retval < 0) {
606  "Failure in setting keepalive time on the socket " +
607  integerToString(fd) +
608  " with errno " + strerror(errno));
609  return retval;
610  }
611 #else
612 #error No TCP keepalive option defined.
613 #endif
614 
615 #ifdef TCP_KEEPCNT
616  retval = setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT,
617  reinterpret_cast<const char *>(&tcp_keepalive_probes), sizeof(tcp_keepalive_probes));
618  if (retval < 0) {
620  "Failure in setting keepalive probes on the socket " +
621  integerToString(fd) +
622  " with errno " + strerror(errno));
623  return retval;
624  }
625 #endif
626 
627 #ifdef TCP_KEEPINTVL
628  retval = setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL,
629  reinterpret_cast<const char *>(&tcp_keepalive_interval), sizeof(tcp_keepalive_interval));
630  if (retval < 0) {
632  "Failure in setting keepalive interval on the socket " +
633  integerToString(fd) +
634  " with errno " + strerror(errno));
635  return retval;
636  }
637 #endif
638  return retval;
639 }
640 
641 void TcpServer::GetRxSocketStats(SocketIOStats *socket_stats) const {
642  stats_.GetRxStats(socket_stats);
643 }
644 
645 void TcpServer::GetTxSocketStats(SocketIOStats *socket_stats) const {
646  stats_.GetTxStats(socket_stats);
647 }
648 
649 //
650 // TcpServerManager class routines
651 //
653 
655  impl_.AddServer(server);
656 }
657 
659  // Wait for pending writes to be complete
660  server->WaitForEmpty();
661  impl_.DeleteServer(server);
662 }
663 
665  return impl_.GetServerCount();
666 }
boost::asio::ip::address_v6 Ip6Address
Definition: address.h:15
boost::asio::ip::address IpAddress
Definition: address.h:13
boost::asio::io_context * io_service()
Definition: event_manager.h:42
static void AddServer(ServerType *server)
size_t GetServerCount()
static void DeleteServer(ServerType *server)
static size_t GetServerCount()
Definition: tcp_server.cc:664
static void DeleteServer(TcpServer *server)
Definition: tcp_server.cc:658
static void AddServer(TcpServer *server)
Definition: tcp_server.cc:654
static ServerManager< TcpServer, TcpServerPtr > impl_
Definition: tcp_server.h:211
io::SocketStats stats_
Definition: tcp_server.h:174
void Shutdown()
Definition: tcp_server.cc:144
uint8_t GetDscpValue(NativeSocketType fd) const
Definition: tcp_server.cc:554
boost::asio::ip::tcp::endpoint Endpoint
Definition: tcp_server.h:30
Endpoint LocalEndpoint() const
Definition: tcp_server.cc:308
std::condition_variable cond_var_
Definition: tcp_server.h:178
boost::intrusive_ptr< TcpServer > TcpServerPtr
Definition: tcp_server.h:110
virtual void Connect(TcpSession *session, Endpoint remote)
Definition: tcp_server.cc:476
std::unique_ptr< Socket > so_accept_
Definition: tcp_server.h:181
void GetRxSocketStats(SocketIOStats *socket_stats) const
Definition: tcp_server.cc:641
int SetListenSocketMd5Option(uint32_t peer_ip, const std::string &md5_password)
Definition: tcp_server.cc:519
std::set< TcpSessionPtr, TcpSessionPtrCmp > SessionSet
Definition: tcp_server.h:155
std::string name_
Definition: tcp_server.h:184
boost::scoped_ptr< boost::asio::ip::tcp::acceptor > acceptor_
Definition: tcp_server.h:182
int SetKeepAliveSocketOption(int fd, const SandeshConfig &sandesh_config)
Definition: tcp_server.cc:576
bool RemoveSessionFromMap(Endpoint remote, TcpSession *session)
Definition: tcp_server.cc:226
boost::asio::ip::tcp::socket::native_handle_type NativeSocketType
Definition: tcp_server.h:32
int SetListenSocketDscp(uint8_t value)
Definition: tcp_server.cc:529
virtual ~TcpServer()
Definition: tcp_server.cc:43
virtual TcpSession * AllocSession(Socket *socket)=0
void ConnectHandler(TcpServerPtr server, TcpSessionPtr session, const boost::system::error_code &error)
Definition: tcp_server.cc:441
virtual Socket * accept_socket() const
Definition: tcp_server.cc:338
virtual bool Initialize(unsigned short port)
Definition: tcp_server.cc:60
std::mutex mutex_
Definition: tcp_server.h:177
void AcceptHandlerInternal(TcpServerPtr server, const boost::system::error_code &error)
Definition: tcp_server.cc:356
TcpSession * GetSession(Endpoint remote)
Definition: tcp_server.cc:432
int SetSocketOptions(const SandeshConfig &sandesh_config)
Definition: tcp_server.cc:568
virtual TcpSession * CreateSession()
Definition: tcp_server.cc:190
void UpdateSessionsDscp(uint8_t dscp)
Definition: tcp_server.cc:179
TcpServer(EventManager *evm)
Definition: tcp_server.cc:32
std::atomic< int > refcount_
Definition: tcp_server.h:183
boost::intrusive_ptr< TcpSession > TcpSessionPtr
Definition: tcp_server.h:111
bool HasSessions() const
Definition: tcp_server.cc:287
void AsyncAccept()
Definition: tcp_server.cc:263
SessionMap session_map_
Definition: tcp_server.h:180
virtual void DeleteSession(TcpSession *session)
Definition: tcp_server.cc:199
void ClearSessions()
Definition: tcp_server.cc:160
int intf_id_
Definition: tcp_server.h:186
EventManager * evm_
Definition: tcp_server.h:175
int SetDscpSocketOption(NativeSocketType fd, uint8_t value)
Definition: tcp_server.cc:537
void InsertSessionToMap(Endpoint remote, TcpSession *session)
Definition: tcp_server.cc:217
boost::asio::ip::tcp::socket Socket
Definition: tcp_server.h:31
void WaitForEmpty()
Definition: tcp_server.cc:256
int GetPort() const
Definition: tcp_server.cc:274
bool HasSessionReadAvailable() const
Definition: tcp_server.cc:292
virtual void set_accept_socket()
Definition: tcp_server.cc:342
bool InitializeInternal(boost::asio::ip::tcp::endpoint localaddr)
Definition: tcp_server.cc:82
void OnSessionClose(TcpSession *session)
Definition: tcp_server.cc:237
void ResetAcceptor()
Definition: tcp_server.cc:55
void GetTxSocketStats(SocketIOStats *socket_stats) const
Definition: tcp_server.cc:645
virtual void ConnectHandlerComplete(TcpSessionPtr session)
Definition: tcp_server.cc:453
virtual bool AcceptSession(TcpSession *session)
Definition: tcp_server.cc:346
void SetName(Endpoint local_endpoint)
Definition: tcp_server.cc:49
int SetMd5SocketOption(NativeSocketType fd, uint32_t peer_ip, const std::string &md5_password)
Definition: tcp_server.cc:484
SessionSet session_ref_
Definition: tcp_server.h:179
virtual void AcceptHandlerComplete(TcpSessionPtr session)
Definition: tcp_server.cc:407
virtual Socket * socket() const
Definition: tcp_session.h:82
std::atomic< int > refcount_
Definition: tcp_session.h:278
Endpoint remote_endpoint() const
Definition: tcp_session.h:131
int SetDscpSocketOption(uint8_t value)
Definition: tcp_session.cc:570
void Close()
Definition: tcp_session.cc:355
static EventManager evm
#define TCP_SERVER_LOG_INFO(server, dir, arg)
Definition: io_log.h:103
#define TCP_SERVER_LOG_ERROR(server, dir, arg)
Definition: io_log.h:100
#define TCP_SESSION_LOG_DEBUG(session, dir, arg)
Definition: io_log.h:123
#define TCP_SERVER_LOG_UT_DEBUG(server, dir, arg)
Definition: io_log.h:109
#define TCP_DIR_NA
Definition: io_log.h:48
#define TCP_SERVER_LOG_DEBUG(server, dir, arg)
Definition: io_log.h:106
#define TCP_DIR_OUT
Definition: io_log.h:46
#define TCP_SESSION_LOG_ERROR(session, dir, arg)
Definition: io_log.h:117
#define TCP_DIR_IN
Definition: io_log.h:47
#define TCP_SESSION_LOG_UT_DEBUG(session, dir, arg)
Definition: io_log.h:126
static const std::string integerToString(const NumberType &num)
Definition: string_util.h:19
int tcp_keepalive_idle_time
bool tcp_keepalive_enable
int tcp_keepalive_interval
void GetRxStats(SocketIOStats *socket_stats) const
Definition: io_utils.cc:28
void GetTxStats(SocketIOStats *socket_stats) const
Definition: io_utils.cc:47