forwarder.cc revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
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)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <errno.h>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdio.h>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdlib.h>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string.h>
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/posix/eintr_wrapper.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/safe_strerror_posix.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "tools/android/forwarder2/socket.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace forwarder2 {
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Helper class to buffer reads and writes from one socket to another.
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class BufferedCopier {
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Does NOT own the pointers.
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BufferedCopier(Socket* socket_from,
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 Socket* socket_to)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : socket_from_(socket_from),
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        socket_to_(socket_to),
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        bytes_read_(0),
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        write_offset_(0) {
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool AddToReadSet(fd_set* read_fds) {
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (bytes_read_ == 0)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return socket_from_->AddFdToSet(read_fds);
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool AddToWriteSet(fd_set* write_fds) {
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (write_offset_ < bytes_read_)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return socket_to_->AddFdToSet(write_fds);
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool TryRead(const fd_set& read_fds) {
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!socket_from_->IsFdInSet(read_fds))
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (bytes_read_ != 0)  // Can't read.
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int ret = socket_from_->Read(buffer_, kBufferSize);
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ret > 0) {
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bytes_read_ = ret;
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool TryWrite(const fd_set& write_fds) {
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!socket_to_->IsFdInSet(write_fds))
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (write_offset_ >= bytes_read_)  // Nothing to write.
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int ret = socket_to_->Write(buffer_ + write_offset_,
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                bytes_read_ - write_offset_);
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ret > 0) {
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      write_offset_ += ret;
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (write_offset_ == bytes_read_) {
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        write_offset_ = 0;
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        bytes_read_ = 0;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Not owned.
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Socket* socket_from_;
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Socket* socket_to_;
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // A big buffer to let our file-over-http bridge work more like real file.
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const int kBufferSize = 1024 * 128;
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int bytes_read_;
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int write_offset_;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char buffer_[kBufferSize];
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(BufferedCopier);
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Forwarder::Forwarder(scoped_ptr<Socket> socket1, scoped_ptr<Socket> socket2)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : socket1_(socket1.Pass()),
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      socket2_(socket2.Pass()) {
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(socket1_.get());
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(socket2_.get());
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The forwarder thread doesn't need to listen to notifications. It can be
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // keept alive until either the conenction is broken or the program exit.
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  socket1_->reset_exit_notifier_fd();
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  socket2_->reset_exit_notifier_fd();
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Forwarder::~Forwarder() {
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  socket1_->Close();
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  socket2_->Close();
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Forwarder::Run() {
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int nfds = Socket::GetHighestFileDescriptor(*socket1_, *socket2_) + 1;
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fd_set read_fds;
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fd_set write_fds;
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Copy from socket1 to socket2
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BufferedCopier buffer1(socket1_.get(), socket2_.get());
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Copy from socket2 to socket1
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BufferedCopier buffer2(socket2_.get(), socket1_.get());
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool run = true;
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (run) {
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FD_ZERO(&read_fds);
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FD_ZERO(&write_fds);
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    buffer1.AddToReadSet(&read_fds);
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    buffer2.AddToReadSet(&read_fds);
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    buffer1.AddToWriteSet(&write_fds);
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    buffer2.AddToWriteSet(&write_fds);
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (HANDLE_EINTR(select(nfds, &read_fds, &write_fds, NULL, NULL)) <= 0) {
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(ERROR) << "Select error: " << safe_strerror(errno);
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // When a socket in the read set closes the connection, select() returns
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // with that socket descriptor set as "ready to read".  When we call
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TryRead() below, it will return false, but the while loop will continue
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // to run until all the write operations are finished, to make sure the
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // buffers are completely flushed out.
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Keep running while we have some operation to do.
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    run = buffer1.TryRead(read_fds);
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    run = run || buffer2.TryRead(read_fds);
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    run = run || buffer1.TryWrite(write_fds);
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    run = run || buffer2.TryWrite(write_fds);
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete this;
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Forwarder::Join() {
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTREACHED() << "Can't Join a Forwarder thread.";
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace forwarder
154