9 #include <boost/asio/connect.hpp>
10 #include <boost/asio/placeholders.hpp>
11 #include <boost/bind/bind.hpp>
12 #include <netinet/tcp.h>
20 using boost::asio::ip::address;
21 using boost::asio::ip::tcp;
22 using boost::asio::placeholders::error;
23 using boost::asio::socket_base;
25 using boost::system::error_code;
26 using namespace boost::placeholders;
28 using boost::asio::socket_base;
29 using std::ostringstream;
33 : evm_(
evm), socket_open_failure_(false), intf_id_(-1) {
51 out << local_endpoint;
62 tcp::endpoint localaddr(tcp::v4(), port);
69 tcp::endpoint localaddr(host_ip, port);
70 tcp::endpoint serv_ep(host_ip, port);
72 if (host_ip.is_v6()) {
76 serv_ep.address(ipaddr);
90 if (localaddr.address().is_v4())
101 acceptor_->set_option(socket_base::reuse_address(
true), ec);
112 ":" << localaddr.port() <<
"): " << ec.message());
117 tcp::endpoint local_endpoint =
acceptor_->local_endpoint(ec);
120 "Cannot retrieve acceptor local-endpont");
130 acceptor_->listen(socket_base::max_connections, ec);
133 "): " << ec.message());
145 std::scoped_lock lock(
mutex_);
163 std::scoped_lock lock(
mutex_);
167 for (SessionSet::iterator iter = refs.begin(), next = iter;
168 iter != refs.end(); iter = next) {
180 std::scoped_lock lock(
mutex_);
182 for (SessionSet::iterator iter =
session_ref_.begin(), next = iter;
193 std::scoped_lock lock(
mutex_);
204 std::scoped_lock lock(
mutex_);
227 for (SessionMap::iterator iter =
session_map_.find(remote);
228 iter !=
session_map_.end() && iter->first == remote; ++iter) {
229 if (iter->second == session) {
238 std::scoped_lock lock(
mutex_);
257 std::unique_lock<std::mutex> lock(
mutex_);
264 std::scoped_lock lock(
mutex_);
275 std::scoped_lock lock(
mutex_);
280 tcp::endpoint ep =
acceptor_->local_endpoint(ec);
288 std::scoped_lock lock(
mutex_);
293 std::scoped_lock lock(
mutex_);
298 for (SessionMap::const_iterator iter =
session_map_.begin();
301 if (iter->second->socket()->available(error) > 0) {
309 std::scoped_lock lock(
mutex_);
323 if (server_session) {
327 if (session != NULL) {
357 const error_code& error) {
358 tcp::endpoint remote;
361 bool need_close =
false;
370 "Accept: No remote endpoint: " << ec.message());
376 "Session accepted after server shutdown: "
377 << remote.address().to_string()
378 <<
":" << remote.port());
384 if (session == NULL) {
389 ec = session->SetSocketOptions();
392 "Accept: Non-blocking error: " << ec.message());
402 session->CloseInternal(ec,
false,
false);
408 tcp::endpoint remote = session->remote_endpoint();
410 std::scoped_lock lock(
mutex_);
413 "Accepted session from "
414 << remote.address().to_string()
415 <<
":" << remote.port());
420 "Rejected session from "
421 << remote.address().to_string()
422 <<
":" << remote.port());
424 session->CloseInternal(ec,
false,
false);
433 std::scoped_lock lock(
mutex_);
434 SessionMap::const_iterator iter =
session_map_.find(remote);
442 const error_code &error) {
445 "Connect failure: " << error.message());
446 session->ConnectFailed();
455 Endpoint remote = session->socket()->remote_endpoint(ec);
458 "Connect getsockaddr: " << ec.message());
459 session->ConnectFailed();
464 std::scoped_lock lock(
mutex_);
470 if (!session->Connected(remote)) {
471 std::scoped_lock lock(
mutex_);
479 socket->async_connect(remote,
485 const string &md5_password) {
486 assert(md5_password.size() <= TCP_MD5SIG_MAXKEYLEN);
492 struct sockaddr_in local_addr;
493 memset(&local_addr, 0,
sizeof(local_addr));
495 local_addr.sin_family = AF_INET;
496 local_addr.sin_addr.s_addr = htonl(peer_ip);
498 struct tcp_md5sig md5sig;
499 memset(&md5sig, 0,
sizeof (md5sig));
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,
508 "Failure in setting md5 key on the socket " +
510 " with errno " + strerror(errno));
513 "Success in setting md5 key on the socket " +
520 const string &md5_password) {
543 int retval = setsockopt(fd, IPPROTO_IP, IP_TOS,
544 reinterpret_cast<const char *
>(&value),
sizeof(value));
547 "Failure in setting DSCP value on the socket " +
549 " with errno " + strerror(errno));
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));
562 "Failure in getting DSCP value on the socket " +
577 int tcp_keepalive_enable = 1, retval = 0;
581 retval = setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE,
582 reinterpret_cast<const char *
>(&tcp_keepalive_enable),
sizeof(tcp_keepalive_enable));
585 "Failure in setting Keepalive enable on the socket " +
587 " with errno " + strerror(errno));
592 retval = setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE,
593 reinterpret_cast<const char *
>(&tcp_keepalive_idle_time),
sizeof(tcp_keepalive_idle_time));
596 "Failure in setting keepalive idle time on the socket " +
598 " with errno " + strerror(errno));
602 retval = setsockopt(fd, IPPROTO_TCP, TCP_KEEPALIVE,
603 reinterpret_cast<const char *
>(&tcp_keepalive_idle_time),
sizeof(tcp_keepalive_idle_time));
606 "Failure in setting keepalive time on the socket " +
608 " with errno " + strerror(errno));
612 #error No TCP keepalive option defined.
616 retval = setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT,
617 reinterpret_cast<const char *
>(&tcp_keepalive_probes),
sizeof(tcp_keepalive_probes));
620 "Failure in setting keepalive probes on the socket " +
622 " with errno " + strerror(errno));
628 retval = setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL,
629 reinterpret_cast<const char *
>(&tcp_keepalive_interval),
sizeof(tcp_keepalive_interval));
632 "Failure in setting keepalive interval on the socket " +
634 " with errno " + strerror(errno));
boost::asio::ip::address_v6 Ip6Address
boost::asio::ip::address IpAddress
boost::asio::io_context * io_service()
static void AddServer(ServerType *server)
static void DeleteServer(ServerType *server)
static size_t GetServerCount()
static void DeleteServer(TcpServer *server)
static void AddServer(TcpServer *server)
static ServerManager< TcpServer, TcpServerPtr > impl_
uint8_t GetDscpValue(NativeSocketType fd) const
boost::asio::ip::tcp::endpoint Endpoint
Endpoint LocalEndpoint() const
std::condition_variable cond_var_
boost::intrusive_ptr< TcpServer > TcpServerPtr
virtual void Connect(TcpSession *session, Endpoint remote)
std::unique_ptr< Socket > so_accept_
void GetRxSocketStats(SocketIOStats *socket_stats) const
int SetListenSocketMd5Option(uint32_t peer_ip, const std::string &md5_password)
std::set< TcpSessionPtr, TcpSessionPtrCmp > SessionSet
boost::scoped_ptr< boost::asio::ip::tcp::acceptor > acceptor_
int SetKeepAliveSocketOption(int fd, const SandeshConfig &sandesh_config)
bool RemoveSessionFromMap(Endpoint remote, TcpSession *session)
boost::asio::ip::tcp::socket::native_handle_type NativeSocketType
int SetListenSocketDscp(uint8_t value)
virtual TcpSession * AllocSession(Socket *socket)=0
void ConnectHandler(TcpServerPtr server, TcpSessionPtr session, const boost::system::error_code &error)
virtual Socket * accept_socket() const
virtual bool Initialize(unsigned short port)
void AcceptHandlerInternal(TcpServerPtr server, const boost::system::error_code &error)
TcpSession * GetSession(Endpoint remote)
int SetSocketOptions(const SandeshConfig &sandesh_config)
virtual TcpSession * CreateSession()
void UpdateSessionsDscp(uint8_t dscp)
TcpServer(EventManager *evm)
std::atomic< int > refcount_
boost::intrusive_ptr< TcpSession > TcpSessionPtr
virtual void DeleteSession(TcpSession *session)
int SetDscpSocketOption(NativeSocketType fd, uint8_t value)
void InsertSessionToMap(Endpoint remote, TcpSession *session)
boost::asio::ip::tcp::socket Socket
bool HasSessionReadAvailable() const
virtual void set_accept_socket()
bool InitializeInternal(boost::asio::ip::tcp::endpoint localaddr)
void OnSessionClose(TcpSession *session)
void GetTxSocketStats(SocketIOStats *socket_stats) const
virtual void ConnectHandlerComplete(TcpSessionPtr session)
virtual bool AcceptSession(TcpSession *session)
void SetName(Endpoint local_endpoint)
int SetMd5SocketOption(NativeSocketType fd, uint32_t peer_ip, const std::string &md5_password)
virtual void AcceptHandlerComplete(TcpSessionPtr session)
virtual Socket * socket() const
std::atomic< int > refcount_
Endpoint remote_endpoint() const
int SetDscpSocketOption(uint8_t value)
#define TCP_SERVER_LOG_INFO(server, dir, arg)
#define TCP_SERVER_LOG_ERROR(server, dir, arg)
#define TCP_SESSION_LOG_DEBUG(session, dir, arg)
#define TCP_SERVER_LOG_UT_DEBUG(server, dir, arg)
#define TCP_SERVER_LOG_DEBUG(server, dir, arg)
#define TCP_SESSION_LOG_ERROR(session, dir, arg)
#define TCP_SESSION_LOG_UT_DEBUG(session, dir, arg)
static const std::string integerToString(const NumberType &num)
int tcp_keepalive_idle_time
bool tcp_keepalive_enable
int tcp_keepalive_interval
void GetRxStats(SocketIOStats *socket_stats) const
void GetTxStats(SocketIOStats *socket_stats) const