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

Side by Side Diff: services/native_support/redirectors.cc

Issue 1321253010: Add a "native_support" service. (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: fix android? Created 5 years, 2 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
« no previous file with comments | « services/native_support/redirectors.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "services/native_support/redirectors.h"
6
7 #include <errno.h>
8 #include <string.h>
9
10 #include "base/bind.h"
11 #include "base/logging.h"
12 #include "base/posix/eintr_wrapper.h"
13
14 namespace native_support {
15
16 // FDToMojoFileRedirector ------------------------------------------------------
17
18 FDToMojoFileRedirector::FDToMojoFileRedirector(int fd,
19 mojo::files::File* file,
20 size_t buffer_size)
21 : fd_(fd),
22 file_(file),
23 buffer_size_(buffer_size),
24 num_bytes_(0),
25 offset_(0),
26 weak_factory_(this) {
27 DCHECK_NE(fd_, -1);
28 DCHECK(file_);
29 }
30
31 FDToMojoFileRedirector::~FDToMojoFileRedirector() {}
32
33 void FDToMojoFileRedirector::Start() {
34 // One-shot watch (since we'll need to wait for write callbacks).
35 bool success = base::MessageLoopForIO::current()->WatchFileDescriptor(
36 fd_, false, base::MessageLoopForIO::WATCH_READ, &watcher_, this);
37 DCHECK(success);
38 }
39
40 void FDToMojoFileRedirector::Stop() {
41 watcher_.StopWatchingFileDescriptor();
42 }
43
44 void FDToMojoFileRedirector::OnFileCanReadWithoutBlocking(int fd) {
45 DCHECK_EQ(fd, fd_);
46
47 if (!buffer_)
48 buffer_.reset(new char[buffer_size_]);
49
50 ssize_t result = HANDLE_EINTR(read(fd_, buffer_.get(), buffer_size_));
51 if (result < 0) {
52 if (errno == EAGAIN || errno == EWOULDBLOCK) {
53 LOG(WARNING) << "Could not read from FD without blocking";
54 Start();
55 return;
56 }
57 PLOG(WARNING) << "Failed to read from FD";
58 // TODO(vtl): Should maybe close |file_|?
59 return;
60 }
61 if (!result) { // EOF.
62 // TODO(vtl): Should maybe close |file_|?
63 return;
64 }
65
66 num_bytes_ = static_cast<size_t>(result);
67 offset_ = 0;
68 DoWrite();
69 }
70
71 void FDToMojoFileRedirector::OnFileCanWriteWithoutBlocking(int /*fd*/) {
72 NOTREACHED();
73 }
74
75 void FDToMojoFileRedirector::DoWrite() {
76 CHECK_GT(num_bytes_, offset_);
77 size_t num_bytes_to_write = num_bytes_ - offset_;
78
79 // TODO(vtl): Is there a more natural (or efficient) way to do this?
80 mojo::Array<uint8_t> bytes_to_write(num_bytes_to_write);
81 memcpy(&bytes_to_write[offset_], buffer_.get(), num_bytes_to_write);
82
83 file_->Write(bytes_to_write.Pass(), 0, mojo::files::WHENCE_FROM_CURRENT,
84 base::Bind(&FDToMojoFileRedirector::DidWrite,
85 weak_factory_.GetWeakPtr()));
86 }
87
88 void FDToMojoFileRedirector::DidWrite(mojo::files::Error error,
89 uint32_t num_bytes_written) {
90 if (error != mojo::files::ERROR_OK) {
91 LOG(WARNING) << "Failed to write to Mojo File";
92 // TODO(vtl): Should maybe close |file_|?
93 return;
94 }
95
96 CHECK_GT(num_bytes_, offset_);
97 size_t num_bytes_to_write = num_bytes_ - offset_;
98 if (num_bytes_written > num_bytes_to_write) {
99 LOG(ERROR) << "Bad result from write to Mojo File";
100 return;
101 }
102
103 offset_ += num_bytes_written;
104 if (offset_ < num_bytes_) {
105 DoWrite();
106 } else {
107 num_bytes_ = 0;
108 offset_ = 0;
109 Start();
110 }
111 }
112
113 // MojoFileToFDRedirector ------------------------------------------------------
114
115 MojoFileToFDRedirector::MojoFileToFDRedirector(mojo::files::File* file,
116 int fd,
117 size_t buffer_size)
118 : file_(file),
119 fd_(fd),
120 buffer_size_(buffer_size),
121 running_(false),
122 read_pending_(false),
123 weak_factory_(this) {}
124
125 MojoFileToFDRedirector::~MojoFileToFDRedirector() {}
126
127 void MojoFileToFDRedirector::Start() {
128 running_ = true;
129
130 if (read_pending_)
131 return;
132
133 file_->Read(
134 static_cast<uint32_t>(buffer_size_), 0, mojo::files::WHENCE_FROM_CURRENT,
135 base::Bind(&MojoFileToFDRedirector::DidRead, weak_factory_.GetWeakPtr()));
136 read_pending_ = true;
137 }
138
139 void MojoFileToFDRedirector::Stop() {
140 running_ = false;
141 }
142
143 void MojoFileToFDRedirector::DidRead(mojo::files::Error error,
144 mojo::Array<uint8_t> bytes_read) {
145 DCHECK(read_pending_);
146 read_pending_ = false;
147
148 if (error != mojo::files::ERROR_OK) {
149 LOG(ERROR) << "Read failed";
150 // TODO(vtl): Should maybe close |file_|?
151 return;
152 }
153
154 ssize_t result = HANDLE_EINTR(write(fd_, &bytes_read[0], bytes_read.size()));
155 if (result < 0) {
156 if (errno == EAGAIN || errno == EWOULDBLOCK) {
157 LOG(ERROR) << "Could not write to FD without blocking";
158 if (running_)
159 Start();
160 return;
161 }
162 PLOG(WARNING) << "Failed to write to FD";
163 // TODO(vtl): Should maybe close |file_|?
164 return;
165 }
166 if (static_cast<size_t>(result) != bytes_read.size())
167 LOG(ERROR) << "Failed to write everything to FD";
168
169 if (running_)
170 Start();
171 }
172
173 } // namespace native_support
OLDNEW
« no previous file with comments | « services/native_support/redirectors.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698