Kernel: Cleanup OSI layer overlapping
This commit is contained in:
		
							parent
							
								
									5d78cd3016
								
							
						
					
					
						commit
						ff49d8b84f
					
				|  | @ -104,8 +104,8 @@ namespace Kernel | |||
| 		BAN::ErrorOr<void> bind(const sockaddr* address, socklen_t address_len); | ||||
| 		BAN::ErrorOr<void> connect(const sockaddr* address, socklen_t address_len); | ||||
| 		BAN::ErrorOr<void> listen(int backlog); | ||||
| 		BAN::ErrorOr<size_t> sendto(const sys_sendto_t*); | ||||
| 		BAN::ErrorOr<size_t> recvfrom(sys_recvfrom_t*); | ||||
| 		BAN::ErrorOr<size_t> sendto(BAN::ConstByteSpan message, const sockaddr* address, socklen_t address_len); | ||||
| 		BAN::ErrorOr<size_t> recvfrom(BAN::ByteSpan buffer, sockaddr* address, socklen_t* address_len); | ||||
| 
 | ||||
| 		// General API
 | ||||
| 		BAN::ErrorOr<size_t> read(off_t, BAN::ByteSpan buffer); | ||||
|  | @ -131,12 +131,12 @@ namespace Kernel | |||
| 		virtual BAN::ErrorOr<BAN::String> link_target_impl()				{ return BAN::Error::from_errno(ENOTSUP); } | ||||
| 
 | ||||
| 		// Socket API
 | ||||
| 		virtual BAN::ErrorOr<long> accept_impl(sockaddr*, socklen_t*)		{ return BAN::Error::from_errno(ENOTSUP); } | ||||
| 		virtual BAN::ErrorOr<void> connect_impl(const sockaddr*, socklen_t)	{ return BAN::Error::from_errno(ENOTSUP); } | ||||
| 		virtual BAN::ErrorOr<void> listen_impl(int)							{ return BAN::Error::from_errno(ENOTSUP); } | ||||
| 		virtual BAN::ErrorOr<void> bind_impl(const sockaddr*, socklen_t)	{ return BAN::Error::from_errno(ENOTSUP); } | ||||
| 		virtual BAN::ErrorOr<size_t> sendto_impl(const sys_sendto_t*)		{ return BAN::Error::from_errno(ENOTSUP); } | ||||
| 		virtual BAN::ErrorOr<size_t> recvfrom_impl(sys_recvfrom_t*)			{ return BAN::Error::from_errno(ENOTSUP); } | ||||
| 		virtual BAN::ErrorOr<long> accept_impl(sockaddr*, socklen_t*)								{ return BAN::Error::from_errno(ENOTSUP); } | ||||
| 		virtual BAN::ErrorOr<void> connect_impl(const sockaddr*, socklen_t)							{ return BAN::Error::from_errno(ENOTSUP); } | ||||
| 		virtual BAN::ErrorOr<void> listen_impl(int)													{ return BAN::Error::from_errno(ENOTSUP); } | ||||
| 		virtual BAN::ErrorOr<void> bind_impl(const sockaddr*, socklen_t)							{ return BAN::Error::from_errno(ENOTSUP); } | ||||
| 		virtual BAN::ErrorOr<size_t> sendto_impl(BAN::ConstByteSpan, const sockaddr*, socklen_t)	{ return BAN::Error::from_errno(ENOTSUP); } | ||||
| 		virtual BAN::ErrorOr<size_t> recvfrom_impl(BAN::ByteSpan, sockaddr*, socklen_t*)				{ return BAN::Error::from_errno(ENOTSUP); } | ||||
| 
 | ||||
| 		// General API
 | ||||
| 		virtual BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan)		{ return BAN::Error::from_errno(ENOTSUP); } | ||||
|  |  | |||
|  | @ -32,7 +32,7 @@ namespace Kernel | |||
| 	}; | ||||
| 	static_assert(sizeof(IPv4Header) == 20); | ||||
| 
 | ||||
| 	class IPv4Layer : public NetworkLayer | ||||
| 	class IPv4Layer final : public NetworkLayer | ||||
| 	{ | ||||
| 		BAN_NON_COPYABLE(IPv4Layer); | ||||
| 		BAN_NON_MOVABLE(IPv4Layer); | ||||
|  | @ -45,8 +45,9 @@ namespace Kernel | |||
| 
 | ||||
| 		void add_ipv4_packet(NetworkInterface&, BAN::ConstByteSpan); | ||||
| 
 | ||||
| 		virtual void unbind_socket(uint16_t port, BAN::RefPtr<NetworkSocket>) override; | ||||
| 		virtual BAN::ErrorOr<void> bind_socket(uint16_t port, BAN::RefPtr<NetworkSocket>) override; | ||||
| 		virtual void unbind_socket(BAN::RefPtr<NetworkSocket>, uint16_t port) override; | ||||
| 		virtual BAN::ErrorOr<void> bind_socket_to_unused(BAN::RefPtr<NetworkSocket>, const sockaddr* send_address, socklen_t send_address_len) override; | ||||
| 		virtual BAN::ErrorOr<void> bind_socket_to_address(BAN::RefPtr<NetworkSocket>, const sockaddr* address, socklen_t address_len) override; | ||||
| 
 | ||||
| 		virtual BAN::ErrorOr<size_t> sendto(NetworkSocket&, BAN::ConstByteSpan, const sockaddr*, socklen_t) override; | ||||
| 
 | ||||
|  | @ -65,7 +66,7 @@ namespace Kernel | |||
| 		}; | ||||
| 
 | ||||
