TcpConnection.cc revision 2a18e699
12a18e699SShuo Chen// excerpts from http://code.google.com/p/muduo/ 22a18e699SShuo Chen// 32a18e699SShuo Chen// Use of this source code is governed by a BSD-style license 42a18e699SShuo Chen// that can be found in the License file. 52a18e699SShuo Chen// 62a18e699SShuo Chen// Author: Shuo Chen (chenshuo at chenshuo dot com) 72a18e699SShuo Chen 82a18e699SShuo Chen#include "TcpConnection.h" 92a18e699SShuo Chen 102a18e699SShuo Chen#include "logging/Logging.h" 112a18e699SShuo Chen#include "Channel.h" 122a18e699SShuo Chen#include "EventLoop.h" 132a18e699SShuo Chen#include "Socket.h" 142a18e699SShuo Chen#include "SocketsOps.h" 152a18e699SShuo Chen 162a18e699SShuo Chen#include <boost/bind.hpp> 172a18e699SShuo Chen 182a18e699SShuo Chen#include <errno.h> 192a18e699SShuo Chen#include <stdio.h> 202a18e699SShuo Chen 212a18e699SShuo Chenusing namespace muduo; 222a18e699SShuo Chen 232a18e699SShuo ChenTcpConnection::TcpConnection(EventLoop* loop, 242a18e699SShuo Chen const std::string& nameArg, 252a18e699SShuo Chen int sockfd, 262a18e699SShuo Chen const InetAddress& localAddr, 272a18e699SShuo Chen const InetAddress& peerAddr) 282a18e699SShuo Chen : loop_(CHECK_NOTNULL(loop)), 292a18e699SShuo Chen name_(nameArg), 302a18e699SShuo Chen state_(kConnecting), 312a18e699SShuo Chen socket_(new Socket(sockfd)), 322a18e699SShuo Chen channel_(new Channel(loop, sockfd)), 332a18e699SShuo Chen localAddr_(localAddr), 342a18e699SShuo Chen peerAddr_(peerAddr) 352a18e699SShuo Chen{ 362a18e699SShuo Chen LOG_DEBUG << "TcpConnection::ctor[" << name_ << "] at " << this 372a18e699SShuo Chen << " fd=" << sockfd; 382a18e699SShuo Chen channel_->setReadCallback( 392a18e699SShuo Chen boost::bind(&TcpConnection::handleRead, this, _1)); 402a18e699SShuo Chen channel_->setWriteCallback( 412a18e699SShuo Chen boost::bind(&TcpConnection::handleWrite, this)); 422a18e699SShuo Chen channel_->setCloseCallback( 432a18e699SShuo Chen boost::bind(&TcpConnection::handleClose, this)); 442a18e699SShuo Chen channel_->setErrorCallback( 452a18e699SShuo Chen boost::bind(&TcpConnection::handleError, this)); 462a18e699SShuo Chen} 472a18e699SShuo Chen 482a18e699SShuo ChenTcpConnection::~TcpConnection() 492a18e699SShuo Chen{ 502a18e699SShuo Chen LOG_DEBUG << "TcpConnection::dtor[" << name_ << "] at " << this 512a18e699SShuo Chen << " fd=" << channel_->fd(); 522a18e699SShuo Chen} 532a18e699SShuo Chen 542a18e699SShuo Chenvoid TcpConnection::connectEstablished() 552a18e699SShuo Chen{ 562a18e699SShuo Chen loop_->assertInLoopThread(); 572a18e699SShuo Chen assert(state_ == kConnecting); 582a18e699SShuo Chen setState(kConnected); 592a18e699SShuo Chen channel_->enableReading(); 602a18e699SShuo Chen connectionCallback_(shared_from_this()); 612a18e699SShuo Chen} 622a18e699SShuo Chen 632a18e699SShuo Chenvoid TcpConnection::connectDestroyed() 642a18e699SShuo Chen{ 652a18e699SShuo Chen loop_->assertInLoopThread(); 662a18e699SShuo Chen assert(state_ == kConnected); 672a18e699SShuo Chen setState(kDisconnected); 682a18e699SShuo Chen channel_->disableAll(); 692a18e699SShuo Chen connectionCallback_(shared_from_this()); 702a18e699SShuo Chen 712a18e699SShuo Chen loop_->removeChannel(get_pointer(channel_)); 722a18e699SShuo Chen} 732a18e699SShuo Chen 742a18e699SShuo Chenvoid TcpConnection::handleRead(Timestamp receiveTime) 752a18e699SShuo Chen{ 762a18e699SShuo Chen int savedErrno = 0; 772a18e699SShuo Chen ssize_t n = inputBuffer_.readFd(channel_->fd(), &savedErrno); 782a18e699SShuo Chen if (n > 0) { 792a18e699SShuo Chen messageCallback_(shared_from_this(), &inputBuffer_, receiveTime); 802a18e699SShuo Chen } else if (n == 0) { 812a18e699SShuo Chen handleClose(); 822a18e699SShuo Chen } else { 832a18e699SShuo Chen // FIXME: check savedErrno 842a18e699SShuo Chen handleError(); 852a18e699SShuo Chen } 862a18e699SShuo Chen} 872a18e699SShuo Chen 882a18e699SShuo Chenvoid TcpConnection::handleWrite() 892a18e699SShuo Chen{ 902a18e699SShuo Chen} 912a18e699SShuo Chen 922a18e699SShuo Chenvoid TcpConnection::handleClose() 932a18e699SShuo Chen{ 942a18e699SShuo Chen loop_->assertInLoopThread(); 952a18e699SShuo Chen LOG_TRACE << "TcpConnection::handleClose state = " << state_; 962a18e699SShuo Chen assert(state_ == kConnected); 972a18e699SShuo Chen // we don't close fd, leave it to dtor, so we can find leaks easily. 982a18e699SShuo Chen channel_->disableAll(); 992a18e699SShuo Chen // must be the last line 1002a18e699SShuo Chen closeCallback_(shared_from_this()); 1012a18e699SShuo Chen} 1022a18e699SShuo Chen 1032a18e699SShuo Chenvoid TcpConnection::handleError() 1042a18e699SShuo Chen{ 1052a18e699SShuo Chen int err = sockets::getSocketError(channel_->fd()); 1062a18e699SShuo Chen LOG_ERROR << "TcpConnection::handleError [" << name_ 1072a18e699SShuo Chen << "] - SO_ERROR = " << err << " " << strerror_tl(err); 1082a18e699SShuo Chen} 109