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(vhal_proto::EmulatorMessage const & msg)63 void SocketComm::sendMessage(vhal_proto::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 if (::listen(mListenFd, 1) == -1) {
96 ALOGE("%s: Error on listening: errno: %d: %s", __FUNCTION__, errno, strerror(errno));
97 return false;
98 }
99 return true;
100 }
101
accept()102 SocketConn* SocketComm::accept() {
103 sockaddr_in cliAddr;
104 socklen_t cliLen = sizeof(cliAddr);
105 int sfd = ::accept(mListenFd, reinterpret_cast<struct sockaddr*>(&cliAddr), &cliLen);
106
107 if (sfd > 0) {
108 char addr[INET_ADDRSTRLEN];
109 inet_ntop(AF_INET, &cliAddr.sin_addr, addr, INET_ADDRSTRLEN);
110
111 ALOGD("%s: Incoming connection received from %s:%d", __FUNCTION__, addr, cliAddr.sin_port);
112 return new SocketConn(mMessageProcessor, sfd);
113 }
114
115 return nullptr;
116 }
117
listenThread()118 void SocketComm::listenThread() {
119 while (true) {
120 SocketConn* conn = accept();
121 if (conn == nullptr) {
122 return;
123 }
124
125 conn->start();
126 {
127 std::lock_guard<std::mutex> lock(mMutex);
128 mOpenConnections.push_back(std::unique_ptr<SocketConn>(conn));
129 }
130 }
131 }
132
133 /**
134 * Called occasionally to clean up connections that have been closed.
135 */
removeClosedConnections()136 void SocketComm::removeClosedConnections() {
137 std::lock_guard<std::mutex> lock(mMutex);
138 std::remove_if(mOpenConnections.begin(), mOpenConnections.end(),
139 [](std::unique_ptr<SocketConn> const& c) { return !c->isOpen(); });
140 }
141
SocketConn(MessageProcessor * messageProcessor,int sfd)142 SocketConn::SocketConn(MessageProcessor* messageProcessor, int sfd)
143 : CommConn(messageProcessor), mSockFd(sfd) {}
144
145 /**
146 * Reads, in a loop, exactly numBytes from the given fd. If the connection is closed, returns
147 * an empty buffer, otherwise will return exactly the given number of bytes.
148 */
readExactly(int fd,int numBytes)149 std::vector<uint8_t> readExactly(int fd, int numBytes) {
150 std::vector<uint8_t> buffer(numBytes);
151 int totalRead = 0;
152 int offset = 0;
153 while (totalRead < numBytes) {
154 int numRead = ::read(fd, &buffer.data()[offset], numBytes - offset);
155 if (numRead == 0) {
156 buffer.resize(0);
157 return buffer;
158 }
159
160 totalRead += numRead;
161 }
162 return buffer;
163 }
164
165 /**
166 * Reads an int, guaranteed to be non-zero, from the given fd. If the connection is closed, returns
167 * -1.
168 */
readInt(int fd)169 int32_t readInt(int fd) {
170 std::vector<uint8_t> buffer = readExactly(fd, sizeof(int32_t));
171 if (buffer.size() == 0) {
172 return -1;
173 }
174
175 int32_t value = *reinterpret_cast<int32_t*>(buffer.data());
176 return ntohl(value);
177 }
178
read()179 std::vector<uint8_t> SocketConn::read() {
180 int32_t msgSize = readInt(mSockFd);
181 if (msgSize <= 0) {
182 ALOGD("%s: Connection terminated on socket %d", __FUNCTION__, mSockFd);
183 return std::vector<uint8_t>();
184 }
185
186 return readExactly(mSockFd, msgSize);
187 }
188
stop()189 void SocketConn::stop() {
190 if (mSockFd > 0) {
191 close(mSockFd);
192 mSockFd = -1;
193 }
194 }
195
write(const std::vector<uint8_t> & data)196 int SocketConn::write(const std::vector<uint8_t>& data) {
197 static constexpr int MSG_HEADER_LEN = 4;
198 int retVal = 0;
199 union {
200 uint32_t msgLen;
201 uint8_t msgLenBytes[MSG_HEADER_LEN];
202 };
203
204 // Prepare header for the message
205 msgLen = static_cast<uint32_t>(data.size());
206 msgLen = htonl(msgLen);
207
208 if (mSockFd > 0) {
209 retVal = ::write(mSockFd, msgLenBytes, MSG_HEADER_LEN);
210
211 if (retVal == MSG_HEADER_LEN) {
212 retVal = ::write(mSockFd, data.data(), data.size());
213 }
214 }
215
216 return retVal;
217 }
218
219 } // impl
220
221 } // namespace V2_0
222 } // namespace vehicle
223 } // namespace automotive
224 } // namespace hardware
225 } // namespace android
226
227