예제 #1
0
int cavan_mux_add_link(struct cavan_mux *mux, struct cavan_mux_link *link, u16 port)
{
	struct cavan_mux_link **head;

	cavan_lock_acquire(&mux->lock);

	head = mux->links + (cavan_mux_link_head_index(port));
	while ((*head) && (*head)->local_port < port)
	{
		head = &(*head)->next;
	}

	if ((*head) && (*head)->local_port == port)
	{
		pr_red_info("port %d already exists!", port);
		cavan_lock_release(&mux->lock);
		return -EINVAL;
	}

	link->local_port = port;

	link->next = *head;
	*head = link;

	cavan_lock_release(&mux->lock);

	return 0;
}
예제 #2
0
파일: mux.c 프로젝트: FuangCao/cavan
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;
}
예제 #3
0
ssize_t cavan_mux_link_send(struct cavan_mux_link *link, const void *buff, size_t size)
{
	struct cavan_mux_package *package;
	struct cavan_mux *mux = link->mux;

	package = cavan_mux_package_alloc(mux, size);
	if (package == NULL)
	{
		pr_red_info("cavan_mux_package_alloc");
		return -ENOMEM;
	}

	cavan_lock_acquire(&link->lock);

	package->src_port = link->local_port;
	package->dest_port = link->remote_port;

	cavan_lock_release(&link->lock);

	memcpy(package->data, buff, size);

	cavan_mux_append_send_package(mux, package);

	return size;
}
예제 #4
0
int cavan_mux_find_free_port(struct cavan_mux *mux, u16 *pport)
{
	int i, j;
	int ret = 0;

	cavan_lock_acquire(&mux->lock);

	for (i = 0; i < NELEM(mux->links); i++)
	{
		struct cavan_mux_link *head = mux->links[i];

		for (j = 0; j < (1 << (sizeof(u16) << 3)) / NELEM(mux->links); j++)
		{
			u16 port = j * NELEM(mux->links) + i;

			if (head && head->local_port == port)
			{
				head = head->next;
			}
			else if (port != 0)
			{
				*pport = port;
				goto label_found;
			}
		}
	}

	ret = -EBUSY;

label_found:
	cavan_lock_release(&mux->lock);
	return ret;
}
예제 #5
0
void cavan_mux_unbind(struct cavan_mux *mux, struct cavan_mux_link *link)
{
	struct cavan_mux_link **head;

	cavan_lock_acquire(&mux->lock);

	head = mux->links + (cavan_mux_link_head_index(link->local_port));
	if (link == *head)
	{
		*head = link->next;
	}
	else
	{
		struct cavan_mux_link *prev;

		for (prev = *head; prev && prev->next != link; prev = prev->next);

		if (prev)
		{
			prev->next = link->next;
		}
	}

	cavan_lock_release(&mux->lock);
}
예제 #6
0
파일: mux.c 프로젝트: FuangCao/cavan
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;
}
예제 #7
0
파일: mux.c 프로젝트: FuangCao/cavan
int cavan_mux_bind(struct cavan_mux *mux, struct cavan_mux_link *link, u16 port)
{
	int ret;

	cavan_lock_acquire(&mux->lock);

	if (port == 0) {
		ret = cavan_mux_find_free_port(mux, &port);
		if (ret < 0) {
			cavan_lock_release(&mux->lock);
			return ret;
		}
	}

	ret = cavan_mux_add_link(mux, link, port);

	cavan_lock_release(&mux->lock);

	return ret;
}
예제 #8
0
struct cavan_mux_link *cavan_mux_find_link(struct cavan_mux *mux, u16 port)
{
	struct cavan_mux_link *link;

	cavan_lock_acquire(&mux->lock);

	for (link = mux->links[cavan_mux_link_head_index(port)]; link && link->local_port != port; link = link->next);

	cavan_lock_release(&mux->lock);

	return link;
}
예제 #9
0
파일: mux.c 프로젝트: FuangCao/cavan
void cavan_mux_show_packages(struct cavan_mux *mux)
{
	struct cavan_mux_package_raw *package;

	cavan_lock_acquire(&mux->lock);

	for (package = mux->packages; package; package = package->next) {
		println("length = %d", package->length);
	}

	cavan_lock_release(&mux->lock);
}
예제 #10
0
void cavan_mux_append_package(struct cavan_mux *mux, struct cavan_mux_package_raw *package)
{
	struct cavan_mux_package_raw **head;

	cavan_lock_acquire(&mux->lock);

	for (head = &mux->packages; *head && (*head)->length < package->length; head = &(*head)->next);

	package->next = *head;
	*head = package;

	cavan_lock_release(&mux->lock);
}
예제 #11
0
void cavan_mux_append_send_package(struct cavan_mux *mux, struct cavan_mux_package *package)
{
	struct cavan_mux_package_raw *package_raw = CAVAN_MUX_PACKAGE_GET_RAW(package);

	package->magic = CAVAN_MUX_MAGIC;

	cavan_lock_acquire(&mux->lock);

	*mux->package_tail = package_raw;
	package_raw->next = NULL;
	mux->package_tail = &package_raw->next;
	cavan_thread_resume(&mux->send_thread);

	cavan_lock_release(&mux->lock);
}
예제 #12
0
파일: mux.c 프로젝트: FuangCao/cavan
int cavan_mux_append_receive_package(struct cavan_mux *mux, struct cavan_mux_package *package)
{
	int ret;
	struct cavan_mux_link *link;

	cavan_lock_acquire(&mux->lock);

	link = cavan_mux_find_link(mux, package->dest_port);
	if (link == NULL) {
		pr_red_info("invalid port %d", package->dest_port);
		ret = -EINVAL;
	} else {
		ret = cavan_mux_link_append_receive_package(link, package);;
	}

	cavan_lock_release(&mux->lock);

	return ret;
}
예제 #13
0
파일: mux.c 프로젝트: FuangCao/cavan
int cavan_mux_link_append_receive_package(struct cavan_mux_link *link, struct cavan_mux_package *package)
{
	struct cavan_mux_package_raw *package_raw = CAVAN_MUX_PACKAGE_GET_RAW(package);

	cavan_lock_acquire(&link->lock);

	*link->package_tail = package_raw;
	package_raw->next = NULL;
	link->package_tail = &package_raw->next;

	link->remote_port = package->src_port;

	if (link->on_received) {
		link->on_received(link);
	}

	cavan_lock_release(&link->lock);

	return 0;
}
예제 #14
0
파일: mux.c 프로젝트: FuangCao/cavan
void cavan_mux_deinit(struct cavan_mux *mux)
{
	struct cavan_mux_package_raw *head;

	cavan_thread_stop(&mux->recv_thread);

	cavan_lock_acquire(&mux->lock);

	head = mux->packages;
	while (head) {
		struct cavan_mux_package_raw *next = head->next;

		free(head);
		head = next;
	}

	cavan_lock_release(&mux->lock);

	cavan_lock_deinit(&mux->lock);
}
예제 #15
0
파일: mux.c 프로젝트: FuangCao/cavan
struct cavan_mux_package_raw *cavan_mux_dequeue_package(struct cavan_mux *mux, size_t length)
{
	struct cavan_mux_package_raw **head;
	struct cavan_mux_package_raw *package;

	cavan_lock_acquire(&mux->lock);

	head = &mux->packages;

	while (*head && (*head)->length < length) {
		head = &(*head)->next;
	}

	package = *head;
	if (package) {
		*head = package->next;
	}

	cavan_lock_release(&mux->lock);

	return package;
}