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