1048f6023SShuo Chen // excerpts from http://code.google.com/p/muduo/ 2048f6023SShuo Chen // 3048f6023SShuo Chen // Use of this source code is governed by a BSD-style license 4048f6023SShuo Chen // that can be found in the License file. 5048f6023SShuo Chen // 6048f6023SShuo Chen // Author: Shuo Chen (chenshuo at chenshuo dot com) 7048f6023SShuo Chen 8048f6023SShuo Chen #include "TcpServer.h" 9048f6023SShuo Chen 10048f6023SShuo Chen #include "logging/Logging.h" 11048f6023SShuo Chen #include "Acceptor.h" 12048f6023SShuo Chen #include "EventLoop.h" 13048f6023SShuo Chen #include "SocketsOps.h" 14048f6023SShuo Chen 15048f6023SShuo Chen #include <boost/bind.hpp> 16048f6023SShuo Chen 17048f6023SShuo Chen #include <stdio.h> // snprintf 18048f6023SShuo Chen 19048f6023SShuo Chen using namespace muduo; 20048f6023SShuo Chen 21048f6023SShuo Chen TcpServer::TcpServer(EventLoop* loop, const InetAddress& listenAddr) 22048f6023SShuo Chen : loop_(CHECK_NOTNULL(loop)), 23048f6023SShuo Chen name_(listenAddr.toHostPort()), 24048f6023SShuo Chen acceptor_(new Acceptor(loop, listenAddr)), 25048f6023SShuo Chen started_(false), 26048f6023SShuo Chen nextConnId_(1) 27048f6023SShuo Chen { 28048f6023SShuo Chen acceptor_->setNewConnectionCallback( 29048f6023SShuo Chen boost::bind(&TcpServer::newConnection, this, _1, _2)); 30048f6023SShuo Chen } 31048f6023SShuo Chen 32048f6023SShuo Chen TcpServer::~TcpServer() 33048f6023SShuo Chen { 34048f6023SShuo Chen } 35048f6023SShuo Chen 36048f6023SShuo Chen void TcpServer::start() 37048f6023SShuo Chen { 38048f6023SShuo Chen if (!started_) 39048f6023SShuo Chen { 40048f6023SShuo Chen started_ = true; 41048f6023SShuo Chen } 42048f6023SShuo Chen 43048f6023SShuo Chen if (!acceptor_->listenning()) 44048f6023SShuo Chen { 45048f6023SShuo Chen loop_->runInLoop( 46048f6023SShuo Chen boost::bind(&Acceptor::listen, get_pointer(acceptor_))); 47048f6023SShuo Chen } 48048f6023SShuo Chen } 49048f6023SShuo Chen 50048f6023SShuo Chen void TcpServer::newConnection(int sockfd, const InetAddress& peerAddr) 51048f6023SShuo Chen { 52048f6023SShuo Chen loop_->assertInLoopThread(); 53048f6023SShuo Chen char buf[32]; 54048f6023SShuo Chen snprintf(buf, sizeof buf, "#%d", nextConnId_); 55048f6023SShuo Chen ++nextConnId_; 56048f6023SShuo Chen std::string connName = name_ + buf; 57048f6023SShuo Chen 58048f6023SShuo Chen LOG_INFO << "TcpServer::newConnection [" << name_ 59048f6023SShuo Chen << "] - new connection [" << connName 60048f6023SShuo Chen << "] from " << peerAddr.toHostPort(); 61048f6023SShuo Chen InetAddress localAddr(sockets::getLocalAddr(sockfd)); 62048f6023SShuo Chen // FIXME poll with zero timeout to double confirm the new connection 63048f6023SShuo Chen TcpConnectionPtr conn( 64048f6023SShuo Chen new TcpConnection(loop_, connName, sockfd, localAddr, peerAddr)); 65048f6023SShuo Chen connections_[connName] = conn; 66048f6023SShuo Chen conn->setConnectionCallback(connectionCallback_); 67048f6023SShuo Chen conn->setMessageCallback(messageCallback_); 68048f6023SShuo Chen+ conn->setCloseCallback( 69048f6023SShuo Chen+ boost::bind(&TcpServer::removeConnection, this, _1)); 70048f6023SShuo Chen conn->connectEstablished(); 71048f6023SShuo Chen } 72048f6023SShuo Chen 73048f6023SShuo Chen+void TcpServer::removeConnection(const TcpConnectionPtr& conn) 74048f6023SShuo Chen+{ 75048f6023SShuo Chen+ loop_->assertInLoopThread(); 76048f6023SShuo Chen+ LOG_INFO << "TcpServer::removeConnection [" << name_ 77048f6023SShuo Chen+ << "] - connection " << conn->name(); 78048f6023SShuo Chen+ size_t n = connections_.erase(conn->name()); 79048f6023SShuo Chen+ assert(n == 1); (void)n; 80048f6023SShuo Chen+ loop_->queueInLoop( 81048f6023SShuo Chen+ boost::bind(&TcpConnection::connectDestroyed, conn)); 82048f6023SShuo Chen+} 83048f6023SShuo Chen+ 84