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