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->setCloseCallback(
69+      boost::bind(&TcpServer::removeConnection, this, _1));
70   conn->connectEstablished();
71 }
72 
73+void TcpServer::removeConnection(const TcpConnectionPtr& conn)
74+{
75+  loop_->assertInLoopThread();
76+  LOG_INFO << "TcpServer::removeConnection [" << name_
77+           << "] - connection " << conn->name();
78+  size_t n = connections_.erase(conn->name());
79+  assert(n == 1); (void)n;
80+  loop_->queueInLoop(
81+      boost::bind(&TcpConnection::connectDestroyed, conn));
82+}
83+
84