1 /*
2 * Copyright (C) 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <source/InputSink.h>
18
19 #include <linux/input.h>
20
21 #include <string.h>
22 #include <sys/socket.h>
23 #include <sys/types.h>
24 #include <unistd.h>
25
26 #include <glog/logging.h>
27 #include <https/SafeCallbackable.h>
28 #include <https/Support.h>
29
30 namespace android {
31
32 namespace {
33
34 // TODO de-dup this from vnc server and here
35 struct virtio_input_event {
36 uint16_t type;
37 uint16_t code;
38 int32_t value;
39 };
40
41 template <typename T>
42 struct InputEventBufferImpl : public InputEventBuffer {
InputEventBufferImplandroid::__anon43f8ac510111::InputEventBufferImpl43 InputEventBufferImpl() {
44 buffer_.reserve(6); // 6 is usually enough even for multi-touch
45 }
addEventandroid::__anon43f8ac510111::InputEventBufferImpl46 void addEvent(uint16_t type, uint16_t code, int32_t value) override {
47 buffer_.push_back({.type = type, .code = code, .value = value});
48 }
dataandroid::__anon43f8ac510111::InputEventBufferImpl49 T* data() { return buffer_.data(); }
dataandroid::__anon43f8ac510111::InputEventBufferImpl50 const void* data() const override { return buffer_.data(); }
sizeandroid::__anon43f8ac510111::InputEventBufferImpl51 std::size_t size() const override { return buffer_.size() * sizeof(T); }
52
53 private:
54 std::vector<T> buffer_;
55 };
56
57 } // namespace
58
InputSink(std::shared_ptr<RunLoop> runLoop,int serverFd,bool write_virtio_input)59 InputSink::InputSink(std::shared_ptr<RunLoop> runLoop, int serverFd,
60 bool write_virtio_input)
61 : mRunLoop(runLoop),
62 mServerFd(serverFd),
63 mClientFd(-1),
64 mSendPending(false),
65 mWriteVirtioInput(write_virtio_input) {
66 if (mServerFd >= 0) {
67 makeFdNonblocking(mServerFd);
68 }
69 }
70
~InputSink()71 InputSink::~InputSink() {
72 if (mClientFd >= 0) {
73 mRunLoop->cancelSocket(mClientFd);
74
75 close(mClientFd);
76 mClientFd = -1;
77 }
78
79 if (mServerFd >= 0) {
80 mRunLoop->cancelSocket(mServerFd);
81
82 close(mServerFd);
83 mServerFd = -1;
84 }
85 }
86
start()87 void InputSink::start() {
88 if (mServerFd < 0) {
89 return;
90 }
91
92 mRunLoop->postSocketRecv(
93 mServerFd, makeSafeCallback(this, &InputSink::onServerConnection));
94 }
95
getEventBuffer() const96 std::unique_ptr<InputEventBuffer> InputSink::getEventBuffer() const {
97 InputEventBuffer* raw_ptr;
98 if (mWriteVirtioInput) {
99 raw_ptr = new InputEventBufferImpl<virtio_input_event>();
100 } else {
101 raw_ptr = new InputEventBufferImpl<input_event>();
102 }
103 return std::unique_ptr<InputEventBuffer>(raw_ptr);
104 }
105
SendEvents(std::unique_ptr<InputEventBuffer> evt_buffer)106 void InputSink::SendEvents(std::unique_ptr<InputEventBuffer> evt_buffer) {
107 sendRawEvents(evt_buffer->data(), evt_buffer->size());
108 }
109
onServerConnection()110 void InputSink::onServerConnection() {
111 int s = accept(mServerFd, nullptr, nullptr);
112
113 if (s >= 0) {
114 if (mClientFd >= 0) {
115 LOG(INFO) << "Rejecting client, we already have one.";
116
117 // We already have a client.
118 close(s);
119 s = -1;
120 } else {
121 LOG(INFO) << "Accepted client socket " << s << ".";
122
123 makeFdNonblocking(s);
124
125 mClientFd = s;
126 mRunLoop->postSocketRecv(
127 mClientFd, makeSafeCallback(this, &InputSink::onSocketRecv));
128 }
129 }
130
131 mRunLoop->postSocketRecv(
132 mServerFd, makeSafeCallback(this, &InputSink::onServerConnection));
133 }
134
sendRawEvents(const void * evt_buffer,size_t size)135 void InputSink::sendRawEvents(const void* evt_buffer, size_t size) {
136 if (size <= 0) return;
137
138 std::lock_guard autoLock(mLock);
139
140 if (mClientFd < 0) {
141 return;
142 }
143
144 size_t offset = mOutBuffer.size();
145 mOutBuffer.resize(offset + size);
146 memcpy(mOutBuffer.data() + offset, evt_buffer, size);
147
148 if (!mSendPending) {
149 mSendPending = true;
150
151 mRunLoop->postSocketSend(mClientFd,
152 makeSafeCallback(this, &InputSink::onSocketSend));
153 }
154 }
155
onSocketRecv()156 void InputSink::onSocketRecv() {
157 if (mClientFd < 0) return;
158
159 char buff[512];
160 auto n = recv(mClientFd, buff, sizeof(buff), 0 /* flags */);
161 if (n > 0) {
162 LOG(INFO) << "Discarding " << n << " bytes received from the input device.";
163 mRunLoop->postSocketRecv(
164 mClientFd, makeSafeCallback(this, &InputSink::onSocketRecv));
165 } else {
166 // Client disconnected
167 if (n < 0) {
168 auto errno_save = errno;
169 LOG(ERROR) << "Error receiving from socket: " << strerror(errno_save);
170 }
171 mRunLoop->cancelSocket(mClientFd);
172 close(mClientFd);
173 mClientFd = -1;
174 }
175 }
176
onSocketSend()177 void InputSink::onSocketSend() {
178 std::lock_guard autoLock(mLock);
179
180 CHECK(mSendPending);
181 mSendPending = false;
182
183 if (mClientFd < 0) {
184 return;
185 }
186
187 ssize_t n;
188 while (!mOutBuffer.empty()) {
189 do {
190 n = ::send(mClientFd, mOutBuffer.data(), mOutBuffer.size(), 0);
191 } while (n < 0 && errno == EINTR);
192
193 if (n <= 0) {
194 break;
195 }
196
197 mOutBuffer.erase(mOutBuffer.begin(), mOutBuffer.begin() + n);
198 }
199
200 if ((n < 0 && errno != EAGAIN && errno != EWOULDBLOCK) || n == 0) {
201 LOG(ERROR) << "Client is gone.";
202
203 // Client is gone.
204 mRunLoop->cancelSocket(mClientFd);
205
206 close(mClientFd);
207 mClientFd = -1;
208 return;
209 }
210
211 if (!mOutBuffer.empty()) {
212 mSendPending = true;
213 mRunLoop->postSocketSend(mClientFd,
214 makeSafeCallback(this, &InputSink::onSocketSend));
215 }
216 }
217
218 } // namespace android
219