diff --git a/core/dap_circular_buffer.c b/core/dap_circular_buffer.c index ff756880595992a733f8fccf4e18766262f410a8..2127f49530455f63812166548fa1200bdf30cd20 100755 --- a/core/dap_circular_buffer.c +++ b/core/dap_circular_buffer.c @@ -4,18 +4,24 @@ // Created by 罗亮富(Roen zxllf23@163.com) on 14-1-14. // Copyright (c) 2014年 All rights reserved. // +// Note: Edited by Kurotych Anatolii #include "dap_circular_buffer.h" #include <string.h> +#include <errno.h> + +#include "dap_common.h" + +#define LOG_TAG "circular_buffer" struct s_circularBuffer{ - size_t size; //capacity bytes size + size_t capacity; //capacity bytes size size_t dataSize; //occupied data size size_t tailOffset; //head offset, the oldest byte position offset size_t headOffset; //tail offset, the lastest byte position offset - void *buffer; + u_int8_t *buffer; }; @@ -25,7 +31,7 @@ extern CircularBuffer CircularBufferCreate(size_t size) void *p = malloc(totalSize); CircularBuffer buffer = (CircularBuffer)p; buffer->buffer = p + sizeof(struct s_circularBuffer); - buffer->size = size; + buffer->capacity = size; CircularBufferReset(buffer); return buffer; } @@ -33,7 +39,7 @@ extern CircularBuffer CircularBufferCreate(size_t size) void CircularBufferFree(CircularBuffer cBuf) { CircularBufferReset(cBuf); - cBuf->size = 0; + cBuf->capacity = 0; cBuf->dataSize = 0; cBuf->buffer = NULL; free(cBuf); @@ -46,9 +52,9 @@ void CircularBufferReset(CircularBuffer cBuf) cBuf->dataSize = 0; } -size_t CircularBufferGetSize(CircularBuffer cBuf) +size_t CircularBufferGetCapacity(CircularBuffer cBuf) { - return cBuf->size; + return cBuf->capacity; } size_t CircularBufferGetDataSize(CircularBuffer cBuf) @@ -58,20 +64,23 @@ size_t CircularBufferGetDataSize(CircularBuffer cBuf) void CircularBufferPush(CircularBuffer cBuf,void *src, size_t length) { + if(length == 0) + return; + size_t writableLen = length; void *pSrc = src; - if(writableLen > cBuf->size)//in case of size overflow + if(writableLen > cBuf->capacity)//in case of size overflow { - size_t overFlowLen = writableLen - cBuf->size; - writableLen = cBuf->size; + size_t overFlowLen = writableLen - cBuf->capacity; + writableLen = cBuf->capacity; pSrc = src + overFlowLen; } bool resetHead = false; //in case the circle buffer won't be full after adding the data - if(cBuf->tailOffset+writableLen < cBuf->size) + if(cBuf->tailOffset+writableLen < cBuf->capacity) { memcpy(&cBuf->buffer[cBuf->tailOffset + 1], pSrc, writableLen); @@ -82,7 +91,7 @@ void CircularBufferPush(CircularBuffer cBuf,void *src, size_t length) } else//in case the circle buffer will be overflow after adding the data { - size_t remainSize = cBuf->size - cBuf->tailOffset - 1; //the remain size + size_t remainSize = cBuf->capacity - cBuf->tailOffset - 1; //the remain size memcpy(&cBuf->buffer[cBuf->tailOffset+1], pSrc, remainSize); size_t coverSize = writableLen - remainSize; //size of data to be covered from the beginning @@ -99,27 +108,113 @@ void CircularBufferPush(CircularBuffer cBuf,void *src, size_t length) cBuf->tailOffset = coverSize - 1; } - if(cBuf->headOffset == -1) + if(cBuf->headOffset == (size_t)-1) cBuf->headOffset = 0; if(resetHead) { - if(cBuf->tailOffset+1 < cBuf->size) + if(cBuf->tailOffset+1 < cBuf->capacity) cBuf->headOffset = cBuf->tailOffset + 1; else cBuf->headOffset = 0; - cBuf->dataSize = cBuf->size; + cBuf->dataSize = cBuf->capacity; } else { if(cBuf->tailOffset >= cBuf->headOffset) cBuf->dataSize = cBuf->tailOffset - cBuf->headOffset + 1; else - cBuf->dataSize = cBuf->size - (cBuf->headOffset - cBuf->tailOffset - 1); + cBuf->dataSize = cBuf->capacity - (cBuf->headOffset - cBuf->tailOffset - 1); + } +} + +#ifdef __unix__ +#include <sys/types.h> +#include <sys/socket.h> + +int CircularBufferWriteInSocket(CircularBuffer cBuf, int sockfd) +{ + if(cBuf->dataSize == 0) { + return 0; + } + + ssize_t rdLen = -1; + + if(cBuf->headOffset <= cBuf->tailOffset) + { + rdLen = send(sockfd, + &cBuf->buffer[cBuf->headOffset], + cBuf->dataSize, MSG_DONTWAIT | MSG_NOSIGNAL | MSG_DONTROUTE); + if(rdLen < 0) { + log_it(L_ERROR, "Can't write data in socket. %s", strerror(errno)); + return -1; + } + + cBuf->headOffset += rdLen; + if(cBuf->headOffset > cBuf->tailOffset) + { + cBuf->headOffset = -1; + cBuf->tailOffset = -1; + } + + cBuf->dataSize -= rdLen; + } + else + { + if(cBuf->headOffset + cBuf->dataSize <= cBuf->capacity) + { + log_it(L_CRITICAL, "We always trying write all data!"); + abort(); + } + else + { + size_t countBytesToEnd = cBuf->capacity - cBuf->headOffset; + rdLen = send(sockfd, + &cBuf->buffer[cBuf->headOffset], + countBytesToEnd, MSG_DONTWAIT | MSG_NOSIGNAL); + // log_it(L_DEBUG, "Write in socket: %s", &cBuf->buffer[cBuf->headOffset]); + if(rdLen < 0) { + log_it(L_ERROR, "Can't write data in socket. %s", strerror(errno)); + return -1; + } + + if(rdLen < (ssize_t)countBytesToEnd) { + log_it(L_WARNING, "rdLen < countBytesToEnd"); + CircularBufferPop(cBuf, rdLen, NULL); + return rdLen; + } + + cBuf->dataSize -= countBytesToEnd; + cBuf->headOffset = 0; + cBuf->tailOffset = cBuf->dataSize - 1; + + ssize_t rdLen2 = send(sockfd, + cBuf->buffer, + cBuf->dataSize, MSG_DONTWAIT | MSG_NOSIGNAL); + + if(rdLen2 < 0) { + log_it(L_ERROR, "Can't write data in socket. %s", strerror(errno)); + return rdLen; + } + + cBuf->headOffset = rdLen2; + if(cBuf->headOffset > cBuf->tailOffset) + { + cBuf->headOffset = -1; + cBuf->tailOffset = -1; + cBuf->dataSize = 0; + } + return countBytesToEnd + rdLen2; + } } + + return rdLen; + } +#endif + size_t inter_circularBuffer_read(CircularBuffer cBuf, size_t length, void *dataOut, bool resetHead) { if(cBuf->dataSize == 0 || length == 0) @@ -148,7 +243,7 @@ size_t inter_circularBuffer_read(CircularBuffer cBuf, size_t length, void *dataO } else { - if(cBuf->headOffset+rdLen <= cBuf->size) + if(cBuf->headOffset+rdLen <= cBuf->capacity) { if(dataOut) memcpy(dataOut, &cBuf->buffer[cBuf->headOffset], rdLen); @@ -156,13 +251,13 @@ size_t inter_circularBuffer_read(CircularBuffer cBuf, size_t length, void *dataO if(resetHead) { cBuf->headOffset += rdLen; - if(cBuf->headOffset == cBuf->size) + if(cBuf->headOffset == cBuf->capacity) cBuf->headOffset = 0; } } else { - size_t frg1Len = cBuf->size - cBuf->headOffset; + size_t frg1Len = cBuf->capacity - cBuf->headOffset; if(dataOut) memcpy(dataOut, &cBuf->buffer[cBuf->headOffset], frg1Len); @@ -203,8 +298,8 @@ size_t CircularBufferRead(CircularBuffer cBuf, size_t length, void *dataOut) //print circular buffer's content into str, void CircularBufferPrint(CircularBuffer cBuf, bool hex) { - char *b = cBuf->buffer; - size_t cSize = CircularBufferGetSize(cBuf); + u_int8_t *b = cBuf->buffer; + size_t cSize = CircularBufferGetCapacity(cBuf); char *str = malloc(2*cSize+1); char c; @@ -235,7 +330,7 @@ void CircularBufferPrint(CircularBuffer cBuf, bool hex) sprintf(str+i*2, "%c|",c); } - printf("CircularBuffer: %s <size %zu dataSize:%zu>\n",str,CircularBufferGetSize(cBuf),CircularBufferGetDataSize(cBuf)); + printf("CircularBuffer: %s <size %zu dataSize:%zu>\n",str,CircularBufferGetCapacity(cBuf),CircularBufferGetDataSize(cBuf)); free(str); } diff --git a/core/dap_circular_buffer.h b/core/dap_circular_buffer.h index 459402b247011145bc81de4bc520cbd25331fd64..68ee8ee995fc6685e8c0a9aa0fa744188c7e7c91 100755 --- a/core/dap_circular_buffer.h +++ b/core/dap_circular_buffer.h @@ -27,7 +27,7 @@ extern void CircularBufferFree(CircularBuffer cBuf); extern void CircularBufferReset(CircularBuffer cBuf); //get the capacity of CircularBuffer -extern size_t CircularBufferGetSize(CircularBuffer cBuf); +extern size_t CircularBufferGetCapacity(CircularBuffer cBuf); //get occupied data size of CircularBuffer extern size_t CircularBufferGetDataSize(CircularBuffer cBuf); @@ -44,4 +44,8 @@ extern size_t CircularBufferRead(CircularBuffer cBuf, size_t length, void *dataO //for test purpose, print the circular buffer's data content by printf(...); the 'hex' parameters indicates that if the data should be printed in asscii string or hex data format. extern void CircularBufferPrint(CircularBuffer cBuf, bool hex); +#ifdef __unix__ +// Read data from a circular buffer to socketFd +extern int CircularBufferWriteInSocket(CircularBuffer cBuf, int sockfd); +#endif #endif diff --git a/test/core/dap_circular_test.c b/test/core/dap_circular_test.c index af021e41f4631aa50e5a6636d2a42d97edeeed22..cc397a06d325edef8c96d0f10fbcf6b45602e8b0 100644 --- a/test/core/dap_circular_test.c +++ b/test/core/dap_circular_test.c @@ -1,8 +1,213 @@ #include "dap_circular_test.h" #include "dap_circular_buffer.h" +#include <string.h> +#include <sys/socket.h> +#include <unistd.h> + +static char *chars_string = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; + +#define MAX_RESULT_BUF_LEN 8096 +void dap_circular_test_simple() +{ + const int buf_size = 8; + CircularBuffer cb = CircularBufferCreate(buf_size); + + CircularBufferPush(cb, chars_string, buf_size); + + int fd[2]; + socketpair(PF_LOCAL, SOCK_STREAM, 0, fd); + + int ret = CircularBufferWriteInSocket(cb, fd[0]); + dap_assert(ret == buf_size, "Check ret write in socket"); + + ret = CircularBufferWriteInSocket(cb, fd[0]); + dap_assert(ret == 0, "Check ret write in socket"); + char result_buff[MAX_RESULT_BUF_LEN] = {0}; + ssize_t res = read(fd[1], result_buff, 44); + + dap_assert(res == buf_size, "Check buf size"); + + dap_assert(dap_strn_equals(result_buff, chars_string, buf_size), + "Check result buf"); + dap_assert(CircularBufferGetDataSize(cb) == 0, "Check data size"); + + close(fd[0]); + close(fd[1]); + CircularBufferFree(cb); + dap_pass_msg("Test simple"); +} + +void dap_circular_test_double_write() +{ + const int buf_size = 8; + const char* expected_string = "0123456701"; + int expected_string_len = strlen(expected_string); + CircularBuffer cb = CircularBufferCreate(buf_size); + + CircularBufferPush(cb, chars_string, buf_size); + + int fd[2]; + socketpair(PF_LOCAL, SOCK_STREAM, 0, fd); + + int ret = CircularBufferWriteInSocket(cb, fd[0]); + + CircularBufferPush(cb, chars_string, 2); + + ret = CircularBufferWriteInSocket(cb, fd[0]); + dap_assert(ret == 2, "Check ret write in socket"); + + char result_buff[MAX_RESULT_BUF_LEN] = {0}; + ssize_t res = read(fd[1], result_buff, 44); + + dap_assert(res == expected_string_len, "Check buf size"); + + dap_assert(dap_str_equals(result_buff, expected_string), + "Check result buf"); + dap_assert(CircularBufferGetDataSize(cb) == 0, "Check data size"); + dap_pass_msg("Double write"); + + CircularBufferFree(cb); + close(fd[0]); + close(fd[1]); +} + +void dap_circular_test_defrag_write() +{ + const int buf_size = 8; + const char* expected_string = "56701201"; + int expected_string_len = strlen(expected_string); + CircularBuffer cb = CircularBufferCreate(buf_size); + + CircularBufferPush(cb, chars_string, buf_size); + CircularBufferPop(cb, 5, NULL); + CircularBufferPush(cb, chars_string, 3); + // expected string here 567012 + + + int fd[2]; + socketpair(PF_LOCAL, SOCK_STREAM, 0, fd); + + // write 567012 + int ret = CircularBufferWriteInSocket(cb, fd[0]); + dap_assert(ret == 6, "Check ret write in socket"); + + // push 01 + CircularBufferPush(cb, chars_string, 2); + + // write 01 + ret = CircularBufferWriteInSocket(cb, fd[0]); + dap_assert(ret == 2, "Check ret write in socket"); + + char result_buff[MAX_RESULT_BUF_LEN] = {0}; + ssize_t res = read(fd[1], result_buff, MAX_RESULT_BUF_LEN); + + dap_assert(res == expected_string_len, "Check buf size"); + + dap_assert(dap_str_equals(result_buff, expected_string), + "Check result buf"); + + dap_pass_msg("Double write"); + dap_assert(CircularBufferGetDataSize(cb) == 0, "Check data size"); + CircularBufferFree(cb); + close(fd[0]); + close(fd[1]); +} + +void dap_circular_test_write_bad_socket() +{ + const int buf_size = 8; + CircularBuffer cb = CircularBufferCreate(buf_size); + + CircularBufferPush(cb, chars_string, buf_size); + + int fd[2]; + socketpair(PF_LOCAL, SOCK_STREAM, 0, fd); + int fd2[2]; + socketpair(PF_LOCAL, SOCK_STREAM, 0, fd2); + + close(fd[0]); + int ret = CircularBufferWriteInSocket(cb, fd[0]); + dap_assert(ret == -1, "Check ret write in socket"); + + ret = CircularBufferWriteInSocket(cb, fd2[0]); + dap_assert(ret == 8, "Check ret write in socket"); + char result_buff[MAX_RESULT_BUF_LEN] = {0}; + ssize_t res = read(fd2[1], result_buff, MAX_RESULT_BUF_LEN); + + dap_assert(res == buf_size, "Check buf size"); + + dap_assert(dap_strn_equals(result_buff, chars_string, buf_size), + "Check result buf"); + + ret = CircularBufferWriteInSocket(cb, fd2[0]); + dap_assert(ret == 0, "Check zero write"); + dap_assert(CircularBufferGetDataSize(cb) == 0, "Check data size"); + close(fd[1]); + close(fd2[0]); + close(fd2[1]); + CircularBufferFree(cb); + dap_pass_msg("Test simple"); +} + +void dap_circular_load_test() +{ + srand(time(NULL)); + + int iterations = 230; + + const char *digits = "123456789"; + + const int buf_size = strlen(digits); + CircularBuffer cb = CircularBufferCreate(buf_size); + + int fd[2]; + socketpair(PF_LOCAL, SOCK_STREAM, 0, fd); + + int count_writed_bytes = 0; + + // defrag buffer + CircularBufferPush(cb, (void*)digits, strlen(digits)); + CircularBufferPop(cb, strlen(digits) - 1, NULL); + CircularBufferPush(cb, (void*)digits, 3); + count_writed_bytes = 4; + + char expectedBuffer[MAX_RESULT_BUF_LEN]; + CircularBufferRead(cb, count_writed_bytes, expectedBuffer); + + int count_write_bytes = 4; + do { + int r = CircularBufferWriteInSocket(cb, fd[0]); + dap_assert_PIF(r == count_write_bytes, "Check write bytes"); + dap_assert_PIF(CircularBufferGetDataSize(cb) == 0, "buf size must be 0!"); + + count_write_bytes = rand() % strlen(digits); + CircularBufferPush(cb, (void*)digits, count_write_bytes); + strncat(expectedBuffer, digits, count_write_bytes); + count_writed_bytes += count_write_bytes; + } while (--iterations); + count_writed_bytes -= count_write_bytes; // last bytes will not be writed + + char result_buff[MAX_RESULT_BUF_LEN] = {0}; + ssize_t res = read(fd[1], result_buff, MAX_RESULT_BUF_LEN); + dap_assert(res == count_writed_bytes, "Check count writed and readed from socket bytes"); + + dap_assert(memcmp(expectedBuffer, result_buff, res) == 0, "Check expected and result buffer"); + + CircularBufferFree(cb); + close(fd[0]); + close(fd[1]); +} void dap_circular_test_run() { dap_print_module_name("dap_circular"); + + dap_circular_test_simple(); + dap_circular_test_double_write(); + dap_circular_test_defrag_write(); +#ifdef __linux__ + dap_circular_test_write_bad_socket(); + dap_circular_load_test(); +#endif } diff --git a/test/core/main.c b/test/core/main.c index cd9355a4afe461d2519a0a10e25ef1d8b120ad7f..84291baf4fe4083f5b1728f2a44c791d731163ba 100755 --- a/test/core/main.c +++ b/test/core/main.c @@ -1,20 +1,20 @@ #include "dap_config_test.h" #include "dap_common_test.h" #include "dap_network_monitor_test.h" -#include "dap_circular_test.h" #include "dap_common.h" int main(void) { // switch off debug info from library set_log_level(L_CRITICAL); - dap_circular_test_run(); dap_config_tests_run(); dap_common_test_run(); -#ifdef __linux__ +#ifdef __unix__ #include "dap_process_mem_test.h" #include "dap_cpu_monitor_test.h" #include "dap_network_monitor.h" +#include "dap_circular_test.h" + dap_circular_test_run(); dap_process_mem_test_run(); dap_cpu_monitor_test_run(); dap_network_monitor_test_run(); diff --git a/test/libdap-test b/test/libdap-test index 6d69cc4be2ccbc5fc978adadab4fbcc52bc31d36..d2257789e0c796a5a3b637e14dcbaf8a8c7880cc 160000 --- a/test/libdap-test +++ b/test/libdap-test @@ -1 +1 @@ -Subproject commit 6d69cc4be2ccbc5fc978adadab4fbcc52bc31d36 +Subproject commit d2257789e0c796a5a3b637e14dcbaf8a8c7880cc