1// excerpts from http://code.google.com/p/muduo/ 2// 3// Use of this source code is governed by a BSD-style license 4// that can be found in the License file. 5// 6// Author: Shuo Chen (chenshuo at chenshuo dot com) 7 8#include "TcpConnection.h" 9 10#include "logging/Logging.h" 11#include "Channel.h" 12#include "EventLoop.h" 13#include "Socket.h" 14#include "SocketsOps.h" 15 16#include <boost/bind.hpp> 17 18#include <errno.h> 19#include <stdio.h> 20 21using namespace muduo; 22 23TcpConnection::TcpConnection(EventLoop* loop, 24 const std::string& nameArg, 25 int sockfd, 26 const InetAddress& localAddr, 27 const InetAddress& peerAddr) 28 : loop_(CHECK_NOTNULL(loop)), 29 name_(nameArg), 30 state_(kConnecting), 31 socket_(new Socket(sockfd)), 32 channel_(new Channel(loop, sockfd)), 33 localAddr_(localAddr), 34 peerAddr_(peerAddr) 35{ 36 LOG_DEBUG << "TcpConnection::ctor[" << name_ << "] at " << this 37 << " fd=" << sockfd; 38 channel_->setReadCallback( 39 boost::bind(&TcpConnection::handleRead, this, _1)); 40 channel_->setWriteCallback( 41 boost::bind(&TcpConnection::handleWrite, this)); 42 channel_->setCloseCallback( 43 boost::bind(&TcpConnection::handleClose, this)); 44 channel_->setErrorCallback( 45 boost::bind(&TcpConnection::handleError, this)); 46} 47 48TcpConnection::~TcpConnection() 49{ 50 LOG_DEBUG << "TcpConnection::dtor[" << name_ << "] at " << this 51 << " fd=" << channel_->fd(); 52} 53 54void TcpConnection::connectEstablished() 55{ 56 loop_->assertInLoopThread(); 57 assert(state_ == kConnecting); 58 setState(kConnected); 59 channel_->enableReading(); 60 connectionCallback_(shared_from_this()); 61} 62 63void TcpConnection::connectDestroyed() 64{ 65 loop_->assertInLoopThread(); 66 assert(state_ == kConnected); 67 setState(kDisconnected); 68 channel_->disableAll(); 69 connectionCallback_(shared_from_this()); 70 71 loop_->removeChannel(get_pointer(channel_)); 72} 73 74void TcpConnection::handleRead(Timestamp receiveTime) 75{ 76 int savedErrno = 0; 77 ssize_t n = inputBuffer_.readFd(channel_->fd(), &savedErrno); 78 if (n > 0) { 79 messageCallback_(shared_from_this(), &inputBuffer_, receiveTime); 80 } else if (n == 0) { 81 handleClose(); 82 } else { 83 errno = savedErrno; 84 LOG_SYSERR << "TcpConnection::handleRead"; 85 handleError(); 86 } 87} 88 89void TcpConnection::handleWrite() 90{ 91} 92 93void TcpConnection::handleClose() 94{ 95 loop_->assertInLoopThread(); 96 LOG_TRACE << "TcpConnection::handleClose state = " << state_; 97 assert(state_ == kConnected); 98 // we don't close fd, leave it to dtor, so we can find leaks easily. 99 channel_->disableAll(); 100 // must be the last line 101 closeCallback_(shared_from_this()); 102} 103 104void TcpConnection::handleError() 105{ 106 int err = sockets::getSocketError(channel_->fd()); 107 LOG_ERROR << "TcpConnection::handleError [" << name_ 108 << "] - SO_ERROR = " << err << " " << strerror_tl(err); 109} 110