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