⛏️ index : haiku.git

/*
 * Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de.
 * Distributed under the terms of the MIT License.
 */

#include "stack_private.h"


/*!	Interface module providing networking to the kernel.
*/


static status_t
stack_interface_open(int family, int type, int protocol, net_socket** _socket)
{
	return gNetSocketModule.open_socket(family, type, protocol, _socket);
}


static status_t
stack_interface_close(net_socket* socket)
{
	return gNetSocketModule.close(socket);
}


static status_t
stack_interface_free(net_socket* socket)
{
	gNetSocketModule.free(socket);
	return B_OK;
}


static status_t
stack_interface_bind(net_socket* socket, const struct sockaddr* address,
	socklen_t addressLength)
{
	return gNetSocketModule.bind(socket, address, addressLength);
}


static status_t
stack_interface_shutdown(net_socket* socket, int how)
{
	return gNetSocketModule.shutdown(socket, how);
}


static status_t
stack_interface_connect(net_socket* socket, const struct sockaddr* address,
	socklen_t addressLength)
{
	return gNetSocketModule.connect(socket, address, addressLength);
}


static status_t
stack_interface_listen(net_socket* socket, int backlog)
{
	return gNetSocketModule.listen(socket, backlog);
}


static status_t
stack_interface_accept(net_socket* socket, struct sockaddr* address,
	socklen_t* _addressLength, net_socket** _acceptedSocket)
{
	return gNetSocketModule.accept(socket, address, _addressLength,
		_acceptedSocket);
}


static ssize_t
stack_interface_recv(net_socket* socket, void* data, size_t length, int flags)
{
	return gNetSocketModule.receive(socket, NULL, data, length, flags);
}


static ssize_t
stack_interface_recvfrom(net_socket* socket, void* data, size_t length,
	int flags, struct sockaddr* address, socklen_t* _addressLength)
{
	msghdr message;
	iovec vec = { data, length };
	message.msg_name = address;
	if (_addressLength != NULL)
		message.msg_namelen = *_addressLength;
	else
		message.msg_namelen = 0;
	message.msg_iov = &vec;
	message.msg_iovlen = 1;
	message.msg_control = NULL;
	message.msg_controllen = 0;
	message.msg_flags = 0;

	ssize_t received = gNetSocketModule.receive(socket, &message, data, length,
		flags);

	if (received >= 0 && _addressLength != NULL)
		*_addressLength = message.msg_namelen;

	return received;
}


static ssize_t
stack_interface_recvmsg(net_socket* socket, struct msghdr* message, int flags)
{
	void* buffer = NULL;
	size_t length = 0;
	if (message->msg_iovlen > 0) {
		buffer = message->msg_iov[0].iov_base;
		length = message->msg_iov[0].iov_len;
	}

	return gNetSocketModule.receive(socket, message, buffer, length, flags);
}


static ssize_t
stack_interface_send(net_socket* socket, const void* data, size_t length,
	int flags)
{
	return gNetSocketModule.send(socket, NULL, data, length, flags);
}


static ssize_t
stack_interface_sendto(net_socket* socket, const void* data, size_t length,
	int flags, const struct sockaddr* address, socklen_t addressLength)
{
	msghdr message;
	iovec vec = { (void*)data, length };
	message.msg_name = (void*)address;
	message.msg_namelen = addressLength;
	message.msg_iov = &vec;
	message.msg_iovlen = 1;
	message.msg_control = NULL;
	message.msg_controllen = 0;
	message.msg_flags = 0;

	return gNetSocketModule.send(socket, &message, data, length, flags);
}


static ssize_t
stack_interface_sendmsg(net_socket* socket, const struct msghdr* message,
	int flags)
{
	void* buffer = NULL;
	size_t length = 0;
	if (message->msg_iovlen > 0) {
		buffer = message->msg_iov[0].iov_base;
		length = message->msg_iov[0].iov_len;
	}

	return gNetSocketModule.send(socket, (msghdr*)message, buffer, length,
		flags);
}


static status_t
stack_interface_getsockopt(net_socket* socket, int level, int option,
	void* value, socklen_t* _length)
{
	int length = *_length;
	status_t error = gNetSocketModule.getsockopt(socket, level, option, value,
		&length);
	*_length = length;
	return error;
}


static status_t
stack_interface_setsockopt(net_socket* socket, int level, int option,
	const void* value, socklen_t length)
{
	return gNetSocketModule.setsockopt(socket, level, option, value, length);
}


static status_t
stack_interface_getpeername(net_socket* socket, struct sockaddr* address,
	socklen_t* _addressLength)
{
	return gNetSocketModule.getpeername(socket, address, _addressLength);
}


static status_t
stack_interface_getsockname(net_socket* socket, struct sockaddr* address,
	socklen_t* _addressLength)
{
	return gNetSocketModule.getsockname(socket, address, _addressLength);
}


static int
stack_interface_sockatmark(net_socket* socket)
{
	// TODO: sockatmark() missing
	return B_UNSUPPORTED;
}


static status_t
stack_interface_socketpair(int family, int type, int protocol,
	net_socket* _sockets[2])
{
	return gNetSocketModule.socketpair(family, type, protocol, _sockets);
}


static status_t
stack_interface_ioctl(net_socket* socket, uint32 op, void* buffer,
	size_t length)
{
	return gNetSocketModule.control(socket, op, buffer, length);
}


static status_t
stack_interface_select(net_socket* socket, uint8 event, struct selectsync* sync)
{
	return gNetSocketModule.request_notification(socket, event, sync);
}


static status_t
stack_interface_deselect(net_socket* socket, uint8 event,
	struct selectsync* sync)
{
	return gNetSocketModule.cancel_notification(socket, event, sync);
}


status_t
stack_interface_get_next_socket_stat(int family, uint32* cookie,
	struct net_stat* stat)
{
	return gNetSocketModule.get_next_stat(cookie, family, stat);
}


static status_t
stack_interface_std_ops(int32 op, ...)
{
	switch (op) {
		case B_MODULE_INIT:
			return init_stack();
		case B_MODULE_UNINIT:
			return uninit_stack();

		default:
			return B_ERROR;
	}
}


net_stack_interface_module_info gNetStackInterfaceModule = {
	{
		NET_STACK_INTERFACE_MODULE_NAME,
		0,
		stack_interface_std_ops
	},

	&stack_interface_open,
	&stack_interface_close,
	&stack_interface_free,

	&stack_interface_bind,
	&stack_interface_shutdown,
	&stack_interface_connect,
	&stack_interface_listen,
	&stack_interface_accept,

	&stack_interface_recv,
	&stack_interface_recvfrom,
	&stack_interface_recvmsg,

	&stack_interface_send,
	&stack_interface_sendto,
	&stack_interface_sendmsg,

	&stack_interface_getsockopt,
	&stack_interface_setsockopt,

	&stack_interface_getpeername,
	&stack_interface_getsockname,

	&stack_interface_sockatmark,

	&stack_interface_socketpair,

	&stack_interface_ioctl,
	&stack_interface_select,
	&stack_interface_deselect,

	&stack_interface_get_next_socket_stat
};