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 21 using namespace muduo; 22 23 TcpConnection::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)); 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 48 TcpConnection::~TcpConnection() 49 { 50 LOG_DEBUG << "TcpConnection::dtor[" << name_ << "] at " << this 51 << " fd=" << channel_->fd(); 52 } 53 54 void TcpConnection::connectEstablished() 55 { 56 loop_->assertInLoopThread(); 57 assert(state_ == kConnecting); 58 setState(kConnected); 59 channel_->enableReading(); 60 connectionCallback_(shared_from_this()); 61 } 62 63+void 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 74 void TcpConnection::handleRead() 75 { 76 char buf[65536]; 77 ssize_t n = ::read(channel_->fd(), buf, sizeof buf); 78+ if (n > 0) { 79 messageCallback_(shared_from_this(), buf, n); 80+ } else if (n == 0) { 81+ handleClose(); 82+ } else { 83+ handleError(); 84+ } 85 } 86 87+void TcpConnection::handleWrite() 88+{ 89+} 90+ 91+void TcpConnection::handleClose() 92+{ 93+ loop_->assertInLoopThread(); 94+ LOG_TRACE << "TcpConnection::handleClose state = " << state_; 95+ assert(state_ == kConnected); 96+ // we don't close fd, leave it to dtor, so we can find leaks easily. 97+ channel_->disableAll(); 98+ // must be the last line 99+ closeCallback_(shared_from_this()); 100+} 101+ 102+void TcpConnection::handleError() 103+{ 104+ int err = sockets::getSocketError(channel_->fd()); 105+ LOG_ERROR << "TcpConnection::handleError [" << name_ 106+ << "] - SO_ERROR = " << err << " " << strerror_tl(err); 107+} 108