165c497a3SShuo Chen// excerpts from http://code.google.com/p/muduo/
265c497a3SShuo Chen//
365c497a3SShuo Chen// Use of this source code is governed by a BSD-style license
465c497a3SShuo Chen// that can be found in the License file.
565c497a3SShuo Chen//
665c497a3SShuo Chen// Author: Shuo Chen (chenshuo at chenshuo dot com)
765c497a3SShuo Chen
865c497a3SShuo Chen#include "TcpServer.h"
965c497a3SShuo Chen
1065c497a3SShuo Chen#include "logging/Logging.h"
1165c497a3SShuo Chen#include "Acceptor.h"
1265c497a3SShuo Chen#include "EventLoop.h"
1365c497a3SShuo Chen#include "SocketsOps.h"
1465c497a3SShuo Chen
1565c497a3SShuo Chen#include <boost/bind.hpp>
1665c497a3SShuo Chen
1765c497a3SShuo Chen#include <stdio.h>  // snprintf
1865c497a3SShuo Chen
1965c497a3SShuo Chenusing namespace muduo;
2065c497a3SShuo Chen
2165c497a3SShuo ChenTcpServer::TcpServer(EventLoop* loop, const InetAddress& listenAddr)
2265c497a3SShuo Chen  : loop_(CHECK_NOTNULL(loop)),
2365c497a3SShuo Chen    name_(listenAddr.toHostPort()),
2465c497a3SShuo Chen    acceptor_(new Acceptor(loop, listenAddr)),
2565c497a3SShuo Chen    started_(false),
2665c497a3SShuo Chen    nextConnId_(1)
2765c497a3SShuo Chen{
2865c497a3SShuo Chen  acceptor_->setNewConnectionCallback(
2965c497a3SShuo Chen      boost::bind(&TcpServer::newConnection, this, _1, _2));
3065c497a3SShuo Chen}
3165c497a3SShuo Chen
3265c497a3SShuo ChenTcpServer::~TcpServer()
3365c497a3SShuo Chen{
3465c497a3SShuo Chen}
3565c497a3SShuo Chen
3665c497a3SShuo Chenvoid TcpServer::start()
3765c497a3SShuo Chen{
3865c497a3SShuo Chen  if (!started_)
3965c497a3SShuo Chen  {
4065c497a3SShuo Chen    started_ = true;
4165c497a3SShuo Chen  }
4265c497a3SShuo Chen
4365c497a3SShuo Chen  if (!acceptor_->listenning())
4465c497a3SShuo Chen  {
4565c497a3SShuo Chen    loop_->runInLoop(
4665c497a3SShuo Chen        boost::bind(&Acceptor::listen, get_pointer(acceptor_)));
4765c497a3SShuo Chen  }
4865c497a3SShuo Chen}
4965c497a3SShuo Chen
5065c497a3SShuo Chenvoid TcpServer::newConnection(int sockfd, const InetAddress& peerAddr)
5165c497a3SShuo Chen{
5265c497a3SShuo Chen  loop_->assertInLoopThread();
5365c497a3SShuo Chen  char buf[32];
5465c497a3SShuo Chen  snprintf(buf, sizeof buf, "#%d", nextConnId_);
5565c497a3SShuo Chen  ++nextConnId_;
5665c497a3SShuo Chen  std::string connName = name_ + buf;
5765c497a3SShuo Chen
5865c497a3SShuo Chen  LOG_INFO << "TcpServer::newConnection [" << name_
5965c497a3SShuo Chen           << "] - new connection [" << connName
6065c497a3SShuo Chen           << "] from " << peerAddr.toHostPort();
6165c497a3SShuo Chen  InetAddress localAddr(sockets::getLocalAddr(sockfd));
6265c497a3SShuo Chen  // FIXME poll with zero timeout to double confirm the new connection
6365c497a3SShuo Chen  TcpConnectionPtr conn(
6465c497a3SShuo Chen      new TcpConnection(loop_, connName, sockfd, localAddr, peerAddr));
6565c497a3SShuo Chen  connections_[connName] = conn;
6665c497a3SShuo Chen  conn->setConnectionCallback(connectionCallback_);
6765c497a3SShuo Chen  conn->setMessageCallback(messageCallback_);
6865c497a3SShuo Chen  conn->setCloseCallback(
6965c497a3SShuo Chen      boost::bind(&TcpServer::removeConnection, this, _1));
7065c497a3SShuo Chen  conn->connectEstablished();
7165c497a3SShuo Chen}
7265c497a3SShuo Chen
7365c497a3SShuo Chenvoid TcpServer::removeConnection(const TcpConnectionPtr& conn)
7465c497a3SShuo Chen{
7565c497a3SShuo Chen  loop_->assertInLoopThread();
7665c497a3SShuo Chen  LOG_INFO << "TcpServer::removeConnection [" << name_
7765c497a3SShuo Chen           << "] - connection " << conn->name();
7865c497a3SShuo Chen  size_t n = connections_.erase(conn->name());
7965c497a3SShuo Chen  assert(n == 1); (void)n;
8065c497a3SShuo Chen  loop_->queueInLoop(
8165c497a3SShuo Chen      boost::bind(&TcpConnection::connectDestroyed, conn));
8265c497a3SShuo Chen}
8365c497a3SShuo Chen
84