1 /*
2 * Copyright (C) 2021-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 "context.h"
17 #include <securec.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <sys/un.h>
21 #include "common.h"
22 #include "net.h"
23
CreateContext(int capacity)24 Context *CreateContext(int capacity)
25 {
26 if (capacity < CONTEXT_BUFFER_MIN_SIZE) {
27 capacity = CONTEXT_BUFFER_MIN_SIZE;
28 } else if (capacity > CONTEXT_BUFFER_MAX_SIZE) {
29 capacity = CONTEXT_BUFFER_MAX_SIZE;
30 }
31 Context *context = (Context *)calloc(1, sizeof(Context));
32 if (context == NULL) {
33 return NULL;
34 }
35 context->rCapacity = (uint32_t)capacity;
36 context->wCapacity = (uint32_t)capacity;
37 context->szRead = (char *)calloc(capacity, sizeof(char));
38 if (context->szRead == NULL) {
39 free(context);
40 context = NULL;
41 return NULL;
42 }
43 context->szWrite = (char *)calloc(capacity, sizeof(char));
44 if (context->szWrite == NULL) {
45 free(context->szRead);
46 free(context);
47 context = NULL;
48 return NULL;
49 }
50 context->cSplit = '\t';
51 context->cMsgEnd = "$$$$$$";
52 return context;
53 }
54
ReleaseContext(Context * context)55 void ReleaseContext(Context *context)
56 {
57 if (context == NULL) {
58 return;
59 }
60
61 if (context != NULL) {
62 free(context->szRead);
63 free(context->szWrite);
64 free(context);
65 context = NULL;
66 }
67 }
68
69 /**
70 * when context's read/write buffer is less then request len
71 * expand the buffer size
72 */
ExpandReadCache(Context * context,int len)73 static int ExpandReadCache(Context *context, int len)
74 {
75 if (context == NULL) {
76 return -1;
77 }
78
79 int left = (int)((context->rBegin <= context->rEnd) ? (context->rCapacity - 1 - context->rEnd + context->rBegin)
80 : (context->rBegin - context->rEnd - 1));
81 if (left < len) {
82 uint32_t capacity = context->rCapacity;
83 while (left < len) {
84 capacity += context->rCapacity;
85 left += context->rCapacity;
86 }
87 char *p = (char *)calloc(capacity, sizeof(char));
88 if (p == NULL) {
89 return -1;
90 }
91 if (memmove_s(p, capacity, context->szRead, context->rCapacity) != EOK) {
92 free(p);
93 p = NULL;
94 return -1;
95 }
96 if (context->rBegin > context->rEnd &&
97 memmove_s(p + context->rCapacity, context->rCapacity, p, context->rEnd) != EOK) {
98 free(p);
99 p = NULL;
100 return -1;
101 }
102 char *pFree = context->szRead;
103 context->szRead = p;
104 if (context->rBegin > context->rEnd) {
105 context->rEnd += context->rCapacity;
106 }
107 context->rCapacity = capacity;
108 free(pFree);
109 pFree = NULL;
110 }
111 return 0;
112 }
113
ExpandWriteCache(Context * context,int len)114 static int ExpandWriteCache(Context *context, int len)
115 {
116 if (context == NULL) {
117 return -1;
118 }
119
120 int left = (int)((context->wBegin <= context->wEnd) ? (context->wCapacity - 1 - context->wEnd + context->wBegin)
121 : (context->wBegin - context->wEnd - 1));
122 if (left < len) {
123 uint32_t capacity = context->wCapacity;
124 while (left < len) {
125 capacity += context->wCapacity;
126 left += (int)context->wCapacity;
127 }
128 char *p = (char *)calloc(capacity, sizeof(char));
129 if (p == NULL) {
130 return -1;
131 }
132 if (context->wCapacity < 0) {
133 free(p);
134 p = NULL;
135 return -1;
136 }
137 if (memmove_s(p, capacity, context->szWrite, context->wCapacity) != EOK) {
138 free(p);
139 p = NULL;
140 return -1;
141 }
142 if (context->wBegin > context->wEnd &&
143 memmove_s(p + context->wCapacity, context->wCapacity, p, context->wEnd) != EOK) {
144 free(p);
145 p = NULL;
146 return -1;
147 }
148 char *pFree = context->szWrite;
149 context->szWrite = p;
150 if (context->wBegin > context->wEnd) {
151 context->wEnd += context->wCapacity;
152 }
153 context->wCapacity = capacity;
154 free(pFree);
155 pFree = NULL;
156 }
157 return 0;
158 }
159
ContextAppendRead(Context * context,const char * buf,int len)160 static int ContextAppendRead(Context *context, const char *buf, int len)
161 {
162 if (context == NULL) {
163 return -1;
164 }
165
166 if (ExpandReadCache(context, len) < 0) {
167 return -1;
168 }
169 if (context->rEnd + len < context->rCapacity) {
170 if (memmove_s(context->szRead + context->rEnd, context->rCapacity - context->rEnd, buf, len) != EOK) {
171 return -1;
172 }
173 context->rEnd += len;
174 } else {
175 int tmp = (int)(context->rCapacity - context->rEnd);
176 if (tmp > 0 && memmove_s(context->szRead + context->rEnd, tmp, buf, tmp) != EOK) {
177 return -1;
178 }
179 if (tmp < len && memmove_s(context->szRead, len - tmp, buf + tmp, len - tmp) != EOK) {
180 return -1;
181 }
182 context->rEnd = (uint32_t)(len - tmp);
183 }
184 return 0;
185 }
186
ContextAppendWrite(Context * context,const char * buf,int len)187 int ContextAppendWrite(Context *context, const char *buf, int len)
188 {
189 if (context == NULL) {
190 return -1;
191 }
192
193 if (ExpandWriteCache(context, len) < 0) {
194 return -1;
195 }
196 if (context->wEnd + len < context->wCapacity) {
197 if (memmove_s(context->szWrite + context->wEnd, context->wCapacity - context->wEnd, buf, len) != EOK) {
198 return -1;
199 }
200 context->wEnd += len;
201 } else {
202 int tmp = (int)(context->wCapacity - context->wEnd);
203 if (tmp > 0 && memmove_s(context->szWrite + context->wEnd, tmp, buf, tmp) != EOK) {
204 return -1;
205 }
206 if (tmp < len && memmove_s(context->szWrite, len - tmp, buf + tmp, len - tmp) != EOK) {
207 return -1;
208 }
209 context->wEnd = (uint32_t)(len - tmp);
210 }
211 return 0;
212 }
213
ContextGetReadRecord(Context * context)214 char *ContextGetReadRecord(Context *context)
215 {
216 if (context == NULL) {
217 return NULL;
218 }
219
220 if (context->rBegin == context->rEnd) {
221 return NULL;
222 }
223 uint32_t len = (context->rBegin <= context->rEnd) ? (context->rEnd - context->rBegin)
224 : (context->rCapacity - context->rBegin + context->rEnd);
225 char *buf = (char *)calloc(len + 1, sizeof(char));
226 if (buf == NULL) {
227 return NULL;
228 }
229 if (context->rBegin < context->rEnd) {
230 if (memmove_s(buf, len, context->szRead + context->rBegin, len) != EOK) {
231 free(buf);
232 return NULL;
233 }
234 } else {
235 int tmp = (int)(context->rCapacity - context->rBegin);
236 if (tmp > 0 && memmove_s(buf, len + 1, context->szRead + context->rBegin, tmp) != EOK) {
237 free(buf);
238 return NULL;
239 }
240 if (context->rEnd > 0 && memmove_s(buf + tmp, len + 1 - tmp, context->szRead, context->rEnd) != EOK) {
241 free(buf);
242 return NULL;
243 }
244 }
245 buf[len] = 0;
246 char *p = strstr(buf, context->cMsgEnd);
247 if (p == NULL) {
248 free(buf);
249 return NULL;
250 }
251 *p = 0;
252 uint32_t num = p - buf + strlen(context->cMsgEnd);
253 context->rBegin += num;
254 if (context->rBegin >= context->rCapacity) {
255 context->rBegin -= context->rCapacity;
256 }
257 return buf;
258 }
259
ContextReadNet(Context * context)260 int ContextReadNet(Context *context)
261 {
262 if (context == NULL) {
263 return -1;
264 }
265
266 char line[MAX_ONE_LINE_SIZE] = {0};
267 int ret = MyRead(context->fd, line, sizeof(line) - 1);
268 if (ret == SOCK_ERR) {
269 return SOCK_ERR;
270 }
271 int len = strlen(line);
272 if (len > 0 && ContextAppendRead(context, line, len) < 0) {
273 return -1;
274 }
275 return ret;
276 }
277
ContextWriteNet(Context * context)278 int ContextWriteNet(Context *context)
279 {
280 if (context == NULL) {
281 return -1;
282 }
283
284 if (context->wBegin == context->wEnd) {
285 return 0;
286 }
287 if (context->wBegin < context->wEnd) {
288 int ret = MyWrite(context->fd, context->szWrite + context->wBegin, context->wEnd - context->wBegin);
289 if (ret > 0) {
290 context->wBegin += ret;
291 }
292 return ret;
293 }
294 int len = (int)(context->wCapacity - context->wBegin);
295 int ret = MyWrite(context->fd, context->szWrite + context->wBegin, len);
296 if (ret < 0) {
297 return ret;
298 }
299 if (ret < len) {
300 context->wBegin += ret;
301 return ret;
302 }
303 context->wBegin = 0;
304 ret = MyWrite(context->fd, context->szWrite, context->wEnd);
305 if (ret > 0) {
306 context->wBegin = (uint32_t)ret;
307 }
308 return ret;
309 }
310