1 /**
2 * Copyright (C) 2022 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 #include <stdio.h>
18 #include <unistd.h>
19 #include <fcntl.h>
20 #include <sys/types.h>
21 #include <sys/socket.h>
22 #include <netinet/in.h>
23 #include <netdb.h>
24 #include <string.h>
25 #include <errno.h>
26 #include <arpa/inet.h>
27 #include <sys/ioctl.h>
28 #include <net/if.h>
29 #include <thread>
30 #include <ImsMediaSocket.h>
31 #include <ImsMediaTrace.h>
32 #include <ImsMediaNetworkUtil.h>
33
34 // static valuable
35 std::list<ImsMediaSocket*> ImsMediaSocket::slistRxSocket;
36 std::list<ImsMediaSocket*> ImsMediaSocket::slistSocket;
37 int32_t ImsMediaSocket::sRxSocketCount = 0;
38 bool ImsMediaSocket::mSocketListUpdated = false;
39 bool ImsMediaSocket::mTerminateMonitor = false;
40 ImsMediaCondition ImsMediaSocket::mConditionExit;
41 std::mutex ImsMediaSocket::sMutexRxSocket;
42 std::mutex ImsMediaSocket::sMutexSocketList;
43
44 enum kDscp
45 {
46 DSCP_CS0 = 0,
47 DSCP_CS1 = 8,
48 DSCP_CS2 = 16,
49 DSCP_CS3 = 24,
50 DSCP_CS4 = 32,
51 DSCP_CS5 = 40,
52 DSCP_CS6 = 48,
53 DSCP_CS7 = 56,
54 DSCP_AF11 = 10,
55 DSCP_AF12 = 12,
56 DSCP_AF13 = 14,
57 DSCP_AF21 = 18,
58 DSCP_AF22 = 20,
59 DSCP_AF23 = 22,
60 DSCP_AF31 = 26,
61 DSCP_AF32 = 28,
62 DSCP_AF33 = 30,
63 DSCP_AF41 = 34,
64 DSCP_AF42 = 36,
65 DSCP_AF43 = 38,
66 DSCP_EF = 46,
67 DSCP_VOICEADMIT = 44,
68 };
69
70 const std::initializer_list<kDscp> dscpValues = {DSCP_EF, DSCP_AF41, DSCP_CS0, DSCP_CS1, DSCP_CS2,
71 DSCP_CS3, DSCP_CS4, DSCP_CS5, DSCP_CS6, DSCP_CS7, DSCP_AF11, DSCP_AF12, DSCP_AF13,
72 DSCP_AF21, DSCP_AF22, DSCP_AF23, DSCP_AF31, DSCP_AF32, DSCP_AF33, DSCP_AF42, DSCP_AF43,
73 DSCP_VOICEADMIT};
74
GetInstance(uint32_t localPort,const char * peerIpAddress,uint32_t peerPort)75 ImsMediaSocket* ImsMediaSocket::GetInstance(
76 uint32_t localPort, const char* peerIpAddress, uint32_t peerPort)
77 {
78 ImsMediaSocket* pImsMediaSocket = nullptr;
79 std::lock_guard<std::mutex> guard(sMutexSocketList);
80
81 for (auto& i : slistSocket)
82 {
83 if (strcmp(i->GetPeerIPAddress(), peerIpAddress) == 0 && i->GetLocalPort() == localPort &&
84 i->GetPeerPort() == peerPort)
85 {
86 return i;
87 }
88 }
89
90 pImsMediaSocket = new ImsMediaSocket();
91 return pImsMediaSocket;
92 }
93
ReleaseInstance(ImsMediaSocket * pSocket)94 void ImsMediaSocket::ReleaseInstance(ImsMediaSocket* pSocket)
95 {
96 if (pSocket != nullptr && pSocket->mRefCount == 0)
97 {
98 delete pSocket;
99 }
100 }
101
ImsMediaSocket()102 ImsMediaSocket::ImsMediaSocket()
103 {
104 mListener = nullptr;
105 mRefCount = 0;
106 mLocalIPVersion = IPV4;
107 mPeerIPVersion = IPV4;
108 mLocalPort = 0;
109 mPeerPort = 0;
110 mSocketFd = -1;
111 mRemoteIpFiltering = true;
112 IMLOGD0("[ImsMediaSocket] enter");
113 }
114
~ImsMediaSocket()115 ImsMediaSocket::~ImsMediaSocket()
116 {
117 IMLOGD_PACKET5(IM_PACKET_LOG_SOCKET, "[~ImsMediaSocket] %x, %s:%d %s:%d", this, mLocalIP,
118 mLocalPort, mPeerIP, mPeerPort);
119 }
120
SetLocalEndpoint(const char * ipAddress,const uint32_t port)121 void ImsMediaSocket::SetLocalEndpoint(const char* ipAddress, const uint32_t port)
122 {
123 strlcpy(mLocalIP, ipAddress, MAX_IP_LEN);
124 mLocalPort = port;
125
126 if (strstr(mLocalIP, ":") == nullptr)
127 {
128 mLocalIPVersion = IPV4;
129 }
130 else
131 {
132 mLocalIPVersion = IPV6;
133 }
134 }
135
SetPeerEndpoint(const char * ipAddress,const uint32_t port)136 void ImsMediaSocket::SetPeerEndpoint(const char* ipAddress, const uint32_t port)
137 {
138 strlcpy(mPeerIP, ipAddress, MAX_IP_LEN);
139 mPeerPort = port;
140
141 if (strstr(mPeerIP, ":") == nullptr)
142 {
143 mPeerIPVersion = IPV4;
144 }
145 else
146 {
147 mPeerIPVersion = IPV6;
148 }
149 }
150
GetLocalPort()151 int ImsMediaSocket::GetLocalPort()
152 {
153 return mLocalPort;
154 }
GetPeerPort()155 int ImsMediaSocket::GetPeerPort()
156 {
157 return mPeerPort;
158 }
GetLocalIPAddress()159 char* ImsMediaSocket::GetLocalIPAddress()
160 {
161 return mLocalIP;
162 }
GetPeerIPAddress()163 char* ImsMediaSocket::GetPeerIPAddress()
164 {
165 return mPeerIP;
166 }
167
Open(int socketFd)168 bool ImsMediaSocket::Open(int socketFd)
169 {
170 if (socketFd == -1)
171 {
172 return false;
173 }
174
175 IMLOGD5("[Open] %s:%d, %s:%d, nRefCount[%d]", mLocalIP, mLocalPort, mPeerIP, mPeerPort,
176 mRefCount);
177
178 if (mRefCount > 0)
179 {
180 IMLOGD0("[Open] exit - Socket is opened already");
181 mRefCount++;
182 return true;
183 }
184
185 mSocketFd = socketFd;
186 sMutexSocketList.lock();
187 slistSocket.push_back(this);
188 mRefCount++;
189 sMutexSocketList.unlock();
190 return true;
191 }
192
Listen(ISocketListener * listener)193 void ImsMediaSocket::Listen(ISocketListener* listener)
194 {
195 IMLOGD0("[Listen]");
196 mListener = listener;
197
198 if (listener != nullptr)
199 {
200 // add socket list, run thread
201 sMutexRxSocket.lock();
202 slistRxSocket.push_back(this);
203 sMutexRxSocket.unlock();
204
205 if (sRxSocketCount == 0)
206 {
207 StartSocketMonitor();
208 }
209 else
210 {
211 mSocketListUpdated = true;
212 }
213
214 sRxSocketCount++;
215 IMLOGD1("[Listen] add sRxSocketCount[%d]", sRxSocketCount);
216 }
217 else
218 {
219 sMutexRxSocket.lock();
220 slistRxSocket.remove(this);
221 sMutexRxSocket.unlock();
222 sRxSocketCount--;
223
224 if (sRxSocketCount <= 0)
225 {
226 StopSocketMonitor();
227 sRxSocketCount = 0;
228 }
229 else
230 {
231 mSocketListUpdated = true;
232 }
233
234 IMLOGD1("[Listen] remove RxSocketCount[%d]", sRxSocketCount);
235 }
236 }
237
SendTo(uint8_t * pData,uint32_t nDataSize)238 int32_t ImsMediaSocket::SendTo(uint8_t* pData, uint32_t nDataSize)
239 {
240 int32_t len;
241 IMLOGD_PACKET2(IM_PACKET_LOG_SOCKET, "[SendTo] fd[%d],[%d] bytes", mSocketFd, nDataSize);
242
243 if (nDataSize == 0)
244 {
245 return 0;
246 }
247
248 struct sockaddr_in stAddr4;
249 struct sockaddr_in6 stAddr6;
250 struct sockaddr* pstSockAddr = nullptr;
251 socklen_t nSockAddrLen = 0;
252
253 if (mPeerIPVersion == IPV4)
254 {
255 nSockAddrLen = sizeof(stAddr4);
256 memset(&stAddr4, 0, nSockAddrLen);
257 stAddr4.sin_family = AF_INET;
258 stAddr4.sin_port = htons(mPeerPort);
259
260 if (inet_pton(AF_INET, mPeerIP, &(stAddr4.sin_addr.s_addr)) != 1)
261 {
262 IMLOGE1("[ImsMediaSocket:SendTo] IPv4[%s]", mPeerIP);
263 return 0;
264 }
265
266 pstSockAddr = (struct sockaddr*)&stAddr4;
267 }
268 else
269 {
270 nSockAddrLen = sizeof(stAddr6);
271 memset(&stAddr6, 0, nSockAddrLen);
272 stAddr6.sin6_family = AF_INET6;
273 stAddr6.sin6_port = htons(mPeerPort);
274
275 if (inet_pton(AF_INET6, mPeerIP, &(stAddr6.sin6_addr.s6_addr)) != 1)
276 {
277 IMLOGE1("[ImsMediaSocket:SendTo] Ipv6[%s]", mPeerIP);
278 return 0;
279 }
280
281 pstSockAddr = (struct sockaddr*)&stAddr6;
282 }
283
284 len = sendto(mSocketFd, reinterpret_cast<const char*>(pData), nDataSize, 0, pstSockAddr,
285 nSockAddrLen);
286
287 if (len < 0)
288 {
289 IMLOGE4("[ImsMediaSocket:SendTo] FAILED len(%d), nDataSize(%d) failed (%d, %s)", len,
290 nDataSize, errno, strerror(errno));
291 }
292
293 return len;
294 }
295
ReceiveFrom(uint8_t * pData,uint32_t nBufferSize)296 int32_t ImsMediaSocket::ReceiveFrom(uint8_t* pData, uint32_t nBufferSize)
297 {
298 int32_t len;
299 struct sockaddr* pstSockAddr = nullptr;
300 socklen_t nSockAddrLen = 0;
301 sockaddr_storage ss;
302 pstSockAddr = reinterpret_cast<sockaddr*>(&ss);
303 len = recvfrom(mSocketFd, pData, nBufferSize, 0, pstSockAddr, &nSockAddrLen);
304
305 if (len > 0)
306 {
307 static char pSourceIP[MAX_IP_LEN];
308 memset(pSourceIP, 0, sizeof(pSourceIP));
309 IMLOGD_PACKET2(IM_PACKET_LOG_SOCKET, "[ReceiveFrom] fd[%d], len[%d]", mSocketFd, len);
310 }
311 else if (EWOULDBLOCK == errno)
312 {
313 IMLOGE0("[ReceiveFrom], WBlock");
314 }
315 else
316 {
317 IMLOGE0("[ReceiveFrom] Fail");
318 }
319
320 return len;
321 }
322
RetrieveOptionMsg(uint32_t type,int32_t & value)323 bool ImsMediaSocket::RetrieveOptionMsg(uint32_t type, int32_t& value)
324 {
325 if (type == kSocketOptionIpTtl)
326 {
327 uint8_t buffer[DEFAULT_MTU];
328 struct iovec iov[1] = {{buffer, sizeof(buffer)}};
329 struct sockaddr_storage srcAddress;
330 uint8_t ctrlDataBuffer[CMSG_SPACE(1) + CMSG_SPACE(1) + CMSG_SPACE(1)];
331 struct msghdr hdr = {.msg_name = &srcAddress,
332 .msg_namelen = sizeof(srcAddress),
333 .msg_iov = iov,
334 .msg_iovlen = 1,
335 .msg_control = ctrlDataBuffer,
336 .msg_controllen = sizeof(ctrlDataBuffer)};
337
338 if (recvmsg(mSocketFd, &hdr, 0) > 0)
339 {
340 struct cmsghdr* cmsg = CMSG_FIRSTHDR(&hdr);
341
342 for (; cmsg; cmsg = CMSG_NXTHDR(&hdr, cmsg))
343 {
344 if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_RECVTTL)
345 {
346 uint8_t* ttlPtr = reinterpret_cast<uint8_t*>(CMSG_DATA(cmsg));
347 value = reinterpret_cast<int32_t&>(*ttlPtr);
348 return true;
349 }
350 }
351 }
352 else
353 {
354 IMLOGE1("[RetrieveOptionMsg] fail to read type[%d]", type);
355 }
356 }
357
358 return false;
359 }
360
Close()361 void ImsMediaSocket::Close()
362 {
363 IMLOGD1("[Close] enter, nRefCount[%d]", mRefCount);
364 mRefCount--;
365
366 if (mRefCount > 0)
367 {
368 IMLOGD0("[Close] exit - Socket is used");
369 return;
370 }
371
372 // close(mSocketFd);
373 std::lock_guard<std::mutex> guard(sMutexSocketList);
374 slistSocket.remove(this);
375 IMLOGD0("[Close] exit");
376 }
377
isValidDscp(int32_t dscp)378 bool ImsMediaSocket::isValidDscp(int32_t dscp)
379 {
380 for (const auto value : dscpValues)
381 {
382 if (value == dscp)
383 {
384 return true;
385 }
386 }
387
388 return false;
389 }
390
convertDscpToTos(int32_t dscp)391 int32_t ImsMediaSocket::convertDscpToTos(int32_t dscp)
392 {
393 if (dscp == DSCP_CS0 || !isValidDscp(dscp))
394 {
395 return (DSCP_EF << 2) & 0XFF;
396 }
397
398 return (dscp << 2) & 0xFF;
399 }
400
SetSocketOpt(kSocketOption nOption,int32_t nOptionValue)401 bool ImsMediaSocket::SetSocketOpt(kSocketOption nOption, int32_t nOptionValue)
402 {
403 if (mSocketFd == -1)
404 {
405 IMLOGD0("[SetSocketOpt] socket handle is invalid");
406 return false;
407 }
408
409 int32_t tos = 0;
410
411 switch (nOption)
412 {
413 case kSocketOptionIpTos:
414 tos = convertDscpToTos(nOptionValue);
415 if (mLocalIPVersion == IPV4)
416 {
417 if (-1 == setsockopt(mSocketFd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)))
418 {
419 IMLOGW0("[SetSocketOpt] IP_TOS - IPv4");
420 return false;
421 }
422 }
423 else
424 {
425 if (-1 == setsockopt(mSocketFd, IPPROTO_IPV6, IPV6_TCLASS, &tos, sizeof(tos)))
426 {
427 IMLOGW0("[SetSocketOpt] IP_TOS - IPv6");
428 return false;
429 }
430 }
431
432 IMLOGD1("[SetSocketOpt] IP_QOS[%d]", tos);
433 break;
434 case kSocketOptionIpTtl:
435 if (-1 ==
436 setsockopt(
437 mSocketFd, IPPROTO_IP, IP_RECVTTL, &nOptionValue, sizeof(nOptionValue)))
438 {
439 IMLOGW0("[SetSocketOpt] IP_RECVTTL");
440 return false;
441 }
442 IMLOGD0("[SetSocketOpt] IP_RECVTTL");
443 return true;
444 default:
445 IMLOGD1("[SetSocketOpt] Unsupported socket option[%d]", nOption);
446 return false;
447 }
448
449 return true;
450 }
451
GetSocketFd()452 int32_t ImsMediaSocket::GetSocketFd()
453 {
454 return mSocketFd;
455 }
456
GetListener()457 ISocketListener* ImsMediaSocket::GetListener()
458 {
459 return mListener;
460 }
461
StartSocketMonitor()462 void ImsMediaSocket::StartSocketMonitor()
463 {
464 if (mTerminateMonitor == true)
465 {
466 IMLOGD0("[StartSocketMonitor] Send Signal");
467 mTerminateMonitor = false;
468 mConditionExit.signal();
469 return;
470 }
471
472 mTerminateMonitor = false;
473 IMLOGD_PACKET0(IM_PACKET_LOG_SOCKET, "[StartSocketMonitor] start monitor thread");
474
475 std::thread socketMonitorThread(&ImsMediaSocket::SocketMonitorThread);
476 socketMonitorThread.detach();
477 }
478
StopSocketMonitor()479 void ImsMediaSocket::StopSocketMonitor()
480 {
481 IMLOGD_PACKET0(IM_PACKET_LOG_SOCKET, "[StopSocketMonitor] stop monitor thread");
482 mTerminateMonitor = true;
483 mConditionExit.wait();
484 }
485
SetSocketFD(void * pReadFds,void * pWriteFds,void * pExceptFds)486 uint32_t ImsMediaSocket::SetSocketFD(void* pReadFds, void* pWriteFds, void* pExceptFds)
487 {
488 uint32_t nMaxSD = 0;
489 std::lock_guard<std::mutex> guard(sMutexRxSocket);
490 FD_ZERO(reinterpret_cast<fd_set*>(pReadFds));
491 FD_ZERO(reinterpret_cast<fd_set*>(pWriteFds));
492 FD_ZERO(reinterpret_cast<fd_set*>(pExceptFds));
493 IMLOGD_PACKET0(IM_PACKET_LOG_SOCKET, "[SetSocketFD]");
494
495 for (auto& i : slistRxSocket)
496 {
497 int32_t socketFD = i->GetSocketFd();
498 FD_SET(socketFD, reinterpret_cast<fd_set*>(pReadFds));
499
500 if (socketFD > nMaxSD)
501 {
502 nMaxSD = socketFD;
503 }
504 }
505
506 mSocketListUpdated = false;
507 return nMaxSD;
508 }
509
ReadDataFromSocket(void * pReadfds)510 void ImsMediaSocket::ReadDataFromSocket(void* pReadfds)
511 {
512 std::lock_guard<std::mutex> guard(sMutexRxSocket);
513 IMLOGD_PACKET0(IM_PACKET_LOG_SOCKET, "[ReadDataFromSocket]");
514
515 for (auto& rxSocket : slistRxSocket)
516 {
517 if (rxSocket != nullptr)
518 {
519 int32_t socketFD = rxSocket->GetSocketFd();
520
521 if (FD_ISSET(socketFD, reinterpret_cast<fd_set*>(pReadfds)))
522 {
523 IMLOGD_PACKET1(IM_PACKET_LOG_SOCKET,
524 "[ReadDataFromSocket] send notify to listener %p", rxSocket->GetListener());
525
526 if (rxSocket->GetListener() != nullptr)
527 {
528 rxSocket->GetListener()->OnReadDataFromSocket();
529 }
530 }
531 }
532 }
533 }
534
SocketMonitorThread()535 void ImsMediaSocket::SocketMonitorThread()
536 {
537 static fd_set ReadFds;
538 static fd_set WriteFds;
539 static fd_set ExceptFds;
540 static fd_set TmpReadfds;
541 static fd_set TmpWritefds;
542 static fd_set TmpExcepfds;
543 int nMaxSD;
544 IMLOGD0("[SocketMonitorThread] enter");
545 nMaxSD = SetSocketFD(&ReadFds, &WriteFds, &ExceptFds);
546
547 for (;;)
548 {
549 struct timeval tv;
550 tv.tv_sec = 0;
551 tv.tv_usec = 100 * 1000; // micro-second
552
553 if (mTerminateMonitor)
554 {
555 break;
556 }
557
558 if (mSocketListUpdated)
559 {
560 nMaxSD = SetSocketFD(&ReadFds, &WriteFds, &ExceptFds);
561 }
562
563 memcpy(&TmpReadfds, &ReadFds, sizeof(fd_set));
564 memcpy(&TmpWritefds, &WriteFds, sizeof(fd_set));
565 memcpy(&TmpExcepfds, &ExceptFds, sizeof(fd_set));
566
567 int32_t res = select(nMaxSD + 1, &TmpReadfds, &TmpWritefds, &TmpExcepfds, &tv);
568
569 if (mTerminateMonitor)
570 {
571 break;
572 }
573
574 if (res == -1)
575 {
576 IMLOGE0("[SocketMonitorThread] select function Error!!");
577 }
578 else
579 {
580 ReadDataFromSocket(&TmpReadfds);
581 }
582 }
583
584 IMLOGD0("[SocketMonitorThread] exit");
585 mTerminateMonitor = false;
586 mConditionExit.signal();
587 }
588