TcpServer.cc revision 354280cf
1354280cfSShuo Chen// excerpts from http://code.google.com/p/muduo/ 2354280cfSShuo Chen// 3354280cfSShuo Chen// Use of this source code is governed by a BSD-style license 4354280cfSShuo Chen// that can be found in the License file. 5354280cfSShuo Chen// 6354280cfSShuo Chen// Author: Shuo Chen (chenshuo at chenshuo dot com) 7354280cfSShuo Chen 8354280cfSShuo Chen#include "TcpServer.h" 9354280cfSShuo Chen 10354280cfSShuo Chen#include "logging/Logging.h" 11354280cfSShuo Chen#include "Acceptor.h" 12354280cfSShuo Chen#include "EventLoop.h" 13354280cfSShuo Chen#include "EventLoopThreadPool.h" 14354280cfSShuo Chen#include "SocketsOps.h" 15354280cfSShuo Chen 16354280cfSShuo Chen#include <boost/bind.hpp> 17354280cfSShuo Chen 18354280cfSShuo Chen#include <stdio.h> // snprintf 19354280cfSShuo Chen 20354280cfSShuo Chenusing namespace muduo; 21354280cfSShuo Chen 22354280cfSShuo ChenTcpServer::TcpServer(EventLoop* loop, const InetAddress& listenAddr) 23354280cfSShuo Chen : loop_(CHECK_NOTNULL(loop)), 24354280cfSShuo Chen name_(listenAddr.toHostPort()), 25354280cfSShuo Chen acceptor_(new Acceptor(loop, listenAddr)), 26354280cfSShuo Chen threadPool_(new EventLoopThreadPool(loop)), 27354280cfSShuo Chen started_(false), 28354280cfSShuo Chen nextConnId_(1) 29354280cfSShuo Chen{ 30354280cfSShuo Chen acceptor_->setNewConnectionCallback( 31354280cfSShuo Chen boost::bind(&TcpServer::newConnection, this, _1, _2)); 32354280cfSShuo Chen} 33354280cfSShuo Chen 34354280cfSShuo ChenTcpServer::~TcpServer() 35354280cfSShuo Chen{ 36354280cfSShuo Chen} 37354280cfSShuo Chen 38354280cfSShuo Chenvoid TcpServer::setThreadNum(int numThreads) 39354280cfSShuo Chen{ 40354280cfSShuo Chen assert(0 <= numThreads); 41354280cfSShuo Chen threadPool_->setThreadNum(numThreads); 42354280cfSShuo Chen} 43354280cfSShuo Chen 44354280cfSShuo Chenvoid TcpServer::start() 45354280cfSShuo Chen{ 46354280cfSShuo Chen if (!started_) 47354280cfSShuo Chen { 48354280cfSShuo Chen started_ = true; 49354280cfSShuo Chen threadPool_->start(); 50354280cfSShuo Chen } 51354280cfSShuo Chen 52354280cfSShuo Chen if (!acceptor_->listenning()) 53354280cfSShuo Chen { 54354280cfSShuo Chen loop_->runInLoop( 55354280cfSShuo Chen boost::bind(&Acceptor::listen, get_pointer(acceptor_))); 56354280cfSShuo Chen } 57354280cfSShuo Chen} 58354280cfSShuo Chen 59354280cfSShuo Chenvoid TcpServer::newConnection(int sockfd, const InetAddress& peerAddr) 60354280cfSShuo Chen{ 61354280cfSShuo Chen loop_->assertInLoopThread(); 62354280cfSShuo Chen char buf[32]; 63354280cfSShuo Chen snprintf(buf, sizeof buf, "#%d", nextConnId_); 64354280cfSShuo Chen ++nextConnId_; 65354280cfSShuo Chen std::string connName = name_ + buf; 66354280cfSShuo Chen 67354280cfSShuo Chen LOG_INFO << "TcpServer::newConnection [" << name_ 68354280cfSShuo Chen << "] - new connection [" << connName 69354280cfSShuo Chen << "] from " << peerAddr.toHostPort(); 70354280cfSShuo Chen InetAddress localAddr(sockets::getLocalAddr(sockfd)); 71354280cfSShuo Chen // FIXME poll with zero timeout to double confirm the new connection 72354280cfSShuo Chen EventLoop* ioLoop = threadPool_->getNextLoop(); 73354280cfSShuo Chen TcpConnectionPtr conn( 74354280cfSShuo Chen new TcpConnection(ioLoop, connName, sockfd, localAddr, peerAddr)); 75354280cfSShuo Chen connections_[connName] = conn; 76354280cfSShuo Chen conn->setConnectionCallback(connectionCallback_); 77354280cfSShuo Chen conn->setMessageCallback(messageCallback_); 78354280cfSShuo Chen conn->setWriteCompleteCallback(writeCompleteCallback_); 79354280cfSShuo Chen conn->setCloseCallback( 80354280cfSShuo Chen boost::bind(&TcpServer::removeConnection, this, _1)); // FIXME: unsafe 81354280cfSShuo Chen ioLoop->runInLoop(boost::bind(&TcpConnection::connectEstablished, conn)); 82354280cfSShuo Chen} 83354280cfSShuo Chen 84354280cfSShuo Chenvoid TcpServer::removeConnection(const TcpConnectionPtr& conn) 85354280cfSShuo Chen{ 86354280cfSShuo Chen // FIXME: unsafe 87354280cfSShuo Chen loop_->runInLoop(boost::bind(&TcpServer::removeConnectionInLoop, this, conn)); 88354280cfSShuo Chen} 89354280cfSShuo Chen 90354280cfSShuo Chenvoid TcpServer::removeConnectionInLoop(const TcpConnectionPtr& conn) 91354280cfSShuo Chen{ 92354280cfSShuo Chen loop_->assertInLoopThread(); 93354280cfSShuo Chen LOG_INFO << "TcpServer::removeConnectionInLoop [" << name_ 94354280cfSShuo Chen << "] - connection " << conn->name(); 95354280cfSShuo Chen size_t n = connections_.erase(conn->name()); 96354280cfSShuo Chen assert(n == 1); (void)n; 97354280cfSShuo Chen EventLoop* ioLoop = conn->getLoop(); 98354280cfSShuo Chen ioLoop->queueInLoop( 99354280cfSShuo Chen boost::bind(&TcpConnection::connectDestroyed, conn)); 100354280cfSShuo Chen} 101354280cfSShuo Chen 102