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