• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "socket_opt.h"
17 #include "sockets.h"
18 #include "socket_common.h"
19 #include "spunge.h"
20 #include "spunge_message.h"
21 
22 #ifdef __cplusplus
23 extern "C" {
24 #endif
25 
SockGetOptSendCache(struct FtSocket * sock,void * optVal,FILLP_INT * optLen)26 static FILLP_INT SockGetOptSendCache(struct FtSocket *sock, void *optVal, FILLP_INT *optLen)
27 {
28     struct FillpCurrentSendCacheInf *currentSendCacheInfo = FILLP_NULL_PTR;
29     struct FillpSendPcb *sendPcb = FILLP_NULL_PTR;
30     if ((*optLen < (FILLP_INT)sizeof(struct FillpCurrentSendCacheInf)) || (sock->netconn == FILLP_NULL_PTR)) {
31         SET_ERRNO(FILLP_EINVAL);
32         return -1;
33     }
34     if ((sock->netconn == FILLP_NULL_PTR) || (sock->netconn->state != CONN_STATE_CONNECTED)) {
35         FILLP_LOGERR("SockGetSockOpt: sock state must be connected Invalid sock = %d", sock->index);
36         SET_ERRNO(FILLP_EBADF);
37         return -1;
38     }
39 
40     currentSendCacheInfo = (struct FillpCurrentSendCacheInf *)optVal;
41     sendPcb = &(sock->netconn->pcb->fpcb.send);
42     currentSendCacheInfo->currentSendCacheSize = sendPcb->curItemCount;
43     currentSendCacheInfo->currentDataSizeInCache = (FILLP_UINT32)(sendPcb->unSendList.size +
44         sendPcb->unackList.count + sendPcb->redunList.nodeNum + sendPcb->unrecvList.nodeNum +
45         sendPcb->itemWaitTokenLists.nodeNum);
46 
47     return ERR_OK;
48 }
49 
SockGetSockOptFillp(struct FtSocket * sock,FILLP_INT optName,void * optVal,FILLP_INT * optLen)50 static FILLP_INT SockGetSockOptFillp(struct FtSocket *sock, FILLP_INT optName, void *optVal, FILLP_INT *optLen)
51 {
52     FILLP_INT err;
53     switch (optName) {
54         case FILLP_PKT_DATA_OPTS_TIMESTAMP:
55             if (*optLen < (FILLP_INT)sizeof(FILLP_INT)) {
56                 SET_ERRNO(FILLP_EINVAL);
57                 err = -1;
58                 break;
59             }
60             if (sock->dataOptionFlag & FILLP_OPT_FLAG_TIMESTAMP) {
61                 *(FILLP_INT *)optVal = 1;
62                 *optLen = (FILLP_INT)sizeof(FILLP_INT);
63             } else {
64                 *(FILLP_INT *)optVal = 0;
65                 *optLen = (FILLP_INT)sizeof(FILLP_INT);
66             }
67             err = ERR_OK;
68             break;
69         case FILLP_SOCK_SEND_CACHE_INFO:
70             err = SockGetOptSendCache(sock, optVal, optLen);
71             break;
72         case SO_LINGER:
73             if (*optLen < (FILLP_INT)sizeof(struct linger)) {
74                 SET_ERRNO(FILLP_EINVAL);
75                 err = -1;
76             } else {
77                 err = memcpy_s(optVal, (FILLP_UINT32)(*optLen), (void *)&sock->fillpLinger, sizeof(struct linger));
78                 if (err != EOK) {
79                     FILLP_LOGERR("memcpy_s failed with errcode %d", err);
80                     SET_ERRNO(FILLP_EINVAL);
81                     err = -1;
82                 } else {
83                     *optLen = (FILLP_INT)sizeof(struct linger);
84                     err = ERR_OK;
85                 }
86             }
87             break;
88         default:
89             SET_ERRNO(FILLP_EINVAL);
90             err = -1;
91             break;
92     }
93     return err;
94 }
95 
SockGetSockOpt(FILLP_INT sockIndex,FILLP_INT level,FILLP_INT optName,void * optVal,FILLP_INT * optLen)96 FILLP_INT SockGetSockOpt(
97     FILLP_INT           sockIndex,
98     FILLP_INT           level,
99     FILLP_INT           optName,
100     void               *optVal,
101     FILLP_INT          *optLen)
102 {
103     struct FtSocket *sock = SockApiGetAndCheck(sockIndex);
104     struct SockOsSocket *osSock = FILLP_NULL_PTR;
105     FillpErrorType err = ERR_OK;
106 
107     FILLP_LOGINF("SockGetSockOpt: sock = %d", sockIndex);
108 
109     if (sock == FILLP_NULL_PTR) {
110         return -1;
111     }
112 
113     if ((optLen == FILLP_NULL_PTR) || (optVal == FILLP_NULL_PTR)) {
114         (void)SYS_ARCH_RWSEM_RDPOST(&sock->sockConnSem);
115         SET_ERRNO(FILLP_EFAULT);
116         return -1;
117     }
118 
119     if ((optName == SO_ERROR) && (level == SOL_SOCKET)) {
120         if (*optLen < (FILLP_INT)sizeof(int)) {
121             (void)SYS_ARCH_RWSEM_RDPOST(&sock->sockConnSem);
122             SET_ERRNO(FILLP_EINVAL);
123             return -1;
124         }
125 
126         if (sock->err == FILLP_EINPROGRESS) {
127             int errToErrno = FillpErrToErrno(sock->netconn->lastErr);
128             FILLP_SOCK_SET_ERR(sock, errToErrno);
129         }
130 
131         *(int *)optVal = sock->err;
132         sock->err = ERR_OK;
133     } else if (level == IPPROTO_FILLP) {
134         err = SockGetSockOptFillp(sock, optName, optVal, optLen);
135     } else {
136         osSock = NETCONN_GET_OSSOCK(sock->netconn, sock->inst->instIndex);
137         if (!OS_SOCK_OPS_FUNC_VALID(osSock, getsockopt)) {
138             SET_ERRNO(FILLP_EINVAL);
139             err = -1;
140         } else {
141             err = osSock->ioSock->ops->getsockopt(osSock->ioSock, level, optName, optVal, optLen);
142         }
143     }
144 
145     (void)SYS_ARCH_RWSEM_RDPOST(&sock->sockConnSem);
146     FILLP_LOGINF("SockGetSockOpt: return fillp_sock_id:%d, err:%d", sockIndex, err);
147 
148     if (err != ERR_OK) {
149         err = -1;
150     }
151 
152     return err;
153 }
154 
SockSetOptTimestamp(struct FtSocket * sock,FILLP_CONST void * optVal,socklen_t optLen)155 static FILLP_INT SockSetOptTimestamp(struct FtSocket *sock, FILLP_CONST void *optVal, socklen_t optLen)
156 {
157     FILLP_INT err;
158 
159     if (optLen < (FILLP_INT)sizeof(FILLP_INT)) {
160         SET_ERRNO(FILLP_EINVAL);
161         return ERR_PARAM;
162     }
163 
164     if (*(FILLP_CONST FILLP_INT *)optVal) {
165         err = SockUpdatePktDataOpt(sock, (FILLP_UINT16)FILLP_OPT_FLAG_TIMESTAMP, 0);
166     } else {
167         err = SockUpdatePktDataOpt(sock, 0, (FILLP_UINT16)FILLP_OPT_FLAG_TIMESTAMP);
168     }
169     if (err != ERR_OK) {
170         SET_ERRNO(FILLP_EINVAL);
171     }
172 
173     return err;
174 }
175 
SockSetOptLinger(struct FtSocket * sock,FILLP_CONST void * optVal,socklen_t optLen)176 static FILLP_INT SockSetOptLinger(struct FtSocket *sock, FILLP_CONST void *optVal, socklen_t optLen)
177 {
178     FILLP_INT err = ERR_PARAM;
179     if (optLen < (FILLP_INT)sizeof(struct linger)) {
180         SET_ERRNO(FILLP_EINVAL);
181     } else {
182         err = memcpy_s((void *)&sock->fillpLinger, sizeof(struct linger), optVal, (FILLP_UINT32)optLen);
183         if (err != EOK) {
184             FILLP_LOGERR("memcpy_s failed with errcode %d", err);
185             SET_ERRNO(FILLP_EINVAL);
186             err = ERR_PARAM;
187         }
188     }
189 
190     return err;
191 }
192 
SockSetFcAlg(struct FtSocket * sock,FILLP_UINT32 alg)193 static FILLP_INT SockSetFcAlg(struct FtSocket *sock, FILLP_UINT32 alg)
194 {
195     FILLP_UINT8 connState;
196 
197     if (sock->netconn == FILLP_NULL_PTR) {
198         FILLP_LOGERR("netconn is NULL, fillp_sock_id:%d", sock->index);
199         return FILLP_EINVAL;
200     }
201 
202     connState = NETCONN_GET_STATE(sock->netconn);
203     if (connState != CONN_STATE_IDLE) {
204         FILLP_LOGERR("Netconn state is not idle fillp_sock_id:%d,state:%u", sock->index, connState);
205         return FILLP_EINVAL;
206     }
207 
208     if (sock->netconn->pcb == FILLP_NULL_PTR) {
209         FILLP_LOGERR("pcb is NULL, fillp_sock_id:%d", sock->index);
210         return FILLP_EINVAL;
211     }
212 
213     if (alg != FILLP_ALG_ONE && alg != FILLP_ALG_TWO && alg != FILLP_ALG_THREE &&
214         alg != FILLP_ALG_MSG && alg != FILLP_ALG_BASE) {
215         FILLP_LOGERR("alg %u is not supported", alg);
216         return FILLP_EINVAL;
217     }
218 
219     if (alg != FILLP_ALG_BASE) {
220         sock->netconn->pcb->fpcb.fcAlg = (FILLP_UINT8)FILLP_SUPPORT_ALG_N(alg);
221     } else {
222         sock->netconn->pcb->fpcb.fcAlg = FILLP_SUPPORT_ALG_BASE;
223     }
224     if (alg == FILLP_ALG_MSG) {
225         sock->resConf.common.recvCache = FILLP_DEFAULT_MSG_RECV_CACHE;
226         sock->resConf.common.sendCache = FILLP_DEFAULT_MSG_SEND_CACHE;
227         NetconnSetRecvCacheSize(sock->netconn, sock->resConf.common.recvCache);
228         NetconnSetSendCacheSize(sock->netconn, sock->resConf.common.sendCache);
229     }
230     return FILLP_OK;
231 }
232 
SockSetOptFcAlg(struct FtSocket * sock,FILLP_CONST void * optVal,socklen_t optLen)233 static FILLP_INT SockSetOptFcAlg(struct FtSocket *sock, FILLP_CONST void *optVal, socklen_t optLen)
234 {
235     FILLP_INT err = ERR_PARAM;
236 
237     if (optLen < (FILLP_INT)sizeof(FILLP_UINT32)) {
238         SET_ERRNO(FILLP_EINVAL);
239         return err;
240     }
241 
242     if (SockSetFcAlg(sock, *(FILLP_UINT32 *)optVal) != ERR_OK) {
243         SET_ERRNO(FILLP_EINVAL);
244     } else {
245         err = 0;
246     }
247 
248     return err;
249 }
250 
SockSetOptDirectlySend(struct FtSocket * sock,FILLP_CONST void * optVal,socklen_t optLen)251 static FILLP_INT SockSetOptDirectlySend(struct FtSocket *sock, FILLP_CONST void *optVal, socklen_t optLen)
252 {
253     if (optLen < (FILLP_INT)sizeof(FILLP_INT)) {
254         SET_ERRNO(FILLP_EINVAL);
255         return ERR_PARAM;
256     }
257 
258     sock->directlySend = *(FILLP_INT *)optVal;
259     FILLP_LOGBUTT("fillp sock id: %d, set directlySend to %d", sock->index, sock->directlySend);
260     return ERR_OK;
261 }
262 
SockSetSockOptFillp(struct FtSocket * sock,FILLP_INT optName,FILLP_CONST void * optVal,socklen_t optLen)263 static FILLP_INT SockSetSockOptFillp(struct FtSocket *sock,
264     FILLP_INT optName, FILLP_CONST void *optVal, socklen_t optLen)
265 {
266     FILLP_INT err = -1;
267     switch (optName) {
268         case FILLP_PKT_DATA_OPTS_TIMESTAMP:
269             err = SockSetOptTimestamp(sock, optVal, optLen);
270             break;
271         case SO_LINGER:
272             err = SockSetOptLinger(sock, optVal, optLen);
273             break;
274         case FILLP_SOCK_FC_ALG:
275             err = SockSetOptFcAlg(sock, optVal, optLen);
276             break;
277         case FILLP_SOCK_DIRECTLY_SEND:
278             err = SockSetOptDirectlySend(sock, optVal, optLen);
279             break;
280         default:
281             SET_ERRNO(FILLP_EINVAL);
282             break;
283     }
284     return err;
285 }
286 
SockSetSockOpt(FILLP_INT sockIndex,FILLP_INT level,FILLP_INT optName,FILLP_CONST void * optVal,socklen_t optLen)287 FILLP_INT SockSetSockOpt(
288     FILLP_INT           sockIndex,
289     FILLP_INT           level,
290     FILLP_INT           optName,
291     FILLP_CONST void   *optVal,
292     socklen_t           optLen)
293 {
294     struct FtSocket *sock = FILLP_NULL_PTR;
295     struct SockOsSocket *osSock = FILLP_NULL_PTR;
296     FillpErrorType err;
297 
298     FILLP_LOGINF("SockSetSockOpt: sock = %d", sockIndex);
299 
300     if (optVal == FILLP_NULL_PTR) {
301         SET_ERRNO(FILLP_EFAULT);
302         return -1;
303     }
304 
305     if ((level == SOL_SOCKET) && ((optName == SO_SNDBUF) || (optName == SO_RCVBUF))) {
306         FILLP_LOGERR("SockSetSockOpt: sock = %d invalid param optName=%d", sockIndex, optName);
307         SET_ERRNO(FILLP_EOPNOTSUPP);
308         return -1;
309     }
310 
311     sock = SockApiGetAndCheck(sockIndex);
312     if (sock == FILLP_NULL_PTR) {
313         return -1;
314     }
315 
316     if (level == IPPROTO_FILLP) {
317         err = SockSetSockOptFillp(sock, optName, optVal, optLen);
318     } else {
319         osSock = NETCONN_GET_OSSOCK(sock->netconn, sock->inst->instIndex);
320         if (OS_SOCK_OPS_FUNC_VALID(osSock, setsockopt)) {
321             err = osSock->ioSock->ops->setsockopt(osSock->ioSock, level, optName, optVal, optLen);
322         } else {
323             SET_ERRNO(FILLP_EINVAL);
324             err = -1;
325         }
326     }
327 
328     if (err != ERR_OK) {
329         err = -1;
330     }
331 
332     (void)SYS_ARCH_RWSEM_RDPOST(&sock->sockConnSem);
333     FILLP_LOGINF("SockSetSockOpt: return fillp_sock_id:%d, err:%d", sockIndex, err);
334 
335     return err;
336 }
337 
338 #ifdef __cplusplus
339 }
340 #endif
341