| 	private: | ||||
| 		SpinLock				m_lock; | ||||
| 		RecursiveSpinLock		m_lock; | ||||
| 
 | ||||
| 		BAN::UniqPtr<ARPTable>	m_arp_table; | ||||
| 		Process*				m_process { nullptr }; | ||||
|  |  | |||
|  | @ -22,8 +22,9 @@ namespace Kernel | |||
| 	public: | ||||
| 		virtual ~NetworkLayer() {} | ||||
| 
 | ||||
| 		virtual void unbind_socket(uint16_t port, BAN::RefPtr<NetworkSocket>) = 0; | ||||
| 		virtual BAN::ErrorOr<void> bind_socket(uint16_t port, BAN::RefPtr<NetworkSocket>) = 0; | ||||
| 		virtual void unbind_socket(BAN::RefPtr<NetworkSocket>, uint16_t port) = 0; | ||||
| 		virtual BAN::ErrorOr<void> bind_socket_to_unused(BAN::RefPtr<NetworkSocket>, const sockaddr* send_address, socklen_t send_address_len) = 0; | ||||
| 		virtual BAN::ErrorOr<void> bind_socket_to_address(BAN::RefPtr<NetworkSocket>, const sockaddr* address, socklen_t address_len) = 0; | ||||
| 
 | ||||
| 		virtual BAN::ErrorOr<size_t> sendto(NetworkSocket&, BAN::ConstByteSpan, const sockaddr*, socklen_t) = 0; | ||||
| 
 | ||||
|  |  | |||
|  | @ -6,8 +6,6 @@ | |||
| #include <kernel/Networking/NetworkInterface.h> | ||||
| #include <kernel/Networking/NetworkLayer.h> | ||||
| 
 | ||||
| #include <netinet/in.h> | ||||
| 
 | ||||
| namespace Kernel | ||||
| { | ||||
| 
 | ||||
|  | @ -35,25 +33,21 @@ namespace Kernel | |||
| 		virtual void add_protocol_header(BAN::ByteSpan packet, uint16_t dst_port, PseudoHeader) = 0; | ||||
| 		virtual NetworkProtocol protocol() const = 0; | ||||
| 
 | ||||
| 		virtual void add_packet(BAN::ConstByteSpan, BAN::IPv4Address sender_address, uint16_t sender_port) = 0; | ||||
| 		virtual void receive_packet(BAN::ConstByteSpan, const sockaddr_storage& sender) = 0; | ||||
| 
 | ||||
| 		bool is_bound() const { return m_interface != nullptr; } | ||||
| 
 | ||||
| 	protected: | ||||
| 		NetworkSocket(NetworkLayer&, ino_t, const TmpInodeInfo&); | ||||
| 
 | ||||
| 		virtual BAN::ErrorOr<size_t> read_packet(BAN::ByteSpan, sockaddr_in* sender_address) = 0; | ||||
| 
 | ||||
| 		virtual void on_close_impl() override; | ||||
| 
 | ||||
| 		virtual BAN::ErrorOr<void> bind_impl(const sockaddr* address, socklen_t address_len) override; | ||||
| 		virtual BAN::ErrorOr<size_t> sendto_impl(const sys_sendto_t*) override; | ||||
| 		virtual BAN::ErrorOr<size_t> recvfrom_impl(sys_recvfrom_t*) override; | ||||
| 
 | ||||
| 		virtual BAN::ErrorOr<long> ioctl_impl(int request, void* arg) override; | ||||
| 
 | ||||
| 	protected: | ||||
| 		NetworkLayer&		m_network_layer; | ||||
| 		NetworkInterface*	m_interface	= nullptr; | ||||
| 		uint16_t			m_port		= PORT_NONE; | ||||
| 		uint16_t			m_port { PORT_NONE }; | ||||
| 	}; | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -30,23 +30,25 @@ namespace Kernel | |||
| 		virtual void add_protocol_header(BAN::ByteSpan packet, uint16_t dst_port, PseudoHeader) override; | ||||
| 
 | ||||
| 	protected: | ||||
| 		virtual void add_packet(BAN::ConstByteSpan, BAN::IPv4Address sender_addr, uint16_t sender_port) override; | ||||
| 		virtual BAN::ErrorOr<size_t> read_packet(BAN::ByteSpan, sockaddr_in* sender_address) override; | ||||
| 		virtual void receive_packet(BAN::ConstByteSpan, const sockaddr_storage& sender) override; | ||||
| 
 | ||||
| 		virtual BAN::ErrorOr<void> bind_impl(const sockaddr* address, socklen_t address_len) override; | ||||
| 		virtual BAN::ErrorOr<size_t> sendto_impl(BAN::ConstByteSpan message, const sockaddr* address, socklen_t address_len) override; | ||||
| 		virtual BAN::ErrorOr<size_t> recvfrom_impl(BAN::ByteSpan buffer, sockaddr* address, socklen_t* address_len) override; | ||||
| 
 | ||||
| 	private: | ||||
| 		UDPSocket(NetworkLayer&, ino_t, const TmpInodeInfo&); | ||||
| 
 | ||||
| 		struct PacketInfo | ||||
| 		{ | ||||
| 			BAN::IPv4Address	sender_addr; | ||||
| 			uint16_t			sender_port; | ||||
| 			sockaddr_storage	sender; | ||||
| 			size_t				packet_size; | ||||
| 		}; | ||||
| 
 | ||||
| 	private: | ||||
| 		static constexpr size_t				packet_buffer_size = 10 * PAGE_SIZE; | ||||
| 		BAN::UniqPtr<VirtualRange>			m_packet_buffer; | ||||
| 		BAN::CircularQueue<PacketInfo, 128>	m_packets; | ||||
| 		BAN::CircularQueue<PacketInfo, 32>	m_packets; | ||||
| 		size_t								m_packet_total_size { 0 }; | ||||
| 		SpinLock							m_packet_lock; | ||||
| 		Semaphore							m_packet_semaphore; | ||||
|  |  | |||
|  | @ -23,8 +23,8 @@ namespace Kernel | |||
| 		virtual BAN::ErrorOr<void> connect_impl(const sockaddr*, socklen_t) override; | ||||
| 		virtual BAN::ErrorOr<void> listen_impl(int) override; | ||||
| 		virtual BAN::ErrorOr<void> bind_impl(const sockaddr*, socklen_t) override; | ||||
| 		virtual BAN::ErrorOr<size_t> sendto_impl(const sys_sendto_t*) override; | ||||
| 		virtual BAN::ErrorOr<size_t> recvfrom_impl(sys_recvfrom_t*) override; | ||||
| 		virtual BAN::ErrorOr<size_t> sendto_impl(BAN::ConstByteSpan, const sockaddr*, socklen_t) override; | ||||
| 		virtual BAN::ErrorOr<size_t> recvfrom_impl(BAN::ByteSpan, sockaddr*, socklen_t*) override; | ||||
| 
 | ||||
| 	private: | ||||
| 		UnixDomainSocket(SocketType, ino_t, const TmpInodeInfo&); | ||||
|  |  | |||
|  | @ -148,20 +148,20 @@ namespace Kernel | |||
| 		return listen_impl(backlog); | ||||
| 	} | ||||
| 
 | ||||
| 	BAN::ErrorOr<size_t> Inode::sendto(const sys_sendto_t* arguments) | ||||
| 	BAN::ErrorOr<size_t> Inode::sendto(BAN::ConstByteSpan message, const sockaddr* address, socklen_t address_len) | ||||
| 	{ | ||||
| 		LockGuard _(m_lock); | ||||
| 		if (!mode().ifsock()) | ||||
| 			return BAN::Error::from_errno(ENOTSOCK); | ||||
| 		return sendto_impl(arguments); | ||||
| 		return sendto_impl(message, address, address_len); | ||||
| 	}; | ||||
| 
 | ||||
| 	BAN::ErrorOr<size_t> Inode::recvfrom(sys_recvfrom_t* arguments) | ||||
| 	BAN::ErrorOr<size_t> Inode::recvfrom(BAN::ByteSpan buffer, sockaddr* address, socklen_t* address_len) | ||||
| 	{ | ||||
| 		LockGuard _(m_lock); | ||||
| 		if (!mode().ifsock()) | ||||
| 			return BAN::Error::from_errno(ENOTSOCK); | ||||
| 		return recvfrom_impl(arguments); | ||||
| 		return recvfrom_impl(buffer, address, address_len); | ||||
| 	}; | ||||
| 
 | ||||
| 	BAN::ErrorOr<size_t> Inode::read(off_t offset, BAN::ByteSpan buffer) | ||||
|  |  | |||
|  | @ -66,7 +66,7 @@ namespace Kernel | |||
| 		header.checksum			= calculate_internet_checksum(BAN::ConstByteSpan::from(header), {}); | ||||
| 	} | ||||
| 
 | ||||
| 	void IPv4Layer::unbind_socket(uint16_t port, BAN::RefPtr<NetworkSocket> socket) | ||||
| 	void IPv4Layer::unbind_socket(BAN::RefPtr<NetworkSocket> socket, uint16_t port) | ||||
| 	{ | ||||
| 		LockGuard _(m_lock); | ||||
| 		if (m_bound_sockets.contains(port)) | ||||
|  | @ -78,29 +78,52 @@ namespace Kernel | |||
| 		NetworkManager::get().TmpFileSystem::remove_from_cache(socket); | ||||
| 	} | ||||
| 
 | ||||
