• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * This file is part of the openHiTLS project.
3  *
4  * openHiTLS is licensed under the Mulan PSL v2.
5  * You can use this software according to the terms and conditions of the Mulan PSL v2.
6  * You may obtain a copy of Mulan PSL v2 at:
7  *
8  *     http://license.coscl.org.cn/MulanPSL2
9  *
10  * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
11  * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
12  * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
13  * See the Mulan PSL v2 for more details.
14  */
15 
16 #include "hitls_build.h"
17 #ifdef HITLS_BSL_UIO_TCP
18 #include "bsl_binlog_id.h"
19 #include "bsl_err_internal.h"
20 #include "bsl_log_internal.h"
21 #include "bsl_log.h"
22 #include "bsl_sal.h"
23 #include "bsl_errno.h"
24 #include "sal_net.h"
25 #include "uio_base.h"
26 #include "uio_abstraction.h"
27 
28 typedef struct {
29     int32_t fd;
30 } TcpPrameters;
31 
TcpNew(BSL_UIO * uio)32 static int32_t TcpNew(BSL_UIO *uio)
33 {
34     if (uio->ctx != NULL) {
35         BSL_LOG_BINLOG_FIXLEN(BINLOG_ID05056, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
36             "Uio: ctx is already existed.", 0, 0, 0, 0);
37         BSL_ERR_PUSH_ERROR(BSL_UIO_FAIL);
38         return BSL_UIO_FAIL;
39     }
40 
41     TcpPrameters *parameters = (TcpPrameters *)BSL_SAL_Calloc(1u, sizeof(TcpPrameters));
42     if (parameters == NULL) {
43         BSL_LOG_BINLOG_FIXLEN(BINLOG_ID05057, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
44             "Uio: tcp param malloc fail.", 0, 0, 0, 0);
45         BSL_ERR_PUSH_ERROR(BSL_UIO_FAIL);
46         return BSL_UIO_FAIL;
47     }
48 
49     parameters->fd = -1;
50     uio->ctx = parameters;
51     uio->ctxLen = sizeof(TcpPrameters);
52     // Specifies whether to be closed by uio when setting fd.
53     // The default value of init is 0. Set the value of init to 1 after the fd is set.
54     return BSL_SUCCESS;
55 }
56 
TcpSocketDestroy(BSL_UIO * uio)57 static int32_t TcpSocketDestroy(BSL_UIO *uio)
58 {
59     if (uio == NULL) {
60         return BSL_SUCCESS;
61     }
62     uio->init = 0;
63     TcpPrameters *ctx = BSL_UIO_GetCtx(uio);
64     if (ctx != NULL) {
65         if (BSL_UIO_GetIsUnderlyingClosedByUio(uio) && ctx->fd != -1) {
66             (void)BSL_SAL_SockClose(ctx->fd);
67         }
68         BSL_SAL_FREE(ctx);
69         BSL_UIO_SetCtx(uio, NULL);
70     }
71     return BSL_SUCCESS;
72 }
73 
TcpSocketWrite(BSL_UIO * uio,const void * buf,uint32_t len,uint32_t * writeLen)74 static int32_t TcpSocketWrite(BSL_UIO *uio, const void *buf, uint32_t len, uint32_t *writeLen)
75 {
76     *writeLen = 0;
77     int32_t err = 0;
78     int32_t fd = BSL_UIO_GetFd(uio);
79     if (fd < 0) {
80         BSL_ERR_PUSH_ERROR(BSL_UIO_IO_EXCEPTION);
81         return BSL_UIO_IO_EXCEPTION;
82     }
83     int32_t ret = SAL_Write(fd, buf, len, &err);
84     (void)BSL_UIO_ClearFlags(uio, BSL_UIO_FLAGS_RWS | BSL_UIO_FLAGS_SHOULD_RETRY);
85     if (ret > 0) {
86         *writeLen = (uint32_t)ret;
87         return BSL_SUCCESS;
88     }
89     // If the value of ret is less than or equal to 0, check errno first.
90     if (UioIsNonFatalErr(err)) { // Indicates the errno for determining whether retry is allowed.
91         (void)BSL_UIO_SetFlags(uio, BSL_UIO_FLAGS_WRITE | BSL_UIO_FLAGS_SHOULD_RETRY);
92         return BSL_SUCCESS;
93     }
94     BSL_ERR_PUSH_ERROR(BSL_UIO_IO_EXCEPTION);
95     return BSL_UIO_IO_EXCEPTION;
96 }
97 
TcpSocketRead(BSL_UIO * uio,void * buf,uint32_t len,uint32_t * readLen)98 static int32_t TcpSocketRead(BSL_UIO *uio, void *buf, uint32_t len, uint32_t *readLen)
99 {
100     *readLen = 0;
101 
102     int32_t err = 0;
103     (void)BSL_UIO_ClearFlags(uio, BSL_UIO_FLAGS_RWS | BSL_UIO_FLAGS_SHOULD_RETRY);
104     int32_t fd = BSL_UIO_GetFd(uio);
105     if (fd < 0) {
106         BSL_ERR_PUSH_ERROR(BSL_UIO_IO_EXCEPTION);
107         return BSL_UIO_IO_EXCEPTION;
108     }
109     int32_t ret = SAL_Read(fd, buf, len, &err);
110     if (ret > 0) { // Success
111         *readLen = (uint32_t)ret;
112         return BSL_SUCCESS;
113     }
114     // If the value of ret is less than or equal to 0, check errno first.
115     if (UioIsNonFatalErr(err)) { // Indicates the errno for determining whether retry is allowed.
116         (void)BSL_UIO_SetFlags(uio, BSL_UIO_FLAGS_READ | BSL_UIO_FLAGS_SHOULD_RETRY);
117         return BSL_SUCCESS;
118     }
119     if (ret == 0) {
120         BSL_ERR_PUSH_ERROR(BSL_UIO_IO_EOF);
121         return BSL_UIO_IO_EOF;
122     }
123     BSL_ERR_PUSH_ERROR(BSL_UIO_IO_EXCEPTION);
124     return BSL_UIO_IO_EXCEPTION;
125 }
126 
TcpSetFd(BSL_UIO * uio,int32_t size,const int32_t * fd)127 static int32_t TcpSetFd(BSL_UIO *uio, int32_t size, const int32_t *fd)
128 {
129     bool invalid = (fd == NULL) || (uio == NULL);
130     if (invalid) {
131         BSL_ERR_PUSH_ERROR(BSL_NULL_INPUT);
132         return BSL_NULL_INPUT;
133     }
134     if (size != (int32_t)sizeof(*fd)) {
135         BSL_ERR_PUSH_ERROR(BSL_INVALID_ARG);
136         return BSL_INVALID_ARG;
137     }
138     TcpPrameters *ctx = BSL_UIO_GetCtx(uio);
139     if (ctx == NULL) {
140         BSL_ERR_PUSH_ERROR(BSL_NULL_INPUT);
141         return BSL_NULL_INPUT;
142     }
143     if (ctx->fd != -1) {
144         if (BSL_UIO_GetIsUnderlyingClosedByUio(uio)) {
145             (void)BSL_SAL_SockClose(ctx->fd);
146         }
147     }
148     ctx->fd = *fd;
149     uio->init = 1;
150     return BSL_SUCCESS;
151 }
152 
TcpGetFd(BSL_UIO * uio,int32_t size,int32_t * fd)153 static int32_t TcpGetFd(BSL_UIO *uio, int32_t size, int32_t *fd)
154 {
155     bool invalid = uio == NULL || fd == NULL;
156     if (invalid) {
157         BSL_ERR_PUSH_ERROR(BSL_NULL_INPUT);
158         return BSL_NULL_INPUT;
159     }
160     if (size != (int32_t)sizeof(*fd)) {
161         BSL_ERR_PUSH_ERROR(BSL_INVALID_ARG);
162         return BSL_INVALID_ARG;
163     }
164     TcpPrameters *ctx = BSL_UIO_GetCtx(uio);
165     if (ctx == NULL) {
166         BSL_ERR_PUSH_ERROR(BSL_NULL_INPUT);
167         return BSL_NULL_INPUT;
168     }
169     *fd = ctx->fd;
170     return BSL_SUCCESS;
171 }
172 
TcpSocketCtrl(BSL_UIO * uio,int32_t cmd,int32_t larg,void * parg)173 static int32_t TcpSocketCtrl(BSL_UIO *uio, int32_t cmd, int32_t larg, void *parg)
174 {
175     switch (cmd) {
176         case BSL_UIO_SET_FD:
177             return TcpSetFd(uio, larg, parg);
178         case BSL_UIO_GET_FD:
179             return TcpGetFd(uio, larg, parg);
180         case BSL_UIO_FLUSH:
181             return BSL_SUCCESS;
182         default:
183             break;
184     }
185     BSL_ERR_PUSH_ERROR(BSL_UIO_FAIL);
186     return BSL_UIO_FAIL;
187 }
188 
BSL_UIO_TcpMethod(void)189 const BSL_UIO_Method *BSL_UIO_TcpMethod(void)
190 {
191     static const BSL_UIO_Method method = {
192         BSL_UIO_TCP,
193         TcpSocketWrite,
194         TcpSocketRead,
195         TcpSocketCtrl,
196         NULL,
197         NULL,
198         TcpNew,
199         TcpSocketDestroy
200     };
201     return &method;
202 }
203 
204 #endif /* HITLS_BSL_UIO_TCP */
205