15af4b7fbSShuo Chen // excerpts from http://code.google.com/p/muduo/ 25af4b7fbSShuo Chen // 35af4b7fbSShuo Chen // Use of this source code is governed by a BSD-style license 45af4b7fbSShuo Chen // that can be found in the License file. 55af4b7fbSShuo Chen // 65af4b7fbSShuo Chen // Author: Shuo Chen (chenshuo at chenshuo dot com) 75af4b7fbSShuo Chen 85af4b7fbSShuo Chen #include "TcpServer.h" 95af4b7fbSShuo Chen 105af4b7fbSShuo Chen #include "logging/Logging.h" 115af4b7fbSShuo Chen #include "Acceptor.h" 125af4b7fbSShuo Chen #include "EventLoop.h" 135af4b7fbSShuo Chen #include "SocketsOps.h" 145af4b7fbSShuo Chen 155af4b7fbSShuo Chen #include <boost/bind.hpp> 165af4b7fbSShuo Chen 175af4b7fbSShuo Chen #include <stdio.h> // snprintf 185af4b7fbSShuo Chen 195af4b7fbSShuo Chen using namespace muduo; 205af4b7fbSShuo Chen 215af4b7fbSShuo Chen TcpServer::TcpServer(EventLoop* loop, const InetAddress& listenAddr) 225af4b7fbSShuo Chen : loop_(CHECK_NOTNULL(loop)), 235af4b7fbSShuo Chen name_(listenAddr.toHostPort()), 245af4b7fbSShuo Chen acceptor_(new Acceptor(loop, listenAddr)), 255af4b7fbSShuo Chen started_(false), 265af4b7fbSShuo Chen nextConnId_(1) 275af4b7fbSShuo Chen { 285af4b7fbSShuo Chen acceptor_->setNewConnectionCallback( 295af4b7fbSShuo Chen boost::bind(&TcpServer::newConnection, this, _1, _2)); 305af4b7fbSShuo Chen } 315af4b7fbSShuo Chen 325af4b7fbSShuo Chen TcpServer::~TcpServer() 335af4b7fbSShuo Chen { 345af4b7fbSShuo Chen } 355af4b7fbSShuo Chen 365af4b7fbSShuo Chen void TcpServer::start() 375af4b7fbSShuo Chen { 385af4b7fbSShuo Chen if (!started_) 395af4b7fbSShuo Chen { 405af4b7fbSShuo Chen started_ = true; 415af4b7fbSShuo Chen } 425af4b7fbSShuo Chen 435af4b7fbSShuo Chen if (!acceptor_->listenning()) 445af4b7fbSShuo Chen { 455af4b7fbSShuo Chen loop_->runInLoop( 465af4b7fbSShuo Chen boost::bind(&Acceptor::listen, get_pointer(acceptor_))); 475af4b7fbSShuo Chen } 485af4b7fbSShuo Chen } 495af4b7fbSShuo Chen 505af4b7fbSShuo Chen void TcpServer::newConnection(int sockfd, const InetAddress& peerAddr) 515af4b7fbSShuo Chen { 525af4b7fbSShuo Chen loop_->assertInLoopThread(); 535af4b7fbSShuo Chen char buf[32]; 545af4b7fbSShuo Chen snprintf(buf, sizeof buf, "#%d", nextConnId_); 555af4b7fbSShuo Chen ++nextConnId_; 565af4b7fbSShuo Chen std::string connName = name_ + buf; 575af4b7fbSShuo Chen 585af4b7fbSShuo Chen LOG_INFO << "TcpServer::newConnection [" << name_ 595af4b7fbSShuo Chen << "] - new connection [" << connName 605af4b7fbSShuo Chen << "] from " << peerAddr.toHostPort(); 615af4b7fbSShuo Chen InetAddress localAddr(sockets::getLocalAddr(sockfd)); 625af4b7fbSShuo Chen // FIXME poll with zero timeout to double confirm the new connection 635af4b7fbSShuo Chen TcpConnectionPtr conn( 645af4b7fbSShuo Chen new TcpConnection(loop_, connName, sockfd, localAddr, peerAddr)); 655af4b7fbSShuo Chen connections_[connName] = conn; 665af4b7fbSShuo Chen conn->setConnectionCallback(connectionCallback_); 675af4b7fbSShuo Chen conn->setMessageCallback(messageCallback_); 685af4b7fbSShuo Chen+ conn->setWriteCompleteCallback(writeCompleteCallback_); 695af4b7fbSShuo Chen conn->setCloseCallback( 705af4b7fbSShuo Chen boost::bind(&TcpServer::removeConnection, this, _1)); 715af4b7fbSShuo Chen conn->connectEstablished(); 725af4b7fbSShuo Chen } 735af4b7fbSShuo Chen 745af4b7fbSShuo Chen void TcpServer::removeConnection(const TcpConnectionPtr& conn) 755af4b7fbSShuo Chen { 765af4b7fbSShuo Chen loop_->assertInLoopThread(); 775af4b7fbSShuo Chen LOG_INFO << "TcpServer::removeConnection [" << name_ 785af4b7fbSShuo Chen << "] - connection " << conn->name(); 795af4b7fbSShuo Chen size_t n = connections_.erase(conn->name()); 805af4b7fbSShuo Chen assert(n == 1); (void)n; 815af4b7fbSShuo Chen loop_->queueInLoop( 825af4b7fbSShuo Chen boost::bind(&TcpConnection::connectDestroyed, conn)); 835af4b7fbSShuo Chen } 845af4b7fbSShuo Chen 85