| 	BAN::ErrorOr<void> IPv4Layer::bind_socket(uint16_t port, BAN::RefPtr<NetworkSocket> socket) | ||||
| 	BAN::ErrorOr<void> IPv4Layer::bind_socket_to_unused(BAN::RefPtr<NetworkSocket> socket, const sockaddr* address, socklen_t address_len) | ||||
| 	{ | ||||
| 		if (!address || address_len < (socklen_t)sizeof(sockaddr_in)) | ||||
| 			return BAN::Error::from_errno(EINVAL); | ||||
| 		if (address->sa_family != AF_INET) | ||||
| 			return BAN::Error::from_errno(EAFNOSUPPORT); | ||||
| 		auto& sockaddr_in = *reinterpret_cast<const struct sockaddr_in*>(address); | ||||
| 
 | ||||
| 		LockGuard _(m_lock); | ||||
| 
 | ||||
| 		uint16_t port = NetworkSocket::PORT_NONE; | ||||
| 		for (uint32_t temp = 0xC000; temp < 0xFFFF; temp++) | ||||
| 		{ | ||||
| 			if (!m_bound_sockets.contains(temp)) | ||||
| 			{ | ||||
| 				port = temp; | ||||
| 				break; | ||||
| 			} | ||||
| 		} | ||||
| 		if (port == NetworkSocket::PORT_NONE) | ||||
| 		{ | ||||
| 			dwarnln("No ports available"); | ||||
| 			return BAN::Error::from_errno(EAGAIN); | ||||
| 		} | ||||
| 
 | ||||
| 		struct sockaddr_in target; | ||||
| 		target.sin_family = AF_INET; | ||||
| 		target.sin_port = BAN::host_to_network_endian(port); | ||||
| 		target.sin_addr.s_addr = sockaddr_in.sin_addr.s_addr; | ||||
| 		return bind_socket_to_address(socket, (sockaddr*)&target, sizeof(sockaddr_in)); | ||||
| 	} | ||||
| 
 | ||||
| 	BAN::ErrorOr<void> IPv4Layer::bind_socket_to_address(BAN::RefPtr<NetworkSocket> socket, const sockaddr* address, socklen_t address_len) | ||||
| 	{ | ||||
| 		if (NetworkManager::get().interfaces().empty()) | ||||
| 			return BAN::Error::from_errno(EADDRNOTAVAIL); | ||||
| 
 | ||||
| 		LockGuard _(m_lock); | ||||
| 		if (!address || address_len < (socklen_t)sizeof(sockaddr_in)) | ||||
| 			return BAN::Error::from_errno(EINVAL); | ||||
| 		if (address->sa_family != AF_INET) | ||||
| 			return BAN::Error::from_errno(EAFNOSUPPORT); | ||||
| 
 | ||||
| 		if (port == NetworkSocket::PORT_NONE) | ||||
| 		{ | ||||
| 			for (uint32_t temp = 0xC000; temp < 0xFFFF; temp++) | ||||
| 			{ | ||||
| 				if (!m_bound_sockets.contains(temp)) | ||||
| 				{ | ||||
| 					port = temp; | ||||
| 					break; | ||||
| 				} | ||||
| 			} | ||||
| 			if (port == NetworkSocket::PORT_NONE) | ||||
| 			{ | ||||
| 				dwarnln("No ports available"); | ||||
| 				return BAN::Error::from_errno(EAGAIN); | ||||
| 			} | ||||
| 		} | ||||
| 		auto& sockaddr_in = *reinterpret_cast<const struct sockaddr_in*>(address); | ||||
| 		uint16_t port = BAN::host_to_network_endian(sockaddr_in.sin_port); | ||||
| 
 | ||||
| 		LockGuard _(m_lock); | ||||
| 
 | ||||
| 		if (m_bound_sockets.contains(port)) | ||||
| 			return BAN::Error::from_errno(EADDRINUSE); | ||||
|  | @ -163,6 +186,10 @@ namespace Kernel | |||
| 		auto ipv4_data = packet.slice(sizeof(IPv4Header)); | ||||
| 
 | ||||
| 		auto src_ipv4 = ipv4_header.src_address; | ||||
| 
 | ||||
| 		uint16_t dst_port = NetworkSocket::PORT_NONE; | ||||
| 		uint16_t src_port = NetworkSocket::PORT_NONE; | ||||
| 
 | ||||
| 		switch (ipv4_header.protocol) | ||||
| 		{ | ||||
| 			case NetworkProtocol::ICMP: | ||||
|  | @ -188,37 +215,53 @@ namespace Kernel | |||
| 						dprintln("Unhandleded ICMP packet (type {2H})", icmp_header.type); | ||||
| 						break; | ||||
| 				} | ||||
| 				break; | ||||
| 				return {}; | ||||
| 			} | ||||
| 			case NetworkProtocol::UDP: | ||||
| 			{ | ||||
| 				auto& udp_header = ipv4_data.as<const UDPHeader>(); | ||||
| 				uint16_t src_port = udp_header.src_port; | ||||
| 				uint16_t dst_port = udp_header.dst_port; | ||||
| 
 | ||||
| 				LockGuard _(m_lock); | ||||
| 
 | ||||
| 				if (!m_bound_sockets.contains(dst_port)) | ||||
| 				{ | ||||
| 					dprintln_if(DEBUG_IPV4, "no one is listening on port {}", dst_port); | ||||
| 					return {}; | ||||
| 				} | ||||
| 				auto socket = m_bound_sockets[dst_port].lock(); | ||||
| 				if (!socket) | ||||
| 				{ | ||||
| 					dprintln_if(DEBUG_IPV4, "no one is listening on port {}", dst_port); | ||||
| 					return {}; | ||||
| 				} | ||||
| 
 | ||||
| 				auto udp_data = ipv4_data.slice(sizeof(UDPHeader)); | ||||
| 				socket->add_packet(udp_data, src_ipv4, src_port); | ||||
| 				dst_port = udp_header.dst_port; | ||||
| 				src_port = udp_header.src_port; | ||||
| 				break; | ||||
| 			} | ||||
| 			default: | ||||
| 				dprintln_if(DEBUG_IPV4, "Unknown network protocol 0x{2H}", ipv4_header.protocol); | ||||
| 				break; | ||||
| 				return {}; | ||||
| 		} | ||||
| 
 | ||||
