9 #include <boost/asio/connect.hpp>
10 #include <boost/asio/placeholders.hpp>
11 #include <boost/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;
27 using boost::asio::socket_base;
28 using std::ostringstream;
32 : evm_(evm), socket_open_failure_(false), intf_id_(-1) {
61 tcp::endpoint localaddr(tcp::v4(), port);
68 tcp::endpoint localaddr(host_ip, port);
69 tcp::endpoint serv_ep(host_ip, port);
71 if (host_ip.is_v6()) {
75 serv_ep.address(ipaddr);
89 if (localaddr.address().is_v4())
100 acceptor_->set_option(socket_base::reuse_address(
true), ec);
111 ":" << localaddr.port() <<
"): " << ec.message());
119 "Cannot retrieve acceptor local-endpont");
129 acceptor_->listen(socket_base::max_connections, ec);
132 "): " << ec.message());
144 tbb::mutex::scoped_lock lock(
mutex_);
160 tbb::mutex::scoped_lock lock(
mutex_);
165 for (SessionSet::iterator iter = refs.begin(), next = iter;
166 iter != refs.end(); iter = next) {
178 tbb::mutex::scoped_lock lock(
mutex_);
180 for (SessionSet::iterator iter =
session_ref_.begin(), next = iter;
191 tbb::mutex::scoped_lock lock(
mutex_);
202 tbb::mutex::scoped_lock lock(
mutex_);
225 for (SessionMap::iterator iter =
session_map_.find(remote);
226 iter !=
session_map_.end() && iter->first == remote; ++iter) {
227 if (iter->second == session) {
236 tbb::mutex::scoped_lock lock(
mutex_);
255 tbb::interface5::unique_lock<tbb::mutex> lock(
mutex_);
262 tbb::mutex::scoped_lock lock(
mutex_);
273 tbb::mutex::scoped_lock lock(
mutex_);
278 tcp::endpoint ep =
acceptor_->local_endpoint(ec);
286 tbb::mutex::scoped_lock lock(
mutex_);
291 tbb::mutex::scoped_lock lock(
mutex_);
296 for (SessionMap::const_iterator iter =
session_map_.begin();
299 if (iter->second->socket()->available(error) > 0) {
307 tbb::mutex::scoped_lock lock(
mutex_);
321 if (server_session) {
325 if (session != NULL) {
355 const error_code& error) {
356 tcp::endpoint remote;
359 bool need_close =
false;
368 "Accept: No remote endpoint: " << ec.message());
374 "Session accepted after server shutdown: "
375 << remote.address().to_string()
376 <<
":" << remote.port());
382 if (session == NULL) {
387 ec = session->SetSocketOptions();
390 "Accept: Non-blocking error: " << ec.message());
400 session->CloseInternal(ec,
false,
false);
406 tcp::endpoint remote = session->remote_endpoint();
408 tbb::mutex::scoped_lock lock(
mutex_);
411 "Accepted session from "
412 << remote.address().to_string()
413 <<
":" << remote.port());
418 "Rejected session from "
419 << remote.address().to_string()
420 <<
":" << remote.port());
422 session->CloseInternal(ec,
false,
false);
431 tbb::mutex::scoped_lock lock(
mutex_);
432 SessionMap::const_iterator iter =
session_map_.find(remote);
440 const error_code &error) {
443 "Connect failure: " << error.message());
444 session->ConnectFailed();
453 Endpoint remote = session->socket()->remote_endpoint(ec);
456 "Connect getsockaddr: " << ec.message());
457 session->ConnectFailed();
462 tbb::mutex::scoped_lock lock(
mutex_);
468 if (!session->Connected(remote)) {
469 tbb::mutex::scoped_lock lock(
mutex_);
477 socket->async_connect(remote,
483 const string &md5_password) {
484 assert(md5_password.size() <= TCP_MD5SIG_MAXKEYLEN);
490 struct sockaddr_in local_addr;
491 memset(&local_addr, 0,
sizeof(local_addr));
493 local_addr.sin_family = AF_INET;
494 local_addr.sin_addr.s_addr = htonl(peer_ip);
496 struct tcp_md5sig md5sig;
497 memset(&md5sig, 0,
sizeof (md5sig));
499 memcpy(md5sig.tcpm_key, md5_password.c_str(), md5_password.size());
500 md5sig.tcpm_keylen = md5_password.size();
501 memcpy(&md5sig.tcpm_addr, &local_addr,
sizeof(local_addr));
502 int retval = setsockopt(fd, IPPROTO_TCP, TCP_MD5SIG, (
const char *)&md5sig,
506 "Failure in setting md5 key on the socket " +
508 " with errno " + strerror(errno));
511 "Success in setting md5 key on the socket " +
518 const string &md5_password) {
541 int retval = setsockopt(fd, IPPROTO_IP, IP_TOS,
542 reinterpret_cast<const char *>(&value),
sizeof(value));
545 "Failure in setting DSCP value on the socket " +
547 " with errno " + strerror(errno));
554 unsigned int optlen =
sizeof(dscp);
555 int retval = getsockopt(fd, IPPROTO_IP, IP_TOS,
556 reinterpret_cast<char *>(&dscp),
557 reinterpret_cast<socklen_t *>(&optlen));
560 "Failure in getting DSCP value on the socket " +
575 int tcp_keepalive_enable = 1, retval = 0;
579 retval = setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE,
580 reinterpret_cast<const char *>(&tcp_keepalive_enable),
sizeof(tcp_keepalive_enable));
583 "Failure in setting Keepalive enable on the socket " +
585 " with errno " + strerror(errno));
590 retval = setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE,
591 reinterpret_cast<const char *>(&tcp_keepalive_idle_time),
sizeof(tcp_keepalive_idle_time));
594 "Failure in setting keepalive idle time on the socket " +
596 " with errno " + strerror(errno));
600 retval = setsockopt(fd, IPPROTO_TCP, TCP_KEEPALIVE,
601 reinterpret_cast<const char *>(&tcp_keepalive_idle_time),
sizeof(tcp_keepalive_idle_time));
604 "Failure in setting keepalive time on the socket " +
606 " with errno " + strerror(errno));
610 #error No TCP keepalive option defined.
614 retval = setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT,
615 reinterpret_cast<const char *>(&tcp_keepalive_probes),
sizeof(tcp_keepalive_probes));
618 "Failure in setting keepalive probes on the socket " +
620 " with errno " + strerror(errno));
626 retval = setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL,
627 reinterpret_cast<const char *>(&tcp_keepalive_interval),
sizeof(tcp_keepalive_interval));
630 "Failure in setting keepalive interval on the socket " +
632 " with errno " + strerror(errno));
static void AddServer(TcpServer *server)
void UpdateSessionsDscp(uint8_t dscp)
Endpoint local_endpoint() const
virtual void DeleteSession(TcpSession *session)
static void DeleteServer(ServerType *server)
boost::asio::ip::tcp::socket Socket
tbb::atomic< int > refcount_
tbb::interface5::condition_variable cond_var_
virtual void Connect(TcpSession *session, Endpoint remote)
std::set< TcpSessionPtr, TcpSessionPtrCmp > SessionSet
#define TCP_SERVER_LOG_UT_DEBUG(server, dir, arg)
boost::asio::ip::address IpAddress
TcpSession * GetSession(Endpoint remote)
virtual TcpSession * CreateSession()
void GetTxStats(SocketIOStats *socket_stats) const
void GetTxSocketStats(SocketIOStats *socket_stats) const
#define TCP_SERVER_LOG_INFO(server, dir, arg)
bool tcp_keepalive_enable
std::unique_ptr< Socket > so_accept_
boost::asio::io_context * io_service()
static ServerManager< TcpServer, TcpServerPtr > impl_
int SetKeepAliveSocketOption(int fd, const SandeshConfig &sandesh_config)
static void AddServer(ServerType *server)
void GetRxSocketStats(SocketIOStats *socket_stats) const
#define TCP_SERVER_LOG_DEBUG(server, dir, arg)
void AcceptHandlerInternal(TcpServerPtr server, const boost::system::error_code &error)
int tcp_keepalive_idle_time
tbb::atomic< int > refcount_
Endpoint LocalEndpoint() const
virtual void AcceptHandlerComplete(TcpSessionPtr session)
void ConnectHandler(TcpServerPtr server, TcpSessionPtr session, const boost::system::error_code &error)
boost::intrusive_ptr< TcpServer > TcpServerPtr
int SetDscpSocketOption(NativeSocketType fd, uint8_t value)
virtual TcpSession * AllocSession(Socket *socket)=0
bool HasSessionReadAvailable() const
#define TCP_SESSION_LOG_DEBUG(session, dir, arg)
static const std::string integerToString(const NumberType &num)
void GetRxStats(SocketIOStats *socket_stats) const
int SetSocketOptions(const SandeshConfig &sandesh_config)
boost::asio::ip::address_v6 Ip6Address
boost::scoped_ptr< boost::asio::ip::tcp::acceptor > acceptor_
#define TCP_SESSION_LOG_ERROR(session, dir, arg)
static void DeleteServer(TcpServer *server)
TcpServer(EventManager *evm)
static size_t GetServerCount()
bool InitializeInternal(boost::asio::ip::tcp::endpoint localaddr)
void OnSessionClose(TcpSession *session)
uint8_t GetDscpValue(NativeSocketType fd) const
void InsertSessionToMap(Endpoint remote, TcpSession *session)
int SetListenSocketMd5Option(uint32_t peer_ip, const std::string &md5_password)
virtual bool AcceptSession(TcpSession *session)
int SetListenSocketDscp(uint8_t value)
int SetDscpSocketOption(uint8_t value)
Endpoint remote_endpoint() const
virtual bool Initialize(unsigned short port)
#define TCP_SESSION_LOG_UT_DEBUG(session, dir, arg)
virtual void ConnectHandlerComplete(TcpSessionPtr session)
bool RemoveSessionFromMap(Endpoint remote, TcpSession *session)
int tcp_keepalive_interval
virtual Socket * accept_socket() const
boost::asio::ip::tcp::socket::native_handle_type NativeSocketType
virtual Socket * socket() const
#define TCP_SERVER_LOG_ERROR(server, dir, arg)
boost::asio::ip::tcp::endpoint Endpoint
int SetMd5SocketOption(NativeSocketType fd, uint32_t peer_ip, const std::string &md5_password)
void SetName(Endpoint local_endpoint)
virtual void set_accept_socket()
boost::intrusive_ptr< TcpSession > TcpSessionPtr