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