12a18e699SShuo Chen// excerpts from http://code.google.com/p/muduo/ 22a18e699SShuo Chen// 32a18e699SShuo Chen// Use of this source code is governed by a BSD-style license 42a18e699SShuo Chen// that can be found in the License file. 52a18e699SShuo Chen// 62a18e699SShuo Chen// Author: Shuo Chen (chenshuo at chenshuo dot com) 72a18e699SShuo Chen 82a18e699SShuo Chen#include "TcpServer.h" 92a18e699SShuo Chen 102a18e699SShuo Chen#include "logging/Logging.h" 112a18e699SShuo Chen#include "Acceptor.h" 122a18e699SShuo Chen#include "EventLoop.h" 132a18e699SShuo Chen#include "SocketsOps.h" 142a18e699SShuo Chen 152a18e699SShuo Chen#include <boost/bind.hpp> 162a18e699SShuo Chen 172a18e699SShuo Chen#include <stdio.h> // snprintf 182a18e699SShuo Chen 192a18e699SShuo Chenusing namespace muduo; 202a18e699SShuo Chen 212a18e699SShuo ChenTcpServer::TcpServer(EventLoop* loop, const InetAddress& listenAddr) 222a18e699SShuo Chen : loop_(CHECK_NOTNULL(loop)), 232a18e699SShuo Chen name_(listenAddr.toHostPort()), 242a18e699SShuo Chen acceptor_(new Acceptor(loop, listenAddr)), 252a18e699SShuo Chen started_(false), 262a18e699SShuo Chen nextConnId_(1) 272a18e699SShuo Chen{ 282a18e699SShuo Chen acceptor_->setNewConnectionCallback( 292a18e699SShuo Chen boost::bind(&TcpServer::newConnection, this, _1, _2)); 302a18e699SShuo Chen} 312a18e699SShuo Chen 322a18e699SShuo ChenTcpServer::~TcpServer() 332a18e699SShuo Chen{ 342a18e699SShuo Chen} 352a18e699SShuo Chen 362a18e699SShuo Chenvoid TcpServer::start() 372a18e699SShuo Chen{ 382a18e699SShuo Chen if (!started_) 392a18e699SShuo Chen { 402a18e699SShuo Chen started_ = true; 412a18e699SShuo Chen } 422a18e699SShuo Chen 432a18e699SShuo Chen if (!acceptor_->listenning()) 442a18e699SShuo Chen { 452a18e699SShuo Chen loop_->runInLoop( 462a18e699SShuo Chen boost::bind(&Acceptor::listen, get_pointer(acceptor_))); 472a18e699SShuo Chen } 482a18e699SShuo Chen} 492a18e699SShuo Chen 502a18e699SShuo Chenvoid TcpServer::newConnection(int sockfd, const InetAddress& peerAddr) 512a18e699SShuo Chen{ 522a18e699SShuo Chen loop_->assertInLoopThread(); 532a18e699SShuo Chen char buf[32]; 542a18e699SShuo Chen snprintf(buf, sizeof buf, "#%d", nextConnId_); 552a18e699SShuo Chen ++nextConnId_; 562a18e699SShuo Chen std::string connName = name_ + buf; 572a18e699SShuo Chen 582a18e699SShuo Chen LOG_INFO << "TcpServer::newConnection [" << name_ 592a18e699SShuo Chen << "] - new connection [" << connName 602a18e699SShuo Chen << "] from " << peerAddr.toHostPort(); 612a18e699SShuo Chen InetAddress localAddr(sockets::getLocalAddr(sockfd)); 622a18e699SShuo Chen // FIXME poll with zero timeout to double confirm the new connection 632a18e699SShuo Chen TcpConnectionPtr conn( 642a18e699SShuo Chen new TcpConnection(loop_, connName, sockfd, localAddr, peerAddr)); 652a18e699SShuo Chen connections_[connName] = conn; 662a18e699SShuo Chen conn->setConnectionCallback(connectionCallback_); 672a18e699SShuo Chen conn->setMessageCallback(messageCallback_); 682a18e699SShuo Chen conn->setCloseCallback( 692a18e699SShuo Chen boost::bind(&TcpServer::removeConnection, this, _1)); 702a18e699SShuo Chen conn->connectEstablished(); 712a18e699SShuo Chen} 722a18e699SShuo Chen 732a18e699SShuo Chenvoid TcpServer::removeConnection(const TcpConnectionPtr& conn) 742a18e699SShuo Chen{ 752a18e699SShuo Chen loop_->assertInLoopThread(); 762a18e699SShuo Chen LOG_INFO << "TcpServer::removeConnection [" << name_ 772a18e699SShuo Chen << "] - connection " << conn->name(); 782a18e699SShuo Chen size_t n = connections_.erase(conn->name()); 792a18e699SShuo Chen assert(n == 1); (void)n; 802a18e699SShuo Chen loop_->queueInLoop( 812a18e699SShuo Chen boost::bind(&TcpConnection::connectDestroyed, conn)); 822a18e699SShuo Chen} 832a18e699SShuo Chen 84