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