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