• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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