This repository has been archived by the owner on Sep 11, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 27
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Kernel: Basic userspace socket functionality
Can only receive UDP packets so far. Much work remains to be done
- Loading branch information
Showing
32 changed files
with
807 additions
and
18 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
/* SPDX-License-Identifier: GPL-3.0-or-later */ | ||
/* Copyright © 2016-2024 Byteduck */ | ||
|
||
#pragma once | ||
|
||
#include "socket.h" | ||
|
||
__DECL_BEGIN | ||
|
||
typedef uint16_t in_port_t; | ||
typedef uint32_t in_addr_t; | ||
|
||
struct in_addr { | ||
in_addr_t s_addr; | ||
}; | ||
|
||
struct sockaddr_in { | ||
sa_family_t sin_family; | ||
in_port_t sin_port; | ||
struct in_addr sin_addr; | ||
}; | ||
|
||
# define INADDR_ANY ((uint32_t) 0x00000000) | ||
# define INADDR_NONE 0xffffffff | ||
# define INPORT_ANY 0 | ||
#define IPPROTO_TCP 0 | ||
#define IPPROTO_UDP 0 | ||
|
||
__DECL_END |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
/* SPDX-License-Identifier: GPL-3.0-or-later */ | ||
/* Copyright © 2016-2024 Byteduck */ | ||
|
||
#pragma once | ||
|
||
#include "cdefs.h" | ||
#include "types.h" | ||
#include "un.h" | ||
|
||
__DECL_BEGIN | ||
|
||
// Domains | ||
#define AF_UNSPEC 0 | ||
#define AF_UNIX 1 | ||
#define AF_LOCAL 2 | ||
#define AF_INET 3 | ||
#define AF_PACKET 4 | ||
|
||
// Types | ||
#define SOCK_STREAM 1 | ||
#define SOCK_DGRAM 2 | ||
#define SOCK_RAW 3 | ||
|
||
typedef uint16_t sa_family_t; | ||
typedef uint32_t socklen_t; | ||
|
||
struct sockaddr { | ||
sa_family_t sa_family; | ||
char sa_data[14]; | ||
}; | ||
|
||
struct iovec { | ||
void* iov_base; | ||
size_t iov_len; | ||
}; | ||
|
||
struct msghdr { | ||
void* msg_name; | ||
socklen_t msg_namelen; | ||
struct iovec* msg_iov; | ||
size_t msg_iovlen; | ||
void* msg_control; | ||
size_t msg_controllen; | ||
int msg_flags; | ||
}; | ||
|
||
struct sockaddr_storage { | ||
sa_family_t ss_family; | ||
struct sockaddr_un __un; | ||
}; | ||
|
||
__DECL_END |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
/* SPDX-License-Identifier: GPL-3.0-or-later */ | ||
/* Copyright © 2016-2024 Byteduck */ | ||
|
||
#pragma once | ||
|
||
#include "endian.h" | ||
|
||
struct UDPPacket { | ||
BigEndian<uint16_t> source_port; | ||
BigEndian<uint16_t> dest_port; | ||
BigEndian<uint16_t> len; | ||
BigEndian<uint16_t> checksum = 0; | ||
uint8_t payload[]; | ||
} __attribute__((packed)); | ||
|
||
static_assert(sizeof(UDPPacket) == 8); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
/* SPDX-License-Identifier: GPL-3.0-or-later */ | ||
/* Copyright © 2016-2024 Byteduck */ | ||
|
||
#pragma once | ||
|
||
#include "types.h" | ||
|
||
__DECL_BEGIN | ||
|
||
#define UNIX_PATH_MAX 100 | ||
|
||
struct sockaddr_un { | ||
uint16_t sun_family; | ||
char sun_path[UNIX_PATH_MAX]; | ||
}; | ||
|
||
__DECL_END |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
/* SPDX-License-Identifier: GPL-3.0-or-later */ | ||
/* Copyright © 2016-2024 Byteduck */ | ||
|
||
#pragma once | ||
|
||
#include "types.h" | ||
#include "Optional.h" | ||
|
||
namespace kstd { | ||
|
||
template<typename T, size_t max_count> | ||
class ListQueue { | ||
public: | ||
ListQueue() = default; | ||
|
||
bool enqueue(const T& val) { | ||
if (m_count >= max_count) | ||
return false; | ||
|
||
if (m_tail == nullptr) { | ||
m_head = new Entry {nullptr, val}; | ||
m_head = m_tail; | ||
} else { | ||
m_tail->next = new Entry {nullptr, val}; | ||
m_tail = m_tail->next; | ||
} | ||
|
||
m_count++; | ||
|
||
return true; | ||
} | ||
|
||
Optional<T> dequeue() { | ||
if (!m_head) | ||
return nullopt; | ||
|
||
m_count--; | ||
auto* ent = m_head; | ||
m_head = ent->next; | ||
if (m_tail == ent) | ||
m_tail = nullptr; | ||
return ent->val; | ||
} | ||
|
||
Optional<T> peek() { | ||
if (!m_head) | ||
return nullopt; | ||
return m_head->val; | ||
} | ||
|
||
[[nodiscard]] bool empty() const { | ||
return m_count == 0; | ||
} | ||
|
||
[[nodiscard]] size_t count() const { | ||
return count; | ||
} | ||
|
||
private: | ||
struct Entry { | ||
Entry* next; | ||
T val; | ||
}; | ||
|
||
Entry* m_head = nullptr; | ||
Entry* m_tail = nullptr; | ||
size_t m_count = 0; | ||
}; | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
/* SPDX-License-Identifier: GPL-3.0-or-later */ | ||
/* Copyright © 2016-2024 Byteduck */ | ||
|
||
#include "IPSocket.h" | ||
#include "UDPSocket.h" | ||
#include "../api/in.h" | ||
#include "../kstd/KLog.h" | ||
#include "../tasking/PollBlocker.h" | ||
#include "../filesystem/FileDescriptor.h" | ||
|
||
IPSocket::IPSocket(Socket::Type type, int protocol): Socket(Domain::Inet, type, protocol) { | ||
|
||
} | ||
|
||
ResultRet<kstd::Arc<IPSocket>> IPSocket::make(Socket::Type type, int protocol) { | ||
switch (type) { | ||
case Type::Dgram: | ||
return kstd::static_pointer_cast<IPSocket>(TRY(UDPSocket::make())); | ||
default: | ||
return Result(EINVAL); | ||
} | ||
} | ||
|
||
Result IPSocket::bind(SafePointer<sockaddr> addr_ptr, socklen_t addrlen) { | ||
if (m_bound || addrlen != sizeof(sockaddr_in)) | ||
return Result(set_error(EINVAL)); | ||
|
||
auto addr = addr_ptr.as<sockaddr_in>().get(); | ||
if (addr.sin_family != AF_INET) | ||
return Result(set_error(EINVAL)); | ||
|
||
m_port = from_big_endian(addr.sin_port); | ||
m_addr = IPv4Address(from_big_endian(addr.sin_addr.s_addr)); | ||
|
||
return do_bind(); | ||
} | ||
|
||
ssize_t IPSocket::recvfrom(FileDescriptor& fd, SafePointer<uint8_t> buf, size_t len, int flags, SafePointer<sockaddr> src_addr, SafePointer<socklen_t> addrlen) { | ||
m_receive_queue_lock.acquire(); | ||
|
||
// Block until we have a packet to read | ||
while (m_receive_queue.empty()) { | ||
if (fd.nonblock()) { | ||
m_receive_queue_lock.release(); | ||
return -EAGAIN; | ||
} | ||
|
||
update_blocker(); | ||
m_receive_queue_lock.release(); | ||
TaskManager::current_thread()->block(m_receive_blocker); | ||
m_receive_queue_lock.acquire(); | ||
} | ||
|
||
// Read our packet | ||
auto* packet = m_receive_queue.pop_front(); | ||
update_blocker(); | ||
m_receive_queue_lock.release(); | ||
auto res = do_recv(packet, buf, len); | ||
kfree(packet); | ||
return res; | ||
} | ||
|
||
Result IPSocket::recv_packet(const void* buf, size_t len) { | ||
LOCK(m_receive_queue_lock); | ||
|
||
if (m_receive_queue.size() == m_receive_queue.capacity()) { | ||
KLog::warn("IPSocket", "Dropping packet because receive queue is full"); | ||
return Result(ENOSPC); | ||
} | ||
|
||
auto* src_pkt = (const IPv4Packet*) buf; | ||
auto* new_pkt = (IPv4Packet*) kmalloc(len); | ||
memcpy(new_pkt, src_pkt, len); | ||
|
||
m_receive_queue.push_back(new_pkt); | ||
update_blocker(); | ||
|
||
return Result(SUCCESS); | ||
} | ||
|
||
bool IPSocket::can_read(const FileDescriptor& fd) { | ||
return !m_receive_queue.empty(); | ||
} | ||
|
||
void IPSocket::update_blocker() { | ||
m_receive_blocker.set_ready(!m_receive_queue.empty()); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
/* SPDX-License-Identifier: GPL-3.0-or-later */ | ||
/* Copyright © 2016-2024 Byteduck */ | ||
|
||
#pragma once | ||
|
||
#include "Socket.h" | ||
#include "../api/ipv4.h" | ||
#include "../kstd/ListQueue.h" | ||
|
||
class IPSocket: public Socket { | ||
public: | ||
static ResultRet<kstd::Arc<IPSocket>> make(Socket::Type type, int protocol); | ||
|
||
// Socket | ||
Result bind(SafePointer<sockaddr> addr, socklen_t addrlen) override; | ||
ssize_t recvfrom(FileDescriptor &fd, SafePointer<uint8_t> buf, size_t len, int flags, SafePointer<sockaddr> src_addr, SafePointer<socklen_t> addrlen) override; | ||
Result recv_packet(const void* buf, size_t len) override; | ||
|
||
// File | ||
bool can_read(const FileDescriptor &fd) override; | ||
|
||
protected: | ||
IPSocket(Socket::Type type, int protocol); | ||
|
||
virtual ssize_t do_recv(const IPv4Packet* pkt, SafePointer<uint8_t> buf, size_t len) = 0; | ||
virtual Result do_bind() = 0; | ||
|
||
void update_blocker(); | ||
|
||
bool m_bound = false; | ||
uint16_t m_port; | ||
IPv4Address m_addr; | ||
kstd::circular_queue<IPv4Packet*> m_receive_queue { 16 }; | ||
Mutex m_receive_queue_lock { "IPSocket::receive_queue" }; | ||
BooleanBlocker m_receive_blocker; | ||
}; |
Oops, something went wrong.