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_client.h"
17 
18 #ifdef __cplusplus
19 extern "C" {
20 #endif
21 
22 enum PollRec {
23     POLL_FAILED = (-1),
24     POLL_RETRY = 0,
25     POLL_SUCCESS = 1,
26 };
27 
MakeNonBlock(int sock)28 bool MakeNonBlock(int sock)
29 {
30     int flags = fcntl(sock, F_GETFL, 0);
31     if (flags == -1 && errno == EINTR) {
32         flags = fcntl(sock, F_GETFL, 0);
33     }
34     if (flags == -1) {
35         NETSYS_CLIENT_PRINT("make non block failed %s", strerror(errno));
36         return false;
37     }
38     uint32_t tempFlags = (uint32_t)flags | O_NONBLOCK;
39     int ret = fcntl(sock, F_SETFL, tempFlags);
40     if (ret == -1 && errno == EINTR) {
41         ret = fcntl(sock, F_SETFL, tempFlags);
42     }
43     if (ret == -1) {
44         NETSYS_CLIENT_PRINT("make non block failed %s", strerror(errno));
45         return false;
46     }
47     return true;
48 }
49 
SendWrapper(int fd,char * buf,size_t len)50 static int64_t SendWrapper(int fd, char *buf, size_t len)
51 {
52     return send(fd, buf, len, MSG_NOSIGNAL);
53 }
54 
RecvWrapper(int fd,char * buf,size_t len)55 static int64_t RecvWrapper(int fd, char *buf, size_t len)
56 {
57     return recv(fd, buf, len, 0);
58 }
59 
Poll(int sock,short event,int * retry)60 int64_t Poll(int sock, short event, int *retry)
61 {
62     nfds_t num = 1;
63     struct pollfd fds[1] = {{0}};
64     fds[0].fd = sock;
65     fds[0].events = event;
66 
67     int ret = poll(fds, num, DEFAULT_POLL_TIMEOUT);
68     if (ret == -1) {
69         NETSYS_CLIENT_PRINT("poll to proc failed %s", strerror(errno));
70         return POLL_RETRY;
71     }
72     if (ret == 0) {
73         if (*retry < MAX_POLL_RETRY) {
74             ++(*retry);
75             return POLL_RETRY;
76         }
77         NETSYS_CLIENT_PRINT("poll to proc timeout");
78         return POLL_FAILED;
79     }
80     return POLL_SUCCESS;
81 }
82 
ProcData(int sock,char * data,size_t size,short event,int64_t (* func)(int fd,char * buf,size_t len))83 static bool ProcData(int sock, char *data, size_t size, short event, int64_t (*func)(int fd, char *buf, size_t len))
84 {
85     char *curPos = data;
86     size_t leftSize = size;
87 
88     int retry = 0;
89     while (leftSize > 0) {
90         int32_t resPoll = Poll(sock, event, &retry);
91         if (resPoll < 0) {
92             return false;
93         } else if (resPoll == 0) {
94             continue;
95         }
96 
97         int64_t length = func(sock, curPos, leftSize);
98         if (length < 0) {
99             if (errno == EAGAIN && retry < MAX_POLL_RETRY) {
100                 ++retry;
101                 continue;
102             }
103             NETSYS_CLIENT_PRINT("proc failed %s", strerror(errno));
104             return false;
105         }
106         if (length == 0) {
107             break;
108         }
109         curPos += length;
110         leftSize -= length;
111     }
112 
113     if (leftSize != 0) {
114         NETSYS_CLIENT_PRINT("proc not complete");
115         return false;
116     }
117     return true;
118 }
119 
PollSendData(int sock,const char * data,size_t size)120 bool PollSendData(int sock, const char *data, size_t size)
121 {
122     return ProcData(sock, (char *)data, size, POLLOUT, SendWrapper);
123 }
124 
PollRecvData(int sock,char * data,size_t size)125 bool PollRecvData(int sock, char *data, size_t size)
126 {
127     return ProcData(sock, data, size, POLLIN, RecvWrapper);
128 }
129 #ifdef __cplusplus
130 }
131 #endif
132