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