mirror of
https://github.com/RGBCube/serenity
synced 2025-07-24 21:07:34 +00:00
IPv4: Save the source address/port together with incoming packet payloads.
We need the address/port to fill in the out-params in recvfrom(). It should now be more or less possible to create a UDP server. :^)
This commit is contained in:
parent
c4bb9a3ccb
commit
780d2a08c4
6 changed files with 29 additions and 21 deletions
|
@ -178,11 +178,16 @@ ssize_t IPv4Socket::recvfrom(FileDescriptor& descriptor, void* buffer, size_t bu
|
||||||
kprintf("recvfrom: type=%d, source_port=%u\n", type(), source_port());
|
kprintf("recvfrom: type=%d, source_port=%u\n", type(), source_port());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
IPv4Address peer_address;
|
||||||
|
word peer_port = 0;
|
||||||
ByteBuffer packet_buffer;
|
ByteBuffer packet_buffer;
|
||||||
{
|
{
|
||||||
LOCKER(lock());
|
LOCKER(lock());
|
||||||
if (!m_receive_queue.is_empty()) {
|
if (!m_receive_queue.is_empty()) {
|
||||||
packet_buffer = m_receive_queue.take_first();
|
auto packet = m_receive_queue.take_first();
|
||||||
|
packet_buffer = packet.data;
|
||||||
|
peer_address = packet.source_address;
|
||||||
|
peer_port = packet.source_port;
|
||||||
m_can_read = !m_receive_queue.is_empty();
|
m_can_read = !m_receive_queue.is_empty();
|
||||||
#ifdef IPV4_SOCKET_DEBUG
|
#ifdef IPV4_SOCKET_DEBUG
|
||||||
kprintf("IPv4Socket(%p): recvfrom without blocking %d bytes, packets in queue: %d\n", this, packet_buffer.size(), m_receive_queue.size_slow());
|
kprintf("IPv4Socket(%p): recvfrom without blocking %d bytes, packets in queue: %d\n", this, packet_buffer.size(), m_receive_queue.size_slow());
|
||||||
|
@ -205,7 +210,10 @@ ssize_t IPv4Socket::recvfrom(FileDescriptor& descriptor, void* buffer, size_t bu
|
||||||
}
|
}
|
||||||
ASSERT(m_can_read);
|
ASSERT(m_can_read);
|
||||||
ASSERT(!m_receive_queue.is_empty());
|
ASSERT(!m_receive_queue.is_empty());
|
||||||
packet_buffer = m_receive_queue.take_first();
|
auto packet = m_receive_queue.take_first();
|
||||||
|
packet_buffer = packet.data;
|
||||||
|
peer_address = packet.source_address;
|
||||||
|
peer_port = packet.source_port;
|
||||||
m_can_read = !m_receive_queue.is_empty();
|
m_can_read = !m_receive_queue.is_empty();
|
||||||
#ifdef IPV4_SOCKET_DEBUG
|
#ifdef IPV4_SOCKET_DEBUG
|
||||||
kprintf("IPv4Socket(%p): recvfrom with blocking %d bytes, packets in queue: %d\n", this, packet_buffer.size(), m_receive_queue.size_slow());
|
kprintf("IPv4Socket(%p): recvfrom with blocking %d bytes, packets in queue: %d\n", this, packet_buffer.size(), m_receive_queue.size_slow());
|
||||||
|
@ -215,8 +223,10 @@ ssize_t IPv4Socket::recvfrom(FileDescriptor& descriptor, void* buffer, size_t bu
|
||||||
auto& ipv4_packet = *(const IPv4Packet*)(packet_buffer.pointer());
|
auto& ipv4_packet = *(const IPv4Packet*)(packet_buffer.pointer());
|
||||||
|
|
||||||
if (addr) {
|
if (addr) {
|
||||||
|
dbgprintf("Incoming packet is from: %s:%u\n", peer_address.to_string().characters(), peer_port);
|
||||||
auto& ia = *(sockaddr_in*)addr;
|
auto& ia = *(sockaddr_in*)addr;
|
||||||
memcpy(&ia.sin_addr, &m_destination_address, sizeof(IPv4Address));
|
memcpy(&ia.sin_addr, &peer_address, sizeof(IPv4Address));
|
||||||
|
ia.sin_port = htons(peer_port);
|
||||||
ia.sin_family = AF_INET;
|
ia.sin_family = AF_INET;
|
||||||
ASSERT(addr_length);
|
ASSERT(addr_length);
|
||||||
*addr_length = sizeof(sockaddr_in);
|
*addr_length = sizeof(sockaddr_in);
|
||||||
|
@ -231,11 +241,11 @@ ssize_t IPv4Socket::recvfrom(FileDescriptor& descriptor, void* buffer, size_t bu
|
||||||
return protocol_receive(packet_buffer, buffer, buffer_length, flags, addr, addr_length);
|
return protocol_receive(packet_buffer, buffer, buffer_length, flags, addr, addr_length);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IPv4Socket::did_receive(ByteBuffer&& packet)
|
void IPv4Socket::did_receive(const IPv4Address& source_address, word source_port, ByteBuffer&& packet)
|
||||||
{
|
{
|
||||||
LOCKER(lock());
|
LOCKER(lock());
|
||||||
auto packet_size = packet.size();
|
auto packet_size = packet.size();
|
||||||
m_receive_queue.append(move(packet));
|
m_receive_queue.append({ source_address, source_port, move(packet) });
|
||||||
m_can_read = true;
|
m_can_read = true;
|
||||||
m_bytes_received += packet_size;
|
m_bytes_received += packet_size;
|
||||||
#ifdef IPV4_SOCKET_DEBUG
|
#ifdef IPV4_SOCKET_DEBUG
|
||||||
|
|
|
@ -32,7 +32,7 @@ public:
|
||||||
virtual ssize_t sendto(FileDescriptor&, const void*, size_t, int, const sockaddr*, socklen_t) override;
|
virtual ssize_t sendto(FileDescriptor&, const void*, size_t, int, const sockaddr*, socklen_t) override;
|
||||||
virtual ssize_t recvfrom(FileDescriptor&, void*, size_t, int flags, sockaddr*, socklen_t*) override;
|
virtual ssize_t recvfrom(FileDescriptor&, void*, size_t, int flags, sockaddr*, socklen_t*) override;
|
||||||
|
|
||||||
void did_receive(ByteBuffer&&);
|
void did_receive(const IPv4Address& source_address, word source_port, ByteBuffer&&);
|
||||||
|
|
||||||
const IPv4Address& source_address() const;
|
const IPv4Address& source_address() const;
|
||||||
word source_port() const { return m_source_port; }
|
word source_port() const { return m_source_port; }
|
||||||
|
@ -67,7 +67,13 @@ private:
|
||||||
DoubleBuffer m_for_client;
|
DoubleBuffer m_for_client;
|
||||||
DoubleBuffer m_for_server;
|
DoubleBuffer m_for_server;
|
||||||
|
|
||||||
SinglyLinkedList<ByteBuffer> m_receive_queue;
|
struct ReceivedPacket {
|
||||||
|
IPv4Address source_address;
|
||||||
|
word source_port;
|
||||||
|
ByteBuffer data;
|
||||||
|
};
|
||||||
|
|
||||||
|
SinglyLinkedList<ReceivedPacket> m_receive_queue;
|
||||||
|
|
||||||
word m_source_port { 0 };
|
word m_source_port { 0 };
|
||||||
word m_destination_port { 0 };
|
word m_destination_port { 0 };
|
||||||
|
|
|
@ -218,7 +218,7 @@ void handle_icmp(const EthernetFrameHeader& eth, int frame_size)
|
||||||
LOCKER(socket->lock());
|
LOCKER(socket->lock());
|
||||||
if (socket->protocol() != (unsigned)IPv4Protocol::ICMP)
|
if (socket->protocol() != (unsigned)IPv4Protocol::ICMP)
|
||||||
continue;
|
continue;
|
||||||
socket->did_receive(ByteBuffer::copy(&ipv4_packet, sizeof(IPv4Packet) + ipv4_packet.payload_size()));
|
socket->did_receive(ipv4_packet.source(), 0, ByteBuffer::copy(&ipv4_packet, sizeof(IPv4Packet) + ipv4_packet.payload_size()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -277,7 +277,7 @@ void handle_udp(const EthernetFrameHeader& eth, int frame_size)
|
||||||
|
|
||||||
ASSERT(socket->type() == SOCK_DGRAM);
|
ASSERT(socket->type() == SOCK_DGRAM);
|
||||||
ASSERT(socket->source_port() == udp_packet.destination_port());
|
ASSERT(socket->source_port() == udp_packet.destination_port());
|
||||||
socket->did_receive(ByteBuffer::copy(&ipv4_packet, sizeof(IPv4Packet) + ipv4_packet.payload_size()));
|
socket->did_receive(ipv4_packet.source(), udp_packet.source_port(), ByteBuffer::copy(&ipv4_packet, sizeof(IPv4Packet) + ipv4_packet.payload_size()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void handle_tcp(const EthernetFrameHeader& eth, int frame_size)
|
void handle_tcp(const EthernetFrameHeader& eth, int frame_size)
|
||||||
|
@ -337,7 +337,7 @@ void handle_tcp(const EthernetFrameHeader& eth, int frame_size)
|
||||||
kprintf("handle_tcp: Got FIN, payload_size=%u\n", payload_size);
|
kprintf("handle_tcp: Got FIN, payload_size=%u\n", payload_size);
|
||||||
|
|
||||||
if (payload_size != 0)
|
if (payload_size != 0)
|
||||||
socket->did_receive(ByteBuffer::copy(&ipv4_packet, sizeof(IPv4Packet) + ipv4_packet.payload_size()));
|
socket->did_receive(ipv4_packet.source(), tcp_packet.source_port(), ByteBuffer::copy(&ipv4_packet, sizeof(IPv4Packet) + ipv4_packet.payload_size()));
|
||||||
|
|
||||||
socket->set_ack_number(tcp_packet.sequence_number() + payload_size + 1);
|
socket->set_ack_number(tcp_packet.sequence_number() + payload_size + 1);
|
||||||
socket->send_tcp_packet(TCPFlags::FIN | TCPFlags::ACK);
|
socket->send_tcp_packet(TCPFlags::FIN | TCPFlags::ACK);
|
||||||
|
@ -357,5 +357,5 @@ void handle_tcp(const EthernetFrameHeader& eth, int frame_size)
|
||||||
socket->send_tcp_packet(TCPFlags::ACK);
|
socket->send_tcp_packet(TCPFlags::ACK);
|
||||||
|
|
||||||
if (payload_size != 0)
|
if (payload_size != 0)
|
||||||
socket->did_receive(ByteBuffer::copy(&ipv4_packet, sizeof(IPv4Packet) + ipv4_packet.payload_size()));
|
socket->did_receive(ipv4_packet.source(), tcp_packet.source_port(), ByteBuffer::copy(&ipv4_packet, sizeof(IPv4Packet) + ipv4_packet.payload_size()));
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,10 +54,6 @@ int TCPSocket::protocol_receive(const ByteBuffer& packet_buffer, void* buffer, s
|
||||||
size_t payload_size = packet_buffer.size() - sizeof(IPv4Packet) - tcp_packet.header_size();
|
size_t payload_size = packet_buffer.size() - sizeof(IPv4Packet) - tcp_packet.header_size();
|
||||||
kprintf("payload_size %u, will it fit in %u?\n", payload_size, buffer_size);
|
kprintf("payload_size %u, will it fit in %u?\n", payload_size, buffer_size);
|
||||||
ASSERT(buffer_size >= payload_size);
|
ASSERT(buffer_size >= payload_size);
|
||||||
if (addr) {
|
|
||||||
auto& ia = *(sockaddr_in*)addr;
|
|
||||||
ia.sin_port = htons(tcp_packet.destination_port());
|
|
||||||
}
|
|
||||||
memcpy(buffer, tcp_packet.payload(), payload_size);
|
memcpy(buffer, tcp_packet.payload(), payload_size);
|
||||||
return payload_size;
|
return payload_size;
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,10 +53,6 @@ int UDPSocket::protocol_receive(const ByteBuffer& packet_buffer, void* buffer, s
|
||||||
auto& udp_packet = *static_cast<const UDPPacket*>(ipv4_packet.payload());
|
auto& udp_packet = *static_cast<const UDPPacket*>(ipv4_packet.payload());
|
||||||
ASSERT(udp_packet.length() >= sizeof(UDPPacket)); // FIXME: This should be rejected earlier.
|
ASSERT(udp_packet.length() >= sizeof(UDPPacket)); // FIXME: This should be rejected earlier.
|
||||||
ASSERT(buffer_size >= (udp_packet.length() - sizeof(UDPPacket)));
|
ASSERT(buffer_size >= (udp_packet.length() - sizeof(UDPPacket)));
|
||||||
if (addr) {
|
|
||||||
auto& ia = *(sockaddr_in*)addr;
|
|
||||||
ia.sin_port = htons(udp_packet.destination_port());
|
|
||||||
}
|
|
||||||
memcpy(buffer, udp_packet.payload(), udp_packet.length() - sizeof(UDPPacket));
|
memcpy(buffer, udp_packet.payload(), udp_packet.length() - sizeof(UDPPacket));
|
||||||
return udp_packet.length() - sizeof(UDPPacket);
|
return udp_packet.length() - sizeof(UDPPacket);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2105,9 +2105,9 @@ ssize_t Process::sys$recvfrom(const Syscall::SC_recvfrom_params* params)
|
||||||
if (!validate_write(buffer, buffer_length))
|
if (!validate_write(buffer, buffer_length))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
if (addr_length) {
|
if (addr_length) {
|
||||||
if (!validate_read_typed(addr_length))
|
if (!validate_write_typed(addr_length))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
if (!validate_read(addr, *addr_length))
|
if (!validate_write(addr, *addr_length))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
} else if (addr) {
|
} else if (addr) {
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue