15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "tools/android/forwarder2/forwarder.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch#include "base/basictypes.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/posix/eintr_wrapper.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "tools/android/forwarder2/socket.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace forwarder2 {
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const int kBufferSize = 32 * 1024;
165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace
185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Helper class to buffer reads and writes from one socket to another.
215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Each implements a small buffer connected two one input socket, and
225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// one output socket.
235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)//
245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)//   socket_from_ ---> [BufferedCopier] ---> socket_to_
255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)//
265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// These objects are used in a pair to handle duplex traffic, as in:
275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)//
285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)//                    ------> [BufferedCopier_1] --->
295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)//                  /                                \
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)//      socket_1   *                                  * socket_2
315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)//                  \                                /
325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)//                   <------ [BufferedCopier_2] <----
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)//
345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// When a BufferedCopier is in the READING state (see below), it only listens
355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// to events on its input socket, and won't detect when its output socket
365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// disconnects. To work around this, its peer will call its Close() method
375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// when that happens.
385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class Forwarder::BufferedCopier {
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Possible states:
425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  //    READING - Empty buffer and Waiting for input.
435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  //    WRITING - Data in buffer, and waiting for output.
445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  //    CLOSING - Like WRITING, but do not try to read after that.
455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  //    CLOSED  - Completely closed.
465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  //
475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // State transitions are:
485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  //
495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  //   T01:  READING ---[receive data]---> WRITING
505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  //   T02:  READING ---[error on input socket]---> CLOSED
515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  //   T03:  READING ---[Close() call]---> CLOSED
525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  //
535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  //   T04:  WRITING ---[write partial data]---> WRITING
545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  //   T05:  WRITING ---[write all data]----> READING
555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  //   T06:  WRITING ---[error on output socket]----> CLOSED
565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  //   T07:  WRITING ---[Close() call]---> CLOSING
575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  //
585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  //   T08:  CLOSING ---[write partial data]---> CLOSING
595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  //   T09:  CLOSING ---[write all data]----> CLOSED
605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  //   T10:  CLOSING ---[Close() call]---> CLOSING
615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  //   T11:  CLOSING ---[error on output socket] ---> CLOSED
625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  //
635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  enum State {
645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    STATE_READING = 0,
655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    STATE_WRITING = 1,
665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    STATE_CLOSING = 2,
675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    STATE_CLOSED = 3,
685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  };
695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Does NOT own the pointers.
715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  BufferedCopier(Socket* socket_from, Socket* socket_to)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : socket_from_(socket_from),
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        socket_to_(socket_to),
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        bytes_read_(0),
755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        write_offset_(0),
765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        peer_(NULL),
775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        state_(STATE_READING) {}
785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Sets the 'peer_' field pointing to the other BufferedCopier in a pair.
805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void SetPeer(BufferedCopier* peer) {
815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DCHECK(!peer_);
825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    peer_ = peer;
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bool is_closed() const { return state_ == STATE_CLOSED; }
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Gently asks to close a buffer. Called either by the peer or the forwarder.
885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void Close() {
895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    switch (state_) {
905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      case STATE_READING:
915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        state_ = STATE_CLOSED;  // T03
925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        break;
935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      case STATE_WRITING:
945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        state_ = STATE_CLOSING;  // T07
955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        break;
965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      case STATE_CLOSING:
975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        break;  // T10
985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      case STATE_CLOSED:
995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        ;
1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Call this before select(). This updates |read_fds|,
1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // |write_fds| and |max_fd| appropriately *if* the buffer isn't closed.
1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void PrepareSelect(fd_set* read_fds, fd_set* write_fds, int* max_fd) {
1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    int fd;
1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    switch (state_) {
1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      case STATE_READING:
1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        DCHECK(bytes_read_ == 0);
1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        DCHECK(write_offset_ == 0);
1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        fd = socket_from_->fd();
1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if (fd < 0) {
1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          ForceClose();  // T02
1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          return;
1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        }
1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        FD_SET(fd, read_fds);
1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        break;
1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      case STATE_WRITING:
1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      case STATE_CLOSING:
1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        DCHECK(bytes_read_ > 0);
1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        DCHECK(write_offset_ < bytes_read_);
1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        fd = socket_to_->fd();
1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if (fd < 0) {
1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          ForceClose();  // T06
1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          return;
1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        }
1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        FD_SET(fd, write_fds);
1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        break;
1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      case STATE_CLOSED:
1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        return;
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    *max_fd = std::max(*max_fd, fd);
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Call this after a select() call to operate over the buffer.
1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void ProcessSelect(const fd_set& read_fds, const fd_set& write_fds) {
1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    int fd, ret;
1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    switch (state_) {
1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      case STATE_READING:
1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        fd = socket_from_->fd();
1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if (fd < 0) {
1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          state_ = STATE_CLOSED;  // T02
1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          return;
1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        }
1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if (!FD_ISSET(fd, &read_fds))
1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          return;
1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        ret = socket_from_->NonBlockingRead(buffer_, kBufferSize);
1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if (ret <= 0) {
1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          ForceClose();  // T02
1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          return;
1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        }
1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        bytes_read_ = ret;
1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        write_offset_ = 0;
1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        state_ = STATE_WRITING;  // T01
1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        break;
1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      case STATE_WRITING:
1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      case STATE_CLOSING:
1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        fd = socket_to_->fd();
1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if (fd < 0) {
1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          ForceClose();  // T06 + T11
1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          return;
1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        }
1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if (!FD_ISSET(fd, &write_fds))
1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          return;
1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        ret = socket_to_->NonBlockingWrite(buffer_ + write_offset_,
1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                           bytes_read_ - write_offset_);
1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if (ret <= 0) {
1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          ForceClose();  // T06 + T11
1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          return;
1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        }
1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        write_offset_ += ret;
1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if (write_offset_ < bytes_read_)
1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          return;  // T08 + T04
1805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        write_offset_ = 0;
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        bytes_read_ = 0;
1835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if (state_ == STATE_CLOSING) {
1845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          ForceClose();  // T09
1855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          return;
1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        }
1875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        state_ = STATE_READING;  // T05
1885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        break;
1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      case STATE_CLOSED:
1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        ;
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Internal method used to close the buffer and notify the peer, if any.
1975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void ForceClose() {
1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (peer_) {
1995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      peer_->Close();
2005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      peer_ = NULL;
2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
2025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    state_ = STATE_CLOSED;
2035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Not owned.
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Socket* socket_from_;
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Socket* socket_to_;
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int bytes_read_;
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int write_offset_;
2115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  BufferedCopier* peer_;
2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  State state_;
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char buffer_[kBufferSize];
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(BufferedCopier);
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)Forwarder::Forwarder(scoped_ptr<Socket> socket1,
2195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                     scoped_ptr<Socket> socket2)
2205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    : socket1_(socket1.Pass()),
2215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      socket2_(socket2.Pass()),
2225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      buffer1_(new BufferedCopier(socket1_.get(), socket2_.get())),
2235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      buffer2_(new BufferedCopier(socket2_.get(), socket1_.get())) {
2245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  buffer1_->SetPeer(buffer2_.get());
2255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  buffer2_->SetPeer(buffer1_.get());
2265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)Forwarder::~Forwarder() {
2295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
2305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void Forwarder::RegisterFDs(fd_set* read_fds, fd_set* write_fds, int* max_fd) {
2335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
2345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  buffer1_->PrepareSelect(read_fds, write_fds, max_fd);
2355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  buffer2_->PrepareSelect(read_fds, write_fds, max_fd);
2365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void Forwarder::ProcessEvents(const fd_set& read_fds, const fd_set& write_fds) {
2395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
2405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  buffer1_->ProcessSelect(read_fds, write_fds);
2415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  buffer2_->ProcessSelect(read_fds, write_fds);
2425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
243d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
2445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool Forwarder::IsClosed() const {
2455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
2465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return buffer1_->is_closed() && buffer2_->is_closed();
2475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void Forwarder::Shutdown() {
2505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
2515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  buffer1_->Close();
2525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  buffer2_->Close();
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}  // namespace forwarder2
256