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