1e254a845SShuo Chen// excerpts from http://code.google.com/p/muduo/ 2e254a845SShuo Chen// 3e254a845SShuo Chen// Use of this source code is governed by a BSD-style license 4e254a845SShuo Chen// that can be found in the License file. 5e254a845SShuo Chen// 6e254a845SShuo Chen// Author: Shuo Chen (chenshuo at chenshuo dot com) 7e254a845SShuo Chen 8e254a845SShuo Chen#include "TcpServer.h" 9e254a845SShuo Chen 10e254a845SShuo Chen#include "logging/Logging.h" 11e254a845SShuo Chen#include "Acceptor.h" 12e254a845SShuo Chen#include "EventLoop.h" 1399dd5949SShuo Chen#include "EventLoopThreadPool.h" 14e254a845SShuo Chen#include "SocketsOps.h" 15e254a845SShuo Chen 16e254a845SShuo Chen#include <boost/bind.hpp> 17e254a845SShuo Chen 18e254a845SShuo Chen#include <stdio.h> // snprintf 19e254a845SShuo Chen 20e254a845SShuo Chenusing namespace muduo; 21e254a845SShuo Chen 22e254a845SShuo ChenTcpServer::TcpServer(EventLoop* loop, const InetAddress& listenAddr) 23e254a845SShuo Chen : loop_(CHECK_NOTNULL(loop)), 24e254a845SShuo Chen name_(listenAddr.toHostPort()), 25e254a845SShuo Chen acceptor_(new Acceptor(loop, listenAddr)), 2699dd5949SShuo Chen threadPool_(new EventLoopThreadPool(loop)), 27e254a845SShuo Chen started_(false), 28e254a845SShuo Chen nextConnId_(1) 29e254a845SShuo Chen{ 30e254a845SShuo Chen acceptor_->setNewConnectionCallback( 31e254a845SShuo Chen boost::bind(&TcpServer::newConnection, this, _1, _2)); 32e254a845SShuo Chen} 33e254a845SShuo Chen 34e254a845SShuo ChenTcpServer::~TcpServer() 35e254a845SShuo Chen{ 36e254a845SShuo Chen} 37e254a845SShuo Chen 3899dd5949SShuo Chenvoid TcpServer::setThreadNum(int numThreads) 3999dd5949SShuo Chen{ 4099dd5949SShuo Chen assert(0 <= numThreads); 4199dd5949SShuo Chen threadPool_->setThreadNum(numThreads); 4299dd5949SShuo Chen} 4399dd5949SShuo Chen 44e254a845SShuo Chenvoid TcpServer::start() 45e254a845SShuo Chen{ 46e254a845SShuo Chen if (!started_) 47e254a845SShuo Chen { 48e254a845SShuo Chen started_ = true; 4999dd5949SShuo Chen threadPool_->start(); 50e254a845SShuo Chen } 51e254a845SShuo Chen 52e254a845SShuo Chen if (!acceptor_->listenning()) 53e254a845SShuo Chen { 54e254a845SShuo Chen loop_->runInLoop( 55e254a845SShuo Chen boost::bind(&Acceptor::listen, get_pointer(acceptor_))); 56e254a845SShuo Chen } 57e254a845SShuo Chen} 58e254a845SShuo Chen 59e254a845SShuo Chenvoid TcpServer::newConnection(int sockfd, const InetAddress& peerAddr) 60e254a845SShuo Chen{ 61e254a845SShuo Chen loop_->assertInLoopThread(); 62e254a845SShuo Chen char buf[32]; 63e254a845SShuo Chen snprintf(buf, sizeof buf, "#%d", nextConnId_); 64e254a845SShuo Chen ++nextConnId_; 65e254a845SShuo Chen std::string connName = name_ + buf; 66e254a845SShuo Chen 67e254a845SShuo Chen LOG_INFO << "TcpServer::newConnection [" << name_ 68e254a845SShuo Chen << "] - new connection [" << connName 69e254a845SShuo Chen << "] from " << peerAddr.toHostPort(); 70e254a845SShuo Chen InetAddress localAddr(sockets::getLocalAddr(sockfd)); 71e254a845SShuo Chen // FIXME poll with zero timeout to double confirm the new connection 7299dd5949SShuo Chen EventLoop* ioLoop = threadPool_->getNextLoop(); 73e254a845SShuo Chen TcpConnectionPtr conn( 7499dd5949SShuo Chen new TcpConnection(ioLoop, connName, sockfd, localAddr, peerAddr)); 75e254a845SShuo Chen connections_[connName] = conn; 76e254a845SShuo Chen conn->setConnectionCallback(connectionCallback_); 77e254a845SShuo Chen conn->setMessageCallback(messageCallback_); 78e254a845SShuo Chen conn->setWriteCompleteCallback(writeCompleteCallback_); 79e254a845SShuo Chen conn->setCloseCallback( 8099dd5949SShuo Chen boost::bind(&TcpServer::removeConnection, this, _1)); // FIXME: unsafe 8199dd5949SShuo Chen ioLoop->runInLoop(boost::bind(&TcpConnection::connectEstablished, conn)); 82e254a845SShuo Chen} 83e254a845SShuo Chen 84e254a845SShuo Chenvoid TcpServer::removeConnection(const TcpConnectionPtr& conn) 85e254a845SShuo Chen{ 8699dd5949SShuo Chen // FIXME: unsafe 8799dd5949SShuo Chen loop_->runInLoop(boost::bind(&TcpServer::removeConnectionInLoop, this, conn)); 8899dd5949SShuo Chen} 8999dd5949SShuo Chen 9099dd5949SShuo Chenvoid TcpServer::removeConnectionInLoop(const TcpConnectionPtr& conn) 9199dd5949SShuo Chen{ 92e254a845SShuo Chen loop_->assertInLoopThread(); 9399dd5949SShuo Chen LOG_INFO << "TcpServer::removeConnectionInLoop [" << name_ 94e254a845SShuo Chen << "] - connection " << conn->name(); 95e254a845SShuo Chen size_t n = connections_.erase(conn->name()); 96e254a845SShuo Chen assert(n == 1); (void)n; 9799dd5949SShuo Chen EventLoop* ioLoop = conn->getLoop(); 9899dd5949SShuo Chen ioLoop->queueInLoop( 99e254a845SShuo Chen boost::bind(&TcpConnection::connectDestroyed, conn)); 100e254a845SShuo Chen} 101e254a845SShuo Chen 102