Files
ladybird/Kernel/Net/IPv4Socket.h
Andreas Kling 6347e3aa51 Net: Let Socket have read/write wrappers around sendto/recvfrom
The situations in IPv4Socket and LocalSocket were mirrors of each other
where one had implemented read/write as wrappers and the other had
sendto/recvfrom as wrappers.

Instead of this silliness, move read and write up to the Socket base.
Then mark them final, so subclasses have no choice but to implement
sendto and recvfrom.
2019-08-05 10:03:19 +02:00

103 lines
3.4 KiB
C++

#pragma once
#include <AK/HashMap.h>
#include <AK/SinglyLinkedList.h>
#include <Kernel/KBuffer.h>
#include <Kernel/DoubleBuffer.h>
#include <Kernel/Lock.h>
#include <Kernel/Net/IPv4.h>
#include <Kernel/Net/Socket.h>
class IPv4SocketHandle;
class TCPSocketHandle;
class NetworkAdapter;
class TCPPacket;
class TCPSocket;
class IPv4Socket : public Socket {
public:
static NonnullRefPtr<IPv4Socket> create(int type, int protocol);
virtual ~IPv4Socket() override;
static Lockable<HashTable<IPv4Socket*>>& all_sockets();
virtual KResult bind(const sockaddr*, socklen_t) override;
virtual KResult connect(FileDescription&, const sockaddr*, socklen_t, ShouldBlock = ShouldBlock::Yes) override;
virtual bool get_local_address(sockaddr*, socklen_t*) override;
virtual bool get_peer_address(sockaddr*, socklen_t*) override;
virtual void attach(FileDescription&) override;
virtual void detach(FileDescription&) override;
virtual bool can_read(FileDescription&) const override;
virtual bool can_write(FileDescription&) const override;
virtual ssize_t sendto(FileDescription&, const void*, size_t, int, const sockaddr*, socklen_t) override;
virtual ssize_t recvfrom(FileDescription&, void*, size_t, int flags, sockaddr*, socklen_t*) override;
void did_receive(const IPv4Address& peer_address, u16 peer_port, NonnullRefPtr<KBuffer>&&);
const IPv4Address& local_address() const;
u16 local_port() const { return m_local_port; }
void set_local_port(u16 port) { m_local_port = port; }
const IPv4Address& peer_address() const { return m_peer_address; }
u16 peer_port() const { return m_peer_port; }
void set_peer_port(u16 port) { m_peer_port = port; }
protected:
IPv4Socket(int type, int protocol);
virtual const char* class_name() const override { return "IPv4Socket"; }
int allocate_local_port_if_needed();
virtual KResult protocol_bind() { return KSuccess; }
virtual int protocol_receive(const KBuffer&, void*, size_t, int) { return -ENOTIMPL; }
virtual int protocol_send(const void*, int) { return -ENOTIMPL; }
virtual KResult protocol_connect(FileDescription&, ShouldBlock) { return KSuccess; }
virtual int protocol_allocate_local_port() { return 0; }
virtual bool protocol_is_disconnected() const { return false; }
private:
virtual bool is_ipv4() const override { return true; }
IPv4Address m_local_address;
IPv4Address m_peer_address;
struct ReceivedPacket {
IPv4Address peer_address;
u16 peer_port;
RefPtr<KBuffer> data;
};
SinglyLinkedList<ReceivedPacket> m_receive_queue;
u16 m_local_port { 0 };
u16 m_peer_port { 0 };
u32 m_bytes_received { 0 };
bool m_can_read { false };
};
class IPv4SocketHandle : public SocketHandle {
public:
IPv4SocketHandle() {}
IPv4SocketHandle(RefPtr<IPv4Socket>&& socket)
: SocketHandle(move(socket))
{
}
IPv4SocketHandle(IPv4SocketHandle&& other)
: SocketHandle(move(other))
{
}
IPv4SocketHandle(const IPv4SocketHandle&) = delete;
IPv4SocketHandle& operator=(const IPv4SocketHandle&) = delete;
IPv4Socket* operator->() { return &socket(); }
const IPv4Socket* operator->() const { return &socket(); }
IPv4Socket& socket() { return static_cast<IPv4Socket&>(SocketHandle::socket()); }
const IPv4Socket& socket() const { return static_cast<const IPv4Socket&>(SocketHandle::socket()); }
};