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