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