1 /*
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "netsys_udp_transfer.h"
17 #include "netnative_log_wrapper.h"
18 #include "netsys_client.h"
19 
20 namespace OHOS {
21 namespace nmd {
22 namespace {
23 struct UdpBuffer {
24     size_t size;
25     int32_t sock;
26     int16_t event;
27     AlignedSockAddr addr;
28 };
ProcUdpData(UdpBuffer udpBuffer,char * data,socklen_t & lenAddr,int64_t (* func)(int fd,char * buf,size_t len,AlignedSockAddr & addr,socklen_t & lenAddr))29 int32_t ProcUdpData(UdpBuffer udpBuffer, char *data, socklen_t &lenAddr,
30                     int64_t (*func)(int fd, char *buf, size_t len, AlignedSockAddr &addr, socklen_t &lenAddr))
31 {
32     char *curPos = data;
33     size_t leftSize = udpBuffer.size;
34     int64_t length = -1;
35     int retry = 0;
36     while (leftSize > 0) {
37         length = func(udpBuffer.sock, curPos, leftSize, udpBuffer.addr, lenAddr);
38         if (length <= 0) {
39             if (errno == EAGAIN && retry < MAX_POLL_RETRY) {
40                 ++retry;
41                 continue;
42             }
43             return -1;
44         }
45         return length;
46     }
47     return leftSize;
48 }
SendUdpWrapper(int32_t fd,char * buf,size_t len,AlignedSockAddr & addr,socklen_t & lenAddr)49 int64_t SendUdpWrapper(int32_t fd, char *buf, size_t len, AlignedSockAddr &addr, socklen_t &lenAddr)
50 {
51     (void)lenAddr;
52     size_t addrLen = (addr.sa.sa_family == AF_INET) ? sizeof(sockaddr_in) : sizeof(sockaddr_in6);
53     return sendto(fd, buf, len, 0, (sockaddr *)&addr, addrLen);
54 }
RecvUdpWrapper(int32_t fd,char * buf,size_t len,AlignedSockAddr & addr,socklen_t & lenAddr)55 int64_t RecvUdpWrapper(int32_t fd, char *buf, size_t len, AlignedSockAddr &addr, socklen_t &lenAddr)
56 {
57     return recvfrom(fd, buf, len, 0, (sockaddr *)&addr, &lenAddr);
58 }
59 } // namespace
60 
MakeUdpNonBlock(int32_t sock)61 bool PollUdpDataTransfer::MakeUdpNonBlock(int32_t sock)
62 {
63     if (sock < 0) {
64         return false;
65     }
66     return MakeNonBlock(sock);
67 }
PollUdpSendData(int32_t sock,char * data,size_t size,AlignedSockAddr & addr,socklen_t & lenAddr)68 int32_t PollUdpDataTransfer::PollUdpSendData(int32_t sock, char *data, size_t size, AlignedSockAddr &addr,
69                                              socklen_t &lenAddr)
70 {
71     struct UdpBuffer udpBuffer;
72     udpBuffer.size = size;
73     udpBuffer.sock = sock;
74     udpBuffer.event = POLLOUT;
75     udpBuffer.addr = addr;
76     return ProcUdpData(udpBuffer, data, lenAddr, SendUdpWrapper);
77 }
PollUdpRecvData(int32_t sock,char * data,size_t size,AlignedSockAddr & addr,socklen_t & lenAddr)78 int32_t PollUdpDataTransfer::PollUdpRecvData(int32_t sock, char *data, size_t size, AlignedSockAddr &addr,
79                                              socklen_t &lenAddr)
80 {
81     struct UdpBuffer udpBuffer;
82     udpBuffer.size = size;
83     udpBuffer.sock = sock;
84     udpBuffer.event = POLLIN;
85     udpBuffer.addr = addr;
86     return ProcUdpData(udpBuffer, data, lenAddr, RecvUdpWrapper);
87 }
88 } // namespace nmd
89 } // namespace OHOS