13b467340SShuo Chen // excerpts from http://code.google.com/p/muduo/
23b467340SShuo Chen //
33b467340SShuo Chen // Use of this source code is governed by a BSD-style license
43b467340SShuo Chen // that can be found in the License file.
53b467340SShuo Chen //
63b467340SShuo Chen // Author: Shuo Chen (chenshuo at chenshuo dot com)
73b467340SShuo Chen 
83b467340SShuo Chen #include "TcpConnection.h"
93b467340SShuo Chen 
103b467340SShuo Chen #include "logging/Logging.h"
113b467340SShuo Chen #include "Channel.h"
123b467340SShuo Chen #include "EventLoop.h"
133b467340SShuo Chen #include "Socket.h"
143b467340SShuo Chen #include "SocketsOps.h"
153b467340SShuo Chen 
163b467340SShuo Chen #include <boost/bind.hpp>
173b467340SShuo Chen 
183b467340SShuo Chen #include <errno.h>
193b467340SShuo Chen #include <stdio.h>
203b467340SShuo Chen 
213b467340SShuo Chen using namespace muduo;
223b467340SShuo Chen 
233b467340SShuo Chen TcpConnection::TcpConnection(EventLoop* loop,
243b467340SShuo Chen                              const std::string& nameArg,
253b467340SShuo Chen                              int sockfd,
263b467340SShuo Chen                              const InetAddress& localAddr,
273b467340SShuo Chen                              const InetAddress& peerAddr)
283b467340SShuo Chen   : loop_(CHECK_NOTNULL(loop)),
293b467340SShuo Chen     name_(nameArg),
303b467340SShuo Chen     state_(kConnecting),
313b467340SShuo Chen     socket_(new Socket(sockfd)),
323b467340SShuo Chen     channel_(new Channel(loop, sockfd)),
333b467340SShuo Chen     localAddr_(localAddr),
343b467340SShuo Chen     peerAddr_(peerAddr)
353b467340SShuo Chen {
363b467340SShuo Chen   LOG_DEBUG << "TcpConnection::ctor[" <<  name_ << "] at " << this
373b467340SShuo Chen             << " fd=" << sockfd;
383b467340SShuo Chen   channel_->setReadCallback(
393b467340SShuo Chen!      boost::bind(&TcpConnection::handleRead, this, _1));
403b467340SShuo Chen   channel_->setWriteCallback(
413b467340SShuo Chen       boost::bind(&TcpConnection::handleWrite, this));
423b467340SShuo Chen   channel_->setCloseCallback(
433b467340SShuo Chen       boost::bind(&TcpConnection::handleClose, this));
443b467340SShuo Chen   channel_->setErrorCallback(
453b467340SShuo Chen       boost::bind(&TcpConnection::handleError, this));
463b467340SShuo Chen }
473b467340SShuo Chen 
483b467340SShuo Chen TcpConnection::~TcpConnection()
493b467340SShuo Chen {
503b467340SShuo Chen   LOG_DEBUG << "TcpConnection::dtor[" <<  name_ << "] at " << this
513b467340SShuo Chen             << " fd=" << channel_->fd();
523b467340SShuo Chen }
533b467340SShuo Chen 
543b467340SShuo Chen void TcpConnection::connectEstablished()
553b467340SShuo Chen {
563b467340SShuo Chen   loop_->assertInLoopThread();
573b467340SShuo Chen   assert(state_ == kConnecting);
583b467340SShuo Chen   setState(kConnected);
593b467340SShuo Chen   channel_->enableReading();
603b467340SShuo Chen   connectionCallback_(shared_from_this());
613b467340SShuo Chen }
623b467340SShuo Chen 
633b467340SShuo Chen void TcpConnection::connectDestroyed()
643b467340SShuo Chen {
653b467340SShuo Chen   loop_->assertInLoopThread();
663b467340SShuo Chen   assert(state_ == kConnected);
673b467340SShuo Chen   setState(kDisconnected);
683b467340SShuo Chen   channel_->disableAll();
693b467340SShuo Chen   connectionCallback_(shared_from_this());
703b467340SShuo Chen 
713b467340SShuo Chen   loop_->removeChannel(get_pointer(channel_));
723b467340SShuo Chen }
733b467340SShuo Chen 
743b467340SShuo Chen!void TcpConnection::handleRead(Timestamp receiveTime)
753b467340SShuo Chen {
763b467340SShuo Chen!  int savedErrno = 0;
773b467340SShuo Chen!  ssize_t n = inputBuffer_.readFd(channel_->fd(), &savedErrno);
783b467340SShuo Chen   if (n > 0) {
793b467340SShuo Chen!    messageCallback_(shared_from_this(), &inputBuffer_, receiveTime);
803b467340SShuo Chen   } else if (n == 0) {
813b467340SShuo Chen     handleClose();
823b467340SShuo Chen   } else {
830dd528a5SShuo Chen+    errno = savedErrno;
840dd528a5SShuo Chen+    LOG_SYSERR << "TcpConnection::handleRead";
853b467340SShuo Chen     handleError();
863b467340SShuo Chen   }
873b467340SShuo Chen }
883b467340SShuo Chen 
893b467340SShuo Chen void TcpConnection::handleWrite()
903b467340SShuo Chen {
913b467340SShuo Chen }
923b467340SShuo Chen 
933b467340SShuo Chen void TcpConnection::handleClose()
943b467340SShuo Chen {
953b467340SShuo Chen   loop_->assertInLoopThread();
963b467340SShuo Chen   LOG_TRACE << "TcpConnection::handleClose state = " << state_;
973b467340SShuo Chen   assert(state_ == kConnected);
983b467340SShuo Chen   // we don't close fd, leave it to dtor, so we can find leaks easily.
993b467340SShuo Chen   channel_->disableAll();
1003b467340SShuo Chen   // must be the last line
1013b467340SShuo Chen   closeCallback_(shared_from_this());
1023b467340SShuo Chen }
1033b467340SShuo Chen 
1043b467340SShuo Chen void TcpConnection::handleError()
1053b467340SShuo Chen {
1063b467340SShuo Chen   int err = sockets::getSocketError(channel_->fd());
1073b467340SShuo Chen   LOG_ERROR << "TcpConnection::handleError [" << name_
1083b467340SShuo Chen             << "] - SO_ERROR = " << err << " " << strerror_tl(err);
1093b467340SShuo Chen }
110