1 /*
2 * Copyright (C) 2017 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 #define LOG_TAG "SocketComm"
18
19 #include <android/hardware/automotive/vehicle/2.0/IVehicle.h>
20 #include <android/log.h>
21 #include <arpa/inet.h>
22 #include <log/log.h>
23 #include <netinet/in.h>
24 #include <sys/socket.h>
25
26 #include "SocketComm.h"
27
28 // Socket to use when communicating with Host PC
29 static constexpr int DEBUG_SOCKET = 33452;
30
31 namespace android {
32 namespace hardware {
33 namespace automotive {
34 namespace vehicle {
35 namespace V2_0 {
36
37 namespace impl {
38
SocketComm(MessageProcessor * messageProcessor)39 SocketComm::SocketComm(MessageProcessor* messageProcessor)
40 : mListenFd(-1), mMessageProcessor(messageProcessor) {}
41
~SocketComm()42 SocketComm::~SocketComm() {
43 }
44
start()45 void SocketComm::start() {
46 if (!listen()) {
47 return;
48 }
49
50 mListenThread = std::make_unique<std::thread>(std::bind(&SocketComm::listenThread, this));
51 }
52
stop()53 void SocketComm::stop() {
54 if (mListenFd > 0) {
55 ::close(mListenFd);
56 if (mListenThread->joinable()) {
57 mListenThread->join();
58 }
59 mListenFd = -1;
60 }
61 }
62
sendMessage(emulator::EmulatorMessage const & msg)63 void SocketComm::sendMessage(emulator::EmulatorMessage const& msg) {
64 std::lock_guard<std::mutex> lock(mMutex);
65 for (std::unique_ptr<SocketConn> const& conn : mOpenConnections) {
66 conn->sendMessage(msg);
67 }
68 }
69
listen()70 bool SocketComm::listen() {
71 int retVal;
72 struct sockaddr_in servAddr;
73
74 mListenFd = socket(AF_INET, SOCK_STREAM, 0);
75 if (mListenFd < 0) {
76 ALOGE("%s: socket() failed, mSockFd=%d, errno=%d", __FUNCTION__, mListenFd, errno);
77 mListenFd = -1;
78 return false;
79 }
80
81 memset(&servAddr, 0, sizeof(servAddr));
82 servAddr.sin_family = AF_INET;
83 servAddr.sin_addr.s_addr = INADDR_ANY;
84 servAddr.sin_port = htons(DEBUG_SOCKET);
85
86 retVal = bind(mListenFd, reinterpret_cast<struct sockaddr*>(&servAddr), sizeof(servAddr));
87 if(retVal < 0) {
88 ALOGE("%s: Error on binding: retVal=%d, errno=%d", __FUNCTION__, retVal, errno);
89 close(mListenFd);
90 mListenFd = -1;
91 return false;
92 }
93
94 ALOGI("%s: Listening for connections on port %d", __FUNCTION__, DEBUG_SOCKET);
95 ::listen(mListenFd, 1);
96 return true;
97 }
98
accept()99 SocketConn* SocketComm::accept() {
100 sockaddr_in cliAddr;
101 socklen_t cliLen = sizeof(cliAddr);
102 int sfd = ::accept(mListenFd, reinterpret_cast<struct sockaddr*>(&cliAddr), &cliLen);
103
104 if (sfd > 0) {
105 char addr[INET_ADDRSTRLEN];
106 inet_ntop(AF_INET, &cliAddr.sin_addr, addr, INET_ADDRSTRLEN);
107
108 ALOGD("%s: Incoming connection received from %s:%d", __FUNCTION__, addr, cliAddr.sin_port);
109 return new SocketConn(mMessageProcessor, sfd);
110 }
111
112 return nullptr;
113 }
114
listenThread()115 void SocketComm::listenThread() {
116 while (true) {
117 SocketConn* conn = accept();
118 if (conn == nullptr) {
119 return;
120 }
121
122 conn->start();
123 {
124 std::lock_guard<std::mutex> lock(mMutex);
125 mOpenConnections.push_back(std::unique_ptr<SocketConn>(conn));
126 }
127 }
128 }
129
130 /**
131 * Called occasionally to clean up connections that have been closed.
132 */
removeClosedConnections()133 void SocketComm::removeClosedConnections() {
134 std::lock_guard<std::mutex> lock(mMutex);
135 std::remove_if(mOpenConnections.begin(), mOpenConnections.end(),
136 [](std::unique_ptr<SocketConn> const& c) { return !c->isOpen(); });
137 }
138
SocketConn(MessageProcessor * messageProcessor,int sfd)139 SocketConn::SocketConn(MessageProcessor* messageProcessor, int sfd)
140 : CommConn(messageProcessor), mSockFd(sfd) {}
141
142 /**
143 * Reads, in a loop, exactly numBytes from the given fd. If the connection is closed, returns
144 * an empty buffer, otherwise will return exactly the given number of bytes.
145 */
readExactly(int fd,int numBytes)146 std::vector<uint8_t> readExactly(int fd, int numBytes) {
147 std::vector<uint8_t> buffer(numBytes);
148 int totalRead = 0;
149 int offset = 0;
150 while (totalRead < numBytes) {
151 int numRead = ::read(fd, &buffer.data()[offset], numBytes - offset);
152 if (numRead == 0) {
153 buffer.resize(0);
154 return buffer;
155 }
156
157 totalRead += numRead;
158 }
159 return buffer;
160 }
161
162 /**
163 * Reads an int, guaranteed to be non-zero, from the given fd. If the connection is closed, returns
164 * -1.
165 */
readInt(int fd)166 int32_t readInt(int fd) {
167 std::vector<uint8_t> buffer = readExactly(fd, sizeof(int32_t));
168 if (buffer.size() == 0) {
169 return -1;
170 }
171
172 int32_t value = *reinterpret_cast<int32_t*>(buffer.data());
173 return ntohl(value);
174 }
175
read()176 std::vector<uint8_t> SocketConn::read() {
177 int32_t msgSize = readInt(mSockFd);
178 if (msgSize <= 0) {
179 ALOGD("%s: Connection terminated on socket %d", __FUNCTION__, mSockFd);
180 return std::vector<uint8_t>();
181 }
182
183 return readExactly(mSockFd, msgSize);
184 }
185
stop()186 void SocketConn::stop() {
187 if (mSockFd > 0) {
188 close(mSockFd);
189 mSockFd = -1;
190 }
191 }
192
write(const std::vector<uint8_t> & data)193 int SocketConn::write(const std::vector<uint8_t>& data) {
194 static constexpr int MSG_HEADER_LEN = 4;
195 int retVal = 0;
196 union {
197 uint32_t msgLen;
198 uint8_t msgLenBytes[MSG_HEADER_LEN];
199 };
200
201 // Prepare header for the message
202 msgLen = static_cast<uint32_t>(data.size());
203 msgLen = htonl(msgLen);
204
205 if (mSockFd > 0) {
206 retVal = ::write(mSockFd, msgLenBytes, MSG_HEADER_LEN);
207
208 if (retVal == MSG_HEADER_LEN) {
209 retVal = ::write(mSockFd, data.data(), data.size());
210 }
211 }
212
213 return retVal;
214 }
215
216 } // impl
217
218 } // namespace V2_0
219 } // namespace vehicle
220 } // namespace automotive
221 } // namespace hardware
222 } // namespace android
223
224