• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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