diff --git a/AK/Traits.h b/AK/Traits.h index de6a8671aaa..7c88a2e7cb5 100644 --- a/AK/Traits.h +++ b/AK/Traits.h @@ -22,6 +22,12 @@ struct Traits { static void dump(unsigned u) { kprintf("%u", u); } }; +template<> +struct Traits { + static unsigned hash(unsigned u) { return int_hash(u); } + static void dump(unsigned u) { kprintf("%u", u); } +}; + template struct Traits { static unsigned hash(const T* p) diff --git a/Kernel/IPv4Socket.cpp b/Kernel/IPv4Socket.cpp index 601f2004149..8e46bc334c6 100644 --- a/Kernel/IPv4Socket.cpp +++ b/Kernel/IPv4Socket.cpp @@ -10,6 +10,22 @@ #define IPV4_SOCKET_DEBUG +Lockable>& IPv4Socket::sockets_by_udp_port() +{ + static Lockable>* s_map; + if (!s_map) + s_map = new Lockable>; + return *s_map; +} + +Lockable>& IPv4Socket::sockets_by_tcp_port() +{ + static Lockable>* s_map; + if (!s_map) + s_map = new Lockable>; + return *s_map; +} + Lockable>& IPv4Socket::all_sockets() { static Lockable>* s_table; @@ -100,6 +116,25 @@ bool IPv4Socket::can_write(SocketRole role) const ASSERT_NOT_REACHED(); } +void IPv4Socket::allocate_source_port_if_needed() +{ + if (m_source_port) + return; + if (type() == SOCK_DGRAM) { + // This is not a very efficient allocation algorithm. + // FIXME: Replace it with a bitmap or some other fast-paced looker-upper. + LOCKER(sockets_by_udp_port().lock()); + for (word port = 2000; port < 60000; ++port) { + auto it = sockets_by_udp_port().resource().find(port); + if (it == sockets_by_udp_port().resource().end()) { + m_source_port = port; + return; + } + } + ASSERT_NOT_REACHED(); + } +} + ssize_t IPv4Socket::sendto(const void* data, size_t data_length, int flags, const sockaddr* addr, socklen_t addr_length) { (void)flags; @@ -121,7 +156,7 @@ ssize_t IPv4Socket::sendto(const void* data, size_t data_length, int flags, cons m_destination_address = IPv4Address((const byte*)&ia.sin_addr.s_addr); m_destination_port = ntohs(ia.sin_port); - m_source_port = 2413; + allocate_source_port_if_needed(); kprintf("sendto: destination=%s:%u\n", m_destination_address.to_string().characters(), m_destination_port); diff --git a/Kernel/IPv4Socket.h b/Kernel/IPv4Socket.h index b9b9c68e847..0e15497330d 100644 --- a/Kernel/IPv4Socket.h +++ b/Kernel/IPv4Socket.h @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -12,6 +13,8 @@ public: virtual ~IPv4Socket() override; static Lockable>& all_sockets(); + static Lockable>& sockets_by_udp_port(); + static Lockable>& sockets_by_tcp_port(); virtual KResult bind(const sockaddr*, socklen_t) override; virtual KResult connect(const sockaddr*, socklen_t) override; @@ -36,6 +39,8 @@ private: IPv4Socket(int type, int protocol); virtual bool is_ipv4() const override { return true; } + void allocate_source_port_if_needed(); + bool m_bound { false }; int m_attached_fds { 0 }; IPv4Address m_destination_address;