• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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