| 		ASSERT(dst_port != NetworkSocket::PORT_NONE); | ||||
| 		ASSERT(src_port != NetworkSocket::PORT_NONE); | ||||
| 
 | ||||
| 		BAN::RefPtr<Kernel::NetworkSocket> bound_socket; | ||||
| 
 | ||||
| 		{ | ||||
| 			LockGuard _(m_lock); | ||||
| 			if (!m_bound_sockets.contains(dst_port)) | ||||
| 			{ | ||||
| 				dprintln_if(DEBUG_IPV4, "no one is listening on port {}", dst_port); | ||||
| 				return {}; | ||||
| 			} | ||||
| 			bound_socket = m_bound_sockets[dst_port].lock(); | ||||
| 		} | ||||
| 
 | ||||
| 		if (!bound_socket) | ||||
| 		{ | ||||
| 			dprintln_if(DEBUG_IPV4, "no one is listening on port {}", dst_port); | ||||
| 			return {}; | ||||
| 		} | ||||
| 
 | ||||
| 		if (bound_socket->protocol() != ipv4_header.protocol) | ||||
| 		{ | ||||
| 			dprintln_if(DEBUG_IPV4, "got data with wrong protocol ({}) on port {} (bound as {})", ipv4_header.protocol, dst_port, (uint8_t)bound_socket->protocol()); | ||||
| 			return {}; | ||||
| 		} | ||||
| 
 | ||||
| 		sockaddr_in sender; | ||||
| 		sender.sin_family = AF_INET; | ||||
| 		sender.sin_port = BAN::NetworkEndian<uint16_t>(src_port); | ||||
| 		sender.sin_addr.s_addr = src_ipv4.raw; | ||||
| 		bound_socket->receive_packet(ipv4_data, *reinterpret_cast<const sockaddr_storage*>(&sender)); | ||||
| 
 | ||||
| 		return {}; | ||||
| 	} | ||||
| 
 | ||||
|  |  | |||
|  | @ -17,8 +17,12 @@ namespace Kernel | |||
| 
 | ||||
