140161064SShuo Chen// excerpts from http://code.google.com/p/muduo/ 240161064SShuo Chen// 340161064SShuo Chen// Use of this source code is governed by a BSD-style license 440161064SShuo Chen// that can be found in the License file. 540161064SShuo Chen// 640161064SShuo Chen// Author: Shuo Chen (chenshuo at chenshuo dot com) 740161064SShuo Chen 840161064SShuo Chen#include "TcpServer.h" 940161064SShuo Chen 1040161064SShuo Chen#include "logging/Logging.h" 1140161064SShuo Chen#include "Acceptor.h" 1240161064SShuo Chen#include "EventLoop.h" 1340161064SShuo Chen#include "EventLoopThreadPool.h" 1440161064SShuo Chen#include "SocketsOps.h" 1540161064SShuo Chen 1640161064SShuo Chen#include <boost/bind.hpp> 1740161064SShuo Chen 1840161064SShuo Chen#include <stdio.h> // snprintf 1940161064SShuo Chen 2040161064SShuo Chenusing namespace muduo; 2140161064SShuo Chen 2240161064SShuo ChenTcpServer::TcpServer(EventLoop* loop, const InetAddress& listenAddr) 2340161064SShuo Chen : loop_(CHECK_NOTNULL(loop)), 2440161064SShuo Chen name_(listenAddr.toHostPort()), 2540161064SShuo Chen acceptor_(new Acceptor(loop, listenAddr)), 2640161064SShuo Chen threadPool_(new EventLoopThreadPool(loop)), 2740161064SShuo Chen started_(false), 2840161064SShuo Chen nextConnId_(1) 2940161064SShuo Chen{ 3040161064SShuo Chen acceptor_->setNewConnectionCallback( 3140161064SShuo Chen boost::bind(&TcpServer::newConnection, this, _1, _2)); 3240161064SShuo Chen} 3340161064SShuo Chen 3440161064SShuo ChenTcpServer::~TcpServer() 3540161064SShuo Chen{ 3640161064SShuo Chen} 3740161064SShuo Chen 3840161064SShuo Chenvoid TcpServer::setThreadNum(int numThreads) 3940161064SShuo Chen{ 4040161064SShuo Chen assert(0 <= numThreads); 4140161064SShuo Chen threadPool_->setThreadNum(numThreads); 4240161064SShuo Chen} 4340161064SShuo Chen 4440161064SShuo Chenvoid TcpServer::start() 4540161064SShuo Chen{ 4640161064SShuo Chen if (!started_) 4740161064SShuo Chen { 4840161064SShuo Chen started_ = true; 4940161064SShuo Chen threadPool_->start(); 5040161064SShuo Chen } 5140161064SShuo Chen 5240161064SShuo Chen if (!acceptor_->listenning()) 5340161064SShuo Chen { 5440161064SShuo Chen loop_->runInLoop( 5540161064SShuo Chen boost::bind(&Acceptor::listen, get_pointer(acceptor_))); 5640161064SShuo Chen } 5740161064SShuo Chen} 5840161064SShuo Chen 5940161064SShuo Chenvoid TcpServer::newConnection(int sockfd, const InetAddress& peerAddr) 6040161064SShuo Chen{ 6140161064SShuo Chen loop_->assertInLoopThread(); 6240161064SShuo Chen char buf[32]; 6340161064SShuo Chen snprintf(buf, sizeof buf, "#%d", nextConnId_); 6440161064SShuo Chen ++nextConnId_; 6540161064SShuo Chen std::string connName = name_ + buf; 6640161064SShuo Chen 6740161064SShuo Chen LOG_INFO << "TcpServer::newConnection [" << name_ 6840161064SShuo Chen << "] - new connection [" << connName 6940161064SShuo Chen << "] from " << peerAddr.toHostPort(); 7040161064SShuo Chen InetAddress localAddr(sockets::getLocalAddr(sockfd)); 7140161064SShuo Chen // FIXME poll with zero timeout to double confirm the new connection 7240161064SShuo Chen EventLoop* ioLoop = threadPool_->getNextLoop(); 7340161064SShuo Chen TcpConnectionPtr conn( 7440161064SShuo Chen new TcpConnection(ioLoop, connName, sockfd, localAddr, peerAddr)); 7540161064SShuo Chen connections_[connName] = conn; 7640161064SShuo Chen conn->setConnectionCallback(connectionCallback_); 7740161064SShuo Chen conn->setMessageCallback(messageCallback_); 7840161064SShuo Chen conn->setWriteCompleteCallback(writeCompleteCallback_); 7940161064SShuo Chen conn->setCloseCallback( 8040161064SShuo Chen boost::bind(&TcpServer::removeConnection, this, _1)); // FIXME: unsafe 8140161064SShuo Chen ioLoop->runInLoop(boost::bind(&TcpConnection::connectEstablished, conn)); 8240161064SShuo Chen} 8340161064SShuo Chen 8440161064SShuo Chenvoid TcpServer::removeConnection(const TcpConnectionPtr& conn) 8540161064SShuo Chen{ 8640161064SShuo Chen // FIXME: unsafe 8740161064SShuo Chen loop_->runInLoop(boost::bind(&TcpServer::removeConnectionInLoop, this, conn)); 8840161064SShuo Chen} 8940161064SShuo Chen 9040161064SShuo Chenvoid TcpServer::removeConnectionInLoop(const TcpConnectionPtr& conn) 9140161064SShuo Chen{ 9240161064SShuo Chen loop_->assertInLoopThread(); 9340161064SShuo Chen LOG_INFO << "TcpServer::removeConnectionInLoop [" << name_ 9440161064SShuo Chen << "] - connection " << conn->name(); 9540161064SShuo Chen size_t n = connections_.erase(conn->name()); 9640161064SShuo Chen assert(n == 1); (void)n; 9740161064SShuo Chen EventLoop* ioLoop = conn->getLoop(); 9840161064SShuo Chen ioLoop->queueInLoop( 9940161064SShuo Chen boost::bind(&TcpConnection::connectDestroyed, conn)); 10040161064SShuo Chen} 10140161064SShuo Chen 102