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