1048f6023SShuo Chen // excerpts from http://code.google.com/p/muduo/
2048f6023SShuo Chen //
3048f6023SShuo Chen // Use of this source code is governed by a BSD-style license
4048f6023SShuo Chen // that can be found in the License file.
5048f6023SShuo Chen //
6048f6023SShuo Chen // Author: Shuo Chen (chenshuo at chenshuo dot com)
7048f6023SShuo Chen 
8048f6023SShuo Chen #include "TcpServer.h"
9048f6023SShuo Chen 
10048f6023SShuo Chen #include "logging/Logging.h"
11048f6023SShuo Chen #include "Acceptor.h"
12048f6023SShuo Chen #include "EventLoop.h"
13048f6023SShuo Chen #include "SocketsOps.h"
14048f6023SShuo Chen 
15048f6023SShuo Chen #include <boost/bind.hpp>
16048f6023SShuo Chen 
17048f6023SShuo Chen #include <stdio.h>  // snprintf
18048f6023SShuo Chen 
19048f6023SShuo Chen using namespace muduo;
20048f6023SShuo Chen 
21048f6023SShuo Chen TcpServer::TcpServer(EventLoop* loop, const InetAddress& listenAddr)
22048f6023SShuo Chen   : loop_(CHECK_NOTNULL(loop)),
23048f6023SShuo Chen     name_(listenAddr.toHostPort()),
24048f6023SShuo Chen     acceptor_(new Acceptor(loop, listenAddr)),
25048f6023SShuo Chen     started_(false),
26048f6023SShuo Chen     nextConnId_(1)
27048f6023SShuo Chen {
28048f6023SShuo Chen   acceptor_->setNewConnectionCallback(
29048f6023SShuo Chen       boost::bind(&TcpServer::newConnection, this, _1, _2));
30048f6023SShuo Chen }
31048f6023SShuo Chen 
32048f6023SShuo Chen TcpServer::~TcpServer()
33048f6023SShuo Chen {
34048f6023SShuo Chen }
35048f6023SShuo Chen 
36048f6023SShuo Chen void TcpServer::start()
37048f6023SShuo Chen {
38048f6023SShuo Chen   if (!started_)
39048f6023SShuo Chen   {
40048f6023SShuo Chen     started_ = true;
41048f6023SShuo Chen   }
42048f6023SShuo Chen 
43048f6023SShuo Chen   if (!acceptor_->listenning())
44048f6023SShuo Chen   {
45048f6023SShuo Chen     loop_->runInLoop(
46048f6023SShuo Chen         boost::bind(&Acceptor::listen, get_pointer(acceptor_)));
47048f6023SShuo Chen   }
48048f6023SShuo Chen }
49048f6023SShuo Chen 
50048f6023SShuo Chen void TcpServer::newConnection(int sockfd, const InetAddress& peerAddr)
51048f6023SShuo Chen {
52048f6023SShuo Chen   loop_->assertInLoopThread();
53048f6023SShuo Chen   char buf[32];
54048f6023SShuo Chen   snprintf(buf, sizeof buf, "#%d", nextConnId_);
55048f6023SShuo Chen   ++nextConnId_;
56048f6023SShuo Chen   std::string connName = name_ + buf;
57048f6023SShuo Chen 
58048f6023SShuo Chen   LOG_INFO << "TcpServer::newConnection [" << name_
59048f6023SShuo Chen            << "] - new connection [" << connName
60048f6023SShuo Chen            << "] from " << peerAddr.toHostPort();
61048f6023SShuo Chen   InetAddress localAddr(sockets::getLocalAddr(sockfd));
62048f6023SShuo Chen   // FIXME poll with zero timeout to double confirm the new connection
63048f6023SShuo Chen   TcpConnectionPtr conn(
64048f6023SShuo Chen       new TcpConnection(loop_, connName, sockfd, localAddr, peerAddr));
65048f6023SShuo Chen   connections_[connName] = conn;
66048f6023SShuo Chen   conn->setConnectionCallback(connectionCallback_);
67048f6023SShuo Chen   conn->setMessageCallback(messageCallback_);
68048f6023SShuo Chen+  conn->setCloseCallback(
69048f6023SShuo Chen+      boost::bind(&TcpServer::removeConnection, this, _1));
70048f6023SShuo Chen   conn->connectEstablished();
71048f6023SShuo Chen }
72048f6023SShuo Chen 
73048f6023SShuo Chen+void TcpServer::removeConnection(const TcpConnectionPtr& conn)
74048f6023SShuo Chen+{
75048f6023SShuo Chen+  loop_->assertInLoopThread();
76048f6023SShuo Chen+  LOG_INFO << "TcpServer::removeConnection [" << name_
77048f6023SShuo Chen+           << "] - connection " << conn->name();
78048f6023SShuo Chen+  size_t n = connections_.erase(conn->name());
79048f6023SShuo Chen+  assert(n == 1); (void)n;
80048f6023SShuo Chen+  loop_->queueInLoop(
81048f6023SShuo Chen+      boost::bind(&TcpConnection::connectDestroyed, conn));
82048f6023SShuo Chen+}
83048f6023SShuo Chen+
84