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