xref: /f-stack/app/micro_thread/mt_cache.cpp (revision a9643ea8)
1*a9643ea8Slogwang 
2*a9643ea8Slogwang /**
3*a9643ea8Slogwang  * Tencent is pleased to support the open source community by making MSEC available.
4*a9643ea8Slogwang  *
5*a9643ea8Slogwang  * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
6*a9643ea8Slogwang  *
7*a9643ea8Slogwang  * Licensed under the GNU General Public License, Version 2.0 (the "License");
8*a9643ea8Slogwang  * you may not use this file except in compliance with the License. You may
9*a9643ea8Slogwang  * obtain a copy of the License at
10*a9643ea8Slogwang  *
11*a9643ea8Slogwang  *     https://opensource.org/licenses/GPL-2.0
12*a9643ea8Slogwang  *
13*a9643ea8Slogwang  * Unless required by applicable law or agreed to in writing, software distributed under the
14*a9643ea8Slogwang  * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
15*a9643ea8Slogwang  * either express or implied. See the License for the specific language governing permissions
16*a9643ea8Slogwang  * and limitations under the License.
17*a9643ea8Slogwang  */
18*a9643ea8Slogwang 
19*a9643ea8Slogwang 
20*a9643ea8Slogwang /**
21*a9643ea8Slogwang  *  @filename mt_cache.cpp
22*a9643ea8Slogwang  *  @info   TCP����buffer����ʵ��
23*a9643ea8Slogwang  */
24*a9643ea8Slogwang 
25*a9643ea8Slogwang #include <stdlib.h>
26*a9643ea8Slogwang #include <errno.h>
27*a9643ea8Slogwang #include <sys/types.h>
28*a9643ea8Slogwang #include <sys/socket.h>
29*a9643ea8Slogwang #include <string.h>
30*a9643ea8Slogwang #include "mt_incl.h"
31*a9643ea8Slogwang #include "kqueue_proxy.h"
32*a9643ea8Slogwang #include "micro_thread.h"
33*a9643ea8Slogwang #include "mt_sys_hook.h"
34*a9643ea8Slogwang #include "ff_hook.h"
35*a9643ea8Slogwang 
36*a9643ea8Slogwang #include "mt_cache.h"
37*a9643ea8Slogwang 
38*a9643ea8Slogwang namespace NS_MICRO_THREAD {
39*a9643ea8Slogwang 
40*a9643ea8Slogwang 
41*a9643ea8Slogwang /**
42*a9643ea8Slogwang  * @brief  Buffer��������
43*a9643ea8Slogwang  * @param  size ʵ�ʵ�buff��С
44*a9643ea8Slogwang  * @return ��NULL block��, ����ʧ��
45*a9643ea8Slogwang  */
46*a9643ea8Slogwang TSkBuffer* new_sk_buffer(uint32_t size)
47*a9643ea8Slogwang {
48*a9643ea8Slogwang     uint32_t total = sizeof(TSkBuffer) + size;
49*a9643ea8Slogwang     total = (total + SK_DFLT_ALIGN_SIZE - 1) / SK_DFLT_ALIGN_SIZE * SK_DFLT_ALIGN_SIZE;
50*a9643ea8Slogwang     TSkBuffer* block = (TSkBuffer*)malloc(total);
51*a9643ea8Slogwang     if (block == NULL)
52*a9643ea8Slogwang     {
53*a9643ea8Slogwang         MTLOG_ERROR("malloc failed, no more memory[%u]", total);
54*a9643ea8Slogwang         return NULL;
55*a9643ea8Slogwang     }
56*a9643ea8Slogwang 
57*a9643ea8Slogwang     block->last_time = 0;
58*a9643ea8Slogwang     block->size = size;
59*a9643ea8Slogwang     block->head = block->buff;
60*a9643ea8Slogwang     block->end  = block->buff + size;
61*a9643ea8Slogwang 
62*a9643ea8Slogwang     block->data = block->head;
63*a9643ea8Slogwang     block->data_len = 0;
64*a9643ea8Slogwang 
65*a9643ea8Slogwang     return block;
66*a9643ea8Slogwang }
67*a9643ea8Slogwang 
68*a9643ea8Slogwang 
69*a9643ea8Slogwang /**
70*a9643ea8Slogwang  * @brief  Buffer�ͷŲ���
71*a9643ea8Slogwang  * @param  block -buff��
72*a9643ea8Slogwang  */
73*a9643ea8Slogwang void delete_sk_buffer(TSkBuffer* block)
74*a9643ea8Slogwang {
75*a9643ea8Slogwang     if (NULL == block) {
76*a9643ea8Slogwang         return;
77*a9643ea8Slogwang     }
78*a9643ea8Slogwang 
79*a9643ea8Slogwang     free(block);
80*a9643ea8Slogwang }
81*a9643ea8Slogwang 
82*a9643ea8Slogwang 
83*a9643ea8Slogwang /**
84*a9643ea8Slogwang  * @brief ������������Ϣ(����Դ�ػ���buff,����չ)
85*a9643ea8Slogwang  * @param buff -���е�buffָ��
86*a9643ea8Slogwang  * @param size -��Ҫ��չ�����ճ��ȴ�С
87*a9643ea8Slogwang  * @return ʵ�ʵ�buff��Ϣ
88*a9643ea8Slogwang  */
89*a9643ea8Slogwang TSkBuffer* reserve_sk_buffer(TSkBuffer* buff, uint32_t size)
90*a9643ea8Slogwang {
91*a9643ea8Slogwang     if (NULL == buff) {
92*a9643ea8Slogwang         return new_sk_buffer(size);
93*a9643ea8Slogwang     }
94*a9643ea8Slogwang 
95*a9643ea8Slogwang     if (buff->size >= size) {
96*a9643ea8Slogwang         return buff;
97*a9643ea8Slogwang     }
98*a9643ea8Slogwang 
99*a9643ea8Slogwang     TSkBuffer* new_buff = new_sk_buffer(size);
100*a9643ea8Slogwang     if (NULL == new_buff) {
101*a9643ea8Slogwang         return buff;
102*a9643ea8Slogwang     }
103*a9643ea8Slogwang     memcpy(new_buff->data, buff->data, buff->data_len);
104*a9643ea8Slogwang     new_buff->data_len = buff->data_len;
105*a9643ea8Slogwang     delete_sk_buffer(buff);
106*a9643ea8Slogwang 
107*a9643ea8Slogwang     return new_buff;
108*a9643ea8Slogwang }
109*a9643ea8Slogwang 
110*a9643ea8Slogwang 
111*a9643ea8Slogwang /**
112*a9643ea8Slogwang  * @brief  cache �صij�ʼ���ӿ�
113*a9643ea8Slogwang  * @param  mng -����ص�ָ��
114*a9643ea8Slogwang  * @param  expired -�����ʱ��, ��λ��
115*a9643ea8Slogwang  * @param  size -�������Ĭ�����ɵĿ��С
116*a9643ea8Slogwang  */
117*a9643ea8Slogwang void sk_buffer_mng_init(TSkBuffMng* mng, uint32_t expired, uint32_t size)
118*a9643ea8Slogwang {
119*a9643ea8Slogwang     TAILQ_INIT(&mng->free_list);
120*a9643ea8Slogwang     mng->expired  = expired;
121*a9643ea8Slogwang     mng->count = 0;
122*a9643ea8Slogwang     mng->size = size;
123*a9643ea8Slogwang }
124*a9643ea8Slogwang 
125*a9643ea8Slogwang /**
126*a9643ea8Slogwang  * @brief  cache �ص����ٽӿ�
127*a9643ea8Slogwang  * @param  mng -����ص�ָ��
128*a9643ea8Slogwang  */
129*a9643ea8Slogwang void sk_buffer_mng_destroy(TSkBuffMng * mng)
130*a9643ea8Slogwang {
131*a9643ea8Slogwang     TSkBuffer* item = NULL;
132*a9643ea8Slogwang     TSkBuffer* tmp = NULL;
133*a9643ea8Slogwang     TAILQ_FOREACH_SAFE(item, &mng->free_list, entry, tmp)
134*a9643ea8Slogwang     {
135*a9643ea8Slogwang         TAILQ_REMOVE(&mng->free_list, item, entry);
136*a9643ea8Slogwang         delete_sk_buffer(item);
137*a9643ea8Slogwang     }
138*a9643ea8Slogwang     mng->count = 0;
139*a9643ea8Slogwang }
140*a9643ea8Slogwang 
141*a9643ea8Slogwang 
142*a9643ea8Slogwang /**
143*a9643ea8Slogwang  * @brief  �������һ��buff
144*a9643ea8Slogwang  * @param  mng -����ص�ָ��
145*a9643ea8Slogwang  * @return ��NULLΪ�ɹ���ȡ��buff��ָ��
146*a9643ea8Slogwang  */
147*a9643ea8Slogwang TSkBuffer* alloc_sk_buffer(TSkBuffMng* mng)
148*a9643ea8Slogwang {
149*a9643ea8Slogwang     if (NULL == mng) {
150*a9643ea8Slogwang         return NULL;
151*a9643ea8Slogwang     }
152*a9643ea8Slogwang 
153*a9643ea8Slogwang     TSkBuffer* item = TAILQ_FIRST(&mng->free_list);
154*a9643ea8Slogwang     if (item != NULL)
155*a9643ea8Slogwang     {
156*a9643ea8Slogwang         TAILQ_REMOVE(&mng->free_list, item, entry);
157*a9643ea8Slogwang         mng->count--;
158*a9643ea8Slogwang         return item;
159*a9643ea8Slogwang     }
160*a9643ea8Slogwang 
161*a9643ea8Slogwang     item = new_sk_buffer(mng->size);
162*a9643ea8Slogwang     if (NULL == item)
163*a9643ea8Slogwang     {
164*a9643ea8Slogwang         return NULL;
165*a9643ea8Slogwang     }
166*a9643ea8Slogwang 
167*a9643ea8Slogwang     return item;
168*a9643ea8Slogwang }
169*a9643ea8Slogwang 
170*a9643ea8Slogwang 
171*a9643ea8Slogwang /**
172*a9643ea8Slogwang  * @brief �ͷ�ָ����buff��
173*a9643ea8Slogwang  * @param  mng -����ص�ָ��
174*a9643ea8Slogwang  * @param  buff -���ͷŵ�buffָ��
175*a9643ea8Slogwang  */
176*a9643ea8Slogwang void free_sk_buffer(TSkBuffMng* mng, TSkBuffer* buff)
177*a9643ea8Slogwang {
178*a9643ea8Slogwang     if ((NULL == mng) || (NULL == buff)) {
179*a9643ea8Slogwang         return;
180*a9643ea8Slogwang     }
181*a9643ea8Slogwang 
182*a9643ea8Slogwang     TAILQ_INSERT_TAIL(&mng->free_list, buff, entry);
183*a9643ea8Slogwang     mng->count++;
184*a9643ea8Slogwang 
185*a9643ea8Slogwang     buff->last_time = (uint32_t)(mt_time_ms() / 1000);
186*a9643ea8Slogwang     buff->data = buff->head;
187*a9643ea8Slogwang     buff->data_len = 0;
188*a9643ea8Slogwang }
189*a9643ea8Slogwang 
190*a9643ea8Slogwang 
191*a9643ea8Slogwang /**
192*a9643ea8Slogwang  * @brief ���չ��ڵ�buff��
193*a9643ea8Slogwang  * @param  mng -����ص�ָ��
194*a9643ea8Slogwang  * @param  now -��ǰ��ʱ��, �뼶��
195*a9643ea8Slogwang  */
196*a9643ea8Slogwang void recycle_sk_buffer(TSkBuffMng* mng, uint32_t now)
197*a9643ea8Slogwang {
198*a9643ea8Slogwang     TSkBuffer* item = NULL;
199*a9643ea8Slogwang     TSkBuffer* tmp = NULL;
200*a9643ea8Slogwang     TAILQ_FOREACH_SAFE(item, &mng->free_list, entry, tmp)
201*a9643ea8Slogwang     {
202*a9643ea8Slogwang         if ((now - item->last_time) < mng->expired)
203*a9643ea8Slogwang         {
204*a9643ea8Slogwang             break;
205*a9643ea8Slogwang         }
206*a9643ea8Slogwang 
207*a9643ea8Slogwang         TAILQ_REMOVE(&mng->free_list, item, entry);
208*a9643ea8Slogwang         delete_sk_buffer(item);
209*a9643ea8Slogwang         mng->count--;
210*a9643ea8Slogwang     }
211*a9643ea8Slogwang }
212*a9643ea8Slogwang 
213*a9643ea8Slogwang 
214*a9643ea8Slogwang /**
215*a9643ea8Slogwang  * @brief Cache��������ʼ��
216*a9643ea8Slogwang  * @param cache -�����ָ��
217*a9643ea8Slogwang  * @param pool -buff��ָ��
218*a9643ea8Slogwang  */
219*a9643ea8Slogwang void rw_cache_init(TRWCache* cache, TSkBuffMng* pool)
220*a9643ea8Slogwang {
221*a9643ea8Slogwang     TAILQ_INIT(&cache->list);
222*a9643ea8Slogwang     cache->len = 0;
223*a9643ea8Slogwang     cache->count = 0;
224*a9643ea8Slogwang     cache->pool = pool;
225*a9643ea8Slogwang }
226*a9643ea8Slogwang 
227*a9643ea8Slogwang /**
228*a9643ea8Slogwang  * @brief Cache����������
229*a9643ea8Slogwang  * @param cache -�����ָ��
230*a9643ea8Slogwang  */
231*a9643ea8Slogwang void rw_cache_destroy(TRWCache* cache)
232*a9643ea8Slogwang {
233*a9643ea8Slogwang     if ((cache == NULL) || (cache->pool == NULL)) {
234*a9643ea8Slogwang         return;
235*a9643ea8Slogwang     }
236*a9643ea8Slogwang 
237*a9643ea8Slogwang     TSkBuffer* item = NULL;
238*a9643ea8Slogwang     TSkBuffer* tmp = NULL;
239*a9643ea8Slogwang     TAILQ_FOREACH_SAFE(item, &cache->list, entry, tmp)
240*a9643ea8Slogwang     {
241*a9643ea8Slogwang         TAILQ_REMOVE(&cache->list, item, entry);
242*a9643ea8Slogwang         free_sk_buffer(cache->pool, item);
243*a9643ea8Slogwang     }
244*a9643ea8Slogwang     cache->count = 0;
245*a9643ea8Slogwang     cache->len = 0;
246*a9643ea8Slogwang     cache->pool = NULL;
247*a9643ea8Slogwang }
248*a9643ea8Slogwang 
249*a9643ea8Slogwang 
250*a9643ea8Slogwang /**
251*a9643ea8Slogwang  * @brief Cacheɾ��������ָ����������
252*a9643ea8Slogwang  * @param cache -�����ָ��
253*a9643ea8Slogwang  * @param buff -���buff��ָ��
254*a9643ea8Slogwang  * @param len -��ɾ���ij���
255*a9643ea8Slogwang  * @return ʵ�ʿ�������
256*a9643ea8Slogwang  */
257*a9643ea8Slogwang uint32_t cache_copy_out(TRWCache* cache, void* buff, uint32_t len)
258*a9643ea8Slogwang {
259*a9643ea8Slogwang     if ((cache == NULL) || (cache->pool == NULL)) {
260*a9643ea8Slogwang         return 0;
261*a9643ea8Slogwang     }
262*a9643ea8Slogwang 
263*a9643ea8Slogwang     char* out_buff = (char*)buff;
264*a9643ea8Slogwang     uint32_t left = len, skip_len = 0;
265*a9643ea8Slogwang     TSkBuffer* item = NULL;
266*a9643ea8Slogwang     TSkBuffer* tmp = NULL;
267*a9643ea8Slogwang     TAILQ_FOREACH_SAFE(item, &cache->list, entry, tmp)
268*a9643ea8Slogwang     {
269*a9643ea8Slogwang         // 1. ȷ�Ͽ������ݴ�С
270*a9643ea8Slogwang         skip_len = (item->data_len > left) ? left : item->data_len;
271*a9643ea8Slogwang         if (out_buff != NULL)
272*a9643ea8Slogwang         {
273*a9643ea8Slogwang             memcpy(out_buff, item->data, skip_len);
274*a9643ea8Slogwang             out_buff += skip_len;
275*a9643ea8Slogwang         }
276*a9643ea8Slogwang 
277*a9643ea8Slogwang         left -= skip_len;
278*a9643ea8Slogwang         item->data_len -= skip_len;
279*a9643ea8Slogwang         item->data += skip_len;
280*a9643ea8Slogwang         if (item->data_len > 0)
281*a9643ea8Slogwang         {
282*a9643ea8Slogwang             break;
283*a9643ea8Slogwang         }
284*a9643ea8Slogwang 
285*a9643ea8Slogwang         // 2. �Ƴ�һ��block
286*a9643ea8Slogwang         if (cache->count > 0) {
287*a9643ea8Slogwang             cache->count--;
288*a9643ea8Slogwang         }
289*a9643ea8Slogwang         TAILQ_REMOVE(&cache->list, item, entry);
290*a9643ea8Slogwang         free_sk_buffer(cache->pool, item);
291*a9643ea8Slogwang 
292*a9643ea8Slogwang         // 3. ѭ����������
293*a9643ea8Slogwang         if (left == 0)
294*a9643ea8Slogwang         {
295*a9643ea8Slogwang             break;
296*a9643ea8Slogwang         }
297*a9643ea8Slogwang     }
298*a9643ea8Slogwang 
299*a9643ea8Slogwang     // ���忼�����ݳ�������, �Ƿ����㹻�������Ƴ�
300*a9643ea8Slogwang     skip_len = len - left;
301*a9643ea8Slogwang     if (cache->len > skip_len)
302*a9643ea8Slogwang     {
303*a9643ea8Slogwang         cache->len -= skip_len;
304*a9643ea8Slogwang     }
305*a9643ea8Slogwang     else
306*a9643ea8Slogwang     {
307*a9643ea8Slogwang         cache->len = 0;
308*a9643ea8Slogwang     }
309*a9643ea8Slogwang 
310*a9643ea8Slogwang     return skip_len;
311*a9643ea8Slogwang }
312*a9643ea8Slogwang 
313*a9643ea8Slogwang 
314*a9643ea8Slogwang /**
315*a9643ea8Slogwang  * @brief Cacheɾ����ָ����������
316*a9643ea8Slogwang  * @param cache -�����ָ��
317*a9643ea8Slogwang  * @param len -��ɾ���ij���
318*a9643ea8Slogwang  */
319*a9643ea8Slogwang void cache_skip_data(TRWCache* cache, uint32_t len)
320*a9643ea8Slogwang {
321*a9643ea8Slogwang     cache_copy_out(cache, NULL, len);
322*a9643ea8Slogwang }
323*a9643ea8Slogwang 
324*a9643ea8Slogwang /**
325*a9643ea8Slogwang  * @brief Cache׷��ָ����������
326*a9643ea8Slogwang  * @param cache -�����ָ��
327*a9643ea8Slogwang  * @param buff -��׷�ӵĿ�ָ��
328*a9643ea8Slogwang  */
329*a9643ea8Slogwang void cache_append_buffer(TRWCache* cache, TSkBuffer* buff)
330*a9643ea8Slogwang {
331*a9643ea8Slogwang     if ((NULL == cache) || (NULL == buff))
332*a9643ea8Slogwang     {
333*a9643ea8Slogwang         return;
334*a9643ea8Slogwang     }
335*a9643ea8Slogwang 
336*a9643ea8Slogwang     TAILQ_INSERT_TAIL(&cache->list, buff, entry);
337*a9643ea8Slogwang     cache->len += buff->data_len;
338*a9643ea8Slogwang     cache->count++;
339*a9643ea8Slogwang }
340*a9643ea8Slogwang 
341*a9643ea8Slogwang /**
342*a9643ea8Slogwang  * @brief Cache�Ƴ���һ���ڴ�, ����free
343*a9643ea8Slogwang  * @param cache -�����ָ��
344*a9643ea8Slogwang  */
345*a9643ea8Slogwang TSkBuffer* cache_skip_first_buffer(TRWCache* cache)
346*a9643ea8Slogwang {
347*a9643ea8Slogwang     TSkBuffer* buff = TAILQ_FIRST(&cache->list);
348*a9643ea8Slogwang     if ((NULL == cache) || (NULL == buff))
349*a9643ea8Slogwang     {
350*a9643ea8Slogwang         return NULL;
351*a9643ea8Slogwang     }
352*a9643ea8Slogwang 
353*a9643ea8Slogwang     TAILQ_REMOVE(&cache->list, buff, entry);
354*a9643ea8Slogwang     if (cache->len >= buff->data_len)
355*a9643ea8Slogwang     {
356*a9643ea8Slogwang         cache->len -= buff->data_len;
357*a9643ea8Slogwang     }
358*a9643ea8Slogwang 
359*a9643ea8Slogwang     if (cache->count > 0)
360*a9643ea8Slogwang     {
361*a9643ea8Slogwang         cache->count--;
362*a9643ea8Slogwang     }
363*a9643ea8Slogwang 
364*a9643ea8Slogwang     return buff;
365*a9643ea8Slogwang }
366*a9643ea8Slogwang 
367*a9643ea8Slogwang 
368*a9643ea8Slogwang /**
369*a9643ea8Slogwang  * @brief Cache׷��ָ����������
370*a9643ea8Slogwang  * @param cache -�����ָ��
371*a9643ea8Slogwang  * @param data -��׷�ӵ�ָ��
372*a9643ea8Slogwang  * @param len -��׷�ӵij���
373*a9643ea8Slogwang  */
374*a9643ea8Slogwang int32_t cache_append_data(TRWCache* cache, const void* data, uint32_t len)
375*a9643ea8Slogwang {
376*a9643ea8Slogwang     if ((NULL == data) || (NULL == cache) || (NULL == cache->pool))
377*a9643ea8Slogwang     {
378*a9643ea8Slogwang         return -1;
379*a9643ea8Slogwang     }
380*a9643ea8Slogwang 
381*a9643ea8Slogwang     if (len == 0)
382*a9643ea8Slogwang     {
383*a9643ea8Slogwang         return 0;
384*a9643ea8Slogwang     }
385*a9643ea8Slogwang 
386*a9643ea8Slogwang     uint32_t left = len;
387*a9643ea8Slogwang     uint32_t remain = 0;
388*a9643ea8Slogwang 
389*a9643ea8Slogwang     // 1. β�ռ��Ƚ���append, ��Ϊ��Ҫ�ع�, ǰһ�����Ȳ�����
390*a9643ea8Slogwang     TSkBuffer* tail = TAILQ_LAST(&cache->list, __sk_buff_list);
391*a9643ea8Slogwang     if (tail != NULL)
392*a9643ea8Slogwang     {
393*a9643ea8Slogwang         if (tail->end > (tail->data + tail->data_len))
394*a9643ea8Slogwang         {
395*a9643ea8Slogwang             remain = tail->end - tail->data - tail->data_len;
396*a9643ea8Slogwang         }
397*a9643ea8Slogwang 
398*a9643ea8Slogwang         if (remain >= len)
399*a9643ea8Slogwang         {
400*a9643ea8Slogwang             memcpy(tail->data + tail->data_len, data, len);
401*a9643ea8Slogwang             tail->data_len += len;
402*a9643ea8Slogwang             cache->len += len;
403*a9643ea8Slogwang             return (int32_t)len;
404*a9643ea8Slogwang         }
405*a9643ea8Slogwang     }
406*a9643ea8Slogwang 
407*a9643ea8Slogwang     // 2. ��ʣ��buff������, ������ʣ���buff, ���޸�β�ڵ�
408*a9643ea8Slogwang     TRWCache keep_list;
409*a9643ea8Slogwang     rw_cache_init(&keep_list, cache->pool);
410*a9643ea8Slogwang     left -= remain;
411*a9643ea8Slogwang     while (left > 0)
412*a9643ea8Slogwang     {
413*a9643ea8Slogwang         TSkBuffer* item = alloc_sk_buffer(cache->pool);
414*a9643ea8Slogwang         if (item == NULL)
415*a9643ea8Slogwang         {
416*a9643ea8Slogwang             rw_cache_destroy(&keep_list);
417*a9643ea8Slogwang             return -2;
418*a9643ea8Slogwang         }
419*a9643ea8Slogwang         cache_append_buffer(&keep_list, item);
420*a9643ea8Slogwang 
421*a9643ea8Slogwang         if (left <= item->size)
422*a9643ea8Slogwang         {
423*a9643ea8Slogwang             memcpy(item->head, (char*)data + len - left, left);
424*a9643ea8Slogwang             item->data_len = left;
425*a9643ea8Slogwang             break;
426*a9643ea8Slogwang         }
427*a9643ea8Slogwang 
428*a9643ea8Slogwang         memcpy(item->head, (char*)data + len - left, item->size);
429*a9643ea8Slogwang         item->data_len = item->size;
430*a9643ea8Slogwang         left -= item->size;
431*a9643ea8Slogwang     }
432*a9643ea8Slogwang 
433*a9643ea8Slogwang     // 3. ���Կ��������buff, ���ﲻ��ع���
434*a9643ea8Slogwang     if ((tail != NULL) && (remain > 0))
435*a9643ea8Slogwang     {
436*a9643ea8Slogwang         memcpy(tail->data + tail->data_len, data, remain);
437*a9643ea8Slogwang         tail->data_len += remain;
438*a9643ea8Slogwang     }
439*a9643ea8Slogwang 
440*a9643ea8Slogwang     cache->len += len;
441*a9643ea8Slogwang     cache->count += keep_list.count;
442*a9643ea8Slogwang     TAILQ_CONCAT(&cache->list, &keep_list.list, entry);
443*a9643ea8Slogwang 
444*a9643ea8Slogwang     return (int32_t)len;
445*a9643ea8Slogwang }
446*a9643ea8Slogwang 
447*a9643ea8Slogwang 
448*a9643ea8Slogwang /**
449*a9643ea8Slogwang  * @brief Cache���ϵ�UDP�ձ��ӿ�, �����ڴ�Ƚ϶�, ������32λʹ��
450*a9643ea8Slogwang  * @param cache -�����ָ��
451*a9643ea8Slogwang  * @param fd - ׼���ձ���fd���
452*a9643ea8Slogwang  * @param remote_addr -�Զ�ip��ַ
453*a9643ea8Slogwang  * @return ʵ�ʽ��ճ���
454*a9643ea8Slogwang  */
455*a9643ea8Slogwang int32_t cache_udp_recv(TRWCache* cache, uint32_t fd, struct sockaddr_in* remote_addr)
456*a9643ea8Slogwang {
457*a9643ea8Slogwang     if (NULL == cache)
458*a9643ea8Slogwang     {
459*a9643ea8Slogwang         return -1;
460*a9643ea8Slogwang     }
461*a9643ea8Slogwang 
462*a9643ea8Slogwang     int32_t total = 0;
463*a9643ea8Slogwang     for (uint32_t i = 0; i < 100; i++)
464*a9643ea8Slogwang     {
465*a9643ea8Slogwang         TSkBuffer* item = alloc_sk_buffer(cache->pool);
466*a9643ea8Slogwang         if (NULL == item)
467*a9643ea8Slogwang         {
468*a9643ea8Slogwang             return -2;
469*a9643ea8Slogwang         }
470*a9643ea8Slogwang 
471*a9643ea8Slogwang         socklen_t addr_len = sizeof(*remote_addr);
472*a9643ea8Slogwang         mt_hook_syscall(recvfrom);
473*a9643ea8Slogwang         int32_t rc = ff_hook_recvfrom(fd, item->data, item->size, 0, (struct sockaddr*)remote_addr, &addr_len);
474*a9643ea8Slogwang         if (rc <= 0)
475*a9643ea8Slogwang         {
476*a9643ea8Slogwang             free_sk_buffer(cache->pool, item);
477*a9643ea8Slogwang 
478*a9643ea8Slogwang             if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
479*a9643ea8Slogwang             {
480*a9643ea8Slogwang                 break;
481*a9643ea8Slogwang             }
482*a9643ea8Slogwang             else
483*a9643ea8Slogwang             {
484*a9643ea8Slogwang                 MTLOG_ERROR("recvfrom failed, fd[%d] ret %d[%m]", fd, rc);
485*a9643ea8Slogwang                 return -3;
486*a9643ea8Slogwang             }
487*a9643ea8Slogwang         }
488*a9643ea8Slogwang 
489*a9643ea8Slogwang         item->data_len += rc;
490*a9643ea8Slogwang         cache_append_buffer(cache, item);
491*a9643ea8Slogwang         total += rc;
492*a9643ea8Slogwang     }
493*a9643ea8Slogwang 
494*a9643ea8Slogwang     return total;
495*a9643ea8Slogwang }
496*a9643ea8Slogwang 
497*a9643ea8Slogwang 
498*a9643ea8Slogwang /**
499*a9643ea8Slogwang  * @brief Cache���ϵ�TCP�ձ��ӿ�
500*a9643ea8Slogwang  * @param cache -�����ָ��
501*a9643ea8Slogwang  * @param fd - ׼���ձ���fd���
502*a9643ea8Slogwang  * @return ʵ�ʽ��ճ���
503*a9643ea8Slogwang  */
504*a9643ea8Slogwang int32_t cache_tcp_recv(TRWCache* cache, uint32_t fd)
505*a9643ea8Slogwang {
506*a9643ea8Slogwang     if (NULL == cache)
507*a9643ea8Slogwang     {
508*a9643ea8Slogwang         return -1;
509*a9643ea8Slogwang     }
510*a9643ea8Slogwang 
511*a9643ea8Slogwang     int32_t total = 0;
512*a9643ea8Slogwang     for (uint32_t i = 0; i < 100; i++)
513*a9643ea8Slogwang     {
514*a9643ea8Slogwang         // 1. ÿ�μ��β�ռ�, �ռ������ʼ״̬, �����¿ռ�
515*a9643ea8Slogwang         TSkBuffer* item = TAILQ_LAST(&cache->list, __sk_buff_list);
516*a9643ea8Slogwang         if ((NULL == item)
517*a9643ea8Slogwang             || ((item->data_len + item->data) >= item->end))
518*a9643ea8Slogwang         {
519*a9643ea8Slogwang             item = alloc_sk_buffer(cache->pool);
520*a9643ea8Slogwang             if (item == NULL)
521*a9643ea8Slogwang             {
522*a9643ea8Slogwang                return -2;
523*a9643ea8Slogwang             }
524*a9643ea8Slogwang             cache_append_buffer(cache, item);
525*a9643ea8Slogwang         }
526*a9643ea8Slogwang 
527*a9643ea8Slogwang         // 2. ����������size��С, Ĭ��64K
528*a9643ea8Slogwang         uint8_t* buff = item->data + item->data_len;
529*a9643ea8Slogwang         uint32_t remain = item->end - item->data - item->data_len;
530*a9643ea8Slogwang         mt_hook_syscall(recv);
531*a9643ea8Slogwang         int32_t recvd_len = ff_hook_recv(fd, buff, remain, 0);
532*a9643ea8Slogwang         if (recvd_len == 0)
533*a9643ea8Slogwang         {
534*a9643ea8Slogwang             MTLOG_DEBUG("remote close, socket: %d", fd);
535*a9643ea8Slogwang             return -SK_ERR_NEED_CLOSE;
536*a9643ea8Slogwang         }
537*a9643ea8Slogwang         else if (recvd_len < 0)
538*a9643ea8Slogwang         {
539*a9643ea8Slogwang             if (errno == EAGAIN)
540*a9643ea8Slogwang             {
541*a9643ea8Slogwang                 return total;
542*a9643ea8Slogwang             }
543*a9643ea8Slogwang             else
544*a9643ea8Slogwang             {
545*a9643ea8Slogwang                 MTLOG_ERROR("recv tcp socket failed, error: %d[%m]", errno);
546*a9643ea8Slogwang                 return -2;
547*a9643ea8Slogwang             }
548*a9643ea8Slogwang         }
549*a9643ea8Slogwang         else
550*a9643ea8Slogwang         {
551*a9643ea8Slogwang             item->data_len += recvd_len;
552*a9643ea8Slogwang             cache->len += recvd_len;
553*a9643ea8Slogwang             total += recvd_len;
554*a9643ea8Slogwang             if (recvd_len < (int32_t)remain) // �ղ���, ����Ϊ����OK
555*a9643ea8Slogwang             {
556*a9643ea8Slogwang                 return total;
557*a9643ea8Slogwang             }
558*a9643ea8Slogwang         }
559*a9643ea8Slogwang     }
560*a9643ea8Slogwang 
561*a9643ea8Slogwang     return total;
562*a9643ea8Slogwang }
563*a9643ea8Slogwang 
564*a9643ea8Slogwang /**
565*a9643ea8Slogwang  * @brief Cache���ϵ�TCP���ͽӿ�
566*a9643ea8Slogwang  * @param cache -�����ָ��
567*a9643ea8Slogwang  * @param fd - ׼��������fd���
568*a9643ea8Slogwang  * @return ʵ�ʷ��ͳ���
569*a9643ea8Slogwang  */
570*a9643ea8Slogwang int32_t cache_tcp_send(TRWCache* cache, uint32_t fd)
571*a9643ea8Slogwang {
572*a9643ea8Slogwang     if ((NULL == cache) || (NULL == cache->pool))
573*a9643ea8Slogwang     {
574*a9643ea8Slogwang         return -1;
575*a9643ea8Slogwang     }
576*a9643ea8Slogwang 
577*a9643ea8Slogwang     if (cache->len == 0)
578*a9643ea8Slogwang     {
579*a9643ea8Slogwang         return 0;
580*a9643ea8Slogwang     }
581*a9643ea8Slogwang 
582*a9643ea8Slogwang 
583*a9643ea8Slogwang     int32_t ret = 0, total = 0;
584*a9643ea8Slogwang     TSkBuffer* item = NULL;
585*a9643ea8Slogwang     TSkBuffer* tmp = NULL;
586*a9643ea8Slogwang     TAILQ_FOREACH_SAFE(item, &cache->list, entry, tmp)
587*a9643ea8Slogwang     {
588*a9643ea8Slogwang         mt_hook_syscall(send);
589*a9643ea8Slogwang         ret = ff_hook_send(fd, item->data, item->data_len, 0);
590*a9643ea8Slogwang         if (ret < 0)
591*a9643ea8Slogwang         {
592*a9643ea8Slogwang             break;
593*a9643ea8Slogwang         }
594*a9643ea8Slogwang 
595*a9643ea8Slogwang         total += ret;
596*a9643ea8Slogwang         if (ret < (int32_t)item->data_len)
597*a9643ea8Slogwang         {
598*a9643ea8Slogwang             break;
599*a9643ea8Slogwang         }
600*a9643ea8Slogwang     }
601*a9643ea8Slogwang 
602*a9643ea8Slogwang     cache_skip_data(cache, total);
603*a9643ea8Slogwang     if (ret < 0)
604*a9643ea8Slogwang     {
605*a9643ea8Slogwang         if (errno != EAGAIN)
606*a9643ea8Slogwang         {
607*a9643ea8Slogwang             MTLOG_ERROR("tcp socket send failed, error: %d[%m]", errno);
608*a9643ea8Slogwang             return -2;
609*a9643ea8Slogwang         }
610*a9643ea8Slogwang     }
611*a9643ea8Slogwang 
612*a9643ea8Slogwang     return total;
613*a9643ea8Slogwang }
614*a9643ea8Slogwang 
615*a9643ea8Slogwang 
616*a9643ea8Slogwang /**
617*a9643ea8Slogwang  * @brief Cache���ϵ�TCP���ͽӿ�, δʹ��IOVEC
618*a9643ea8Slogwang  * @param cache -�����ָ��
619*a9643ea8Slogwang  * @param fd - ׼��������fd���
620*a9643ea8Slogwang  * @param data -������cache��, �������͵�buff
621*a9643ea8Slogwang  * @param len  -�������͵�buff����
622*a9643ea8Slogwang  * @return ʵ�ʷ��ͳ���
623*a9643ea8Slogwang  */
624*a9643ea8Slogwang int32_t cache_tcp_send_buff(TRWCache* cache, uint32_t fd, const void* data, uint32_t len)
625*a9643ea8Slogwang {
626*a9643ea8Slogwang     if ((NULL == cache) || (NULL == data))
627*a9643ea8Slogwang     {
628*a9643ea8Slogwang         return -1;
629*a9643ea8Slogwang     }
630*a9643ea8Slogwang 
631*a9643ea8Slogwang     // 1. ���ȷ���CACHE����
632*a9643ea8Slogwang     int32_t ret = cache_tcp_send(cache, fd);
633*a9643ea8Slogwang     if (ret < 0)
634*a9643ea8Slogwang     {
635*a9643ea8Slogwang         MTLOG_ERROR("tcp socket[%d] send cache data failed, rc: %d", fd, ret);
636*a9643ea8Slogwang         return ret;
637*a9643ea8Slogwang     }
638*a9643ea8Slogwang 
639*a9643ea8Slogwang     // 2. CACHE�Ѿ�������
640*a9643ea8Slogwang     int32_t send_len = 0;
641*a9643ea8Slogwang     if (cache->len == 0)
642*a9643ea8Slogwang     {
643*a9643ea8Slogwang         mt_hook_syscall(send);
644*a9643ea8Slogwang         ret = ff_hook_send(fd, data, len, 0);
645*a9643ea8Slogwang         if (ret >= 0)
646*a9643ea8Slogwang         {
647*a9643ea8Slogwang             send_len += ret;
648*a9643ea8Slogwang         }
649*a9643ea8Slogwang         else
650*a9643ea8Slogwang         {
651*a9643ea8Slogwang             if (errno != EAGAIN)
652*a9643ea8Slogwang             {
653*a9643ea8Slogwang                 MTLOG_ERROR("tcp socket[%d] send failed, error: %d[%m]", fd, errno);
654*a9643ea8Slogwang                 return -2;
655*a9643ea8Slogwang             }
656*a9643ea8Slogwang         }
657*a9643ea8Slogwang     }
658*a9643ea8Slogwang 
659*a9643ea8Slogwang     int32_t rc = cache_append_data(cache, (char*)data + send_len, len - send_len);
660*a9643ea8Slogwang     if (rc < 0)
661*a9643ea8Slogwang     {
662*a9643ea8Slogwang         MTLOG_ERROR("tcp socket[%d] apend data failed, rc: %d", fd, rc);
663*a9643ea8Slogwang         return -3;
664*a9643ea8Slogwang     }
665*a9643ea8Slogwang 
666*a9643ea8Slogwang     return send_len;
667*a9643ea8Slogwang }
668*a9643ea8Slogwang 
669*a9643ea8Slogwang 
670*a9643ea8Slogwang /**
671*a9643ea8Slogwang  * @brief ��ȡcache��Ч�����ܳ���
672*a9643ea8Slogwang  * @param multi -�����ָ��
673*a9643ea8Slogwang  * @return ʵ����Ч���ݳ���
674*a9643ea8Slogwang  */
675*a9643ea8Slogwang uint32_t get_data_len(TBuffVecPtr multi)
676*a9643ea8Slogwang {
677*a9643ea8Slogwang     TRWCache* cache = (TRWCache*)multi;
678*a9643ea8Slogwang     if (NULL == cache) {
679*a9643ea8Slogwang         return 0;
680*a9643ea8Slogwang     } else {
681*a9643ea8Slogwang         return cache->len;
682*a9643ea8Slogwang     }
683*a9643ea8Slogwang }
684*a9643ea8Slogwang 
685*a9643ea8Slogwang /**
686*a9643ea8Slogwang  * @brief ��ȡcache��Ч���ݿ����
687*a9643ea8Slogwang  * @param multi -�����ָ��
688*a9643ea8Slogwang  * @return ʵ����Ч���ݿ����
689*a9643ea8Slogwang  */
690*a9643ea8Slogwang uint32_t get_block_count(TBuffVecPtr multi)
691*a9643ea8Slogwang {
692*a9643ea8Slogwang     TRWCache* cache = (TRWCache*)multi;
693*a9643ea8Slogwang     if (NULL == cache) {
694*a9643ea8Slogwang         return 0;
695*a9643ea8Slogwang     } else {
696*a9643ea8Slogwang         return cache->count;
697*a9643ea8Slogwang     }
698*a9643ea8Slogwang }
699*a9643ea8Slogwang 
700*a9643ea8Slogwang /**
701*a9643ea8Slogwang  * @brief ��ȡcache�ĵ�һ������ָ��
702*a9643ea8Slogwang  * @param multi -�����ָ��
703*a9643ea8Slogwang  * @return ��һ������ָ��
704*a9643ea8Slogwang  */
705*a9643ea8Slogwang TBuffBlockPtr get_first_block(TBuffVecPtr multi)
706*a9643ea8Slogwang {
707*a9643ea8Slogwang     TRWCache* cache = (TRWCache*)multi;
708*a9643ea8Slogwang     if (NULL == cache) {
709*a9643ea8Slogwang         return NULL;
710*a9643ea8Slogwang     } else {
711*a9643ea8Slogwang         return (TBuffBlockPtr)TAILQ_FIRST(&cache->list);
712*a9643ea8Slogwang     }
713*a9643ea8Slogwang }
714*a9643ea8Slogwang 
715*a9643ea8Slogwang /**
716*a9643ea8Slogwang  * @brief ��ȡcache����һ������ָ��
717*a9643ea8Slogwang  * @param multi -�����ָ��
718*a9643ea8Slogwang  * @param block -��ǰ��ָ��
719*a9643ea8Slogwang  * @return ��һ������ָ��
720*a9643ea8Slogwang  */
721*a9643ea8Slogwang TBuffBlockPtr get_next_block(TBuffVecPtr multi, TBuffBlockPtr block)
722*a9643ea8Slogwang {
723*a9643ea8Slogwang     TRWCache* cache = (TRWCache*)multi;
724*a9643ea8Slogwang     TSkBuffer* item = (TSkBuffer*)block;
725*a9643ea8Slogwang     if ((NULL == cache) || (NULL == item))
726*a9643ea8Slogwang     {
727*a9643ea8Slogwang         return NULL;
728*a9643ea8Slogwang     }
729*a9643ea8Slogwang 
730*a9643ea8Slogwang     return (TBuffBlockPtr)TAILQ_NEXT(item, entry);
731*a9643ea8Slogwang 
732*a9643ea8Slogwang }
733*a9643ea8Slogwang 
734*a9643ea8Slogwang /**
735*a9643ea8Slogwang  * @brief ��ȡ���ݿ��ָ�������ݳ���
736*a9643ea8Slogwang  * @param block -��ǰ��ָ��
737*a9643ea8Slogwang  * @param data -����ָ��-modify����
738*a9643ea8Slogwang  * @param len  -����ָ�� modify����
739*a9643ea8Slogwang  */
740*a9643ea8Slogwang void get_block_data(TBuffBlockPtr block, const void** data, int32_t* len)
741*a9643ea8Slogwang {
742*a9643ea8Slogwang     TSkBuffer* item = (TSkBuffer*)block;
743*a9643ea8Slogwang     if (NULL == block)
744*a9643ea8Slogwang     {
745*a9643ea8Slogwang         return;
746*a9643ea8Slogwang     }
747*a9643ea8Slogwang 
748*a9643ea8Slogwang     if (data != NULL)
749*a9643ea8Slogwang     {
750*a9643ea8Slogwang         *(uint8_t**)data = item->data;
751*a9643ea8Slogwang     }
752*a9643ea8Slogwang 
753*a9643ea8Slogwang     if (len != NULL)
754*a9643ea8Slogwang     {
755*a9643ea8Slogwang         *len = (int32_t)item->data_len;
756*a9643ea8Slogwang     }
757*a9643ea8Slogwang }
758*a9643ea8Slogwang 
759*a9643ea8Slogwang 
760*a9643ea8Slogwang /**
761*a9643ea8Slogwang  * @brief ��ȡ���ݿ��ָ�������ݳ���
762*a9643ea8Slogwang  * @param multi -�����ָ��
763*a9643ea8Slogwang  * @param data -����д������ָ��
764*a9643ea8Slogwang  * @param len  -����
765*a9643ea8Slogwang  * @return ���ݶ�ȡ�����ݳ���
766*a9643ea8Slogwang  */
767*a9643ea8Slogwang uint32_t read_cache_data(TBuffVecPtr multi, void* data, uint32_t len)
768*a9643ea8Slogwang {
769*a9643ea8Slogwang     TRWCache* cache = (TRWCache*)multi;
770*a9643ea8Slogwang     if (NULL == cache) {
771*a9643ea8Slogwang         return 0;
772*a9643ea8Slogwang     }
773*a9643ea8Slogwang 
774*a9643ea8Slogwang     uint32_t left_len = len;
775*a9643ea8Slogwang     uint32_t offset = 0;
776*a9643ea8Slogwang     TSkBuffer* item = NULL;
777*a9643ea8Slogwang     TSkBuffer* tmp = NULL;
778*a9643ea8Slogwang     TAILQ_FOREACH_SAFE(item, &cache->list, entry, tmp)
779*a9643ea8Slogwang     {
780*a9643ea8Slogwang         uint32_t copy_len = 0;
781*a9643ea8Slogwang         if (left_len <= item->data_len)
782*a9643ea8Slogwang         {
783*a9643ea8Slogwang             copy_len = left_len;
784*a9643ea8Slogwang         }
785*a9643ea8Slogwang         else
786*a9643ea8Slogwang         {
787*a9643ea8Slogwang             copy_len = item->data_len;
788*a9643ea8Slogwang         }
789*a9643ea8Slogwang 
790*a9643ea8Slogwang         if (data != NULL)
791*a9643ea8Slogwang         {
792*a9643ea8Slogwang             memcpy((char*)data + offset, item->data, copy_len);
793*a9643ea8Slogwang         }
794*a9643ea8Slogwang         offset += copy_len;
795*a9643ea8Slogwang         left_len -= copy_len;
796*a9643ea8Slogwang 
797*a9643ea8Slogwang         if (left_len <= 0)
798*a9643ea8Slogwang         {
799*a9643ea8Slogwang             break;
800*a9643ea8Slogwang         }
801*a9643ea8Slogwang     }
802*a9643ea8Slogwang 
803*a9643ea8Slogwang     return offset;
804*a9643ea8Slogwang }
805*a9643ea8Slogwang 
806*a9643ea8Slogwang 
807*a9643ea8Slogwang 
808*a9643ea8Slogwang /**
809*a9643ea8Slogwang  * @brief ��ȡ���ݿ��ָ�������ݳ���
810*a9643ea8Slogwang  * @param multi -�����ָ��
811*a9643ea8Slogwang  * @param data -����д������ָ��
812*a9643ea8Slogwang  * @param len  -����
813*a9643ea8Slogwang  * @return ���ݶ�ȡ�����ݳ���
814*a9643ea8Slogwang  */
815*a9643ea8Slogwang uint32_t read_cache_begin(TBuffVecPtr multi, uint32_t begin, void* data, uint32_t len)
816*a9643ea8Slogwang {
817*a9643ea8Slogwang     TRWCache* cache = (TRWCache*)multi;
818*a9643ea8Slogwang     if (NULL == cache) {
819*a9643ea8Slogwang         return 0;
820*a9643ea8Slogwang     }
821*a9643ea8Slogwang 
822*a9643ea8Slogwang     if (begin >= cache->len) {
823*a9643ea8Slogwang         return 0;
824*a9643ea8Slogwang     }
825*a9643ea8Slogwang 
826*a9643ea8Slogwang     uint32_t pos_left = begin;
827*a9643ea8Slogwang     uint32_t copy_left = len;
828*a9643ea8Slogwang     uint32_t offset = 0;
829*a9643ea8Slogwang     TSkBuffer* item = NULL;
830*a9643ea8Slogwang     TAILQ_FOREACH(item, &cache->list, entry)
831*a9643ea8Slogwang     {
832*a9643ea8Slogwang         // 1. ��ʼλ����ʣ��, �������ò���
833*a9643ea8Slogwang         uint8_t* start_ptr = item->data;
834*a9643ea8Slogwang         uint32_t real_left = item->data_len;
835*a9643ea8Slogwang         if (pos_left > 0)
836*a9643ea8Slogwang         {
837*a9643ea8Slogwang             uint32_t skip_len = pos_left > real_left ? real_left : pos_left;
838*a9643ea8Slogwang             pos_left -= skip_len;
839*a9643ea8Slogwang             real_left -= skip_len;
840*a9643ea8Slogwang             start_ptr += skip_len;
841*a9643ea8Slogwang         }
842*a9643ea8Slogwang 
843*a9643ea8Slogwang         // 2. �������޳���ʣ��, ��ȴ���һ��
844*a9643ea8Slogwang         if (real_left == 0)
845*a9643ea8Slogwang         {
846*a9643ea8Slogwang             continue;
847*a9643ea8Slogwang         }
848*a9643ea8Slogwang 
849*a9643ea8Slogwang         // 3. ��ʣ��, �������������
850*a9643ea8Slogwang         uint32_t copy_len = copy_left > real_left ? real_left : copy_left;
851*a9643ea8Slogwang         if (data != NULL)
852*a9643ea8Slogwang         {
853*a9643ea8Slogwang             memcpy((char*)data + offset, start_ptr, copy_len);
854*a9643ea8Slogwang         }
855*a9643ea8Slogwang         offset += copy_len;
856*a9643ea8Slogwang         copy_left -= copy_len;
857*a9643ea8Slogwang         if (copy_left == 0)
858*a9643ea8Slogwang         {
859*a9643ea8Slogwang             break;
860*a9643ea8Slogwang         }
861*a9643ea8Slogwang     }
862*a9643ea8Slogwang 
863*a9643ea8Slogwang     return offset;
864*a9643ea8Slogwang }
865*a9643ea8Slogwang 
866*a9643ea8Slogwang 
867*a9643ea8Slogwang 
868*a9643ea8Slogwang };
869*a9643ea8Slogwang 
870