static char* test_cbuffer_append_wraps(void) { CircularBuffer* mybuf = cbuffer_new(); // put us at the end of the buffer mybuf->pos = IO_BUFFER_SIZE - 5; mybuf->tail = IO_BUFFER_SIZE - 5; uint32_t test_data[11] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; cbuffer_append(mybuf, test_data, 11); mu_assert_eq("pos", mybuf->pos, IO_BUFFER_SIZE - 5); mu_assert_eq("size", cbuffer_size(mybuf), 11); mu_assert_eq("tail content", memcmp( &(mybuf->data[mybuf->pos]), test_data, 5 * sizeof(uint32_t)), 0); // make sure we aren't trashing the memory after the buffer. //mu_assert_eq("tail content sanity", mybuf->data[IO_BUFFER_SIZE-1], 4); mu_assert_eq("head content", memcmp( mybuf->data, test_data + 5, 6 * sizeof(uint32_t)), 0); uint32_t test_data2[3] = {11, 12, 13}; cbuffer_append(mybuf, test_data2, 3); mu_assert_eq("size", cbuffer_size(mybuf), 14); mu_assert_eq("content", memcmp(&(mybuf->data[6]), test_data2, 3), 0); cbuffer_free(mybuf); return 0; }
static char* test_cbuffer_pop(void) { CircularBuffer* mybuf = cbuffer_new(); // put us at the end of the buffer mybuf->pos = IO_BUFFER_SIZE - 5; mybuf->tail = IO_BUFFER_SIZE - 5; uint32_t test_data[11] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; cbuffer_append(mybuf, test_data, 11); Buffer* bucky = cbuffer_pop(mybuf, 5); mu_assert_eq("size", cbuffer_size(mybuf), 6); mu_assert_eq("content", memcmp(bucky->data, test_data, 5*sizeof(uint32_t)), 0); Buffer* badger = cbuffer_pop(mybuf, 6); mu_assert_eq("size2", cbuffer_size(mybuf), 0); mu_assert_eq("content2", memcmp(badger->data, test_data + 5, 6), 0); // if we pop an empty collection, we get nothing. Buffer* empty = cbuffer_pop(mybuf, 10); mu_assert_eq("size3", empty->size, 0); cbuffer_free(mybuf); buffer_free(bucky); buffer_free(badger); buffer_free(empty); return 0; }
static char* test_cbuffer_append(void) { CircularBuffer* mybuf = cbuffer_new(); uint32_t test_data[5] = {0, 1, 2, 3, 4}; cbuffer_append(mybuf, test_data, 5); mu_assert_eq("pos", mybuf->pos, 0); mu_assert_eq("size", cbuffer_size(mybuf), 5); mu_assert_eq("content", memcmp(mybuf->data, test_data, 5 * sizeof(uint32_t)), 0); uint32_t test_data2[3] = {6, 7, 8}; cbuffer_append(mybuf, test_data2, 3); mu_assert_eq("pos", mybuf->pos, 0); mu_assert_eq("size", cbuffer_size(mybuf), 8); mu_assert_eq("content2", memcmp(mybuf->data, test_data, 5 * sizeof(uint32_t)), 0); mu_assert_eq("content3", memcmp(&(mybuf->data[5]), test_data2, 3 * sizeof(uint32_t)), 0); cbuffer_free(mybuf); return 0; }
static char* test_spi_stream_construct_tx_packet(void) { uint32_t my_data[5] = {1, 2, 3, 4, 5}; CircularBuffer* mybuf = cbuffer_new(); cbuffer_append(mybuf, my_data, 5); uint32_t my_pkt_expected[10] = {0xBEEF, 5, 1, 2, 3, 4, 5, 0xDEADBEEF, 0xDEADBEEF, -1}; add_checksum(my_pkt_expected, 10); int checksum_err = -1; spi_stream_verify_packet(my_pkt_expected, 10, &checksum_err); mu_assert_eq("no cksum err", checksum_err, 0); uint32_t my_pkt[10]; spi_stream_construct_tx_packet(0xBEEF, my_pkt, 10, mybuf); // for (int i = 0; i < 10; ++i) { // printf("%i %lx %lx\n", i, my_pkt_expected[i], my_pkt[i]); // } mu_assert_eq("packet", memcmp(my_pkt_expected, my_pkt, 10 * sizeof(uint32_t)), 0); mu_assert_eq("consumed", cbuffer_size(mybuf), 0); // put more in the buffer than we can consume at once cbuffer_append(mybuf, my_data, 5); cbuffer_append(mybuf, my_data, 5); cbuffer_append(mybuf, my_data, 5); uint32_t my_pkt_expected_2[10] = {0xBEEF, 7, 1, 2, 3, 4, 5, 1, 2, -1}; add_checksum(my_pkt_expected_2, 10); spi_stream_verify_packet(my_pkt_expected_2, 10, &checksum_err); mu_assert_eq("no cksum err 2", checksum_err, 0); spi_stream_construct_tx_packet(0xBEEF, my_pkt, 10, mybuf); mu_assert_eq("packet", memcmp(my_pkt_expected_2, my_pkt, 10 * sizeof(uint32_t)), 0); mu_assert_eq("consumed", cbuffer_size(mybuf), 8); spi_stream_verify_packet(my_pkt, 10, &checksum_err); mu_assert_eq("no cksum actual", checksum_err, 0); return 0; }
static char* test_cbuffer_value_at_wraps(void) { CircularBuffer* mybuf = cbuffer_new(); // put us at the end of the buffer mybuf->pos = IO_BUFFER_SIZE - 5; mybuf->tail = IO_BUFFER_SIZE - 5; uint32_t test_data[11] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; cbuffer_append(mybuf, test_data, 11); for (int i = 0; i < 11; ++i) { mu_assert_eq("read at", cbuffer_value_at(mybuf, i), test_data[i]); } cbuffer_free(mybuf); return 0; }
static char* test_cbuffer_read_wraps(void) { CircularBuffer* mybuf = cbuffer_new(); // put us at the end of the buffer mybuf->pos = IO_BUFFER_SIZE - 5; mybuf->tail = IO_BUFFER_SIZE - 5; uint32_t test_data[11] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; cbuffer_append(mybuf, test_data, 11); Buffer* readout = buffer_new(NULL, 11); cbuffer_read(mybuf, readout->data, 11); mu_assert_eq("size", readout->size, 11); mu_assert_eq("content", memcmp(readout->data, test_data, 11 * sizeof(uint32_t)), 0); cbuffer_free(mybuf); buffer_free(readout); return 0; }
static char* test_cbuffer_read(void) { CircularBuffer* mybuf = cbuffer_new(); Buffer* readout = buffer_new(NULL, 11); uint32_t test_data[11] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; cbuffer_append(mybuf, test_data, 11); cbuffer_read(mybuf, readout->data, 11); mu_assert_eq("size", readout->size, 11); mu_assert_eq("content", memcmp(readout->data, test_data, 11 * sizeof(uint32_t)), 0); // if we ask for too much it cbuffer gives us what it has. Buffer* readout2 = buffer_new(NULL, 30); int actually_read = cbuffer_read(mybuf, readout2->data, 30); mu_assert_eq("size2", actually_read, 11); mu_assert_eq("content2", memcmp(readout2->data, test_data, 11 * sizeof(uint32_t)), 0); cbuffer_free(mybuf); buffer_free(readout); buffer_free(readout2); return 0; }
static char* test_cbuffer_delete_front_wraps(void) { CircularBuffer* mybuf = cbuffer_new(); uint32_t test_data[11] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; // put us at the end of the buffer mybuf->pos = IO_BUFFER_SIZE - 5; mybuf->tail = IO_BUFFER_SIZE - 5; cbuffer_append(mybuf, test_data, 11); mu_assert_eq("content", memcmp(&(mybuf->data[mybuf->pos]), test_data, 5 * sizeof(uint32_t)), 0); int deleted = cbuffer_deletefront(mybuf, 5); mu_assert_eq("deleted", deleted, 5); mu_assert_eq("pos", mybuf->pos, 0); mu_assert_eq("size", cbuffer_size(mybuf), 6); mu_assert_eq("item0", mybuf->data[mybuf->pos], 5); mu_assert_eq("item1", mybuf->data[mybuf->pos+1], 6); mu_assert_eq("item2", mybuf->data[mybuf->pos+2], 7); mu_assert_eq("remaining content in cbuffer", memcmp( &(mybuf->data[0]), test_data + 5, 6 * sizeof(uint32_t)), 0); Buffer* readout = buffer_new(NULL, 6); cbuffer_read(mybuf, readout->data, 6); mu_assert_eq("remaining content", memcmp( readout->data, (test_data + 5), 6 * sizeof(uint32_t)), 0); // if we ask to delete everything, just return what was actually deleted. int deleted_just_to_end = cbuffer_deletefront(mybuf, 100); mu_assert_eq("deleted just to end", deleted_just_to_end, 6); mu_assert_eq("pos2", mybuf->pos, 6); mu_assert_eq("size2", cbuffer_size(mybuf), 0); cbuffer_free(mybuf); buffer_free(readout); return 0; }
static char* test_cbuffer_pop_front(void) { CircularBuffer* mybuf = cbuffer_new(); // put us at the end of the buffer mybuf->pos = IO_BUFFER_SIZE - 5; mybuf->tail = IO_BUFFER_SIZE - 5; uint32_t test_data[11] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; cbuffer_append(mybuf, test_data, 11); for (int i = 0; i < 11; i++) { mu_assert_eq("pre-pop size", cbuffer_size(mybuf), 11 - i); uint32_t value = cbuffer_pop_front(mybuf); mu_assert_eq("popped_content", (int)value, i); } // if we pop an empty collection, we get dead beef. uint32_t empty = cbuffer_pop_front(mybuf); mu_assert_eq("empty", empty, 0xDEADBEEF); cbuffer_free(mybuf); return 0; }
int main(int argc, char *argv[]) { caught_termination = 0; if (signal(SIGINT, sig_handler) == SIG_ERR) { LOG_ERROR("Can't catch SIGINT"); } if (signal(SIGTERM, sig_handler) == SIG_ERR) { LOG_ERROR("Can't catch SIGTERM"); } if (argc < 3) { LOG_ERROR("Usage: %s /dev/input /dev/output", argv[0]); return 1; } char * inputdevice = argv[1]; char * outputdevice = argv[2]; // initialize mapped memory block membase_init(); LOG_INFO("serving memory @ %016" PRIxPTR " via %s-> ->%s", (uintptr_t)membase, inputdevice, outputdevice); int inputdevicefd = open(inputdevice, O_RDWR | O_NONBLOCK); // in general these are probably the same. int outputdevicefd = inputdevicefd; // but maybe not. if (strcmp(inputdevice, outputdevice) != 0) { outputdevicefd = open(outputdevice, O_RDWR | O_NONBLOCK); } Client client; client.inputstream = cbuffer_new(); client.outputstream = cbuffer_new(); client.inputfd = inputdevicefd; client.outputfd = outputdevicefd; client.byte2word = bytebuffer_ctor(NULL, 0); client.swapbytes = 0; while (1) { if (caught_termination) { break; } bytebuffer_read_fd( &(client.byte2word), client.inputfd, MAX_REQ_LEN); if (client.byte2word.bufsize > 0) { LOG_DEBUG("Processing %i bytes", client.byte2word.bufsize); // Data available! Process the request. CircularBuffer *clibuf = client.inputstream; ByteBuffer* byte2word = &(client.byte2word); size_t nwords = byte2word->bufsize / sizeof(uint32_t); int append_ret = cbuffer_append(clibuf, byte2word->buf, nwords); if (append_ret == 0) { bytebuffer_del_front(byte2word, nwords * sizeof(uint32_t)); } ipbus_process_input_stream(&client); // write out any response cbuffer_write_fd(client.outputstream, client.outputfd, cbuffer_size(client.outputstream)); } } if (inputdevicefd != outputdevicefd) { close(outputdevicefd); } close(inputdevicefd); membase_close(); LOG_INFO("goodbye!\n"); return 0; }