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 "SocketsOps.h" 14 15 #include <boost/bind.hpp> 16 17 #include <stdio.h> // snprintf 18 19 using namespace muduo; 20 21 TcpServer::TcpServer(EventLoop* loop, const InetAddress& listenAddr) 22 : loop_(CHECK_NOTNULL(loop)), 23 name_(listenAddr.toHostPort()), 24 acceptor_(new Acceptor(loop, listenAddr)), 25 started_(false), 26 nextConnId_(1) 27 { 28 acceptor_->setNewConnectionCallback( 29 boost::bind(&TcpServer::newConnection, this, _1, _2)); 30 } 31 32 TcpServer::~TcpServer() 33 { 34 } 35 36 void TcpServer::start() 37 { 38 if (!started_) 39 { 40 started_ = true; 41 } 42 43 if (!acceptor_->listenning()) 44 { 45 loop_->runInLoop( 46 boost::bind(&Acceptor::listen, get_pointer(acceptor_))); 47 } 48 } 49 50 void TcpServer::newConnection(int sockfd, const InetAddress& peerAddr) 51 { 52 loop_->assertInLoopThread(); 53 char buf[32]; 54 snprintf(buf, sizeof buf, "#%d", nextConnId_); 55 ++nextConnId_; 56 std::string connName = name_ + buf; 57 58 LOG_INFO << "TcpServer::newConnection [" << name_ 59 << "] - new connection [" << connName 60 << "] from " << peerAddr.toHostPort(); 61 InetAddress localAddr(sockets::getLocalAddr(sockfd)); 62 // FIXME poll with zero timeout to double confirm the new connection 63 TcpConnectionPtr conn( 64 new TcpConnection(loop_, connName, sockfd, localAddr, peerAddr)); 65 connections_[connName] = conn; 66 conn->setConnectionCallback(connectionCallback_); 67 conn->setMessageCallback(messageCallback_); 68+ conn->setWriteCompleteCallback(writeCompleteCallback_); 69 conn->setCloseCallback( 70 boost::bind(&TcpServer::removeConnection, this, _1)); 71 conn->connectEstablished(); 72 } 73 74 void TcpServer::removeConnection(const TcpConnectionPtr& conn) 75 { 76 loop_->assertInLoopThread(); 77 LOG_INFO << "TcpServer::removeConnection [" << name_ 78 << "] - connection " << conn->name(); 79 size_t n = connections_.erase(conn->name()); 80 assert(n == 1); (void)n; 81 loop_->queueInLoop( 82 boost::bind(&TcpConnection::connectDestroyed, conn)); 83 } 84 85