ssize_t cavan_mux_link_recv(struct cavan_mux_link *link, void *buff, size_t size) { size_t length; const char *data; struct cavan_mux_package *package; struct cavan_mux_package_raw *package_raw; cavan_lock_acquire(&link->lock); package_raw = link->package_head; if (package_raw == NULL) { cavan_lock_release(&link->lock); return 0; } package = &package_raw->package; data = package->data + link->hole_size; length = package->length - link->hole_size; if (size < length) { memcpy(buff, data, size); link->hole_size += size; } else { size = length; memcpy(buff, data, size); cavan_mux_package_free(link->mux, package); link->hole_size = 0; } cavan_lock_release(&link->lock); return size; }
ssize_t cavan_mux_append_receive_data(struct cavan_mux *mux, const void *buff, size_t size) { int ret; size_t wrlen, rdlen; struct cavan_mux_package package; struct cavan_mux_package *ppackage; cavan_lock_acquire(&mux->lock); wrlen = cavan_mem_queue_inqueue(&mux->recv_queue, buff, size); while (1) { rdlen = cavan_mem_queue_dequeue_peek(&mux->recv_queue, &package, sizeof(package)); if (rdlen < sizeof(package)) { goto out_success; } if (package.magic == CAVAN_MUX_MAGIC) { break; } cavan_mem_queue_dequeue(&mux->recv_queue, NULL, 1); } size = cavan_mux_package_get_whole_length(&package); if (cavan_mem_queue_get_used_size(&mux->recv_queue) < size) { goto out_success; } ppackage = cavan_mux_package_alloc(mux, package.length); if (ppackage == NULL) { pr_red_info("cavan_mux_package_alloc"); ret = -ENOMEM; goto out_cavan_lock_release; } if (cavan_mem_queue_dequeue(&mux->recv_queue, ppackage, size) != size) { pr_red_info("cavan_mem_queue_dequeue"); ret = -EFAULT; goto out_cavan_lock_release; } ret = cavan_mux_append_receive_package(mux, ppackage); if (ret < 0) { pr_red_info("cavan_mux_write_recv_package: %d", ret); cavan_mux_package_free(mux, ppackage); } out_success: ret = wrlen; out_cavan_lock_release: cavan_lock_release(&mux->lock); return ret; }
static int cavan_mux_send_thread_handler(struct cavan_thread *thread, void *data) { struct cavan_mux *mux = data; struct cavan_mux_package_raw *package_raw; package_raw = mux->package_head; if (package_raw == NULL) { cavan_thread_suspend(thread); } else { struct cavan_mux_package *package = &package_raw->package; char *data = (char *) package; size_t length = cavan_mux_package_get_whole_length(package); while (length) { ssize_t wrlen; wrlen = mux->send(mux, data, length); if (wrlen < 0) { pr_red_info("mux->send"); return wrlen; } data += wrlen; length -= wrlen; } mux->package_head = package_raw->next; if (mux->package_head == NULL) { mux->package_tail = &mux->package_head; } cavan_mux_package_free(mux, package); } return 0; }
int main(int argc, char *argv[]) { int i; int ret; int count; ssize_t rdlen; char buff[1024]; struct cavan_mux mux; struct cavan_mux_link link1, link2; struct cavan_mux_package *package, *packages[10]; int pipefd[2]; ret = pipe(pipefd); if (ret < 0) { pr_error_info("pipe"); return ret; } mux.send = test_mux_send; mux.recv = test_mux_recv; ret = cavan_mux_init(&mux, pipefd); if (ret < 0) { pr_red_info("cavan_mux_init"); return ret; } cavan_mux_link_init(&link1, &mux); cavan_mux_link_init(&link2, &mux); cavan_mux_show_packages(&mux); for (i = 0; i < NELEM(packages); i++) { packages[i] = cavan_mux_package_alloc(&mux, (i + 1) * 100); } cavan_mux_show_packages(&mux); for (i = NELEM(packages) - 1; i >= 0; i--) { cavan_mux_package_free(&mux, packages[i]); } cavan_mux_show_packages(&mux); (void) package; #if 0 package = cavan_mux_package_alloc(&mux, 560); if (package) { println("alloc length = %d", package->length); } cavan_mux_show_packages(&mux); #endif link1.on_received = link2.on_received = test_mux_on_received; link1.private_data = "Link1"; ret = cavan_mux_bind(&mux, &link1, 2000); if (ret < 0) { pr_red_info("cavan_mux_bind"); } link2.private_data = "Link2"; ret = cavan_mux_bind(&mux, &link2, 12345); if (ret < 0) { pr_red_info("cavan_mux_bind"); } println("port1 = %d, port2 = %d", link1.local_port, link2.local_port); link1.remote_port = link2.local_port; ret = cavan_mux_link_send(&link1, "1234567890", 10); if (ret < 0) { pr_red_info("cavan_mux_link_send"); } cavan_mux_show_packages(&mux); link2.remote_port = link1.local_port; ret = cavan_mux_link_send(&link2, "ABCDEFGHIJKL", 10); if (ret < 0) { pr_red_info("cavan_mux_link_send"); } cavan_mux_show_packages(&mux); (void) count; #if 0 count = 0; while (1) { struct cavan_mux_link *link = malloc(sizeof(struct cavan_mux_link)); ret = cavan_mux_bind(&mux, link, 0); if (ret < 0) { pr_red_info("cavan_mux_bind"); break; } if (link->local_port == link1.local_port || link->local_port == link2.local_port) { pr_red_info("invalid port %d", link->local_port); } count++; println("port = %d, count = %d", link->local_port, count); } #endif msleep(5000); rdlen = cavan_mux_link_recv(&link1, buff, sizeof(buff)); buff[rdlen] = 0; println("link1: buff[%" PRINT_FORMAT_SIZE "] = %s", rdlen, buff); cavan_mux_show_packages(&mux); msleep(5000); rdlen = cavan_mux_link_recv(&link2, buff, sizeof(buff)); buff[rdlen] = 0; println("link2: buff[%" PRINT_FORMAT_SIZE "] = %s", rdlen, buff); cavan_mux_show_packages(&mux); cavan_mux_deinit(&mux); return 0; }