TcpServer.cc revision 354280cf
1354280cfSShuo Chen// excerpts from http://code.google.com/p/muduo/
2354280cfSShuo Chen//
3354280cfSShuo Chen// Use of this source code is governed by a BSD-style license
4354280cfSShuo Chen// that can be found in the License file.
5354280cfSShuo Chen//
6354280cfSShuo Chen// Author: Shuo Chen (chenshuo at chenshuo dot com)
7354280cfSShuo Chen
8354280cfSShuo Chen#include "TcpServer.h"
9354280cfSShuo Chen
10354280cfSShuo Chen#include "logging/Logging.h"
11354280cfSShuo Chen#include "Acceptor.h"
12354280cfSShuo Chen#include "EventLoop.h"
13354280cfSShuo Chen#include "EventLoopThreadPool.h"
14354280cfSShuo Chen#include "SocketsOps.h"
15354280cfSShuo Chen
16354280cfSShuo Chen#include <boost/bind.hpp>
17354280cfSShuo Chen
18354280cfSShuo Chen#include <stdio.h>  // snprintf
19354280cfSShuo Chen
20354280cfSShuo Chenusing namespace muduo;
21354280cfSShuo Chen
22354280cfSShuo ChenTcpServer::TcpServer(EventLoop* loop, const InetAddress& listenAddr)
23354280cfSShuo Chen  : loop_(CHECK_NOTNULL(loop)),
24354280cfSShuo Chen    name_(listenAddr.toHostPort()),
25354280cfSShuo Chen    acceptor_(new Acceptor(loop, listenAddr)),
26354280cfSShuo Chen    threadPool_(new EventLoopThreadPool(loop)),
27354280cfSShuo Chen    started_(false),
28354280cfSShuo Chen    nextConnId_(1)
29354280cfSShuo Chen{
30354280cfSShuo Chen  acceptor_->setNewConnectionCallback(
31354280cfSShuo Chen      boost::bind(&TcpServer::newConnection, this, _1, _2));
32354280cfSShuo Chen}
33354280cfSShuo Chen
34354280cfSShuo ChenTcpServer::~TcpServer()
35354280cfSShuo Chen{
36354280cfSShuo Chen}
37354280cfSShuo Chen
38354280cfSShuo Chenvoid TcpServer::setThreadNum(int numThreads)
39354280cfSShuo Chen{
40354280cfSShuo Chen  assert(0 <= numThreads);
41354280cfSShuo Chen  threadPool_->setThreadNum(numThreads);
42354280cfSShuo Chen}
43354280cfSShuo Chen
44354280cfSShuo Chenvoid TcpServer::start()
45354280cfSShuo Chen{
46354280cfSShuo Chen  if (!started_)
47354280cfSShuo Chen  {
48354280cfSShuo Chen    started_ = true;
49354280cfSShuo Chen    threadPool_->start();
50354280cfSShuo Chen  }
51354280cfSShuo Chen
52354280cfSShuo Chen  if (!acceptor_->listenning())
53354280cfSShuo Chen  {
54354280cfSShuo Chen    loop_->runInLoop(
55354280cfSShuo Chen        boost::bind(&Acceptor::listen, get_pointer(acceptor_)));
56354280cfSShuo Chen  }
57354280cfSShuo Chen}
58354280cfSShuo Chen
59354280cfSShuo Chenvoid TcpServer::newConnection(int sockfd, const InetAddress& peerAddr)
60354280cfSShuo Chen{
61354280cfSShuo Chen  loop_->assertInLoopThread();
62354280cfSShuo Chen  char buf[32];
63354280cfSShuo Chen  snprintf(buf, sizeof buf, "#%d", nextConnId_);
64354280cfSShuo Chen  ++nextConnId_;
65354280cfSShuo Chen  std::string connName = name_ + buf;
66354280cfSShuo Chen
67354280cfSShuo Chen  LOG_INFO << "TcpServer::newConnection [" << name_
68354280cfSShuo Chen           << "] - new connection [" << connName
69354280cfSShuo Chen           << "] from " << peerAddr.toHostPort();
70354280cfSShuo Chen  InetAddress localAddr(sockets::getLocalAddr(sockfd));
71354280cfSShuo Chen  // FIXME poll with zero timeout to double confirm the new connection
72354280cfSShuo Chen  EventLoop* ioLoop = threadPool_->getNextLoop();
73354280cfSShuo Chen  TcpConnectionPtr conn(
74354280cfSShuo Chen      new TcpConnection(ioLoop, connName, sockfd, localAddr, peerAddr));
75354280cfSShuo Chen  connections_[connName] = conn;
76354280cfSShuo Chen  conn->setConnectionCallback(connectionCallback_);
77354280cfSShuo Chen  conn->setMessageCallback(messageCallback_);
78354280cfSShuo Chen  conn->setWriteCompleteCallback(writeCompleteCallback_);
79354280cfSShuo Chen  conn->setCloseCallback(
80354280cfSShuo Chen      boost::bind(&TcpServer::removeConnection, this, _1)); // FIXME: unsafe
81354280cfSShuo Chen  ioLoop->runInLoop(boost::bind(&TcpConnection::connectEstablished, conn));
82354280cfSShuo Chen}
83354280cfSShuo Chen
84354280cfSShuo Chenvoid TcpServer::removeConnection(const TcpConnectionPtr& conn)
85354280cfSShuo Chen{
86354280cfSShuo Chen  // FIXME: unsafe
87354280cfSShuo Chen  loop_->runInLoop(boost::bind(&TcpServer::removeConnectionInLoop, this, conn));
88354280cfSShuo Chen}
89354280cfSShuo Chen
90354280cfSShuo Chenvoid TcpServer::removeConnectionInLoop(const TcpConnectionPtr& conn)
91354280cfSShuo Chen{
92354280cfSShuo Chen  loop_->assertInLoopThread();
93354280cfSShuo Chen  LOG_INFO << "TcpServer::removeConnectionInLoop [" << name_
94354280cfSShuo Chen           << "] - connection " << conn->name();
95354280cfSShuo Chen  size_t n = connections_.erase(conn->name());
96354280cfSShuo Chen  assert(n == 1); (void)n;
97354280cfSShuo Chen  EventLoop* ioLoop = conn->getLoop();
98354280cfSShuo Chen  ioLoop->queueInLoop(
99354280cfSShuo Chen      boost::bind(&TcpConnection::connectDestroyed, conn));
100354280cfSShuo Chen}
101354280cfSShuo Chen
102