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