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