// excerpts from http://code.google.com/p/muduo/ // // Use of this source code is governed by a BSD-style license // that can be found in the License file. // // Author: Shuo Chen (chenshuo at chenshuo dot com) #include "TcpConnection.h" #include "logging/Logging.h" #include "Channel.h" #include "EventLoop.h" #include "Socket.h" +#include "SocketsOps.h" #include #include #include using namespace muduo; TcpConnection::TcpConnection(EventLoop* loop, const std::string& nameArg, int sockfd, const InetAddress& localAddr, const InetAddress& peerAddr) : loop_(CHECK_NOTNULL(loop)), name_(nameArg), state_(kConnecting), socket_(new Socket(sockfd)), channel_(new Channel(loop, sockfd)), localAddr_(localAddr), peerAddr_(peerAddr) { LOG_DEBUG << "TcpConnection::ctor[" << name_ << "] at " << this << " fd=" << sockfd; channel_->setReadCallback( boost::bind(&TcpConnection::handleRead, this)); + channel_->setWriteCallback( + boost::bind(&TcpConnection::handleWrite, this)); + channel_->setCloseCallback( + boost::bind(&TcpConnection::handleClose, this)); + channel_->setErrorCallback( + boost::bind(&TcpConnection::handleError, this)); } TcpConnection::~TcpConnection() { LOG_DEBUG << "TcpConnection::dtor[" << name_ << "] at " << this << " fd=" << channel_->fd(); } void TcpConnection::connectEstablished() { loop_->assertInLoopThread(); assert(state_ == kConnecting); setState(kConnected); channel_->enableReading(); connectionCallback_(shared_from_this()); } +void TcpConnection::connectDestroyed() +{ + loop_->assertInLoopThread(); + assert(state_ == kConnected); + setState(kDisconnected); + channel_->disableAll(); + connectionCallback_(shared_from_this()); + + loop_->removeChannel(get_pointer(channel_)); +} void TcpConnection::handleRead() { char buf[65536]; ssize_t n = ::read(channel_->fd(), buf, sizeof buf); + if (n > 0) { messageCallback_(shared_from_this(), buf, n); + } else if (n == 0) { + handleClose(); + } else { + handleError(); + } } +void TcpConnection::handleWrite() +{ +} + +void TcpConnection::handleClose() +{ + loop_->assertInLoopThread(); + LOG_TRACE << "TcpConnection::handleClose state = " << state_; + assert(state_ == kConnected); + // we don't close fd, leave it to dtor, so we can find leaks easily. + channel_->disableAll(); + // must be the last line + closeCallback_(shared_from_this()); +} + +void TcpConnection::handleError() +{ + int err = sockets::getSocketError(channel_->fd()); + LOG_ERROR << "TcpConnection::handleError [" << name_ + << "] - SO_ERROR = " << err << " " << strerror_tl(err); +}