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