1bfe73648SShuo Chen// excerpts from http://code.google.com/p/muduo/ 2bfe73648SShuo Chen// 3bfe73648SShuo Chen// Use of this source code is governed by a BSD-style license 4bfe73648SShuo Chen// that can be found in the License file. 5bfe73648SShuo Chen// 6bfe73648SShuo Chen// Author: Shuo Chen (chenshuo at chenshuo dot com) 7bfe73648SShuo Chen 8bfe73648SShuo Chen#include "TcpConnection.h" 9bfe73648SShuo Chen 10bfe73648SShuo Chen#include "logging/Logging.h" 11bfe73648SShuo Chen#include "Channel.h" 12bfe73648SShuo Chen#include "EventLoop.h" 13bfe73648SShuo Chen#include "Socket.h" 1417c057c3SShuo Chen#include "SocketsOps.h" 15bfe73648SShuo Chen 16bfe73648SShuo Chen#include <boost/bind.hpp> 17bfe73648SShuo Chen 18bfe73648SShuo Chen#include <errno.h> 19bfe73648SShuo Chen#include <stdio.h> 20bfe73648SShuo Chen 21bfe73648SShuo Chenusing namespace muduo; 22bfe73648SShuo Chen 23bfe73648SShuo ChenTcpConnection::TcpConnection(EventLoop* loop, 24bfe73648SShuo Chen const std::string& nameArg, 25bfe73648SShuo Chen int sockfd, 26bfe73648SShuo Chen const InetAddress& localAddr, 27bfe73648SShuo Chen const InetAddress& peerAddr) 28bfe73648SShuo Chen : loop_(CHECK_NOTNULL(loop)), 29bfe73648SShuo Chen name_(nameArg), 30bfe73648SShuo Chen state_(kConnecting), 31bfe73648SShuo Chen socket_(new Socket(sockfd)), 32bfe73648SShuo Chen channel_(new Channel(loop, sockfd)), 33bfe73648SShuo Chen localAddr_(localAddr), 34bfe73648SShuo Chen peerAddr_(peerAddr) 35bfe73648SShuo Chen{ 36bfe73648SShuo Chen LOG_DEBUG << "TcpConnection::ctor[" << name_ << "] at " << this 37bfe73648SShuo Chen << " fd=" << sockfd; 38bfe73648SShuo Chen channel_->setReadCallback( 39bfe73648SShuo Chen boost::bind(&TcpConnection::handleRead, this)); 4017c057c3SShuo Chen channel_->setWriteCallback( 4117c057c3SShuo Chen boost::bind(&TcpConnection::handleWrite, this)); 4217c057c3SShuo Chen channel_->setCloseCallback( 4317c057c3SShuo Chen boost::bind(&TcpConnection::handleClose, this)); 4417c057c3SShuo Chen channel_->setErrorCallback( 4517c057c3SShuo Chen boost::bind(&TcpConnection::handleError, this)); 46bfe73648SShuo Chen} 47bfe73648SShuo Chen 48bfe73648SShuo ChenTcpConnection::~TcpConnection() 49bfe73648SShuo Chen{ 50bfe73648SShuo Chen LOG_DEBUG << "TcpConnection::dtor[" << name_ << "] at " << this 51bfe73648SShuo Chen << " fd=" << channel_->fd(); 52bfe73648SShuo Chen} 53bfe73648SShuo Chen 54bfe73648SShuo Chenvoid TcpConnection::connectEstablished() 55bfe73648SShuo Chen{ 56bfe73648SShuo Chen loop_->assertInLoopThread(); 57bfe73648SShuo Chen assert(state_ == kConnecting); 58bfe73648SShuo Chen setState(kConnected); 59bfe73648SShuo Chen channel_->enableReading(); 6017c057c3SShuo Chen connectionCallback_(shared_from_this()); 6117c057c3SShuo Chen} 62bfe73648SShuo Chen 6317c057c3SShuo Chenvoid TcpConnection::connectDestroyed() 6417c057c3SShuo Chen{ 6517c057c3SShuo Chen loop_->assertInLoopThread(); 6617c057c3SShuo Chen assert(state_ == kConnected); 6717c057c3SShuo Chen setState(kDisconnected); 6817c057c3SShuo Chen channel_->disableAll(); 69bfe73648SShuo Chen connectionCallback_(shared_from_this()); 7017c057c3SShuo Chen 7117c057c3SShuo Chen loop_->removeChannel(get_pointer(channel_)); 72bfe73648SShuo Chen} 73bfe73648SShuo Chen 74bfe73648SShuo Chenvoid TcpConnection::handleRead() 75bfe73648SShuo Chen{ 76bfe73648SShuo Chen char buf[65536]; 7717c057c3SShuo Chen ssize_t n = ::read(channel_->fd(), buf, sizeof buf); 78048f6023SShuo Chen if (n > 0) { 7917c057c3SShuo Chen messageCallback_(shared_from_this(), buf, n); 80048f6023SShuo Chen } else if (n == 0) { 8117c057c3SShuo Chen handleClose(); 82048f6023SShuo Chen } else { 8317c057c3SShuo Chen handleError(); 8417c057c3SShuo Chen } 8517c057c3SShuo Chen} 8617c057c3SShuo Chen 8717c057c3SShuo Chenvoid TcpConnection::handleWrite() 8817c057c3SShuo Chen{ 89bfe73648SShuo Chen} 90bfe73648SShuo Chen 9117c057c3SShuo Chenvoid TcpConnection::handleClose() 9217c057c3SShuo Chen{ 9317c057c3SShuo Chen loop_->assertInLoopThread(); 9417c057c3SShuo Chen LOG_TRACE << "TcpConnection::handleClose state = " << state_; 9517c057c3SShuo Chen assert(state_ == kConnected); 9617c057c3SShuo Chen // we don't close fd, leave it to dtor, so we can find leaks easily. 9717c057c3SShuo Chen channel_->disableAll(); 9817c057c3SShuo Chen // must be the last line 9917c057c3SShuo Chen closeCallback_(shared_from_this()); 10017c057c3SShuo Chen} 10117c057c3SShuo Chen 10217c057c3SShuo Chenvoid TcpConnection::handleError() 10317c057c3SShuo Chen{ 10417c057c3SShuo Chen int err = sockets::getSocketError(channel_->fd()); 10517c057c3SShuo Chen LOG_ERROR << "TcpConnection::handleError [" << name_ 10617c057c3SShuo Chen << "] - SO_ERROR = " << err << " " << strerror_tl(err); 10717c057c3SShuo Chen} 108