| 	void NetworkSocket::on_close_impl() | ||||
| 	{ | ||||
| 		if (m_interface) | ||||
| 			m_network_layer.unbind_socket(m_port, this); | ||||
| 		if (is_bound()) | ||||
| 		{ | ||||
| 			m_network_layer.unbind_socket(this, m_port); | ||||
| 			m_interface = nullptr; | ||||
| 			m_port = PORT_NONE; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	void NetworkSocket::bind_interface_and_port(NetworkInterface* interface, uint16_t port) | ||||
|  | @ -29,60 +33,6 @@ namespace Kernel | |||
| 		m_port = port; | ||||
| 	} | ||||
| 
 | ||||
| 	BAN::ErrorOr<void> NetworkSocket::bind_impl(const sockaddr* address, socklen_t address_len) | ||||
| 	{ | ||||
| 		if (m_interface || address_len != sizeof(sockaddr_in)) | ||||
| 			return BAN::Error::from_errno(EINVAL); | ||||
| 		auto* addr_in = reinterpret_cast<const sockaddr_in*>(address); | ||||
| 		uint16_t dst_port = BAN::host_to_network_endian(addr_in->sin_port); | ||||
| 		return m_network_layer.bind_socket(dst_port, this); | ||||
| 	} | ||||
| 
 | ||||
| 	BAN::ErrorOr<size_t> NetworkSocket::sendto_impl(const sys_sendto_t* arguments) | ||||
| 	{ | ||||
| 		if (arguments->flags) | ||||
| 		{ | ||||
| 			dprintln("flags not supported"); | ||||
| 			return BAN::Error::from_errno(ENOTSUP); | ||||
| 		} | ||||
| 
 | ||||
| 		if (!m_interface) | ||||
| 			TRY(m_network_layer.bind_socket(PORT_NONE, this)); | ||||
| 
 | ||||
| 		auto buffer = BAN::ConstByteSpan { reinterpret_cast<const uint8_t*>(arguments->message), arguments->length }; | ||||
| 		return TRY(m_network_layer.sendto(*this, buffer, arguments->dest_addr, arguments->dest_len)); | ||||
| 	} | ||||
| 
 | ||||
| 	BAN::ErrorOr<size_t> NetworkSocket::recvfrom_impl(sys_recvfrom_t* arguments) | ||||
| 	{ | ||||
| 		sockaddr_in* sender_addr = nullptr; | ||||
| 		if (arguments->address) | ||||
| 		{ | ||||
| 			ASSERT(arguments->address_len); | ||||
| 			if (*arguments->address_len < (socklen_t)sizeof(sockaddr_in)) | ||||
| 				*arguments->address_len = 0; | ||||
| 			else | ||||
| 			{ | ||||
| 				sender_addr = reinterpret_cast<sockaddr_in*>(arguments->address); | ||||
| 				*arguments->address_len = sizeof(sockaddr_in); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		if (!m_interface) | ||||
| 		{ | ||||
| 			dprintln("No interface bound"); | ||||
| 			return BAN::Error::from_errno(EINVAL); | ||||
| 		} | ||||
| 
 | ||||
| 		if (m_port == PORT_NONE) | ||||
| 		{ | ||||
| 			dprintln("No port bound"); | ||||
| 			return BAN::Error::from_errno(EINVAL); | ||||
| 		} | ||||
| 
 | ||||
| 		return TRY(read_packet(BAN::ByteSpan { reinterpret_cast<uint8_t*>(arguments->buffer), arguments->length }, sender_addr)); | ||||
| 	} | ||||
| 
 | ||||
| 	BAN::ErrorOr<long> NetworkSocket::ioctl_impl(int request, void* arg) | ||||
| 	{ | ||||
| 		if (!arg) | ||||
|  |  | |||
|  | @ -33,8 +33,11 @@ namespace Kernel | |||
| 		header.checksum = 0; | ||||
| 	} | ||||
| 
 | ||||
| 	void UDPSocket::add_packet(BAN::ConstByteSpan packet, BAN::IPv4Address sender_addr, uint16_t sender_port) | ||||
| 	void UDPSocket::receive_packet(BAN::ConstByteSpan packet, const sockaddr_storage& sender) | ||||
| 	{ | ||||
| 		//auto& header = packet.as<const UDPHeader>();
 | ||||
| 		auto payload = packet.slice(sizeof(UDPHeader)); | ||||
| 
 | ||||
| 		LockGuard _(m_packet_lock); | ||||
| 
 | ||||
| 		if (m_packets.full()) | ||||
|  | @ -43,60 +46,82 @@ namespace Kernel | |||
| 			return; | ||||
| 		} | ||||
| 
 | ||||
| 		if (!m_packets.empty() && m_packet_total_size > m_packet_buffer->size()) | ||||
| 		if (m_packet_total_size + payload.size() > m_packet_buffer->size()) | ||||
| 		{ | ||||
| 			dprintln("Packet buffer full, dropping packet"); | ||||
| 			return; | ||||
| 		} | ||||
| 
 | ||||
| 		void* buffer = reinterpret_cast<void*>(m_packet_buffer->vaddr() + m_packet_total_size); | ||||
| 		memcpy(buffer, packet.data(), packet.size()); | ||||
| 		memcpy(buffer, payload.data(), payload.size()); | ||||
| 
 | ||||
| 		m_packets.push(PacketInfo { | ||||
| 			.sender_addr = sender_addr, | ||||
| 			.sender_port = sender_port, | ||||
| 			.packet_size = packet.size() | ||||
| 		m_packets.emplace(PacketInfo { | ||||
| 			.sender = sender, | ||||
| 			.packet_size = payload.size() | ||||
| 		}); | ||||
| 		m_packet_total_size += packet.size(); | ||||
| 		m_packet_total_size += payload.size(); | ||||
| 
 | ||||
| 		m_packet_semaphore.unblock(); | ||||
| 	} | ||||
| 
 | ||||
| 	BAN::ErrorOr<size_t> UDPSocket::read_packet(BAN::ByteSpan buffer, sockaddr_in* sender_addr) | ||||
| 	BAN::ErrorOr<void> UDPSocket::bind_impl(const sockaddr* address, socklen_t address_len) | ||||
| 	{ | ||||
| 		while (m_packets.empty()) | ||||
| 			TRY(Thread::current().block_or_eintr_indefinite(m_packet_semaphore)); | ||||
| 		if (is_bound()) | ||||
| 			return BAN::Error::from_errno(EINVAL); | ||||
| 		return m_network_layer.bind_socket_to_address(this, address, address_len); | ||||
| 	} | ||||
| 
 | ||||
| 	BAN::ErrorOr<size_t> UDPSocket::recvfrom_impl(BAN::ByteSpan buffer, sockaddr* address, socklen_t* address_len) | ||||
| 	{ | ||||
| 		if (!is_bound()) | ||||
| 		{ | ||||
| 			dprintln("No interface bound"); | ||||
| 			return BAN::Error::from_errno(EINVAL); | ||||
| 		} | ||||
| 		ASSERT(m_port != PORT_NONE); | ||||
| 
 | ||||
| 		LockGuard _(m_packet_lock); | ||||
| 		if (m_packets.empty()) | ||||
| 			return read_packet(buffer, sender_addr); | ||||
| 
 | ||||
| 		while (m_packets.empty()) | ||||
| 		{ | ||||
| 			LockFreeGuard free(m_packet_lock); | ||||
| 			TRY(Thread::current().block_or_eintr_indefinite(m_packet_semaphore)); | ||||
| 		} | ||||
| 
 | ||||
| 		auto packet_info = m_packets.front(); | ||||
| 		m_packets.pop(); | ||||
| 
 | ||||
| 		size_t nread = BAN::Math::min<size_t>(packet_info.packet_size, buffer.size()); | ||||
| 
 | ||||
| 		uint8_t* packet_buffer = reinterpret_cast<uint8_t*>(m_packet_buffer->vaddr()); | ||||
| 		memcpy( | ||||
| 			buffer.data(), | ||||
| 			(const void*)m_packet_buffer->vaddr(), | ||||
| 			packet_buffer, | ||||
| 			nread | ||||
| 		); | ||||
| 		memmove( | ||||
| 			(void*)m_packet_buffer->vaddr(), | ||||
| 			(void*)(m_packet_buffer->vaddr() + packet_info.packet_size), | ||||
| 			packet_buffer, | ||||
| 			packet_buffer + packet_info.packet_size, | ||||
| 			m_packet_total_size - packet_info.packet_size | ||||
| 		); | ||||
| 
 | ||||
| 		m_packet_total_size -= packet_info.packet_size; | ||||
| 
 | ||||
| 		if (sender_addr) | ||||
| 		if (address && address_len) | ||||
| 		{ | ||||
| 			sender_addr->sin_family = AF_INET; | ||||
| 			sender_addr->sin_port = BAN::NetworkEndian(packet_info.sender_port); | ||||
| 			sender_addr->sin_addr.s_addr = packet_info.sender_addr.raw; | ||||
| 			if (*address_len > (socklen_t)sizeof(sockaddr_storage)) | ||||
| 				*address_len = sizeof(sockaddr_storage); | ||||
| 			memcpy(address, &packet_info.sender, *address_len); | ||||
| 		} | ||||
| 
 | ||||
| 		return nread; | ||||
| 	} | ||||
| 
 | ||||
| 	BAN::ErrorOr<size_t> UDPSocket::sendto_impl(BAN::ConstByteSpan message, const sockaddr* address, socklen_t address_len) | ||||
| 	{ | ||||
| 		if (!is_bound()) | ||||
| 			TRY(m_network_layer.bind_socket_to_unused(this, address, address_len)); | ||||
| 		return TRY(m_network_layer.sendto(*this, message, address, address_len)); | ||||
| 	} | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -248,29 +248,27 @@ namespace Kernel | |||
| 		return {}; | ||||
| 	} | ||||
| 
 | ||||
| 	BAN::ErrorOr<size_t> UnixDomainSocket::sendto_impl(const sys_sendto_t* arguments) | ||||
| 	BAN::ErrorOr<size_t> UnixDomainSocket::sendto_impl(BAN::ConstByteSpan message, const sockaddr* address, socklen_t address_len) | ||||
| 	{ | ||||
| 		if (arguments->flags) | ||||
| 			return BAN::Error::from_errno(ENOTSUP); | ||||
| 		if (arguments->length > s_packet_buffer_size) | ||||
| 		if (message.size() > s_packet_buffer_size) | ||||
| 			return BAN::Error::from_errno(ENOBUFS); | ||||
| 
 | ||||
| 		if (m_info.has<ConnectionInfo>()) | ||||
| 		{ | ||||
| 			auto& connection_info = m_info.get<ConnectionInfo>(); | ||||
| 			if (arguments->dest_addr) | ||||
| 			if (address) | ||||
| 				return BAN::Error::from_errno(EISCONN); | ||||
| 			auto target = connection_info.connection.lock(); | ||||
| 			if (!target) | ||||
| 				return BAN::Error::from_errno(ENOTCONN); | ||||
| 			TRY(target->add_packet({ reinterpret_cast<const uint8_t*>(arguments->message), arguments->length })); | ||||
| 			return arguments->length; | ||||
| 			TRY(target->add_packet(message)); | ||||
| 			return message.size(); | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			BAN::String canonical_path; | ||||
| 
 | ||||
| 			if (!arguments->dest_addr) | ||||
| 			if (!address) | ||||
| 			{ | ||||
| 				auto& connectionless_info = m_info.get<ConnectionlessInfo>(); | ||||
| 				if (connectionless_info.peer_address.empty()) | ||||
|  | @ -279,9 +277,9 @@ namespace Kernel | |||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				if (arguments->dest_len != sizeof(sockaddr_un)) | ||||
| 				if (address_len != sizeof(sockaddr_un)) | ||||
| 					return BAN::Error::from_errno(EINVAL); | ||||
| 				auto& sockaddr_un = *reinterpret_cast<const struct sockaddr_un*>(arguments->dest_addr); | ||||
| 				auto& sockaddr_un = *reinterpret_cast<const struct sockaddr_un*>(address); | ||||
| 				if (sockaddr_un.sun_family != AF_UNIX) | ||||
| 					return BAN::Error::from_errno(EAFNOSUPPORT); | ||||
| 
 | ||||
|  | @ -301,16 +299,13 @@ namespace Kernel | |||
| 			auto target = s_bound_sockets[canonical_path].lock(); | ||||
| 			if (!target) | ||||
| 				return BAN::Error::from_errno(EDESTADDRREQ); | ||||
| 			TRY(target->add_packet({ reinterpret_cast<const uint8_t*>(arguments->message), arguments->length })); | ||||
| 			return arguments->length; | ||||
| 			TRY(target->add_packet(message)); | ||||
| 			return message.size(); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	BAN::ErrorOr<size_t> UnixDomainSocket::recvfrom_impl(sys_recvfrom_t* arguments) | ||||
| 	BAN::ErrorOr<size_t> UnixDomainSocket::recvfrom_impl(BAN::ByteSpan buffer, sockaddr*, socklen_t*) | ||||
| 	{ | ||||
| 		if (arguments->flags) | ||||
| 			return BAN::Error::from_errno(ENOTSUP); | ||||
| 
 | ||||
| 		if (m_info.has<ConnectionInfo>()) | ||||
| 		{ | ||||
| 			auto& connection_info = m_info.get<ConnectionInfo>(); | ||||
|  | @ -328,14 +323,14 @@ namespace Kernel | |||
| 
 | ||||
| 		size_t nread = 0; | ||||
| 		if (is_streaming()) | ||||
| 			nread = BAN::Math::min(arguments->length, m_packet_size_total); | ||||
| 			nread = BAN::Math::min(buffer.size(), m_packet_size_total); | ||||
| 		else | ||||
| 		{ | ||||
| 			nread = BAN::Math::min(arguments->length, m_packet_sizes.front()); | ||||
| 			nread = BAN::Math::min(buffer.size(), m_packet_sizes.front()); | ||||
| 			m_packet_sizes.pop(); | ||||
| 		} | ||||
| 
 | ||||
| 		memcpy(arguments->buffer, packet_buffer, nread); | ||||
| 		memcpy(buffer.data(), packet_buffer, nread); | ||||
| 		memmove(packet_buffer, packet_buffer + nread, m_packet_size_total - nread); | ||||
| 		m_packet_size_total -= nread; | ||||
| 
 | ||||
|  |  | |||
|  | @ -983,7 +983,8 @@ namespace Kernel | |||
| 		if (!inode->mode().ifsock()) | ||||
| 			return BAN::Error::from_errno(ENOTSOCK); | ||||
| 
 | ||||
| 		return TRY(inode->sendto(arguments)); | ||||
| 		BAN::ConstByteSpan message { reinterpret_cast<const uint8_t*>(arguments->message), arguments->length }; | ||||
| 		return TRY(inode->sendto(message, arguments->dest_addr, arguments->dest_len)); | ||||
| 	} | ||||
| 
 | ||||
| 	BAN::ErrorOr<long> Process::sys_recvfrom(sys_recvfrom_t* arguments) | ||||
|  | @ -1006,7 +1007,8 @@ namespace Kernel | |||
| 		if (!inode->mode().ifsock()) | ||||
| 			return BAN::Error::from_errno(ENOTSOCK); | ||||
| 
 | ||||
| 		return TRY(inode->recvfrom(arguments)); | ||||
| 		BAN::ByteSpan buffer { reinterpret_cast<uint8_t*>(arguments->buffer), arguments->length }; | ||||
| 		return TRY(inode->recvfrom(buffer, arguments->address, arguments->address_len)); | ||||
| 	} | ||||
| 
 | ||||
| 	BAN::ErrorOr<long> Process::sys_ioctl(int fildes, int request, void* arg) | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue