xref: /f-stack/app/micro_thread/mt_cache.cpp (revision 35a81399)
1a9643ea8Slogwang 
2a9643ea8Slogwang /**
3a9643ea8Slogwang  * Tencent is pleased to support the open source community by making MSEC available.
4a9643ea8Slogwang  *
5a9643ea8Slogwang  * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
6a9643ea8Slogwang  *
7a9643ea8Slogwang  * Licensed under the GNU General Public License, Version 2.0 (the "License");
8a9643ea8Slogwang  * you may not use this file except in compliance with the License. You may
9a9643ea8Slogwang  * obtain a copy of the License at
10a9643ea8Slogwang  *
11a9643ea8Slogwang  *     https://opensource.org/licenses/GPL-2.0
12a9643ea8Slogwang  *
13a9643ea8Slogwang  * Unless required by applicable law or agreed to in writing, software distributed under the
14a9643ea8Slogwang  * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
15a9643ea8Slogwang  * either express or implied. See the License for the specific language governing permissions
16a9643ea8Slogwang  * and limitations under the License.
17a9643ea8Slogwang  */
18a9643ea8Slogwang 
19a9643ea8Slogwang 
20a9643ea8Slogwang /**
21a9643ea8Slogwang  *  @filename mt_cache.cpp
22a9643ea8Slogwang  */
23a9643ea8Slogwang 
24a9643ea8Slogwang #include <stdlib.h>
25a9643ea8Slogwang #include <errno.h>
26a9643ea8Slogwang #include <sys/types.h>
27a9643ea8Slogwang #include <sys/socket.h>
28a9643ea8Slogwang #include <string.h>
29a9643ea8Slogwang #include "mt_incl.h"
30a9643ea8Slogwang #include "kqueue_proxy.h"
31a9643ea8Slogwang #include "micro_thread.h"
32a9643ea8Slogwang #include "mt_sys_hook.h"
33a9643ea8Slogwang #include "ff_hook.h"
34a9643ea8Slogwang 
35a9643ea8Slogwang #include "mt_cache.h"
36a9643ea8Slogwang 
37a9643ea8Slogwang namespace NS_MICRO_THREAD {
38a9643ea8Slogwang 
new_sk_buffer(uint32_t size)39a9643ea8Slogwang TSkBuffer* new_sk_buffer(uint32_t size)
40a9643ea8Slogwang {
41a9643ea8Slogwang     uint32_t total = sizeof(TSkBuffer) + size;
42a9643ea8Slogwang     total = (total + SK_DFLT_ALIGN_SIZE - 1) / SK_DFLT_ALIGN_SIZE * SK_DFLT_ALIGN_SIZE;
43a9643ea8Slogwang     TSkBuffer* block = (TSkBuffer*)malloc(total);
44a9643ea8Slogwang     if (block == NULL)
45a9643ea8Slogwang     {
46a9643ea8Slogwang         MTLOG_ERROR("malloc failed, no more memory[%u]", total);
47a9643ea8Slogwang         return NULL;
48a9643ea8Slogwang     }
49a9643ea8Slogwang 
50a9643ea8Slogwang     block->last_time = 0;
51a9643ea8Slogwang     block->size = size;
52a9643ea8Slogwang     block->head = block->buff;
53a9643ea8Slogwang     block->end  = block->buff + size;
54a9643ea8Slogwang 
55a9643ea8Slogwang     block->data = block->head;
56a9643ea8Slogwang     block->data_len = 0;
57a9643ea8Slogwang 
58a9643ea8Slogwang     return block;
59a9643ea8Slogwang }
60a9643ea8Slogwang 
delete_sk_buffer(TSkBuffer * block)61a9643ea8Slogwang void delete_sk_buffer(TSkBuffer* block)
62a9643ea8Slogwang {
63a9643ea8Slogwang     if (NULL == block) {
64a9643ea8Slogwang         return;
65a9643ea8Slogwang     }
66a9643ea8Slogwang 
67a9643ea8Slogwang     free(block);
68a9643ea8Slogwang }
69a9643ea8Slogwang 
reserve_sk_buffer(TSkBuffer * buff,uint32_t size)70a9643ea8Slogwang TSkBuffer* reserve_sk_buffer(TSkBuffer* buff, uint32_t size)
71a9643ea8Slogwang {
72a9643ea8Slogwang     if (NULL == buff) {
73a9643ea8Slogwang         return new_sk_buffer(size);
74a9643ea8Slogwang     }
75a9643ea8Slogwang 
76a9643ea8Slogwang     if (buff->size >= size) {
77a9643ea8Slogwang         return buff;
78a9643ea8Slogwang     }
79a9643ea8Slogwang 
80a9643ea8Slogwang     TSkBuffer* new_buff = new_sk_buffer(size);
81a9643ea8Slogwang     if (NULL == new_buff) {
82a9643ea8Slogwang         return buff;
83a9643ea8Slogwang     }
84a9643ea8Slogwang     memcpy(new_buff->data, buff->data, buff->data_len);
85a9643ea8Slogwang     new_buff->data_len = buff->data_len;
86a9643ea8Slogwang     delete_sk_buffer(buff);
87a9643ea8Slogwang 
88a9643ea8Slogwang     return new_buff;
89a9643ea8Slogwang }
90a9643ea8Slogwang 
sk_buffer_mng_init(TSkBuffMng * mng,uint32_t expired,uint32_t size)91a9643ea8Slogwang void sk_buffer_mng_init(TSkBuffMng* mng, uint32_t expired, uint32_t size)
92a9643ea8Slogwang {
93a9643ea8Slogwang     TAILQ_INIT(&mng->free_list);
94a9643ea8Slogwang     mng->expired  = expired;
95a9643ea8Slogwang     mng->count = 0;
96a9643ea8Slogwang     mng->size = size;
97a9643ea8Slogwang }
98a9643ea8Slogwang 
sk_buffer_mng_destroy(TSkBuffMng * mng)99a9643ea8Slogwang void sk_buffer_mng_destroy(TSkBuffMng * mng)
100a9643ea8Slogwang {
101a9643ea8Slogwang     TSkBuffer* item = NULL;
102a9643ea8Slogwang     TSkBuffer* tmp = NULL;
103a9643ea8Slogwang     TAILQ_FOREACH_SAFE(item, &mng->free_list, entry, tmp)
104a9643ea8Slogwang     {
105a9643ea8Slogwang         TAILQ_REMOVE(&mng->free_list, item, entry);
106a9643ea8Slogwang         delete_sk_buffer(item);
107a9643ea8Slogwang     }
108a9643ea8Slogwang     mng->count = 0;
109a9643ea8Slogwang }
110a9643ea8Slogwang 
alloc_sk_buffer(TSkBuffMng * mng)111a9643ea8Slogwang TSkBuffer* alloc_sk_buffer(TSkBuffMng* mng)
112a9643ea8Slogwang {
113a9643ea8Slogwang     if (NULL == mng) {
114a9643ea8Slogwang         return NULL;
115a9643ea8Slogwang     }
116a9643ea8Slogwang 
117a9643ea8Slogwang     TSkBuffer* item = TAILQ_FIRST(&mng->free_list);
118a9643ea8Slogwang     if (item != NULL)
119a9643ea8Slogwang     {
120a9643ea8Slogwang         TAILQ_REMOVE(&mng->free_list, item, entry);
121a9643ea8Slogwang         mng->count--;
122a9643ea8Slogwang         return item;
123a9643ea8Slogwang     }
124a9643ea8Slogwang 
125a9643ea8Slogwang     item = new_sk_buffer(mng->size);
126a9643ea8Slogwang     if (NULL == item)
127a9643ea8Slogwang     {
128a9643ea8Slogwang         return NULL;
129a9643ea8Slogwang     }
130a9643ea8Slogwang 
131a9643ea8Slogwang     return item;
132a9643ea8Slogwang }
133a9643ea8Slogwang 
free_sk_buffer(TSkBuffMng * mng,TSkBuffer * buff)134a9643ea8Slogwang void free_sk_buffer(TSkBuffMng* mng, TSkBuffer* buff)
135a9643ea8Slogwang {
136a9643ea8Slogwang     if ((NULL == mng) || (NULL == buff)) {
137a9643ea8Slogwang         return;
138a9643ea8Slogwang     }
139a9643ea8Slogwang 
140a9643ea8Slogwang     TAILQ_INSERT_TAIL(&mng->free_list, buff, entry);
141a9643ea8Slogwang     mng->count++;
142a9643ea8Slogwang 
143a9643ea8Slogwang     buff->last_time = (uint32_t)(mt_time_ms() / 1000);
144a9643ea8Slogwang     buff->data = buff->head;
145a9643ea8Slogwang     buff->data_len = 0;
146a9643ea8Slogwang }
147a9643ea8Slogwang 
recycle_sk_buffer(TSkBuffMng * mng,uint32_t now)148a9643ea8Slogwang void recycle_sk_buffer(TSkBuffMng* mng, uint32_t now)
149a9643ea8Slogwang {
150a9643ea8Slogwang     TSkBuffer* item = NULL;
151a9643ea8Slogwang     TSkBuffer* tmp = NULL;
152a9643ea8Slogwang     TAILQ_FOREACH_SAFE(item, &mng->free_list, entry, tmp)
153a9643ea8Slogwang     {
154a9643ea8Slogwang         if ((now - item->last_time) < mng->expired)
155a9643ea8Slogwang         {
156a9643ea8Slogwang             break;
157a9643ea8Slogwang         }
158a9643ea8Slogwang 
159a9643ea8Slogwang         TAILQ_REMOVE(&mng->free_list, item, entry);
160a9643ea8Slogwang         delete_sk_buffer(item);
161a9643ea8Slogwang         mng->count--;
162a9643ea8Slogwang     }
163a9643ea8Slogwang }
164a9643ea8Slogwang 
rw_cache_init(TRWCache * cache,TSkBuffMng * pool)165a9643ea8Slogwang void rw_cache_init(TRWCache* cache, TSkBuffMng* pool)
166a9643ea8Slogwang {
167a9643ea8Slogwang     TAILQ_INIT(&cache->list);
168a9643ea8Slogwang     cache->len = 0;
169a9643ea8Slogwang     cache->count = 0;
170a9643ea8Slogwang     cache->pool = pool;
171a9643ea8Slogwang }
172a9643ea8Slogwang 
rw_cache_destroy(TRWCache * cache)173a9643ea8Slogwang void rw_cache_destroy(TRWCache* cache)
174a9643ea8Slogwang {
175a9643ea8Slogwang     if ((cache == NULL) || (cache->pool == NULL)) {
176a9643ea8Slogwang         return;
177a9643ea8Slogwang     }
178a9643ea8Slogwang 
179a9643ea8Slogwang     TSkBuffer* item = NULL;
180a9643ea8Slogwang     TSkBuffer* tmp = NULL;
181a9643ea8Slogwang     TAILQ_FOREACH_SAFE(item, &cache->list, entry, tmp)
182a9643ea8Slogwang     {
183a9643ea8Slogwang         TAILQ_REMOVE(&cache->list, item, entry);
184a9643ea8Slogwang         free_sk_buffer(cache->pool, item);
185a9643ea8Slogwang     }
186a9643ea8Slogwang     cache->count = 0;
187a9643ea8Slogwang     cache->len = 0;
188a9643ea8Slogwang     cache->pool = NULL;
189a9643ea8Slogwang }
190a9643ea8Slogwang 
cache_copy_out(TRWCache * cache,void * buff,uint32_t len)191a9643ea8Slogwang uint32_t cache_copy_out(TRWCache* cache, void* buff, uint32_t len)
192a9643ea8Slogwang {
193a9643ea8Slogwang     if ((cache == NULL) || (cache->pool == NULL)) {
194a9643ea8Slogwang         return 0;
195a9643ea8Slogwang     }
196a9643ea8Slogwang 
197a9643ea8Slogwang     char* out_buff = (char*)buff;
198a9643ea8Slogwang     uint32_t left = len, skip_len = 0;
199a9643ea8Slogwang     TSkBuffer* item = NULL;
200a9643ea8Slogwang     TSkBuffer* tmp = NULL;
201a9643ea8Slogwang     TAILQ_FOREACH_SAFE(item, &cache->list, entry, tmp)
202a9643ea8Slogwang     {
203a9643ea8Slogwang         skip_len = (item->data_len > left) ? left : item->data_len;
204a9643ea8Slogwang         if (out_buff != NULL)
205a9643ea8Slogwang         {
206a9643ea8Slogwang             memcpy(out_buff, item->data, skip_len);
207a9643ea8Slogwang             out_buff += skip_len;
208a9643ea8Slogwang         }
209a9643ea8Slogwang 
210a9643ea8Slogwang         left -= skip_len;
211a9643ea8Slogwang         item->data_len -= skip_len;
212a9643ea8Slogwang         item->data += skip_len;
213a9643ea8Slogwang         if (item->data_len > 0)
214a9643ea8Slogwang         {
215a9643ea8Slogwang             break;
216a9643ea8Slogwang         }
217a9643ea8Slogwang 
218a9643ea8Slogwang         if (cache->count > 0) {
219a9643ea8Slogwang             cache->count--;
220a9643ea8Slogwang         }
221a9643ea8Slogwang         TAILQ_REMOVE(&cache->list, item, entry);
222a9643ea8Slogwang         free_sk_buffer(cache->pool, item);
223a9643ea8Slogwang 
224a9643ea8Slogwang         if (left == 0)
225a9643ea8Slogwang         {
226a9643ea8Slogwang             break;
227a9643ea8Slogwang         }
228a9643ea8Slogwang     }
229a9643ea8Slogwang 
230a9643ea8Slogwang     skip_len = len - left;
231a9643ea8Slogwang     if (cache->len > skip_len)
232a9643ea8Slogwang     {
233a9643ea8Slogwang         cache->len -= skip_len;
234a9643ea8Slogwang     }
235a9643ea8Slogwang     else
236a9643ea8Slogwang     {
237a9643ea8Slogwang         cache->len = 0;
238a9643ea8Slogwang     }
239a9643ea8Slogwang 
240a9643ea8Slogwang     return skip_len;
241a9643ea8Slogwang }
242a9643ea8Slogwang 
cache_skip_data(TRWCache * cache,uint32_t len)243a9643ea8Slogwang void cache_skip_data(TRWCache* cache, uint32_t len)
244a9643ea8Slogwang {
245a9643ea8Slogwang     cache_copy_out(cache, NULL, len);
246a9643ea8Slogwang }
247a9643ea8Slogwang 
cache_append_buffer(TRWCache * cache,TSkBuffer * buff)248a9643ea8Slogwang void cache_append_buffer(TRWCache* cache, TSkBuffer* buff)
249a9643ea8Slogwang {
250a9643ea8Slogwang     if ((NULL == cache) || (NULL == buff))
251a9643ea8Slogwang     {
252a9643ea8Slogwang         return;
253a9643ea8Slogwang     }
254a9643ea8Slogwang 
255a9643ea8Slogwang     TAILQ_INSERT_TAIL(&cache->list, buff, entry);
256a9643ea8Slogwang     cache->len += buff->data_len;
257a9643ea8Slogwang     cache->count++;
258a9643ea8Slogwang }
259a9643ea8Slogwang 
cache_skip_first_buffer(TRWCache * cache)260a9643ea8Slogwang TSkBuffer* cache_skip_first_buffer(TRWCache* cache)
261a9643ea8Slogwang {
262a9643ea8Slogwang     TSkBuffer* buff = TAILQ_FIRST(&cache->list);
263a9643ea8Slogwang     if ((NULL == cache) || (NULL == buff))
264a9643ea8Slogwang     {
265a9643ea8Slogwang         return NULL;
266a9643ea8Slogwang     }
267a9643ea8Slogwang 
268a9643ea8Slogwang     TAILQ_REMOVE(&cache->list, buff, entry);
269a9643ea8Slogwang     if (cache->len >= buff->data_len)
270a9643ea8Slogwang     {
271a9643ea8Slogwang         cache->len -= buff->data_len;
272a9643ea8Slogwang     }
273a9643ea8Slogwang 
274a9643ea8Slogwang     if (cache->count > 0)
275a9643ea8Slogwang     {
276a9643ea8Slogwang         cache->count--;
277a9643ea8Slogwang     }
278a9643ea8Slogwang 
279a9643ea8Slogwang     return buff;
280a9643ea8Slogwang }
281a9643ea8Slogwang 
cache_append_data(TRWCache * cache,const void * data,uint32_t len)282a9643ea8Slogwang int32_t cache_append_data(TRWCache* cache, const void* data, uint32_t len)
283a9643ea8Slogwang {
284a9643ea8Slogwang     if ((NULL == data) || (NULL == cache) || (NULL == cache->pool))
285a9643ea8Slogwang     {
286a9643ea8Slogwang         return -1;
287a9643ea8Slogwang     }
288a9643ea8Slogwang 
289a9643ea8Slogwang     if (len == 0)
290a9643ea8Slogwang     {
291a9643ea8Slogwang         return 0;
292a9643ea8Slogwang     }
293a9643ea8Slogwang 
294a9643ea8Slogwang     uint32_t left = len;
295a9643ea8Slogwang     uint32_t remain = 0;
296a9643ea8Slogwang 
297a9643ea8Slogwang     TSkBuffer* tail = TAILQ_LAST(&cache->list, __sk_buff_list);
298a9643ea8Slogwang     if (tail != NULL)
299a9643ea8Slogwang     {
300a9643ea8Slogwang         if (tail->end > (tail->data + tail->data_len))
301a9643ea8Slogwang         {
302a9643ea8Slogwang             remain = tail->end - tail->data - tail->data_len;
303a9643ea8Slogwang         }
304a9643ea8Slogwang 
305a9643ea8Slogwang         if (remain >= len)
306a9643ea8Slogwang         {
307a9643ea8Slogwang             memcpy(tail->data + tail->data_len, data, len);
308a9643ea8Slogwang             tail->data_len += len;
309a9643ea8Slogwang             cache->len += len;
310a9643ea8Slogwang             return (int32_t)len;
311a9643ea8Slogwang         }
312a9643ea8Slogwang     }
313a9643ea8Slogwang 
314a9643ea8Slogwang     TRWCache keep_list;
315a9643ea8Slogwang     rw_cache_init(&keep_list, cache->pool);
316a9643ea8Slogwang     left -= remain;
317a9643ea8Slogwang     while (left > 0)
318a9643ea8Slogwang     {
319a9643ea8Slogwang         TSkBuffer* item = alloc_sk_buffer(cache->pool);
320a9643ea8Slogwang         if (item == NULL)
321a9643ea8Slogwang         {
322a9643ea8Slogwang             rw_cache_destroy(&keep_list);
323a9643ea8Slogwang             return -2;
324a9643ea8Slogwang         }
325a9643ea8Slogwang         cache_append_buffer(&keep_list, item);
326a9643ea8Slogwang 
327a9643ea8Slogwang         if (left <= item->size)
328a9643ea8Slogwang         {
329a9643ea8Slogwang             memcpy(item->head, (char*)data + len - left, left);
330a9643ea8Slogwang             item->data_len = left;
331a9643ea8Slogwang             break;
332a9643ea8Slogwang         }
333a9643ea8Slogwang 
334a9643ea8Slogwang         memcpy(item->head, (char*)data + len - left, item->size);
335a9643ea8Slogwang         item->data_len = item->size;
336a9643ea8Slogwang         left -= item->size;
337a9643ea8Slogwang     }
338a9643ea8Slogwang 
339a9643ea8Slogwang     if ((tail != NULL) && (remain > 0))
340a9643ea8Slogwang     {
341a9643ea8Slogwang         memcpy(tail->data + tail->data_len, data, remain);
342a9643ea8Slogwang         tail->data_len += remain;
343a9643ea8Slogwang     }
344a9643ea8Slogwang 
345a9643ea8Slogwang     cache->len += len;
346a9643ea8Slogwang     cache->count += keep_list.count;
347a9643ea8Slogwang     TAILQ_CONCAT(&cache->list, &keep_list.list, entry);
348a9643ea8Slogwang 
349a9643ea8Slogwang     return (int32_t)len;
350a9643ea8Slogwang }
351a9643ea8Slogwang 
cache_udp_recv(TRWCache * cache,uint32_t fd,struct sockaddr_in * remote_addr)352a9643ea8Slogwang int32_t cache_udp_recv(TRWCache* cache, uint32_t fd, struct sockaddr_in* remote_addr)
353a9643ea8Slogwang {
354a9643ea8Slogwang     if (NULL == cache)
355a9643ea8Slogwang     {
356a9643ea8Slogwang         return -1;
357a9643ea8Slogwang     }
358a9643ea8Slogwang 
359a9643ea8Slogwang     int32_t total = 0;
360a9643ea8Slogwang     for (uint32_t i = 0; i < 100; i++)
361a9643ea8Slogwang     {
362a9643ea8Slogwang         TSkBuffer* item = alloc_sk_buffer(cache->pool);
363a9643ea8Slogwang         if (NULL == item)
364a9643ea8Slogwang         {
365a9643ea8Slogwang             return -2;
366a9643ea8Slogwang         }
367a9643ea8Slogwang 
368a9643ea8Slogwang         socklen_t addr_len = sizeof(*remote_addr);
369a9643ea8Slogwang         mt_hook_syscall(recvfrom);
370a9643ea8Slogwang         int32_t rc = ff_hook_recvfrom(fd, item->data, item->size, 0, (struct sockaddr*)remote_addr, &addr_len);
371a9643ea8Slogwang         if (rc <= 0)
372a9643ea8Slogwang         {
373a9643ea8Slogwang             free_sk_buffer(cache->pool, item);
374a9643ea8Slogwang 
375a9643ea8Slogwang             if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
376a9643ea8Slogwang             {
377a9643ea8Slogwang                 break;
378a9643ea8Slogwang             }
379a9643ea8Slogwang             else
380a9643ea8Slogwang             {
381a9643ea8Slogwang                 MTLOG_ERROR("recvfrom failed, fd[%d] ret %d[%m]", fd, rc);
382a9643ea8Slogwang                 return -3;
383a9643ea8Slogwang             }
384a9643ea8Slogwang         }
385a9643ea8Slogwang 
386a9643ea8Slogwang         item->data_len += rc;
387a9643ea8Slogwang         cache_append_buffer(cache, item);
388a9643ea8Slogwang         total += rc;
389a9643ea8Slogwang     }
390a9643ea8Slogwang 
391a9643ea8Slogwang     return total;
392a9643ea8Slogwang }
393a9643ea8Slogwang 
cache_tcp_recv(TRWCache * cache,uint32_t fd)394a9643ea8Slogwang int32_t cache_tcp_recv(TRWCache* cache, uint32_t fd)
395a9643ea8Slogwang {
396a9643ea8Slogwang     if (NULL == cache)
397a9643ea8Slogwang     {
398a9643ea8Slogwang         return -1;
399a9643ea8Slogwang     }
400a9643ea8Slogwang 
401a9643ea8Slogwang     int32_t total = 0;
402a9643ea8Slogwang     for (uint32_t i = 0; i < 100; i++)
403a9643ea8Slogwang     {
404a9643ea8Slogwang         TSkBuffer* item = TAILQ_LAST(&cache->list, __sk_buff_list);
405a9643ea8Slogwang         if ((NULL == item)
406a9643ea8Slogwang             || ((item->data_len + item->data) >= item->end))
407a9643ea8Slogwang         {
408a9643ea8Slogwang             item = alloc_sk_buffer(cache->pool);
409a9643ea8Slogwang             if (item == NULL)
410a9643ea8Slogwang             {
411a9643ea8Slogwang                return -2;
412a9643ea8Slogwang             }
413a9643ea8Slogwang             cache_append_buffer(cache, item);
414a9643ea8Slogwang         }
415a9643ea8Slogwang 
416a9643ea8Slogwang         uint8_t* buff = item->data + item->data_len;
417a9643ea8Slogwang         uint32_t remain = item->end - item->data - item->data_len;
418a9643ea8Slogwang         mt_hook_syscall(recv);
419a9643ea8Slogwang         int32_t recvd_len = ff_hook_recv(fd, buff, remain, 0);
420a9643ea8Slogwang         if (recvd_len == 0)
421a9643ea8Slogwang         {
422a9643ea8Slogwang             MTLOG_DEBUG("remote close, socket: %d", fd);
423a9643ea8Slogwang             return -SK_ERR_NEED_CLOSE;
424a9643ea8Slogwang         }
425a9643ea8Slogwang         else if (recvd_len < 0)
426a9643ea8Slogwang         {
427a9643ea8Slogwang             if (errno == EAGAIN)
428a9643ea8Slogwang             {
429a9643ea8Slogwang                 return total;
430a9643ea8Slogwang             }
431a9643ea8Slogwang             else
432a9643ea8Slogwang             {
433a9643ea8Slogwang                 MTLOG_ERROR("recv tcp socket failed, error: %d[%m]", errno);
434a9643ea8Slogwang                 return -2;
435a9643ea8Slogwang             }
436a9643ea8Slogwang         }
437a9643ea8Slogwang         else
438a9643ea8Slogwang         {
439a9643ea8Slogwang             item->data_len += recvd_len;
440a9643ea8Slogwang             cache->len += recvd_len;
441a9643ea8Slogwang             total += recvd_len;
442*35a81399Slogwang             if (recvd_len < (int32_t)remain)
443a9643ea8Slogwang             {
444a9643ea8Slogwang                 return total;
445a9643ea8Slogwang             }
446a9643ea8Slogwang         }
447a9643ea8Slogwang     }
448a9643ea8Slogwang 
449a9643ea8Slogwang     return total;
450a9643ea8Slogwang }
451a9643ea8Slogwang 
cache_tcp_send(TRWCache * cache,uint32_t fd)452a9643ea8Slogwang int32_t cache_tcp_send(TRWCache* cache, uint32_t fd)
453a9643ea8Slogwang {
454a9643ea8Slogwang     if ((NULL == cache) || (NULL == cache->pool))
455a9643ea8Slogwang     {
456a9643ea8Slogwang         return -1;
457a9643ea8Slogwang     }
458a9643ea8Slogwang 
459a9643ea8Slogwang     if (cache->len == 0)
460a9643ea8Slogwang     {
461a9643ea8Slogwang         return 0;
462a9643ea8Slogwang     }
463a9643ea8Slogwang 
464a9643ea8Slogwang     int32_t ret = 0, total = 0;
465a9643ea8Slogwang     TSkBuffer* item = NULL;
466a9643ea8Slogwang     TSkBuffer* tmp = NULL;
467a9643ea8Slogwang     TAILQ_FOREACH_SAFE(item, &cache->list, entry, tmp)
468a9643ea8Slogwang     {
469a9643ea8Slogwang         mt_hook_syscall(send);
470a9643ea8Slogwang         ret = ff_hook_send(fd, item->data, item->data_len, 0);
471a9643ea8Slogwang         if (ret < 0)
472a9643ea8Slogwang         {
473a9643ea8Slogwang             break;
474a9643ea8Slogwang         }
475a9643ea8Slogwang 
476a9643ea8Slogwang         total += ret;
477a9643ea8Slogwang         if (ret < (int32_t)item->data_len)
478a9643ea8Slogwang         {
479a9643ea8Slogwang             break;
480a9643ea8Slogwang         }
481a9643ea8Slogwang     }
482a9643ea8Slogwang 
483a9643ea8Slogwang     cache_skip_data(cache, total);
484a9643ea8Slogwang     if (ret < 0)
485a9643ea8Slogwang     {
486a9643ea8Slogwang         if (errno != EAGAIN)
487a9643ea8Slogwang         {
488a9643ea8Slogwang             MTLOG_ERROR("tcp socket send failed, error: %d[%m]", errno);
489a9643ea8Slogwang             return -2;
490a9643ea8Slogwang         }
491a9643ea8Slogwang     }
492a9643ea8Slogwang 
493a9643ea8Slogwang     return total;
494a9643ea8Slogwang }
495a9643ea8Slogwang 
cache_tcp_send_buff(TRWCache * cache,uint32_t fd,const void * data,uint32_t len)496a9643ea8Slogwang int32_t cache_tcp_send_buff(TRWCache* cache, uint32_t fd, const void* data, uint32_t len)
497a9643ea8Slogwang {
498a9643ea8Slogwang     if ((NULL == cache) || (NULL == data))
499a9643ea8Slogwang     {
500a9643ea8Slogwang         return -1;
501a9643ea8Slogwang     }
502a9643ea8Slogwang 
503a9643ea8Slogwang     int32_t ret = cache_tcp_send(cache, fd);
504a9643ea8Slogwang     if (ret < 0)
505a9643ea8Slogwang     {
506a9643ea8Slogwang         MTLOG_ERROR("tcp socket[%d] send cache data failed, rc: %d", fd, ret);
507a9643ea8Slogwang         return ret;
508a9643ea8Slogwang     }
509a9643ea8Slogwang 
510a9643ea8Slogwang     int32_t send_len = 0;
511a9643ea8Slogwang     if (cache->len == 0)
512a9643ea8Slogwang     {
513a9643ea8Slogwang         mt_hook_syscall(send);
514a9643ea8Slogwang         ret = ff_hook_send(fd, data, len, 0);
515a9643ea8Slogwang         if (ret >= 0)
516a9643ea8Slogwang         {
517a9643ea8Slogwang             send_len += ret;
518a9643ea8Slogwang         }
519a9643ea8Slogwang         else
520a9643ea8Slogwang         {
521a9643ea8Slogwang             if (errno != EAGAIN)
522a9643ea8Slogwang             {
523a9643ea8Slogwang                 MTLOG_ERROR("tcp socket[%d] send failed, error: %d[%m]", fd, errno);
524a9643ea8Slogwang                 return -2;
525a9643ea8Slogwang             }
526a9643ea8Slogwang         }
527a9643ea8Slogwang     }
528a9643ea8Slogwang 
529a9643ea8Slogwang     int32_t rc = cache_append_data(cache, (char*)data + send_len, len - send_len);
530a9643ea8Slogwang     if (rc < 0)
531a9643ea8Slogwang     {
532a9643ea8Slogwang         MTLOG_ERROR("tcp socket[%d] apend data failed, rc: %d", fd, rc);
533a9643ea8Slogwang         return -3;
534a9643ea8Slogwang     }
535a9643ea8Slogwang 
536a9643ea8Slogwang     return send_len;
537a9643ea8Slogwang }
538a9643ea8Slogwang 
get_data_len(TBuffVecPtr multi)539a9643ea8Slogwang uint32_t get_data_len(TBuffVecPtr multi)
540a9643ea8Slogwang {
541a9643ea8Slogwang     TRWCache* cache = (TRWCache*)multi;
542a9643ea8Slogwang     if (NULL == cache) {
543a9643ea8Slogwang         return 0;
544a9643ea8Slogwang     } else {
545a9643ea8Slogwang         return cache->len;
546a9643ea8Slogwang     }
547a9643ea8Slogwang }
548a9643ea8Slogwang 
get_block_count(TBuffVecPtr multi)549a9643ea8Slogwang uint32_t get_block_count(TBuffVecPtr multi)
550a9643ea8Slogwang {
551a9643ea8Slogwang     TRWCache* cache = (TRWCache*)multi;
552a9643ea8Slogwang     if (NULL == cache) {
553a9643ea8Slogwang         return 0;
554a9643ea8Slogwang     } else {
555a9643ea8Slogwang         return cache->count;
556a9643ea8Slogwang     }
557a9643ea8Slogwang }
558a9643ea8Slogwang 
get_first_block(TBuffVecPtr multi)559a9643ea8Slogwang TBuffBlockPtr get_first_block(TBuffVecPtr multi)
560a9643ea8Slogwang {
561a9643ea8Slogwang     TRWCache* cache = (TRWCache*)multi;
562a9643ea8Slogwang     if (NULL == cache) {
563a9643ea8Slogwang         return NULL;
564a9643ea8Slogwang     } else {
565a9643ea8Slogwang         return (TBuffBlockPtr)TAILQ_FIRST(&cache->list);
566a9643ea8Slogwang     }
567a9643ea8Slogwang }
568a9643ea8Slogwang 
get_next_block(TBuffVecPtr multi,TBuffBlockPtr block)569a9643ea8Slogwang TBuffBlockPtr get_next_block(TBuffVecPtr multi, TBuffBlockPtr block)
570a9643ea8Slogwang {
571a9643ea8Slogwang     TRWCache* cache = (TRWCache*)multi;
572a9643ea8Slogwang     TSkBuffer* item = (TSkBuffer*)block;
573a9643ea8Slogwang     if ((NULL == cache) || (NULL == item))
574a9643ea8Slogwang     {
575a9643ea8Slogwang         return NULL;
576a9643ea8Slogwang     }
577a9643ea8Slogwang 
578a9643ea8Slogwang     return (TBuffBlockPtr)TAILQ_NEXT(item, entry);
579a9643ea8Slogwang 
580a9643ea8Slogwang }
581a9643ea8Slogwang 
get_block_data(TBuffBlockPtr block,const void ** data,int32_t * len)582a9643ea8Slogwang void get_block_data(TBuffBlockPtr block, const void** data, int32_t* len)
583a9643ea8Slogwang {
584a9643ea8Slogwang     TSkBuffer* item = (TSkBuffer*)block;
585a9643ea8Slogwang     if (NULL == block)
586a9643ea8Slogwang     {
587a9643ea8Slogwang         return;
588a9643ea8Slogwang     }
589a9643ea8Slogwang 
590a9643ea8Slogwang     if (data != NULL)
591a9643ea8Slogwang     {
592a9643ea8Slogwang         *(uint8_t**)data = item->data;
593a9643ea8Slogwang     }
594a9643ea8Slogwang 
595a9643ea8Slogwang     if (len != NULL)
596a9643ea8Slogwang     {
597a9643ea8Slogwang         *len = (int32_t)item->data_len;
598a9643ea8Slogwang     }
599a9643ea8Slogwang }
600a9643ea8Slogwang 
read_cache_data(TBuffVecPtr multi,void * data,uint32_t len)601a9643ea8Slogwang uint32_t read_cache_data(TBuffVecPtr multi, void* data, uint32_t len)
602a9643ea8Slogwang {
603a9643ea8Slogwang     TRWCache* cache = (TRWCache*)multi;
604a9643ea8Slogwang     if (NULL == cache) {
605a9643ea8Slogwang         return 0;
606a9643ea8Slogwang     }
607a9643ea8Slogwang 
608a9643ea8Slogwang     uint32_t left_len = len;
609a9643ea8Slogwang     uint32_t offset = 0;
610a9643ea8Slogwang     TSkBuffer* item = NULL;
611a9643ea8Slogwang     TSkBuffer* tmp = NULL;
612a9643ea8Slogwang     TAILQ_FOREACH_SAFE(item, &cache->list, entry, tmp)
613a9643ea8Slogwang     {
614a9643ea8Slogwang         uint32_t copy_len = 0;
615a9643ea8Slogwang         if (left_len <= item->data_len)
616a9643ea8Slogwang         {
617a9643ea8Slogwang             copy_len = left_len;
618a9643ea8Slogwang         }
619a9643ea8Slogwang         else
620a9643ea8Slogwang         {
621a9643ea8Slogwang             copy_len = item->data_len;
622a9643ea8Slogwang         }
623a9643ea8Slogwang 
624a9643ea8Slogwang         if (data != NULL)
625a9643ea8Slogwang         {
626a9643ea8Slogwang             memcpy((char*)data + offset, item->data, copy_len);
627a9643ea8Slogwang         }
628a9643ea8Slogwang         offset += copy_len;
629a9643ea8Slogwang         left_len -= copy_len;
630a9643ea8Slogwang 
631a9643ea8Slogwang         if (left_len <= 0)
632a9643ea8Slogwang         {
633a9643ea8Slogwang             break;
634a9643ea8Slogwang         }
635a9643ea8Slogwang     }
636a9643ea8Slogwang 
637a9643ea8Slogwang     return offset;
638a9643ea8Slogwang }
639a9643ea8Slogwang 
read_cache_begin(TBuffVecPtr multi,uint32_t begin,void * data,uint32_t len)640a9643ea8Slogwang uint32_t read_cache_begin(TBuffVecPtr multi, uint32_t begin, void* data, uint32_t len)
641a9643ea8Slogwang {
642a9643ea8Slogwang     TRWCache* cache = (TRWCache*)multi;
643a9643ea8Slogwang     if (NULL == cache) {
644a9643ea8Slogwang         return 0;
645a9643ea8Slogwang     }
646a9643ea8Slogwang 
647a9643ea8Slogwang     if (begin >= cache->len) {
648a9643ea8Slogwang         return 0;
649a9643ea8Slogwang     }
650a9643ea8Slogwang 
651a9643ea8Slogwang     uint32_t pos_left = begin;
652a9643ea8Slogwang     uint32_t copy_left = len;
653a9643ea8Slogwang     uint32_t offset = 0;
654a9643ea8Slogwang     TSkBuffer* item = NULL;
655a9643ea8Slogwang     TAILQ_FOREACH(item, &cache->list, entry)
656a9643ea8Slogwang     {
657a9643ea8Slogwang         uint8_t* start_ptr = item->data;
658a9643ea8Slogwang         uint32_t real_left = item->data_len;
659a9643ea8Slogwang         if (pos_left > 0)
660a9643ea8Slogwang         {
661a9643ea8Slogwang             uint32_t skip_len = pos_left > real_left ? real_left : pos_left;
662a9643ea8Slogwang             pos_left -= skip_len;
663a9643ea8Slogwang             real_left -= skip_len;
664a9643ea8Slogwang             start_ptr += skip_len;
665a9643ea8Slogwang         }
666a9643ea8Slogwang 
667a9643ea8Slogwang         if (real_left == 0)
668a9643ea8Slogwang         {
669a9643ea8Slogwang             continue;
670a9643ea8Slogwang         }
671a9643ea8Slogwang 
672a9643ea8Slogwang         uint32_t copy_len = copy_left > real_left ? real_left : copy_left;
673a9643ea8Slogwang         if (data != NULL)
674a9643ea8Slogwang         {
675a9643ea8Slogwang             memcpy((char*)data + offset, start_ptr, copy_len);
676a9643ea8Slogwang         }
677a9643ea8Slogwang         offset += copy_len;
678a9643ea8Slogwang         copy_left -= copy_len;
679a9643ea8Slogwang         if (copy_left == 0)
680a9643ea8Slogwang         {
681a9643ea8Slogwang             break;
682a9643ea8Slogwang         }
683a9643ea8Slogwang     }
684a9643ea8Slogwang 
685a9643ea8Slogwang     return offset;
686a9643ea8Slogwang }
687a9643ea8Slogwang 
688a9643ea8Slogwang };
689