Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(191)

Side by Side Diff: tools/android/forwarder2/forwarder.cc

Issue 19478003: Remove Thread wrapper class in forwarder2. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "tools/android/forwarder2/forwarder.h" 5 #include "tools/android/forwarder2/forwarder.h"
6 6
7 #include <errno.h> 7 #include "base/basictypes.h"
8 #include <stdio.h> 8 #include "base/bind.h"
9 #include <stdlib.h>
10 #include <string.h>
11
12 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/memory/ref_counted.h"
13 #include "base/posix/eintr_wrapper.h" 11 #include "base/posix/eintr_wrapper.h"
14 #include "base/safe_strerror_posix.h" 12 #include "base/single_thread_task_runner.h"
15 #include "tools/android/forwarder2/socket.h" 13 #include "tools/android/forwarder2/socket.h"
16 14
17 namespace forwarder2 { 15 namespace forwarder2 {
18
19 namespace { 16 namespace {
20 17
21 // Helper class to buffer reads and writes from one socket to another. 18 // Helper class to buffer reads and writes from one socket to another.
22 class BufferedCopier { 19 class BufferedCopier {
23 public: 20 public:
24 // Does NOT own the pointers. 21 // Does NOT own the pointers.
25 BufferedCopier(Socket* socket_from, 22 BufferedCopier(Socket* socket_from,
26 Socket* socket_to) 23 Socket* socket_to)
27 : socket_from_(socket_from), 24 : socket_from_(socket_from),
28 socket_to_(socket_to), 25 socket_to_(socket_to),
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
79 Socket* socket_to_; 76 Socket* socket_to_;
80 77
81 // A big buffer to let our file-over-http bridge work more like real file. 78 // A big buffer to let our file-over-http bridge work more like real file.
82 static const int kBufferSize = 1024 * 128; 79 static const int kBufferSize = 1024 * 128;
83 int bytes_read_; 80 int bytes_read_;
84 int write_offset_; 81 int write_offset_;
85 char buffer_[kBufferSize]; 82 char buffer_[kBufferSize];
86 83
87 DISALLOW_COPY_AND_ASSIGN(BufferedCopier); 84 DISALLOW_COPY_AND_ASSIGN(BufferedCopier);
88 }; 85 };
89 86
digit1 2013/07/18 20:08:39 I'd recommend adding a comment explaining what the
Philippe 2013/07/22 15:16:14 Thanks :) I'm not completely sure what you meant w
87 class Forwarder {
88 public:
89 Forwarder(scoped_ptr<Socket> socket1, scoped_ptr<Socket> socket2)
90 : socket1_(socket1.Pass()),
91 socket2_(socket2.Pass()),
92 destructor_runner_(base::MessageLoopProxy::current()),
93 thread_("ForwarderThread") {
94 }
95
96 // Self-deletes.
97 ~Forwarder() {}
98
99 void Start() {
100 thread_.Start();
101 thread_.message_loop_proxy()->PostTask(
102 FROM_HERE,
103 base::Bind(&Forwarder::ThreadHandler, base::Unretained(this)));
104 }
105
106 private:
107 void ThreadHandler() {
108 const int nfds = Socket::GetHighestFileDescriptor(*socket1_, *socket2_) + 1;
109 fd_set read_fds;
110 fd_set write_fds;
111
112 // Copy from socket1 to socket2
113 BufferedCopier buffer1(socket1_.get(), socket2_.get());
114 // Copy from socket2 to socket1
115 BufferedCopier buffer2(socket2_.get(), socket1_.get());
116
117 bool run = true;
118 while (run) {
119 FD_ZERO(&read_fds);
120 FD_ZERO(&write_fds);
121
122 buffer1.AddToReadSet(&read_fds);
123 buffer2.AddToReadSet(&read_fds);
124 buffer1.AddToWriteSet(&write_fds);
125 buffer2.AddToWriteSet(&write_fds);
126
127 if (HANDLE_EINTR(select(nfds, &read_fds, &write_fds, NULL, NULL)) <= 0) {
128 PLOG(ERROR) << "select";
129 break;
130 }
131 // When a socket in the read set closes the connection, select() returns
132 // with that socket descriptor set as "ready to read". When we call
133 // TryRead() below, it will return false, but the while loop will continue
134 // to run until all the write operations are finished, to make sure the
135 // buffers are completely flushed out.
136
137 // Keep running while we have some operation to do.
138 run = buffer1.TryRead(read_fds);
139 run = run || buffer2.TryRead(read_fds);
140 run = run || buffer1.TryWrite(write_fds);
141 run = run || buffer2.TryWrite(write_fds);
142 }
143
144 // Note that the thread that |destruction_runner_| runs tasks on could be
145 // temporarily blocked on I/O (e.g. select()) therefore it is safer to close
146 // the sockets now rather than relying on the destructor.
147 socket1_.reset();
148 socket2_.reset();
149
150 destructor_runner_->DeleteSoon(FROM_HERE, this);
151 }
152
153 scoped_ptr<Socket> socket1_;
154 scoped_ptr<Socket> socket2_;
155 scoped_refptr<base::SingleThreadTaskRunner> destructor_runner_;
156 base::Thread thread_;
157 };
158
90 } // namespace 159 } // namespace
91 160
92 Forwarder::Forwarder(scoped_ptr<Socket> socket1, scoped_ptr<Socket> socket2) 161 void StartForwarder(scoped_ptr<Socket> socket1, scoped_ptr<Socket> socket2) {
93 : socket1_(socket1.Pass()), 162 (new Forwarder(socket1.Pass(), socket2.Pass()))->Start();
94 socket2_(socket2.Pass()) {
95 DCHECK(socket1_.get());
96 DCHECK(socket2_.get());
97 } 163 }
98 164
99 Forwarder::~Forwarder() { 165 } // namespace forwarder2
100 Detach();
101 }
102
103 void Forwarder::Run() {
104 const int nfds = Socket::GetHighestFileDescriptor(*socket1_, *socket2_) + 1;
105 fd_set read_fds;
106 fd_set write_fds;
107
108 // Copy from socket1 to socket2
109 BufferedCopier buffer1(socket1_.get(), socket2_.get());
110
111 // Copy from socket2 to socket1
112 BufferedCopier buffer2(socket2_.get(), socket1_.get());
113
114 bool run = true;
115 while (run) {
116 FD_ZERO(&read_fds);
117 FD_ZERO(&write_fds);
118
119 buffer1.AddToReadSet(&read_fds);
120 buffer2.AddToReadSet(&read_fds);
121 buffer1.AddToWriteSet(&write_fds);
122 buffer2.AddToWriteSet(&write_fds);
123
124 if (HANDLE_EINTR(select(nfds, &read_fds, &write_fds, NULL, NULL)) <= 0) {
125 LOG(ERROR) << "Select error: " << safe_strerror(errno);
126 break;
127 }
128 // When a socket in the read set closes the connection, select() returns
129 // with that socket descriptor set as "ready to read". When we call
130 // TryRead() below, it will return false, but the while loop will continue
131 // to run until all the write operations are finished, to make sure the
132 // buffers are completely flushed out.
133
134 // Keep running while we have some operation to do.
135 run = buffer1.TryRead(read_fds);
136 run = run || buffer2.TryRead(read_fds);
137 run = run || buffer1.TryWrite(write_fds);
138 run = run || buffer2.TryWrite(write_fds);
139 }
140
141 delete this;
142 }
143
144 void Forwarder::Join() {
145 NOTREACHED() << "Can't Join a Forwarder thread.";
146 }
147
148 } // namespace forwarder
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698