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