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