15af4b7fbSShuo Chen // excerpts from http://code.google.com/p/muduo/
25af4b7fbSShuo Chen //
35af4b7fbSShuo Chen // Use of this source code is governed by a BSD-style license
45af4b7fbSShuo Chen // that can be found in the License file.
55af4b7fbSShuo Chen //
65af4b7fbSShuo Chen // Author: Shuo Chen (chenshuo at chenshuo dot com)
75af4b7fbSShuo Chen 
85af4b7fbSShuo Chen #include "TcpServer.h"
95af4b7fbSShuo Chen 
105af4b7fbSShuo Chen #include "logging/Logging.h"
115af4b7fbSShuo Chen #include "Acceptor.h"
125af4b7fbSShuo Chen #include "EventLoop.h"
135af4b7fbSShuo Chen #include "SocketsOps.h"
145af4b7fbSShuo Chen 
155af4b7fbSShuo Chen #include <boost/bind.hpp>
165af4b7fbSShuo Chen 
175af4b7fbSShuo Chen #include <stdio.h>  // snprintf
185af4b7fbSShuo Chen 
195af4b7fbSShuo Chen using namespace muduo;
205af4b7fbSShuo Chen 
215af4b7fbSShuo Chen TcpServer::TcpServer(EventLoop* loop, const InetAddress& listenAddr)
225af4b7fbSShuo Chen   : loop_(CHECK_NOTNULL(loop)),
235af4b7fbSShuo Chen     name_(listenAddr.toHostPort()),
245af4b7fbSShuo Chen     acceptor_(new Acceptor(loop, listenAddr)),
255af4b7fbSShuo Chen     started_(false),
265af4b7fbSShuo Chen     nextConnId_(1)
275af4b7fbSShuo Chen {
285af4b7fbSShuo Chen   acceptor_->setNewConnectionCallback(
295af4b7fbSShuo Chen       boost::bind(&TcpServer::newConnection, this, _1, _2));
305af4b7fbSShuo Chen }
315af4b7fbSShuo Chen 
325af4b7fbSShuo Chen TcpServer::~TcpServer()
335af4b7fbSShuo Chen {
345af4b7fbSShuo Chen }
355af4b7fbSShuo Chen 
365af4b7fbSShuo Chen void TcpServer::start()
375af4b7fbSShuo Chen {
385af4b7fbSShuo Chen   if (!started_)
395af4b7fbSShuo Chen   {
405af4b7fbSShuo Chen     started_ = true;
415af4b7fbSShuo Chen   }
425af4b7fbSShuo Chen 
435af4b7fbSShuo Chen   if (!acceptor_->listenning())
445af4b7fbSShuo Chen   {
455af4b7fbSShuo Chen     loop_->runInLoop(
465af4b7fbSShuo Chen         boost::bind(&Acceptor::listen, get_pointer(acceptor_)));
475af4b7fbSShuo Chen   }
485af4b7fbSShuo Chen }
495af4b7fbSShuo Chen 
505af4b7fbSShuo Chen void TcpServer::newConnection(int sockfd, const InetAddress& peerAddr)
515af4b7fbSShuo Chen {
525af4b7fbSShuo Chen   loop_->assertInLoopThread();
535af4b7fbSShuo Chen   char buf[32];
545af4b7fbSShuo Chen   snprintf(buf, sizeof buf, "#%d", nextConnId_);
555af4b7fbSShuo Chen   ++nextConnId_;
565af4b7fbSShuo Chen   std::string connName = name_ + buf;
575af4b7fbSShuo Chen 
585af4b7fbSShuo Chen   LOG_INFO << "TcpServer::newConnection [" << name_
595af4b7fbSShuo Chen            << "] - new connection [" << connName
605af4b7fbSShuo Chen            << "] from " << peerAddr.toHostPort();
615af4b7fbSShuo Chen   InetAddress localAddr(sockets::getLocalAddr(sockfd));
625af4b7fbSShuo Chen   // FIXME poll with zero timeout to double confirm the new connection
635af4b7fbSShuo Chen   TcpConnectionPtr conn(
645af4b7fbSShuo Chen       new TcpConnection(loop_, connName, sockfd, localAddr, peerAddr));
655af4b7fbSShuo Chen   connections_[connName] = conn;
665af4b7fbSShuo Chen   conn->setConnectionCallback(connectionCallback_);
675af4b7fbSShuo Chen   conn->setMessageCallback(messageCallback_);
685af4b7fbSShuo Chen+  conn->setWriteCompleteCallback(writeCompleteCallback_);
695af4b7fbSShuo Chen   conn->setCloseCallback(
705af4b7fbSShuo Chen       boost::bind(&TcpServer::removeConnection, this, _1));
715af4b7fbSShuo Chen   conn->connectEstablished();
725af4b7fbSShuo Chen }
735af4b7fbSShuo Chen 
745af4b7fbSShuo Chen void TcpServer::removeConnection(const TcpConnectionPtr& conn)
755af4b7fbSShuo Chen {
765af4b7fbSShuo Chen   loop_->assertInLoopThread();
775af4b7fbSShuo Chen   LOG_INFO << "TcpServer::removeConnection [" << name_
785af4b7fbSShuo Chen            << "] - connection " << conn->name();
795af4b7fbSShuo Chen   size_t n = connections_.erase(conn->name());
805af4b7fbSShuo Chen   assert(n == 1); (void)n;
815af4b7fbSShuo Chen   loop_->queueInLoop(
825af4b7fbSShuo Chen       boost::bind(&TcpConnection::connectDestroyed, conn));
835af4b7fbSShuo Chen }
845af4b7fbSShuo Chen 
85