Compare commits

..

No commits in common. "684fa1c4b01366b44cf15835237ef176e3722148" and "f022a1b08ffd73982eb24042c318f98b3cb982fb" have entirely different histories.

145 changed files with 952 additions and 3863 deletions

View File

@ -9,10 +9,6 @@ namespace BAN
struct IPv4Address struct IPv4Address
{ {
constexpr IPv4Address()
: IPv4Address(0)
{ }
constexpr IPv4Address(uint32_t u32_address) constexpr IPv4Address(uint32_t u32_address)
{ {
raw = u32_address; raw = u32_address;

View File

@ -6,19 +6,6 @@
#include <float.h> #include <float.h>
// This is ugly but my clangd does not like including
// intrinsic headers at all
#if !defined(__SSE__) || !defined(__SSE2__)
#pragma GCC push_options
#ifndef __SSE__
#pragma GCC target("sse")
#endif
#ifndef __SSE2__
#pragma GCC target("sse2")
#endif
#define BAN_MATH_POP_OPTIONS
#endif
namespace BAN::Math namespace BAN::Math
{ {
@ -180,7 +167,7 @@ namespace BAN::Math
template<floating_point T> template<floating_point T>
static T modf(T x, T* iptr) static T modf(T x, T* iptr)
{ {
const T frac = BAN::Math::fmod<T>(x, (T)1.0); const T frac = BAN::Math::fmod<T>(x, 1);
*iptr = x - frac; *iptr = x - frac;
return frac; return frac;
} }
@ -188,15 +175,15 @@ namespace BAN::Math
template<floating_point T> template<floating_point T>
inline constexpr T frexp(T num, int* exp) inline constexpr T frexp(T num, int* exp)
{ {
if (num == (T)0.0) if (num == 0.0)
{ {
*exp = 0; *exp = 0;
return (T)0.0; return 0.0;
} }
T e; T _exp;
asm("fxtract" : "+t"(num), "=u"(e)); asm("fxtract" : "+t"(num), "=u"(_exp));
*exp = (int)e + 1; *exp = (int)_exp + 1;
return num / (T)2.0; return num / (T)2.0;
} }
@ -264,7 +251,6 @@ namespace BAN::Math
"fstp %%st(1);" "fstp %%st(1);"
: "+t"(x) : "+t"(x)
); );
return x; return x;
} }
@ -277,9 +263,18 @@ namespace BAN::Math
template<floating_point T> template<floating_point T>
inline constexpr T pow(T x, T y) inline constexpr T pow(T x, T y)
{ {
if (x == (T)0.0) asm(
return (T)0.0; "fyl2x;"
return exp2<T>(y * log2<T>(x)); "fld1;"
"fld %%st(1);"
"fprem;"
"f2xm1;"
"faddp;"
"fscale;"
: "+t"(x), "+u"(y)
);
return x;
} }
template<floating_point T> template<floating_point T>
@ -314,28 +309,17 @@ namespace BAN::Math
template<floating_point T> template<floating_point T>
inline constexpr T sqrt(T x) inline constexpr T sqrt(T x)
{
if constexpr(BAN::is_same_v<T, float>)
{
using v4sf = float __attribute__((vector_size(16)));
return __builtin_ia32_sqrtss((v4sf) { x, 0.0f, 0.0f, 0.0f })[0];
}
else if constexpr(BAN::is_same_v<T, double>)
{
using v2df = double __attribute__((vector_size(16)));
return __builtin_ia32_sqrtsd((v2df) { x, 0.0 })[0];
}
else if constexpr(BAN::is_same_v<T, long double>)
{ {
asm("fsqrt" : "+t"(x)); asm("fsqrt" : "+t"(x));
return x; return x;
} }
}
template<floating_point T> template<floating_point T>
inline constexpr T cbrt(T value) inline constexpr T cbrt(T value)
{ {
return pow<T>(value, (T)1.0 / (T)3.0); if (value == 0.0)
return 0.0;
return pow<T>(value, 1.0 / 3.0);
} }
template<floating_point T> template<floating_point T>
@ -362,21 +346,30 @@ namespace BAN::Math
inline constexpr T tan(T x) inline constexpr T tan(T x)
{ {
T one, ret; T one, ret;
asm("fptan" : "=t"(one), "=u"(ret) : "0"(x)); asm(
"fptan"
: "=t"(one), "=u"(ret)
: "0"(x)
);
return ret; return ret;
} }
template<floating_point T> template<floating_point T>
inline constexpr T atan2(T y, T x) inline constexpr T atan2(T y, T x)
{ {
asm("fpatan" : "+t"(x) : "u"(y) : "st(1)"); asm(
"fpatan"
: "+t"(x)
: "u"(y)
: "st(1)"
);
return x; return x;
} }
template<floating_point T> template<floating_point T>
inline constexpr T atan(T x) inline constexpr T atan(T x)
{ {
return atan2<T>(x, (T)1.0); return atan2<T>(x, 1.0);
} }
template<floating_point T> template<floating_point T>
@ -385,10 +378,10 @@ namespace BAN::Math
if (x == (T)0.0) if (x == (T)0.0)
return (T)0.0; return (T)0.0;
if (x == (T)1.0) if (x == (T)1.0)
return +numbers::pi_v<T> / (T)2.0; return numbers::pi_v<T> / (T)2.0;
if (x == (T)-1.0) if (x == (T)-1.0)
return -numbers::pi_v<T> / (T)2.0; return -numbers::pi_v<T> / (T)2.0;
return (T)2.0 * atan<T>(x / ((T)1.0 + sqrt<T>((T)1.0 - x * x))); return (T)2.0 * atan<T>(x / (T(1.0) + sqrt<T>((T)1.0 - x * x)));
} }
template<floating_point T> template<floating_point T>
@ -418,7 +411,7 @@ namespace BAN::Math
template<floating_point T> template<floating_point T>
inline constexpr T tanh(T x) inline constexpr T tanh(T x)
{ {
const T exp_px = exp<T>(+x); const T exp_px = exp<T>(x);
const T exp_nx = exp<T>(-x); const T exp_nx = exp<T>(-x);
return (exp_px - exp_nx) / (exp_px + exp_nx); return (exp_px - exp_nx) / (exp_px + exp_nx);
} }
@ -448,8 +441,3 @@ namespace BAN::Math
} }
} }
#ifdef BAN_MATH_POP_OPTIONS
#undef BAN_MATH_POP_OPTIONS
#pragma GCC pop_options
#endif

View File

@ -9,12 +9,10 @@
namespace BAN namespace BAN
{ {
#if defined(__is_kernel) #if defined(__is_kernel)
static constexpr void*(*allocator)(size_t) = kmalloc; static constexpr void*(&allocator)(size_t) = kmalloc;
static constexpr void*(*reallocator)(void*, size_t) = nullptr; static constexpr void(&deallocator)(void*) = kfree;
static constexpr void(*deallocator)(void*) = kfree;
#else #else
static constexpr void*(*allocator)(size_t) = malloc; static constexpr void*(&allocator)(size_t) = malloc;
static constexpr void*(*reallocator)(void*, size_t) = realloc; static constexpr void(&deallocator)(void*) = free;
static constexpr void(*deallocator)(void*) = free;
#endif #endif
} }

View File

@ -69,6 +69,7 @@ namespace BAN
value_type* data() const value_type* data() const
{ {
ASSERT(m_data);
return m_data; return m_data;
} }
@ -83,6 +84,7 @@ namespace BAN
Span slice(size_type start, size_type length = ~size_type(0)) const Span slice(size_type start, size_type length = ~size_type(0)) const
{ {
ASSERT(m_data);
ASSERT(start <= m_size); ASSERT(start <= m_size);
if (length == ~size_type(0)) if (length == ~size_type(0))
length = m_size - start; length = m_size - start;

View File

@ -14,7 +14,6 @@ namespace BAN
{ {
public: public:
using size_type = size_t; using size_type = size_t;
using value_type = char;
using iterator = IteratorSimple<char, String>; using iterator = IteratorSimple<char, String>;
using const_iterator = ConstIteratorSimple<char, String>; using const_iterator = ConstIteratorSimple<char, String>;
static constexpr size_type sso_capacity = 15; static constexpr size_type sso_capacity = 15;
@ -353,9 +352,10 @@ namespace BAN::Formatter
{ {
template<typename F> template<typename F>
void print_argument(F putc, const String& string, const ValueFormat& format) void print_argument(F putc, const String& string, const ValueFormat&)
{ {
print_argument(putc, string.sv(), format); for (String::size_type i = 0; i < string.size(); i++)
putc(string[i]);
} }
} }

View File

@ -14,7 +14,6 @@ namespace BAN
{ {
public: public:
using size_type = size_t; using size_type = size_t;
using value_type = char;
using const_iterator = ConstIteratorSimple<char, StringView>; using const_iterator = ConstIteratorSimple<char, StringView>;
public: public:
@ -247,12 +246,10 @@ namespace BAN::Formatter
{ {
template<typename F> template<typename F>
void print_argument(F putc, const StringView& sv, const ValueFormat& format) void print_argument(F putc, const StringView& sv, const ValueFormat&)
{ {
for (StringView::size_type i = 0; i < sv.size(); i++) for (StringView::size_type i = 0; i < sv.size(); i++)
putc(sv[i]); putc(sv[i]);
for (int i = sv.size(); i < format.fill; i++)
putc(' ');
} }
} }

View File

@ -61,9 +61,6 @@ namespace BAN
template<typename T> struct is_move_constructible { static constexpr bool value = is_constructible_v<T, T&&>; }; template<typename T> struct is_move_constructible { static constexpr bool value = is_constructible_v<T, T&&>; };
template<typename T> inline constexpr bool is_move_constructible_v = is_move_constructible<T>::value; template<typename T> inline constexpr bool is_move_constructible_v = is_move_constructible<T>::value;
template<typename T> struct is_trivially_copyable { static constexpr bool value = __is_trivially_copyable(T); };
template<typename T> inline constexpr bool is_trivially_copyable_v = is_trivially_copyable<T>::value;
template<typename T> struct is_integral { static constexpr bool value = requires (T t, T* p, void (*f)(T)) { reinterpret_cast<T>(t); f(0); p + t; }; }; template<typename T> struct is_integral { static constexpr bool value = requires (T t, T* p, void (*f)(T)) { reinterpret_cast<T>(t); f(0); p + t; }; };
template<typename T> inline constexpr bool is_integral_v = is_integral<T>::value; template<typename T> inline constexpr bool is_integral_v = is_integral<T>::value;
template<typename T> concept integral = is_integral_v<T>; template<typename T> concept integral = is_integral_v<T>;

View File

@ -381,35 +381,10 @@ namespace BAN
template<typename T> template<typename T>
ErrorOr<void> Vector<T>::ensure_capacity(size_type size) ErrorOr<void> Vector<T>::ensure_capacity(size_type size)
{ {
static_assert(alignof(T) <= alignof(max_align_t), "over aligned types not supported");
if (m_capacity >= size) if (m_capacity >= size)
return {}; return {};
size_type new_cap = BAN::Math::max<size_type>(size, m_capacity * 2);
const size_type new_cap = BAN::Math::max<size_type>(size, m_capacity * 2); T* new_data = (T*)BAN::allocator(new_cap * sizeof(T));
if constexpr (BAN::is_trivially_copyable_v<T>)
{
if constexpr (BAN::reallocator)
{
auto* new_data = static_cast<T*>(BAN::reallocator(m_data, new_cap * sizeof(T)));
if (new_data == nullptr)
return Error::from_errno(ENOMEM);
m_data = new_data;
}
else
{
auto* new_data = static_cast<T*>(BAN::allocator(new_cap * sizeof(T)));
if (new_data == nullptr)
return Error::from_errno(ENOMEM);
memcpy(new_data, m_data, m_size * sizeof(T));
BAN::deallocator(m_data);
m_data = new_data;
}
}
else
{
auto* new_data = static_cast<T*>(BAN::allocator(new_cap * sizeof(T)));
if (new_data == nullptr) if (new_data == nullptr)
return Error::from_errno(ENOMEM); return Error::from_errno(ENOMEM);
for (size_type i = 0; i < m_size; i++) for (size_type i = 0; i < m_size; i++)
@ -419,8 +394,6 @@ namespace BAN
} }
BAN::deallocator(m_data); BAN::deallocator(m_data);
m_data = new_data; m_data = new_data;
}
m_capacity = new_cap; m_capacity = new_cap;
return {}; return {};
} }

View File

@ -50,7 +50,6 @@ set(KERNEL_SOURCES
kernel/InterruptController.cpp kernel/InterruptController.cpp
kernel/kernel.cpp kernel/kernel.cpp
kernel/Lock/SpinLock.cpp kernel/Lock/SpinLock.cpp
kernel/Memory/ByteRingBuffer.cpp
kernel/Memory/DMARegion.cpp kernel/Memory/DMARegion.cpp
kernel/Memory/FileBackedRegion.cpp kernel/Memory/FileBackedRegion.cpp
kernel/Memory/Heap.cpp kernel/Memory/Heap.cpp

View File

@ -1,52 +0,0 @@
#pragma once
#include <kernel/FS/Inode.h>
namespace Kernel
{
class EventFD final : public Inode
{
public:
static BAN::ErrorOr<BAN::RefPtr<Inode>> create(uint64_t initval, bool semaphore);
ino_t ino() const override { return 0; }
Mode mode() const override { return { Mode::IFCHR | Mode::IRUSR | Mode::IWUSR }; }
nlink_t nlink() const override { return ref_count(); }
uid_t uid() const override { return 0; }
gid_t gid() const override { return 0; }
off_t size() const override { return 0; }
timespec atime() const override { return {}; }
timespec mtime() const override { return {}; }
timespec ctime() const override { return {}; }
blksize_t blksize() const override { return 8; }
blkcnt_t blocks() const override { return 0; }
dev_t dev() const override { return 0; }
dev_t rdev() const override { return 0; }
const FileSystem* filesystem() const override { return nullptr; }
protected:
BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) override;
BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) override;
BAN::ErrorOr<void> fsync_impl() final override { return {}; }
bool can_read_impl() const override { return m_value > 0; }
bool can_write_impl() const override { return m_value < UINT64_MAX - 1; }
bool has_error_impl() const override { return false; }
bool has_hungup_impl() const override { return false; }
private:
EventFD(uint64_t initval, bool is_semaphore)
: m_is_semaphore(is_semaphore)
, m_value(initval)
{ }
private:
const bool m_is_semaphore;
uint64_t m_value;
ThreadBlocker m_thread_blocker;
};
}

View File

@ -2,7 +2,6 @@
#include <BAN/Array.h> #include <BAN/Array.h>
#include <kernel/FS/Inode.h> #include <kernel/FS/Inode.h>
#include <kernel/Memory/ByteRingBuffer.h>
#include <kernel/ThreadBlocker.h> #include <kernel/ThreadBlocker.h>
namespace Kernel namespace Kernel
@ -39,7 +38,7 @@ namespace Kernel
virtual BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) override; virtual BAN::ErrorOr<size_t> write_impl(off_t, BAN::ConstByteSpan) override;
virtual BAN::ErrorOr<void> fsync_impl() final override { return {}; } virtual BAN::ErrorOr<void> fsync_impl() final override { return {}; }
virtual bool can_read_impl() const override { return !m_buffer->empty(); } virtual bool can_read_impl() const override { return m_buffer_size > 0; }
virtual bool can_write_impl() const override { return true; } virtual bool can_write_impl() const override { return true; }
virtual bool has_error_impl() const override { return m_reading_count == 0; } virtual bool has_error_impl() const override { return m_reading_count == 0; }
virtual bool has_hungup_impl() const override { return m_writing_count == 0; } virtual bool has_hungup_impl() const override { return m_writing_count == 0; }
@ -55,7 +54,9 @@ namespace Kernel
timespec m_ctime {}; timespec m_ctime {};
ThreadBlocker m_thread_blocker; ThreadBlocker m_thread_blocker;
BAN::UniqPtr<ByteRingBuffer> m_buffer; BAN::Array<uint8_t, PAGE_SIZE> m_buffer;
BAN::Atomic<size_t> m_buffer_size { 0 };
size_t m_buffer_tail { 0 };
BAN::Atomic<uint32_t> m_writing_count { 1 }; BAN::Atomic<uint32_t> m_writing_count { 1 };
BAN::Atomic<uint32_t> m_reading_count { 1 }; BAN::Atomic<uint32_t> m_reading_count { 1 };

View File

@ -1,76 +0,0 @@
#pragma once
#include <BAN/ByteSpan.h>
#include <BAN/UniqPtr.h>
#include <BAN/Vector.h>
#include <kernel/Memory/Types.h>
namespace Kernel
{
class ByteRingBuffer
{
public:
static BAN::ErrorOr<BAN::UniqPtr<ByteRingBuffer>> create(size_t size);
~ByteRingBuffer();
void push(BAN::ConstByteSpan data)
{
ASSERT(data.size() + m_size <= m_capacity);
uint8_t* buffer_head = reinterpret_cast<uint8_t*>(m_vaddr) + (m_tail + m_size) % m_capacity;
memcpy(buffer_head, data.data(), data.size());
m_size += data.size();
}
void pop(size_t size)
{
ASSERT(size <= m_size);
m_tail = (m_tail + size) % m_capacity;
m_size -= size;
}
void pop_back(size_t size)
{
ASSERT(size <= m_size);
m_size -= size;
}
BAN::ConstByteSpan get_data() const
{
const uint8_t* base = reinterpret_cast<const uint8_t*>(m_vaddr);
return { base + m_tail, m_size };
}
uint8_t front() const
{
ASSERT(!empty());
return reinterpret_cast<const uint8_t*>(m_vaddr)[m_tail];
}
uint8_t back() const
{
ASSERT(!empty());
return reinterpret_cast<const uint8_t*>(m_vaddr)[m_tail + m_size];
}
bool empty() const { return m_size == 0; }
bool full() const { return m_size == m_capacity; }
size_t free() const { return m_capacity - m_size; }
size_t size() const { return m_size; }
size_t capacity() const { return m_capacity; }
private:
ByteRingBuffer(size_t capacity)
: m_capacity(capacity)
{ }
private:
size_t m_size { 0 };
size_t m_tail { 0 };
const size_t m_capacity;
vaddr_t m_vaddr { 0 };
};
}

View File

@ -31,18 +31,35 @@ namespace Kernel
public: public:
static BAN::ErrorOr<BAN::UniqPtr<ARPTable>> create(); static BAN::ErrorOr<BAN::UniqPtr<ARPTable>> create();
~ARPTable();
BAN::ErrorOr<BAN::MACAddress> get_mac_from_ipv4(NetworkInterface&, BAN::IPv4Address); BAN::ErrorOr<BAN::MACAddress> get_mac_from_ipv4(NetworkInterface&, BAN::IPv4Address);
BAN::ErrorOr<void> handle_arp_packet(NetworkInterface&, BAN::ConstByteSpan); void add_arp_packet(NetworkInterface&, BAN::ConstByteSpan);
private: private:
ARPTable() = default; ARPTable();
void packet_handle_task();
BAN::ErrorOr<void> handle_arp_packet(NetworkInterface&, const ARPPacket&);
private: private:
SpinLock m_arp_table_lock; struct PendingArpPacket
{
NetworkInterface& interface;
ARPPacket packet;
};
private:
SpinLock m_table_lock;
SpinLock m_pending_lock;
BAN::HashMap<BAN::IPv4Address, BAN::MACAddress> m_arp_table; BAN::HashMap<BAN::IPv4Address, BAN::MACAddress> m_arp_table;
Thread* m_thread { nullptr };
BAN::CircularQueue<PendingArpPacket, 128> m_pending_packets;
ThreadBlocker m_pending_thread_blocker;
friend class BAN::UniqPtr<ARPTable>; friend class BAN::UniqPtr<ARPTable>;
}; };

View File

@ -23,14 +23,14 @@ namespace Kernel
static BAN::ErrorOr<BAN::RefPtr<E1000>> create(PCI::Device&); static BAN::ErrorOr<BAN::RefPtr<E1000>> create(PCI::Device&);
~E1000(); ~E1000();
BAN::MACAddress get_mac_address() const override { return m_mac_address; } virtual BAN::MACAddress get_mac_address() const override { return m_mac_address; }
bool link_up() override { return m_link_up; } virtual bool link_up() override { return m_link_up; }
int link_speed() override; virtual int link_speed() override;
size_t payload_mtu() const override { return E1000_RX_BUFFER_SIZE - sizeof(EthernetHeader); } virtual size_t payload_mtu() const override { return E1000_RX_BUFFER_SIZE - sizeof(EthernetHeader); }
void handle_irq() final override; virtual void handle_irq() final override;
protected: protected:
E1000(PCI::Device& pci_device) E1000(PCI::Device& pci_device)
@ -45,12 +45,12 @@ namespace Kernel
uint32_t read32(uint16_t reg); uint32_t read32(uint16_t reg);
void write32(uint16_t reg, uint32_t value); void write32(uint16_t reg, uint32_t value);
BAN::ErrorOr<void> send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::Span<const BAN::ConstByteSpan> payload) override; virtual BAN::ErrorOr<void> send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::ConstByteSpan) override;
bool can_read_impl() const override { return false; } virtual bool can_read_impl() const override { return false; }
bool can_write_impl() const override { return false; } virtual bool can_write_impl() const override { return false; }
bool has_error_impl() const override { return false; } virtual bool has_error_impl() const override { return false; }
bool has_hungup_impl() const override { return false; } virtual bool has_hungup_impl() const override { return false; }
private: private:
BAN::ErrorOr<void> read_mac_address(); BAN::ErrorOr<void> read_mac_address();
@ -61,7 +61,7 @@ namespace Kernel
void enable_link(); void enable_link();
BAN::ErrorOr<void> enable_interrupt(); BAN::ErrorOr<void> enable_interrupt();
void receive_thread(); void handle_receive();
protected: protected:
PCI::Device& m_pci_device; PCI::Device& m_pci_device;
@ -75,10 +75,6 @@ namespace Kernel
BAN::UniqPtr<DMARegion> m_tx_descriptor_region; BAN::UniqPtr<DMARegion> m_tx_descriptor_region;
SpinLock m_lock; SpinLock m_lock;
bool m_thread_should_die { false };
BAN::Atomic<bool> m_thread_is_dead { true };
ThreadBlocker m_thread_blocker;
BAN::MACAddress m_mac_address {}; BAN::MACAddress m_mac_address {};
bool m_link_up { false }; bool m_link_up { false };

View File

@ -12,8 +12,8 @@ namespace Kernel
static BAN::ErrorOr<BAN::RefPtr<E1000E>> create(PCI::Device&); static BAN::ErrorOr<BAN::RefPtr<E1000E>> create(PCI::Device&);
protected: protected:
void detect_eeprom() override; virtual void detect_eeprom() override;
uint32_t eeprom_read(uint8_t addr) override; virtual uint32_t eeprom_read(uint8_t addr) override;
private: private:
E1000E(PCI::Device& pci_device) E1000E(PCI::Device& pci_device)

View File

@ -38,10 +38,11 @@ namespace Kernel
public: public:
static BAN::ErrorOr<BAN::UniqPtr<IPv4Layer>> create(); static BAN::ErrorOr<BAN::UniqPtr<IPv4Layer>> create();
~IPv4Layer();
ARPTable& arp_table() { return *m_arp_table; } ARPTable& arp_table() { return *m_arp_table; }
BAN::ErrorOr<void> handle_ipv4_packet(NetworkInterface&, BAN::ConstByteSpan); void add_ipv4_packet(NetworkInterface&, BAN::ConstByteSpan);
virtual void unbind_socket(uint16_t port) override; virtual void unbind_socket(uint16_t port) override;
virtual BAN::ErrorOr<void> bind_socket_with_target(BAN::RefPtr<NetworkSocket>, const sockaddr* target_address, socklen_t target_address_len) override; virtual BAN::ErrorOr<void> bind_socket_with_target(BAN::RefPtr<NetworkSocket>, const sockaddr* target_address, socklen_t target_address_len) override;
@ -54,14 +55,34 @@ namespace Kernel
virtual size_t header_size() const override { return sizeof(IPv4Header); } virtual size_t header_size() const override { return sizeof(IPv4Header); }
private: private:
IPv4Layer() = default; IPv4Layer();
void add_ipv4_header(BAN::ByteSpan packet, BAN::IPv4Address src_ipv4, BAN::IPv4Address dst_ipv4, uint8_t protocol) const;
BAN::ErrorOr<in_port_t> find_free_port(); BAN::ErrorOr<in_port_t> find_free_port();
private: void packet_handle_task();
BAN::UniqPtr<ARPTable> m_arp_table; BAN::ErrorOr<void> handle_ipv4_packet(NetworkInterface&, BAN::ByteSpan);
private:
struct PendingIPv4Packet
{
NetworkInterface& interface;
};
private:
RecursiveSpinLock m_bound_socket_lock; RecursiveSpinLock m_bound_socket_lock;
BAN::UniqPtr<ARPTable> m_arp_table;
Thread* m_thread { nullptr };
static constexpr size_t pending_packet_buffer_size = 128 * PAGE_SIZE;
BAN::UniqPtr<VirtualRange> m_pending_packet_buffer;
BAN::CircularQueue<PendingIPv4Packet, 128> m_pending_packets;
ThreadBlocker m_pending_thread_blocker;
SpinLock m_pending_lock;
size_t m_pending_total_size { 0 };
BAN::HashMap<int, BAN::WeakPtr<NetworkSocket>> m_bound_sockets; BAN::HashMap<int, BAN::WeakPtr<NetworkSocket>> m_bound_sockets;
friend class BAN::UniqPtr<IPv4Layer>; friend class BAN::UniqPtr<IPv4Layer>;

View File

@ -9,7 +9,6 @@ namespace Kernel
{ {
public: public:
static constexpr size_t buffer_size = BAN::numeric_limits<uint16_t>::max() + 1; static constexpr size_t buffer_size = BAN::numeric_limits<uint16_t>::max() + 1;
static constexpr size_t buffer_count = 32;
public: public:
static BAN::ErrorOr<BAN::RefPtr<LoopbackInterface>> create(); static BAN::ErrorOr<BAN::RefPtr<LoopbackInterface>> create();
@ -25,9 +24,8 @@ namespace Kernel
LoopbackInterface() LoopbackInterface()
: NetworkInterface(Type::Loopback) : NetworkInterface(Type::Loopback)
{} {}
~LoopbackInterface();
BAN::ErrorOr<void> send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::Span<const BAN::ConstByteSpan> payload) override; BAN::ErrorOr<void> send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::ConstByteSpan) override;
bool can_read_impl() const override { return false; } bool can_read_impl() const override { return false; }
bool can_write_impl() const override { return false; } bool can_write_impl() const override { return false; }
@ -35,27 +33,8 @@ namespace Kernel
bool has_hungup_impl() const override { return false; } bool has_hungup_impl() const override { return false; }
private: private:
void receive_thread(); SpinLock m_buffer_lock;
private:
struct Descriptor
{
uint8_t* addr;
uint32_t size;
uint8_t state;
};
private:
Mutex m_buffer_lock;
BAN::UniqPtr<VirtualRange> m_buffer; BAN::UniqPtr<VirtualRange> m_buffer;
uint32_t m_buffer_tail { 0 };
uint32_t m_buffer_head { 0 };
Descriptor m_descriptors[buffer_count] {};
bool m_thread_should_die { false };
BAN::Atomic<bool> m_thread_is_dead { true };
ThreadBlocker m_thread_blocker;
}; };
} }

View File

@ -60,11 +60,7 @@ namespace Kernel
virtual dev_t rdev() const override { return m_rdev; } virtual dev_t rdev() const override { return m_rdev; }
virtual BAN::StringView name() const override { return m_name; } virtual BAN::StringView name() const override { return m_name; }
BAN::ErrorOr<void> send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::ConstByteSpan payload) virtual BAN::ErrorOr<void> send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::ConstByteSpan) = 0;
{
return send_bytes(destination, protocol, { &payload, 1 });
}
virtual BAN::ErrorOr<void> send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::Span<const BAN::ConstByteSpan> payload) = 0;
private: private:
const Type m_type; const Type m_type;

View File

@ -11,7 +11,7 @@ namespace Kernel
BAN::IPv4Address src_ipv4 { 0 }; BAN::IPv4Address src_ipv4 { 0 };
BAN::IPv4Address dst_ipv4 { 0 }; BAN::IPv4Address dst_ipv4 { 0 };
BAN::NetworkEndian<uint16_t> protocol { 0 }; BAN::NetworkEndian<uint16_t> protocol { 0 };
BAN::NetworkEndian<uint16_t> length { 0 }; BAN::NetworkEndian<uint16_t> extra { 0 };
}; };
static_assert(sizeof(PseudoHeader) == 12); static_assert(sizeof(PseudoHeader) == 12);
@ -36,7 +36,6 @@ namespace Kernel
NetworkLayer() = default; NetworkLayer() = default;
}; };
uint16_t calculate_internet_checksum(BAN::ConstByteSpan buffer); uint16_t calculate_internet_checksum(BAN::ConstByteSpan packet, const PseudoHeader& pseudo_header);
uint16_t calculate_internet_checksum(BAN::Span<const BAN::ConstByteSpan> buffers);
} }

View File

@ -32,7 +32,7 @@ namespace Kernel
BAN::ErrorOr<BAN::RefPtr<NetworkInterface>> interface(const sockaddr* target, socklen_t target_len); BAN::ErrorOr<BAN::RefPtr<NetworkInterface>> interface(const sockaddr* target, socklen_t target_len);
virtual size_t protocol_header_size() const = 0; virtual size_t protocol_header_size() const = 0;
virtual void get_protocol_header(BAN::ByteSpan header, BAN::ConstByteSpan payload, uint16_t dst_port, PseudoHeader) = 0; virtual void add_protocol_header(BAN::ByteSpan packet, uint16_t dst_port, PseudoHeader) = 0;
virtual NetworkProtocol protocol() const = 0; virtual NetworkProtocol protocol() const = 0;
virtual void receive_packet(BAN::ConstByteSpan, const sockaddr* sender, socklen_t sender_len) = 0; virtual void receive_packet(BAN::ConstByteSpan, const sockaddr* sender, socklen_t sender_len) = 0;

View File

@ -29,11 +29,9 @@ namespace Kernel
: NetworkInterface(Type::Ethernet) : NetworkInterface(Type::Ethernet)
, m_pci_device(pci_device) , m_pci_device(pci_device)
{ } { }
~RTL8169();
BAN::ErrorOr<void> initialize(); BAN::ErrorOr<void> initialize();
virtual BAN::ErrorOr<void> send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::Span<const BAN::ConstByteSpan>) override; virtual BAN::ErrorOr<void> send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::ConstByteSpan) override;
virtual bool can_read_impl() const override { return false; } virtual bool can_read_impl() const override { return false; }
virtual bool can_write_impl() const override { return false; } virtual bool can_write_impl() const override { return false; }
@ -49,7 +47,7 @@ namespace Kernel
void enable_link(); void enable_link();
BAN::ErrorOr<void> enable_interrupt(); BAN::ErrorOr<void> enable_interrupt();
void receive_thread(); void handle_receive();
protected: protected:
PCI::Device& m_pci_device; PCI::Device& m_pci_device;
@ -65,9 +63,6 @@ namespace Kernel
BAN::UniqPtr<DMARegion> m_tx_descriptor_region; BAN::UniqPtr<DMARegion> m_tx_descriptor_region;
SpinLock m_lock; SpinLock m_lock;
bool m_thread_should_die { false };
BAN::Atomic<bool> m_thread_is_dead { true };
ThreadBlocker m_thread_blocker; ThreadBlocker m_thread_blocker;
uint32_t m_rx_current { 0 }; uint32_t m_rx_current { 0 };

View File

@ -4,7 +4,7 @@
#include <BAN/Endianness.h> #include <BAN/Endianness.h>
#include <BAN/Queue.h> #include <BAN/Queue.h>
#include <kernel/Lock/Mutex.h> #include <kernel/Lock/Mutex.h>
#include <kernel/Memory/ByteRingBuffer.h> #include <kernel/Memory/VirtualRange.h>
#include <kernel/Networking/NetworkInterface.h> #include <kernel/Networking/NetworkInterface.h>
#include <kernel/Networking/NetworkSocket.h> #include <kernel/Networking/NetworkSocket.h>
#include <kernel/Thread.h> #include <kernel/Thread.h>
@ -50,30 +50,29 @@ namespace Kernel
static BAN::ErrorOr<BAN::RefPtr<TCPSocket>> create(NetworkLayer&, const Info&); static BAN::ErrorOr<BAN::RefPtr<TCPSocket>> create(NetworkLayer&, const Info&);
~TCPSocket(); ~TCPSocket();
NetworkProtocol protocol() const override { return NetworkProtocol::TCP; } virtual NetworkProtocol protocol() const override { return NetworkProtocol::TCP; }
size_t protocol_header_size() const override { return sizeof(TCPHeader) + m_tcp_options_bytes; } virtual size_t protocol_header_size() const override { return sizeof(TCPHeader) + m_tcp_options_bytes; }
void get_protocol_header(BAN::ByteSpan header, BAN::ConstByteSpan payload, uint16_t dst_port, PseudoHeader) override; virtual void add_protocol_header(BAN::ByteSpan packet, uint16_t dst_port, PseudoHeader) override;
protected: protected:
BAN::ErrorOr<long> accept_impl(sockaddr*, socklen_t*, int) override; virtual BAN::ErrorOr<long> accept_impl(sockaddr*, socklen_t*, int) override;
BAN::ErrorOr<void> connect_impl(const sockaddr*, socklen_t) override; virtual BAN::ErrorOr<void> connect_impl(const sockaddr*, socklen_t) override;
BAN::ErrorOr<void> listen_impl(int) override; virtual BAN::ErrorOr<void> listen_impl(int) override;
BAN::ErrorOr<void> bind_impl(const sockaddr*, socklen_t) override; virtual BAN::ErrorOr<void> bind_impl(const sockaddr*, socklen_t) override;
BAN::ErrorOr<size_t> recvmsg_impl(msghdr& message, int flags) override; virtual BAN::ErrorOr<size_t> recvmsg_impl(msghdr& message, int flags) override;
BAN::ErrorOr<size_t> sendmsg_impl(const msghdr& message, int flags) override; virtual BAN::ErrorOr<size_t> sendmsg_impl(const msghdr& message, int flags) override;
BAN::ErrorOr<void> getpeername_impl(sockaddr*, socklen_t*) override; virtual BAN::ErrorOr<void> getpeername_impl(sockaddr*, socklen_t*) override;
BAN::ErrorOr<void> getsockopt_impl(int, int, void*, socklen_t*) override; virtual BAN::ErrorOr<void> getsockopt_impl(int, int, void*, socklen_t*) override;
BAN::ErrorOr<void> setsockopt_impl(int, int, const void*, socklen_t) override;
BAN::ErrorOr<long> ioctl_impl(int, void*) override; virtual BAN::ErrorOr<long> ioctl_impl(int, void*) override;
void receive_packet(BAN::ConstByteSpan, const sockaddr* sender, socklen_t sender_len) override; virtual void receive_packet(BAN::ConstByteSpan, const sockaddr* sender, socklen_t sender_len) override;
bool can_read_impl() const override; virtual bool can_read_impl() const override;
bool can_write_impl() const override; virtual bool can_write_impl() const override;
bool has_error_impl() const override { return false; } virtual bool has_error_impl() const override { return false; }
bool has_hungup_impl() const override; virtual bool has_hungup_impl() const override;
private: private:
enum class State enum class State
@ -97,8 +96,9 @@ namespace Kernel
bool has_ghost_byte { false }; bool has_ghost_byte { false };
uint32_t data_size { 0 }; // number of bytes in this buffer
uint8_t scale_shift { 0 }; // window scale uint8_t scale_shift { 0 }; // window scale
BAN::UniqPtr<ByteRingBuffer> buffer; BAN::UniqPtr<VirtualRange> buffer;
}; };
struct SendWindowInfo struct SendWindowInfo
@ -115,10 +115,10 @@ namespace Kernel
uint64_t last_send_ms { 0 }; // last send time, used for retransmission timeout uint64_t last_send_ms { 0 }; // last send time, used for retransmission timeout
bool has_ghost_byte { false }; bool has_ghost_byte { false };
bool had_zero_window { false };
uint32_t data_size { 0 }; // number of bytes in this buffer
uint32_t sent_size { 0 }; // number of bytes in this buffer that have been sent uint32_t sent_size { 0 }; // number of bytes in this buffer that have been sent
BAN::UniqPtr<ByteRingBuffer> buffer; BAN::UniqPtr<VirtualRange> buffer;
}; };
struct ConnectionInfo struct ConnectionInfo
@ -132,8 +132,6 @@ namespace Kernel
{ {
ConnectionInfo target; ConnectionInfo target;
uint32_t target_start_seq; uint32_t target_start_seq;
uint16_t maximum_seqment_size;
uint8_t window_scale;
}; };
struct ListenKey struct ListenKey
@ -168,17 +166,8 @@ namespace Kernel
State m_next_state { State::Closed }; State m_next_state { State::Closed };
uint8_t m_next_flags { 0 }; uint8_t m_next_flags { 0 };
size_t m_last_sent_window_size { 0 };
Thread* m_thread { nullptr }; Thread* m_thread { nullptr };
// TODO: actually support these
bool m_keep_alive { false };
bool m_no_delay { false };
bool m_should_send_zero_window { false };
bool m_should_send_window_update { false };
uint64_t m_time_wait_start_ms { 0 }; uint64_t m_time_wait_start_ms { 0 };
ThreadBlocker m_thread_blocker; ThreadBlocker m_thread_blocker;

View File

@ -25,28 +25,27 @@ namespace Kernel
public: public:
static BAN::ErrorOr<BAN::RefPtr<UDPSocket>> create(NetworkLayer&, const Socket::Info&); static BAN::ErrorOr<BAN::RefPtr<UDPSocket>> create(NetworkLayer&, const Socket::Info&);
NetworkProtocol protocol() const override { return NetworkProtocol::UDP; } virtual NetworkProtocol protocol() const override { return NetworkProtocol::UDP; }
size_t protocol_header_size() const override { return sizeof(UDPHeader); } virtual size_t protocol_header_size() const override { return sizeof(UDPHeader); }
void get_protocol_header(BAN::ByteSpan header, BAN::ConstByteSpan payload, uint16_t dst_port, PseudoHeader) override; virtual void add_protocol_header(BAN::ByteSpan packet, uint16_t dst_port, PseudoHeader) override;
protected: protected:
void receive_packet(BAN::ConstByteSpan, const sockaddr* sender, socklen_t sender_len) override; virtual void receive_packet(BAN::ConstByteSpan, const sockaddr* sender, socklen_t sender_len) override;
BAN::ErrorOr<void> connect_impl(const sockaddr*, socklen_t) override; virtual BAN::ErrorOr<void> connect_impl(const sockaddr*, socklen_t) override;
BAN::ErrorOr<void> bind_impl(const sockaddr* address, socklen_t address_len) override; virtual BAN::ErrorOr<void> bind_impl(const sockaddr* address, socklen_t address_len) override;
BAN::ErrorOr<size_t> recvmsg_impl(msghdr& message, int flags) override; virtual BAN::ErrorOr<size_t> recvmsg_impl(msghdr& message, int flags) override;
BAN::ErrorOr<size_t> sendmsg_impl(const msghdr& message, int flags) override; virtual BAN::ErrorOr<size_t> sendmsg_impl(const msghdr& message, int flags) override;
BAN::ErrorOr<void> getpeername_impl(sockaddr*, socklen_t*) override { return BAN::Error::from_errno(ENOTCONN); } virtual BAN::ErrorOr<void> getpeername_impl(sockaddr*, socklen_t*) override { return BAN::Error::from_errno(ENOTCONN); }
BAN::ErrorOr<void> getsockopt_impl(int, int, void*, socklen_t*) override; virtual BAN::ErrorOr<void> getsockopt_impl(int, int, void*, socklen_t*) override;
BAN::ErrorOr<void> setsockopt_impl(int, int, const void*, socklen_t) override;
BAN::ErrorOr<long> ioctl_impl(int, void*) override; virtual BAN::ErrorOr<long> ioctl_impl(int, void*) override;
bool can_read_impl() const override { return !m_packets.empty(); } virtual bool can_read_impl() const override { return !m_packets.empty(); }
bool can_write_impl() const override { return true; } virtual bool can_write_impl() const override { return true; }
bool has_error_impl() const override { return false; } virtual bool has_error_impl() const override { return false; }
bool has_hungup_impl() const override { return false; } virtual bool has_hungup_impl() const override { return false; }
private: private:
UDPSocket(NetworkLayer&, const Socket::Info&); UDPSocket(NetworkLayer&, const Socket::Info&);

View File

@ -147,8 +147,6 @@ namespace Kernel
BAN::ErrorOr<long> sys_epoll_ctl(int epfd, int op, int fd, struct epoll_event* event); BAN::ErrorOr<long> sys_epoll_ctl(int epfd, int op, int fd, struct epoll_event* event);
BAN::ErrorOr<long> sys_epoll_pwait2(int epfd, struct epoll_event* events, int maxevents, const struct timespec* timeout, const sigset_t* sigmask); BAN::ErrorOr<long> sys_epoll_pwait2(int epfd, struct epoll_event* events, int maxevents, const struct timespec* timeout, const sigset_t* sigmask);
BAN::ErrorOr<long> sys_eventfd(unsigned int initval_hi, int flags);
BAN::ErrorOr<long> sys_pipe(int fildes[2]); BAN::ErrorOr<long> sys_pipe(int fildes[2]);
BAN::ErrorOr<long> sys_dup2(int fildes, int fildes2); BAN::ErrorOr<long> sys_dup2(int fildes, int fildes2);

View File

@ -3,7 +3,6 @@
#include <BAN/Array.h> #include <BAN/Array.h>
#include <kernel/Device/Device.h> #include <kernel/Device/Device.h>
#include <kernel/Lock/SpinLock.h> #include <kernel/Lock/SpinLock.h>
#include <kernel/Memory/ByteRingBuffer.h>
#include <kernel/Terminal/TerminalDriver.h> #include <kernel/Terminal/TerminalDriver.h>
#include <kernel/ThreadBlocker.h> #include <kernel/ThreadBlocker.h>
#include <LibInput/KeyEvent.h> #include <LibInput/KeyEvent.h>
@ -103,7 +102,8 @@ namespace Kernel
struct Buffer struct Buffer
{ {
BAN::UniqPtr<ByteRingBuffer> buffer; BAN::Array<uint8_t, 1024> buffer;
size_t bytes { 0 };
bool flush { false }; bool flush { false };
ThreadBlocker thread_blocker; ThreadBlocker thread_blocker;
}; };

View File

@ -335,8 +335,6 @@ namespace Debug
void print_prefix(const char* file, int line) void print_prefix(const char* file, int line)
{ {
if (file[0] == '.' && file[1] == '/')
file += 2;
auto ms_since_boot = Kernel::SystemTimer::is_initialized() ? Kernel::SystemTimer::get().ms_since_boot() : 0; auto ms_since_boot = Kernel::SystemTimer::is_initialized() ? Kernel::SystemTimer::get().ms_since_boot() : 0;
BAN::Formatter::print(Debug::putchar, "[{5}.{3}] {}:{}: ", ms_since_boot / 1000, ms_since_boot % 1000, file, line); BAN::Formatter::print(Debug::putchar, "[{5}.{3}] {}:{}: ", ms_since_boot / 1000, ms_since_boot % 1000, file, line);
} }

View File

@ -21,11 +21,10 @@ namespace Kernel
{ {
auto ms_since_boot = SystemTimer::get().ms_since_boot(); auto ms_since_boot = SystemTimer::get().ms_since_boot();
SpinLockGuard _(Debug::s_debug_lock); SpinLockGuard _(Debug::s_debug_lock);
BAN::Formatter::print(Debug::putchar, "[{5}.{3}] {}:{} {}: ", BAN::Formatter::print(Debug::putchar, "[{5}.{3}] {} {}: ",
ms_since_boot / 1000, ms_since_boot / 1000,
ms_since_boot % 1000, ms_since_boot % 1000,
Kernel::Process::current().pid(), Kernel::Process::current().pid(),
Thread::current().tid(),
Kernel::Process::current().name() Kernel::Process::current().name()
); );
for (size_t i = 0; i < buffer.size(); i++) for (size_t i = 0; i < buffer.size(); i++)

View File

@ -209,7 +209,7 @@ namespace Kernel
continue; continue;
SpinLockGuardAsMutex smutex(guard); SpinLockGuardAsMutex smutex(guard);
TRY(Thread::current().block_or_eintr_or_waketime_ns(m_thread_blocker, waketime_ns, false, &smutex)); TRY(Thread::current().block_or_eintr_or_timeout_ns(m_thread_blocker, waketime_ns - current_ns, false, &smutex));
} }
return event_count; return event_count;

View File

@ -1,54 +0,0 @@
#include <kernel/FS/EventFD.h>
#include <sys/epoll.h>
namespace Kernel
{
BAN::ErrorOr<BAN::RefPtr<Inode>> EventFD::create(uint64_t initval, bool semaphore)
{
auto* eventfd_ptr = new EventFD(initval, semaphore);
if (eventfd_ptr == nullptr)
return BAN::Error::from_errno(ENOMEM);
return BAN::RefPtr<Inode>(BAN::RefPtr<EventFD>::adopt(eventfd_ptr));
}
BAN::ErrorOr<size_t> EventFD::read_impl(off_t, BAN::ByteSpan buffer)
{
if (buffer.size() < sizeof(uint64_t))
return BAN::Error::from_errno(EINVAL);
while (m_value == 0)
TRY(Thread::current().block_or_eintr_indefinite(m_thread_blocker, &m_mutex));
const uint64_t read_value = m_is_semaphore ? 1 : m_value;
m_value -= read_value;
buffer.as<uint64_t>() = read_value;
epoll_notify(EPOLLOUT);
return sizeof(uint64_t);
}
BAN::ErrorOr<size_t> EventFD::write_impl(off_t, BAN::ConstByteSpan buffer)
{
if (buffer.size() < sizeof(uint64_t))
return BAN::Error::from_errno(EINVAL);
const uint64_t write_value = buffer.as<const uint64_t>();
if (write_value == UINT64_MAX)
return BAN::Error::from_errno(EINVAL);
while (m_value + write_value < m_value)
TRY(Thread::current().block_or_eintr_indefinite(m_thread_blocker, &m_mutex));
m_value += write_value;
if (m_value > 0)
epoll_notify(EPOLLIN);
return sizeof(uint64_t);
}
}

View File

@ -9,16 +9,12 @@
namespace Kernel namespace Kernel
{ {
static constexpr size_t s_pipe_buffer_size = 0x10000;
BAN::ErrorOr<BAN::RefPtr<Inode>> Pipe::create(const Credentials& credentials) BAN::ErrorOr<BAN::RefPtr<Inode>> Pipe::create(const Credentials& credentials)
{ {
auto* pipe_ptr = new Pipe(credentials); Pipe* pipe = new Pipe(credentials);
if (pipe_ptr == nullptr) if (pipe == nullptr)
return BAN::Error::from_errno(ENOMEM); return BAN::Error::from_errno(ENOMEM);
auto pipe = BAN::RefPtr<Pipe>::adopt(pipe_ptr); return BAN::RefPtr<Inode>::adopt(pipe);
pipe->m_buffer = TRY(ByteRingBuffer::create(s_pipe_buffer_size));
return BAN::RefPtr<Inode>(pipe);
} }
Pipe::Pipe(const Credentials& credentials) Pipe::Pipe(const Credentials& credentials)
@ -73,16 +69,27 @@ namespace Kernel
BAN::ErrorOr<size_t> Pipe::read_impl(off_t, BAN::ByteSpan buffer) BAN::ErrorOr<size_t> Pipe::read_impl(off_t, BAN::ByteSpan buffer)
{ {
while (m_buffer->empty()) while (m_buffer_size == 0)
{ {
if (m_writing_count == 0) if (m_writing_count == 0)
return 0; return 0;
TRY(Thread::current().block_or_eintr_indefinite(m_thread_blocker, &m_mutex)); TRY(Thread::current().block_or_eintr_indefinite(m_thread_blocker, &m_mutex));
} }
const size_t to_copy = BAN::Math::min<size_t>(buffer.size(), m_buffer->size()); const size_t to_copy = BAN::Math::min<size_t>(buffer.size(), m_buffer_size);
memcpy(buffer.data(), m_buffer->get_data().data(), to_copy);
m_buffer->pop(to_copy); if (m_buffer_tail + to_copy <= m_buffer.size())
memcpy(buffer.data(), m_buffer.data() + m_buffer_tail, to_copy);
else
{
const size_t before_wrap = m_buffer.size() - m_buffer_tail;
const size_t after_wrap = to_copy - before_wrap;
memcpy(buffer.data(), m_buffer.data() + m_buffer_tail, before_wrap);
memcpy(buffer.data() + before_wrap, m_buffer.data(), after_wrap);
}
m_buffer_tail = (m_buffer_tail + to_copy) % m_buffer.size();
m_buffer_size -= to_copy;
m_atime = SystemTimer::get().real_time(); m_atime = SystemTimer::get().real_time();
@ -95,7 +102,7 @@ namespace Kernel
BAN::ErrorOr<size_t> Pipe::write_impl(off_t, BAN::ConstByteSpan buffer) BAN::ErrorOr<size_t> Pipe::write_impl(off_t, BAN::ConstByteSpan buffer)
{ {
while (m_buffer->full()) while (m_buffer_size >= m_buffer.size())
{ {
if (m_reading_count == 0) if (m_reading_count == 0)
{ {
@ -105,8 +112,20 @@ namespace Kernel
TRY(Thread::current().block_or_eintr_indefinite(m_thread_blocker, &m_mutex)); TRY(Thread::current().block_or_eintr_indefinite(m_thread_blocker, &m_mutex));
} }
const size_t to_copy = BAN::Math::min(buffer.size(), m_buffer->free()); const size_t to_copy = BAN::Math::min(buffer.size(), m_buffer.size() - m_buffer_size);
m_buffer->push(buffer.slice(0, to_copy)); const size_t buffer_head = (m_buffer_tail + m_buffer_size) % m_buffer.size();
if (buffer_head + to_copy <= m_buffer.size())
memcpy(m_buffer.data() + buffer_head, buffer.data(), to_copy);
else
{
const size_t before_wrap = m_buffer.size() - buffer_head;
const size_t after_wrap = to_copy - before_wrap;
memcpy(m_buffer.data() + buffer_head, buffer.data(), before_wrap);
memcpy(m_buffer.data(), buffer.data() + before_wrap, after_wrap);
}
m_buffer_size += to_copy;
timespec current_time = SystemTimer::get().real_time(); timespec current_time = SystemTimer::get().real_time();
m_mtime = current_time; m_mtime = current_time;

View File

@ -1,49 +0,0 @@
#include <kernel/Memory/ByteRingBuffer.h>
#include <kernel/Memory/Heap.h>
#include <kernel/Memory/PageTable.h>
namespace Kernel
{
BAN::ErrorOr<BAN::UniqPtr<ByteRingBuffer>> ByteRingBuffer::create(size_t size)
{
ASSERT(size % PAGE_SIZE == 0);
const size_t page_count = size / PAGE_SIZE;
auto* buffer_ptr = new ByteRingBuffer(size);
if (buffer_ptr == nullptr)
return BAN::Error::from_errno(ENOMEM);
auto buffer = BAN::UniqPtr<ByteRingBuffer>::adopt(buffer_ptr);
buffer->m_vaddr = PageTable::kernel().reserve_free_contiguous_pages(page_count * 2, KERNEL_OFFSET);
if (buffer->m_vaddr == 0)
return BAN::Error::from_errno(ENOMEM);
for (size_t i = 0; i < page_count; i++)
{
const paddr_t paddr = Heap::get().take_free_page();
if (paddr == 0)
return BAN::Error::from_errno(ENOMEM);
PageTable::kernel().map_page_at(paddr, buffer->m_vaddr + i * PAGE_SIZE, PageTable::ReadWrite | PageTable::Present);
PageTable::kernel().map_page_at(paddr, buffer->m_vaddr + size + i * PAGE_SIZE, PageTable::ReadWrite | PageTable::Present);
}
return buffer;
}
ByteRingBuffer::~ByteRingBuffer()
{
if (m_vaddr == 0)
return;
for (size_t i = 0; i < m_capacity / PAGE_SIZE; i++)
{
const paddr_t paddr = PageTable::kernel().physical_address_of(m_vaddr + i * PAGE_SIZE);
if (paddr == 0)
break;
Heap::get().release_page(paddr);
}
PageTable::kernel().unmap_range(m_vaddr, m_capacity * 2);
}
}

View File

@ -17,7 +17,27 @@ namespace Kernel
BAN::ErrorOr<BAN::UniqPtr<ARPTable>> ARPTable::create() BAN::ErrorOr<BAN::UniqPtr<ARPTable>> ARPTable::create()
{ {
return TRY(BAN::UniqPtr<ARPTable>::create()); auto arp_table = TRY(BAN::UniqPtr<ARPTable>::create());
arp_table->m_thread = TRY(Thread::create_kernel(
[](void* arp_table_ptr)
{
auto& arp_table = *reinterpret_cast<ARPTable*>(arp_table_ptr);
arp_table.packet_handle_task();
}, arp_table.ptr()
));
TRY(Processor::scheduler().add_thread(arp_table->m_thread));
return arp_table;
}
ARPTable::ARPTable()
{
}
ARPTable::~ARPTable()
{
if (m_thread)
m_thread->add_signal(SIGKILL, {});
m_thread = nullptr;
} }
BAN::ErrorOr<BAN::MACAddress> ARPTable::get_mac_from_ipv4(NetworkInterface& interface, BAN::IPv4Address ipv4_address) BAN::ErrorOr<BAN::MACAddress> ARPTable::get_mac_from_ipv4(NetworkInterface& interface, BAN::IPv4Address ipv4_address)
@ -44,7 +64,7 @@ namespace Kernel
ipv4_address = interface.get_gateway(); ipv4_address = interface.get_gateway();
{ {
SpinLockGuard _(m_arp_table_lock); SpinLockGuard _(m_table_lock);
auto it = m_arp_table.find(ipv4_address); auto it = m_arp_table.find(ipv4_address);
if (it != m_arp_table.end()) if (it != m_arp_table.end())
return it->value; return it->value;
@ -67,7 +87,7 @@ namespace Kernel
while (SystemTimer::get().ms_since_boot() < timeout) while (SystemTimer::get().ms_since_boot() < timeout)
{ {
{ {
SpinLockGuard _(m_arp_table_lock); SpinLockGuard _(m_table_lock);
auto it = m_arp_table.find(ipv4_address); auto it = m_arp_table.find(ipv4_address);
if (it != m_arp_table.end()) if (it != m_arp_table.end())
return it->value; return it->value;
@ -78,16 +98,8 @@ namespace Kernel
return BAN::Error::from_errno(ETIMEDOUT); return BAN::Error::from_errno(ETIMEDOUT);
} }
BAN::ErrorOr<void> ARPTable::handle_arp_packet(NetworkInterface& interface, BAN::ConstByteSpan buffer) BAN::ErrorOr<void> ARPTable::handle_arp_packet(NetworkInterface& interface, const ARPPacket& packet)
{ {
if (buffer.size() < sizeof(ARPPacket))
{
dwarnln_if(DEBUG_ARP, "Too small ARP packet");
return {};
}
const auto& packet = buffer.as<const ARPPacket>();
if (packet.ptype != EtherType::IPv4) if (packet.ptype != EtherType::IPv4)
{ {
dprintln("Non IPv4 arp packet?"); dprintln("Non IPv4 arp packet?");
@ -100,24 +112,23 @@ namespace Kernel
{ {
if (packet.tpa == interface.get_ipv4_address()) if (packet.tpa == interface.get_ipv4_address())
{ {
const ARPPacket arp_reply { ARPPacket arp_reply;
.htype = 0x0001, arp_reply.htype = 0x0001;
.ptype = EtherType::IPv4, arp_reply.ptype = EtherType::IPv4;
.hlen = 0x06, arp_reply.hlen = 0x06;
.plen = 0x04, arp_reply.plen = 0x04;
.oper = ARPOperation::Reply, arp_reply.oper = ARPOperation::Reply;
.sha = interface.get_mac_address(), arp_reply.sha = interface.get_mac_address();
.spa = interface.get_ipv4_address(), arp_reply.spa = interface.get_ipv4_address();
.tha = packet.sha, arp_reply.tha = packet.sha;
.tpa = packet.spa, arp_reply.tpa = packet.spa;
};
TRY(interface.send_bytes(packet.sha, EtherType::ARP, BAN::ConstByteSpan::from(arp_reply))); TRY(interface.send_bytes(packet.sha, EtherType::ARP, BAN::ConstByteSpan::from(arp_reply)));
} }
break; break;
} }
case ARPOperation::Reply: case ARPOperation::Reply:
{ {
SpinLockGuard _(m_arp_table_lock); SpinLockGuard _(m_table_lock);
auto it = m_arp_table.find(packet.spa); auto it = m_arp_table.find(packet.spa);
if (it != m_arp_table.end()) if (it != m_arp_table.end())
@ -143,4 +154,48 @@ namespace Kernel
return {}; return {};
} }
void ARPTable::packet_handle_task()
{
for (;;)
{
PendingArpPacket pending = ({
SpinLockGuard guard(m_pending_lock);
while (m_pending_packets.empty())
{
SpinLockGuardAsMutex smutex(guard);
m_pending_thread_blocker.block_indefinite(&smutex);
}
auto packet = m_pending_packets.front();
m_pending_packets.pop();
packet;
});
if (auto ret = handle_arp_packet(pending.interface, pending.packet); ret.is_error())
dwarnln("{}", ret.error());
}
}
void ARPTable::add_arp_packet(NetworkInterface& interface, BAN::ConstByteSpan buffer)
{
if (buffer.size() < sizeof(ARPPacket))
{
dwarnln_if(DEBUG_ARP, "ARP packet too small");
return;
}
auto& arp_packet = buffer.as<const ARPPacket>();
SpinLockGuard _(m_pending_lock);
if (m_pending_packets.full())
{
dwarnln_if(DEBUG_ARP, "ARP packet queue full");
return;
}
m_pending_packets.push({ .interface = interface, .packet = arp_packet });
m_pending_thread_blocker.unblock();
}
} }

View File

@ -1,7 +1,6 @@
#include <kernel/IDT.h> #include <kernel/IDT.h>
#include <kernel/InterruptController.h> #include <kernel/InterruptController.h>
#include <kernel/IO.h> #include <kernel/IO.h>
#include <kernel/Lock/SpinLockAsMutex.h>
#include <kernel/Memory/PageTable.h> #include <kernel/Memory/PageTable.h>
#include <kernel/MMIO.h> #include <kernel/MMIO.h>
#include <kernel/Networking/E1000/E1000.h> #include <kernel/Networking/E1000/E1000.h>
@ -58,11 +57,6 @@ namespace Kernel
E1000::~E1000() E1000::~E1000()
{ {
m_thread_should_die = true;
m_thread_blocker.unblock();
while (!m_thread_is_dead)
Processor::yield();
} }
BAN::ErrorOr<void> E1000::initialize() BAN::ErrorOr<void> E1000::initialize()
@ -90,16 +84,6 @@ namespace Kernel
dprintln(" link speed: {} Mbps", speed); dprintln(" link speed: {} Mbps", speed);
} }
auto* thread = TRY(Thread::create_kernel([](void* e1000_ptr) {
static_cast<E1000*>(e1000_ptr)->receive_thread();
}, this));
if (auto ret = Processor::scheduler().add_thread(thread); ret.is_error())
{
delete thread;
return ret.release_error();
}
m_thread_is_dead = false;
return {}; return {};
} }
@ -275,8 +259,10 @@ namespace Kernel
return {}; return {};
} }
BAN::ErrorOr<void> E1000::send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::Span<const BAN::ConstByteSpan> payload) BAN::ErrorOr<void> E1000::send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::ConstByteSpan buffer)
{ {
ASSERT(buffer.size() + sizeof(EthernetHeader) <= E1000_TX_BUFFER_SIZE);
SpinLockGuard _(m_lock); SpinLockGuard _(m_lock);
size_t tx_current = read32(REG_TDT) % E1000_TX_DESCRIPTOR_COUNT; size_t tx_current = read32(REG_TDT) % E1000_TX_DESCRIPTOR_COUNT;
@ -288,38 +274,33 @@ namespace Kernel
ethernet_header.src_mac = get_mac_address(); ethernet_header.src_mac = get_mac_address();
ethernet_header.ether_type = protocol; ethernet_header.ether_type = protocol;
size_t packet_size = sizeof(EthernetHeader); memcpy(tx_buffer + sizeof(EthernetHeader), buffer.data(), buffer.size());
for (const auto& buffer : payload)
{
ASSERT(packet_size + buffer.size() < E1000_TX_BUFFER_SIZE);
memcpy(tx_buffer + packet_size, buffer.data(), buffer.size());
packet_size += buffer.size();
}
auto& descriptor = reinterpret_cast<volatile e1000_tx_desc*>(m_tx_descriptor_region->vaddr())[tx_current]; auto& descriptor = reinterpret_cast<volatile e1000_tx_desc*>(m_tx_descriptor_region->vaddr())[tx_current];
descriptor.length = packet_size; descriptor.length = sizeof(EthernetHeader) + buffer.size();
descriptor.status = 0; descriptor.status = 0;
descriptor.cmd = CMD_EOP | CMD_IFCS | CMD_RS; descriptor.cmd = CMD_EOP | CMD_IFCS | CMD_RS;
// FIXME: there isnt really any reason to wait for transmission
write32(REG_TDT, (tx_current + 1) % E1000_TX_DESCRIPTOR_COUNT); write32(REG_TDT, (tx_current + 1) % E1000_TX_DESCRIPTOR_COUNT);
while (descriptor.status == 0) while (descriptor.status == 0)
continue; continue;
dprintln_if(DEBUG_E1000, "sent {} bytes", packet_size); dprintln_if(DEBUG_E1000, "sent {} bytes", sizeof(EthernetHeader) + buffer.size());
return {}; return {};
} }
void E1000::receive_thread() void E1000::handle_irq()
{ {
const uint32_t icr = read32(REG_ICR);
if (!(icr & (ICR_RxQ0 | ICR_RXT0)))
return;
write32(REG_ICR, icr);
SpinLockGuard _(m_lock); SpinLockGuard _(m_lock);
while (!m_thread_should_die) for (;;) {
{ uint32_t rx_current = (read32(REG_RDT0) + 1) % E1000_RX_DESCRIPTOR_COUNT;
for (;;)
{
const uint32_t rx_current = (read32(REG_RDT0) + 1) % E1000_RX_DESCRIPTOR_COUNT;
auto& descriptor = reinterpret_cast<volatile e1000_rx_desc*>(m_rx_descriptor_region->vaddr())[rx_current]; auto& descriptor = reinterpret_cast<volatile e1000_rx_desc*>(m_rx_descriptor_region->vaddr())[rx_current];
if (!(descriptor.status & 1)) if (!(descriptor.status & 1))
@ -328,36 +309,14 @@ namespace Kernel
dprintln_if(DEBUG_E1000, "got {} bytes", (uint16_t)descriptor.length); dprintln_if(DEBUG_E1000, "got {} bytes", (uint16_t)descriptor.length);
m_lock.unlock(InterruptState::Enabled);
NetworkManager::get().on_receive(*this, BAN::ConstByteSpan { NetworkManager::get().on_receive(*this, BAN::ConstByteSpan {
reinterpret_cast<const uint8_t*>(m_rx_buffer_region->vaddr() + rx_current * E1000_RX_BUFFER_SIZE), reinterpret_cast<const uint8_t*>(m_rx_buffer_region->vaddr() + rx_current * E1000_RX_BUFFER_SIZE),
descriptor.length descriptor.length
}); });
m_lock.lock();
descriptor.status = 0; descriptor.status = 0;
write32(REG_RDT0, rx_current); write32(REG_RDT0, rx_current);
} }
SpinLockAsMutex smutex(m_lock, InterruptState::Enabled);
m_thread_blocker.block_indefinite(&smutex);
}
m_thread_is_dead = true;
}
void E1000::handle_irq()
{
const uint32_t icr = read32(REG_ICR);
write32(REG_ICR, icr);
if (icr & (ICR_RxQ0 | ICR_RXT0))
{
SpinLockGuard _(m_lock);
m_thread_blocker.unblock();
}
} }
} }

View File

@ -21,26 +21,50 @@ namespace Kernel
BAN::ErrorOr<BAN::UniqPtr<IPv4Layer>> IPv4Layer::create() BAN::ErrorOr<BAN::UniqPtr<IPv4Layer>> IPv4Layer::create()
{ {
auto ipv4_manager = TRY(BAN::UniqPtr<IPv4Layer>::create()); auto ipv4_manager = TRY(BAN::UniqPtr<IPv4Layer>::create());
ipv4_manager->m_thread = TRY(Thread::create_kernel(
[](void* ipv4_manager_ptr)
{
auto& ipv4_manager = *reinterpret_cast<IPv4Layer*>(ipv4_manager_ptr);
ipv4_manager.packet_handle_task();
}, ipv4_manager.ptr()
));
TRY(Processor::scheduler().add_thread(ipv4_manager->m_thread));
ipv4_manager->m_pending_packet_buffer = TRY(VirtualRange::create_to_vaddr_range(
PageTable::kernel(),
KERNEL_OFFSET,
~(uintptr_t)0,
pending_packet_buffer_size,
PageTable::Flags::ReadWrite | PageTable::Flags::Present,
true, false
));
ipv4_manager->m_arp_table = TRY(ARPTable::create()); ipv4_manager->m_arp_table = TRY(ARPTable::create());
return ipv4_manager; return ipv4_manager;
} }
static IPv4Header get_ipv4_header(size_t packet_size, BAN::IPv4Address src_ipv4, BAN::IPv4Address dst_ipv4, uint8_t protocol) IPv4Layer::IPv4Layer()
{ }
IPv4Layer::~IPv4Layer()
{ {
IPv4Header header { if (m_thread)
.version_IHL = 0x45, m_thread->add_signal(SIGKILL, {});
.DSCP_ECN = 0x00, m_thread = nullptr;
.total_length = packet_size, }
.identification = 1,
.flags_frament = 0x00, void IPv4Layer::add_ipv4_header(BAN::ByteSpan packet, BAN::IPv4Address src_ipv4, BAN::IPv4Address dst_ipv4, uint8_t protocol) const
.time_to_live = 0x40, {
.protocol = protocol, auto& header = packet.as<IPv4Header>();
.checksum = 0, header.version_IHL = 0x45;
.src_address = src_ipv4, header.DSCP_ECN = 0x00;
.dst_address = dst_ipv4, header.total_length = packet.size();
}; header.identification = 1;
header.checksum = calculate_internet_checksum(BAN::ConstByteSpan::from(header)); header.flags_frament = 0x00;
return header; header.time_to_live = 0x40;
header.protocol = protocol;
header.src_address = src_ipv4;
header.dst_address = dst_ipv4;
header.checksum = 0;
header.checksum = calculate_internet_checksum(BAN::ConstByteSpan::from(header), {});
} }
void IPv4Layer::unbind_socket(uint16_t port) void IPv4Layer::unbind_socket(uint16_t port)
@ -180,7 +204,7 @@ namespace Kernel
return {}; return {};
} }
BAN::ErrorOr<size_t> IPv4Layer::sendto(NetworkSocket& socket, BAN::ConstByteSpan payload, const sockaddr* address, socklen_t address_len) BAN::ErrorOr<size_t> IPv4Layer::sendto(NetworkSocket& socket, BAN::ConstByteSpan buffer, const sockaddr* address, socklen_t address_len)
{ {
if (address->sa_family != AF_INET) if (address->sa_family != AF_INET)
return BAN::Error::from_errno(EINVAL); return BAN::Error::from_errno(EINVAL);
@ -207,63 +231,46 @@ namespace Kernel
if (!receiver) if (!receiver)
return BAN::Error::from_errno(EADDRNOTAVAIL); return BAN::Error::from_errno(EADDRNOTAVAIL);
TRY(socket.interface(receiver->address(), receiver->address_len()));
} }
const auto ipv4_header = get_ipv4_header( BAN::Vector<uint8_t> packet_buffer;
sizeof(IPv4Header) + socket.protocol_header_size() + payload.size(), TRY(packet_buffer.resize(buffer.size() + sizeof(IPv4Header) + socket.protocol_header_size()));
auto packet = BAN::ByteSpan { packet_buffer.span() };
auto pseudo_header = PseudoHeader {
.src_ipv4 = interface->get_ipv4_address(),
.dst_ipv4 = dst_ipv4,
.protocol = socket.protocol()
};
memcpy(
packet.slice(sizeof(IPv4Header)).slice(socket.protocol_header_size()).data(),
buffer.data(),
buffer.size()
);
socket.add_protocol_header(
packet.slice(sizeof(IPv4Header)),
dst_port,
pseudo_header
);
add_ipv4_header(
packet,
interface->get_ipv4_address(), interface->get_ipv4_address(),
dst_ipv4, dst_ipv4,
socket.protocol() socket.protocol()
); );
const auto pseudo_header = PseudoHeader { TRY(interface->send_bytes(dst_mac, EtherType::IPv4, packet));
.src_ipv4 = interface->get_ipv4_address(),
.dst_ipv4 = dst_ipv4,
.protocol = socket.protocol(),
.length = socket.protocol_header_size() + payload.size()
};
uint8_t protocol_header_buffer[32]; return buffer.size();
ASSERT(socket.protocol_header_size() < sizeof(protocol_header_buffer));
auto protocol_header = BAN::ByteSpan::from(protocol_header_buffer).slice(0, socket.protocol_header_size());
socket.get_protocol_header(protocol_header, payload, dst_port, pseudo_header);
BAN::ConstByteSpan buffers[] {
BAN::ConstByteSpan::from(ipv4_header),
protocol_header,
payload,
};
TRY(interface->send_bytes(dst_mac, EtherType::IPv4, { buffers, sizeof(buffers) / sizeof(*buffers) }));
return payload.size();
} }
BAN::ErrorOr<void> IPv4Layer::handle_ipv4_packet(NetworkInterface& interface, BAN::ConstByteSpan packet) BAN::ErrorOr<void> IPv4Layer::handle_ipv4_packet(NetworkInterface& interface, BAN::ByteSpan packet)
{ {
if (packet.size() < sizeof(IPv4Header)) ASSERT(packet.size() >= sizeof(IPv4Header));
{
dwarnln_if(DEBUG_IPV4, "Too small IPv4 packet");
return {};
}
auto& ipv4_header = packet.as<const IPv4Header>(); auto& ipv4_header = packet.as<const IPv4Header>();
if (calculate_internet_checksum(BAN::ConstByteSpan::from(ipv4_header)) != 0) auto ipv4_data = packet.slice(sizeof(IPv4Header));
{
dwarnln_if(DEBUG_IPV4, "IPv4 packet checksum failed");
return {};
}
if (ipv4_header.total_length > packet.size() || ipv4_header.total_length > interface.payload_mtu() || ipv4_header.total_length < sizeof(IPv4Header))
{
if (ipv4_header.flags_frament & IPv4Flags::DF)
dwarnln_if(DEBUG_IPV4, "Invalid IPv4 packet");
else
dwarnln_if(DEBUG_IPV4, "IPv4 fragmentation not supported");
return {};
}
auto ipv4_data = packet.slice(0, ipv4_header.total_length).slice(sizeof(IPv4Header));
auto src_ipv4 = ipv4_header.src_address; auto src_ipv4 = ipv4_header.src_address;
@ -286,33 +293,14 @@ namespace Kernel
{ {
auto dst_mac = TRY(m_arp_table->get_mac_from_ipv4(interface, src_ipv4)); auto dst_mac = TRY(m_arp_table->get_mac_from_ipv4(interface, src_ipv4));
auto send_ipv4_header = get_ipv4_header( auto& reply_icmp_header = ipv4_data.as<ICMPHeader>();
ipv4_data.size(), reply_icmp_header.type = ICMPType::EchoReply;
interface.get_ipv4_address(), reply_icmp_header.checksum = 0;
src_ipv4, reply_icmp_header.checksum = calculate_internet_checksum(ipv4_data, {});
NetworkProtocol::ICMP
);
ICMPHeader send_icmp_header { add_ipv4_header(packet, interface.get_ipv4_address(), src_ipv4, NetworkProtocol::ICMP);
.type = ICMPType::EchoReply,
.code = icmp_header.code,
.checksum = 0,
.rest = icmp_header.rest,
};
auto send_payload = ipv4_data.slice(sizeof(ICMPHeader));
const BAN::ConstByteSpan send_buffers[] {
BAN::ConstByteSpan::from(send_ipv4_header),
BAN::ConstByteSpan::from(send_icmp_header),
send_payload
};
auto send_buffers_span = BAN::Span { send_buffers, sizeof(send_buffers) / sizeof(*send_buffers) };
send_icmp_header.checksum = calculate_internet_checksum(send_buffers_span.slice(1));
TRY(interface.send_bytes(dst_mac, EtherType::IPv4, send_buffers_span));
TRY(interface.send_bytes(dst_mac, EtherType::IPv4, packet));
break; break;
} }
case ICMPType::DestinationUnreachable: case ICMPType::DestinationUnreachable:
@ -394,4 +382,80 @@ namespace Kernel
return {}; return {};
} }
void IPv4Layer::packet_handle_task()
{
for (;;)
{
PendingIPv4Packet pending = ({
SpinLockGuard guard(m_pending_lock);
while (m_pending_packets.empty())
{
SpinLockGuardAsMutex smutex(guard);
m_pending_thread_blocker.block_indefinite(&smutex);
}
auto packet = m_pending_packets.front();
m_pending_packets.pop();
packet;
});
uint8_t* buffer_start = reinterpret_cast<uint8_t*>(m_pending_packet_buffer->vaddr());
const size_t ipv4_packet_size = reinterpret_cast<const IPv4Header*>(buffer_start)->total_length;
if (auto ret = handle_ipv4_packet(pending.interface, BAN::ByteSpan(buffer_start, ipv4_packet_size)); ret.is_error())
dwarnln_if(DEBUG_IPV4, "{}", ret.error());
SpinLockGuard _(m_pending_lock);
m_pending_total_size -= ipv4_packet_size;
if (m_pending_total_size)
memmove(buffer_start, buffer_start + ipv4_packet_size, m_pending_total_size);
}
}
void IPv4Layer::add_ipv4_packet(NetworkInterface& interface, BAN::ConstByteSpan buffer)
{
if (buffer.size() < sizeof(IPv4Header))
{
dwarnln_if(DEBUG_IPV4, "IPv4 packet too small");
return;
}
SpinLockGuard _(m_pending_lock);
if (m_pending_packets.full())
{
dwarnln_if(DEBUG_IPV4, "IPv4 packet queue full");
return;
}
if (m_pending_total_size + buffer.size() > m_pending_packet_buffer->size())
{
dwarnln_if(DEBUG_IPV4, "IPv4 packet queue full");
return;
}
auto& ipv4_header = buffer.as<const IPv4Header>();
if (calculate_internet_checksum(BAN::ConstByteSpan::from(ipv4_header), {}) != 0)
{
dwarnln_if(DEBUG_IPV4, "Invalid IPv4 packet");
return;
}
if (ipv4_header.total_length > buffer.size() || ipv4_header.total_length > interface.payload_mtu())
{
if (ipv4_header.flags_frament & IPv4Flags::DF)
dwarnln_if(DEBUG_IPV4, "Invalid IPv4 packet");
else
dwarnln_if(DEBUG_IPV4, "IPv4 fragmentation not supported");
return;
}
uint8_t* buffer_start = reinterpret_cast<uint8_t*>(m_pending_packet_buffer->vaddr());
memcpy(buffer_start + m_pending_total_size, buffer.data(), ipv4_header.total_length);
m_pending_total_size += ipv4_header.total_length;
m_pending_packets.push({ .interface = interface });
m_pending_thread_blocker.unblock();
}
} }

View File

@ -1,4 +1,3 @@
#include <kernel/Lock/LockGuard.h>
#include <kernel/Networking/Loopback.h> #include <kernel/Networking/Loopback.h>
#include <kernel/Networking/NetworkManager.h> #include <kernel/Networking/NetworkManager.h>
@ -11,121 +10,40 @@ namespace Kernel
if (loopback_ptr == nullptr) if (loopback_ptr == nullptr)
return BAN::Error::from_errno(ENOMEM); return BAN::Error::from_errno(ENOMEM);
auto loopback = BAN::RefPtr<LoopbackInterface>::adopt(loopback_ptr); auto loopback = BAN::RefPtr<LoopbackInterface>::adopt(loopback_ptr);
loopback->m_buffer = TRY(VirtualRange::create_to_vaddr_range( loopback->m_buffer = TRY(VirtualRange::create_to_vaddr_range(
PageTable::kernel(), PageTable::kernel(),
KERNEL_OFFSET, KERNEL_OFFSET,
BAN::numeric_limits<vaddr_t>::max(), BAN::numeric_limits<vaddr_t>::max(),
buffer_size * buffer_count, buffer_size,
PageTable::Flags::ReadWrite | PageTable::Flags::Present, PageTable::Flags::ReadWrite | PageTable::Flags::Present,
true, false true, false
)); ));
auto* thread = TRY(Thread::create_kernel([](void* loopback_ptr) {
static_cast<LoopbackInterface*>(loopback_ptr)->receive_thread();
}, loopback_ptr));
if (auto ret = Processor::scheduler().add_thread(thread); ret.is_error())
{
delete thread;
return ret.release_error();
}
loopback->m_thread_is_dead = false;
loopback->set_ipv4_address({ 127, 0, 0, 1 }); loopback->set_ipv4_address({ 127, 0, 0, 1 });
loopback->set_netmask({ 255, 0, 0, 0 }); loopback->set_netmask({ 255, 0, 0, 0 });
for (size_t i = 0; i < buffer_count; i++)
{
loopback->m_descriptors[i] = {
.addr = reinterpret_cast<uint8_t*>(loopback->m_buffer->vaddr()) + i * buffer_size,
.size = 0,
.state = 0,
};
}
return loopback; return loopback;
} }
LoopbackInterface::~LoopbackInterface() BAN::ErrorOr<void> LoopbackInterface::send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::ConstByteSpan buffer)
{ {
m_thread_should_die = true; ASSERT(buffer.size() + sizeof(EthernetHeader) <= buffer_size);
m_thread_blocker.unblock();
while (!m_thread_is_dead) SpinLockGuard _(m_buffer_lock);
Processor::yield();
}
BAN::ErrorOr<void> LoopbackInterface::send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::Span<const BAN::ConstByteSpan> payload) uint8_t* buffer_vaddr = reinterpret_cast<uint8_t*>(m_buffer->vaddr());
{
auto& descriptor =
[&]() -> Descriptor&
{
LockGuard _(m_buffer_lock);
for (;;)
{
auto& descriptor = m_descriptors[m_buffer_head];
if (descriptor.state == 0)
{
m_buffer_head = (m_buffer_head + 1) % buffer_count;
descriptor.state = 1;
return descriptor;
}
m_thread_blocker.block_indefinite(&m_buffer_lock);
}
}();
auto& ethernet_header = *reinterpret_cast<EthernetHeader*>(descriptor.addr); auto& ethernet_header = *reinterpret_cast<EthernetHeader*>(buffer_vaddr);
ethernet_header.dst_mac = destination; ethernet_header.dst_mac = destination;
ethernet_header.src_mac = get_mac_address(); ethernet_header.src_mac = get_mac_address();
ethernet_header.ether_type = protocol; ethernet_header.ether_type = protocol;
size_t packet_size = sizeof(EthernetHeader); memcpy(buffer_vaddr + sizeof(EthernetHeader), buffer.data(), buffer.size());
for (const auto& buffer : payload)
{
ASSERT(packet_size + buffer.size() <= buffer_size);
memcpy(descriptor.addr + packet_size, buffer.data(), buffer.size());
packet_size += buffer.size();
}
LockGuard _(m_buffer_lock); NetworkManager::get().on_receive(*this, BAN::ConstByteSpan {
descriptor.size = packet_size; buffer_vaddr,
descriptor.state = 2; buffer.size() + sizeof(EthernetHeader)
m_thread_blocker.unblock(); });
return {}; return {};
} }
void LoopbackInterface::receive_thread()
{
LockGuard _(m_buffer_lock);
while (!m_thread_should_die)
{
for (;;)
{
auto& descriptor = m_descriptors[m_buffer_tail];
if (descriptor.state != 2)
break;
m_buffer_tail = (m_buffer_tail + 1) % buffer_count;
m_buffer_lock.unlock();
NetworkManager::get().on_receive(*this, {
descriptor.addr,
descriptor.size,
});
m_buffer_lock.lock();
descriptor.size = 0;
descriptor.state = 0;
m_thread_blocker.unblock();
}
m_thread_blocker.block_indefinite(&m_buffer_lock);
}
m_thread_is_dead = true;
}
} }

View File

@ -3,28 +3,15 @@
namespace Kernel namespace Kernel
{ {
uint16_t calculate_internet_checksum(BAN::ConstByteSpan buffer) uint16_t calculate_internet_checksum(BAN::ConstByteSpan packet, const PseudoHeader& pseudo_header)
{
return calculate_internet_checksum({ &buffer, 1 });
}
uint16_t calculate_internet_checksum(BAN::Span<const BAN::ConstByteSpan> buffers)
{ {
uint32_t checksum = 0; uint32_t checksum = 0;
for (size_t i = 0; i < sizeof(pseudo_header) / sizeof(uint16_t); i++)
for (size_t i = 0; i < buffers.size(); i++) checksum += BAN::host_to_network_endian(reinterpret_cast<const uint16_t*>(&pseudo_header)[i]);
{ for (size_t i = 0; i < packet.size() / sizeof(uint16_t); i++)
auto buffer = buffers[i]; checksum += BAN::host_to_network_endian(reinterpret_cast<const uint16_t*>(packet.data())[i]);
if (packet.size() % 2)
const uint16_t* buffer_u16 = reinterpret_cast<const uint16_t*>(buffer.data()); checksum += (uint16_t)packet[packet.size() - 1] << 8;
for (size_t j = 0; j < buffer.size() / 2; j++)
checksum += BAN::host_to_network_endian(buffer_u16[j]);
if (buffer.size() % 2 == 0)
continue;
ASSERT(i == buffers.size() - 1);
checksum += buffer[buffer.size() - 1] << 8;
}
while (checksum >> 16) while (checksum >> 16)
checksum = (checksum >> 16) + (checksum & 0xFFFF); checksum = (checksum >> 16) + (checksum & 0xFFFF);
return ~(uint16_t)checksum; return ~(uint16_t)checksum;

View File

@ -154,18 +154,18 @@ namespace Kernel
return; return;
auto ethernet_header = packet.as<const EthernetHeader>(); auto ethernet_header = packet.as<const EthernetHeader>();
auto packet_data = packet.slice(sizeof(EthernetHeader));
switch (ethernet_header.ether_type) switch (ethernet_header.ether_type)
{ {
case EtherType::ARP: case EtherType::ARP:
if (auto ret = m_ipv4_layer->arp_table().handle_arp_packet(interface, packet_data); ret.is_error()) {
dwarnln("ARP: {}", ret.error()); m_ipv4_layer->arp_table().add_arp_packet(interface, packet.slice(sizeof(EthernetHeader)));
break; break;
}
case EtherType::IPv4: case EtherType::IPv4:
if (auto ret = m_ipv4_layer->handle_ipv4_packet(interface, packet_data); ret.is_error()) {
dwarnln("IPv4; {}", ret.error()); m_ipv4_layer->add_ipv4_packet(interface, packet.slice(sizeof(EthernetHeader)));
break; break;
}
default: default:
dprintln_if(DEBUG_ETHERTYPE, "Unknown EtherType 0x{4H}", (uint16_t)ethernet_header.ether_type); dprintln_if(DEBUG_ETHERTYPE, "Unknown EtherType 0x{4H}", (uint16_t)ethernet_header.ether_type);
break; break;

View File

@ -7,9 +7,6 @@
namespace Kernel namespace Kernel
{ {
// each buffer is 7440 bytes + padding = 8192
constexpr size_t s_buffer_size = 8192;
bool RTL8169::probe(PCI::Device& pci_device) bool RTL8169::probe(PCI::Device& pci_device)
{ {
if (pci_device.vendor_id() != 0x10ec) if (pci_device.vendor_id() != 0x10ec)
@ -71,28 +68,9 @@ namespace Kernel
// lock config registers // lock config registers
m_io_bar_region->write8(RTL8169_IO_9346CR, RTL8169_9346CR_MODE_NORMAL); m_io_bar_region->write8(RTL8169_IO_9346CR, RTL8169_9346CR_MODE_NORMAL);
auto* thread = TRY(Thread::create_kernel([](void* rtl8169_ptr) {
static_cast<RTL8169*>(rtl8169_ptr)->receive_thread();
}, this));
if (auto ret = Processor::scheduler().add_thread(thread); ret.is_error())
{
delete thread;
return ret.release_error();
}
m_thread_is_dead = false;
return {}; return {};
} }
RTL8169::~RTL8169()
{
m_thread_should_die = true;
m_thread_blocker.unblock();
while (!m_thread_is_dead)
Processor::yield();
}
BAN::ErrorOr<void> RTL8169::reset() BAN::ErrorOr<void> RTL8169::reset()
{ {
m_io_bar_region->write8(RTL8169_IO_CR, RTL8169_CR_RST); m_io_bar_region->write8(RTL8169_IO_CR, RTL8169_CR_RST);
@ -107,12 +85,15 @@ namespace Kernel
BAN::ErrorOr<void> RTL8169::initialize_rx() BAN::ErrorOr<void> RTL8169::initialize_rx()
{ {
m_rx_buffer_region = TRY(DMARegion::create(m_rx_descriptor_count * s_buffer_size)); // each buffer is 7440 bytes + padding = 8192
constexpr size_t buffer_size = 2 * PAGE_SIZE;
m_rx_buffer_region = TRY(DMARegion::create(m_rx_descriptor_count * buffer_size));
m_rx_descriptor_region = TRY(DMARegion::create(m_rx_descriptor_count * sizeof(RTL8169Descriptor))); m_rx_descriptor_region = TRY(DMARegion::create(m_rx_descriptor_count * sizeof(RTL8169Descriptor)));
for (size_t i = 0; i < m_rx_descriptor_count; i++) for (size_t i = 0; i < m_rx_descriptor_count; i++)
{ {
const paddr_t rx_buffer_paddr = m_rx_buffer_region->paddr() + i * s_buffer_size; const paddr_t rx_buffer_paddr = m_rx_buffer_region->paddr() + i * buffer_size;
uint32_t command = 0x1FF8 | RTL8169_DESC_CMD_OWN; uint32_t command = 0x1FF8 | RTL8169_DESC_CMD_OWN;
if (i == m_rx_descriptor_count - 1) if (i == m_rx_descriptor_count - 1)
@ -139,17 +120,21 @@ namespace Kernel
// configure max rx packet size // configure max rx packet size
m_io_bar_region->write16(RTL8169_IO_RMS, RTL8169_RMS_MAX); m_io_bar_region->write16(RTL8169_IO_RMS, RTL8169_RMS_MAX);
return {}; return {};
} }
BAN::ErrorOr<void> RTL8169::initialize_tx() BAN::ErrorOr<void> RTL8169::initialize_tx()
{ {
m_tx_buffer_region = TRY(DMARegion::create(m_tx_descriptor_count * s_buffer_size)); // each buffer is 7440 bytes + padding = 8192
constexpr size_t buffer_size = 2 * PAGE_SIZE;
m_tx_buffer_region = TRY(DMARegion::create(m_tx_descriptor_count * buffer_size));
m_tx_descriptor_region = TRY(DMARegion::create(m_tx_descriptor_count * sizeof(RTL8169Descriptor))); m_tx_descriptor_region = TRY(DMARegion::create(m_tx_descriptor_count * sizeof(RTL8169Descriptor)));
for (size_t i = 0; i < m_tx_descriptor_count; i++) for (size_t i = 0; i < m_tx_descriptor_count; i++)
{ {
const paddr_t tx_buffer_paddr = m_tx_buffer_region->paddr() + i * s_buffer_size; const paddr_t tx_buffer_paddr = m_tx_buffer_region->paddr() + i * buffer_size;
uint32_t command = 0; uint32_t command = 0;
if (i == m_tx_descriptor_count - 1) if (i == m_tx_descriptor_count - 1)
@ -209,8 +194,14 @@ namespace Kernel
return 0; return 0;
} }
BAN::ErrorOr<void> RTL8169::send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::Span<const BAN::ConstByteSpan> payload) BAN::ErrorOr<void> RTL8169::send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::ConstByteSpan buffer)
{ {
constexpr size_t buffer_size = 8192;
const uint16_t packet_size = sizeof(EthernetHeader) + buffer.size();
if (packet_size > buffer_size)
return BAN::Error::from_errno(EINVAL);
if (!link_up()) if (!link_up())
return BAN::Error::from_errno(EADDRNOTAVAIL); return BAN::Error::from_errno(EADDRNOTAVAIL);
@ -228,20 +219,14 @@ namespace Kernel
m_lock.unlock(state); m_lock.unlock(state);
auto* tx_buffer = reinterpret_cast<uint8_t*>(m_tx_buffer_region->vaddr() + tx_current * s_buffer_size); auto* tx_buffer = reinterpret_cast<uint8_t*>(m_tx_buffer_region->vaddr() + tx_current * buffer_size);
// write packet // write packet
auto& ethernet_header = *reinterpret_cast<EthernetHeader*>(tx_buffer); auto& ethernet_header = *reinterpret_cast<EthernetHeader*>(tx_buffer);
ethernet_header.dst_mac = destination; ethernet_header.dst_mac = destination;
ethernet_header.src_mac = get_mac_address(); ethernet_header.src_mac = get_mac_address();
ethernet_header.ether_type = protocol; ethernet_header.ether_type = protocol;
memcpy(tx_buffer + sizeof(EthernetHeader), buffer.data(), buffer.size());
size_t packet_size = sizeof(EthernetHeader);
for (const auto& buffer : payload)
{
memcpy(tx_buffer + packet_size, buffer.data(), buffer.size());
packet_size += buffer.size();
}
// give packet ownership to NIC // give packet ownership to NIC
uint32_t command = packet_size | RTL8169_DESC_CMD_OWN | RTL8169_DESC_CMD_LS | RTL8169_DESC_CMD_FS; uint32_t command = packet_size | RTL8169_DESC_CMD_OWN | RTL8169_DESC_CMD_LS | RTL8169_DESC_CMD_FS;
@ -255,50 +240,6 @@ namespace Kernel
return {}; return {};
} }
void RTL8169::receive_thread()
{
SpinLockGuard _(m_lock);
while (!m_thread_should_die)
{
for (;;)
{
auto& descriptor = reinterpret_cast<volatile RTL8169Descriptor*>(m_rx_descriptor_region->vaddr())[m_rx_current];
if (descriptor.command & RTL8169_DESC_CMD_OWN)
break;
// packet buffer can only hold single packet, so we should not receive any multi-descriptor packets
ASSERT((descriptor.command & RTL8169_DESC_CMD_LS) && (descriptor.command & RTL8169_DESC_CMD_FS));
const uint16_t packet_length = descriptor.command & 0x3FFF;
if (packet_length > s_buffer_size)
dwarnln("Got {} bytes to {} byte buffer", packet_length, s_buffer_size);
else if (descriptor.command & (1u << 21))
; // descriptor has an error
else
{
m_lock.unlock(InterruptState::Enabled);
NetworkManager::get().on_receive(*this, BAN::ConstByteSpan {
reinterpret_cast<const uint8_t*>(m_rx_buffer_region->vaddr() + m_rx_current * s_buffer_size),
packet_length
});
m_lock.lock();
}
m_rx_current = (m_rx_current + 1) % m_rx_descriptor_count;
descriptor.command = descriptor.command | RTL8169_DESC_CMD_OWN;
}
SpinLockAsMutex smutex(m_lock, InterruptState::Enabled);
m_thread_blocker.block_indefinite(&smutex);
}
m_thread_is_dead = true;
}
void RTL8169::handle_irq() void RTL8169::handle_irq()
{ {
const uint16_t interrupt_status = m_io_bar_region->read16(RTL8169_IO_ISR); const uint16_t interrupt_status = m_io_bar_region->read16(RTL8169_IO_ISR);
@ -310,7 +251,7 @@ namespace Kernel
dprintln("link status -> {}", m_link_up.load()); dprintln("link status -> {}", m_link_up.load());
} }
if (interrupt_status & (RTL8169_IR_TOK | RTL8169_IR_ROK)) if (interrupt_status & RTL8169_IR_TOK)
{ {
SpinLockGuard _(m_lock); SpinLockGuard _(m_lock);
m_thread_blocker.unblock(); m_thread_blocker.unblock();
@ -325,6 +266,38 @@ namespace Kernel
if (interrupt_status & RTL8169_IR_FVOW) if (interrupt_status & RTL8169_IR_FVOW)
dwarnln("Rx FIFO overflow"); dwarnln("Rx FIFO overflow");
// dont log TDU is sent after each sent packet // dont log TDU is sent after each sent packet
if (!(interrupt_status & RTL8169_IR_ROK))
return;
constexpr size_t buffer_size = 8192;
for (;;)
{
auto& descriptor = reinterpret_cast<volatile RTL8169Descriptor*>(m_rx_descriptor_region->vaddr())[m_rx_current];
if (descriptor.command & RTL8169_DESC_CMD_OWN)
break;
// packet buffer can only hold single packet, so we should not receive any multi-descriptor packets
ASSERT((descriptor.command & RTL8169_DESC_CMD_LS) && (descriptor.command & RTL8169_DESC_CMD_FS));
const uint16_t packet_length = descriptor.command & 0x3FFF;
if (packet_length > buffer_size)
dwarnln("Got {} bytes to {} byte buffer", packet_length, buffer_size);
else if (descriptor.command & (1u << 21))
; // descriptor has an error
else
{
NetworkManager::get().on_receive(*this, BAN::ConstByteSpan {
reinterpret_cast<const uint8_t*>(m_rx_buffer_region->vaddr() + m_rx_current * buffer_size),
packet_length
});
}
m_rx_current = (m_rx_current + 1) % m_rx_descriptor_count;
descriptor.command = descriptor.command | RTL8169_DESC_CMD_OWN;
}
} }
} }

View File

@ -7,7 +7,6 @@
#include <fcntl.h> #include <fcntl.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <netinet/tcp.h>
#include <sys/epoll.h> #include <sys/epoll.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
@ -25,19 +24,26 @@ namespace Kernel
static constexpr size_t s_recv_window_buffer_size = 16 * PAGE_SIZE; static constexpr size_t s_recv_window_buffer_size = 16 * PAGE_SIZE;
static constexpr size_t s_send_window_buffer_size = 16 * PAGE_SIZE; static constexpr size_t s_send_window_buffer_size = 16 * PAGE_SIZE;
// allows upto 1 MiB windows
static constexpr uint8_t s_window_shift = 4;
// https://www.rfc-editor.org/rfc/rfc1122 4.2.2.6
static constexpr uint16_t s_default_mss = 536;
BAN::ErrorOr<BAN::RefPtr<TCPSocket>> TCPSocket::create(NetworkLayer& network_layer, const Info& info) BAN::ErrorOr<BAN::RefPtr<TCPSocket>> TCPSocket::create(NetworkLayer& network_layer, const Info& info)
{ {
auto socket = TRY(BAN::RefPtr<TCPSocket>::create(network_layer, info)); auto socket = TRY(BAN::RefPtr<TCPSocket>::create(network_layer, info));
socket->m_last_sent_window_size = s_recv_window_buffer_size; socket->m_recv_window.buffer = TRY(VirtualRange::create_to_vaddr_range(
socket->m_recv_window.buffer = TRY(ByteRingBuffer::create(s_recv_window_buffer_size)); PageTable::kernel(),
socket->m_recv_window.scale_shift = s_window_shift; KERNEL_OFFSET,
socket->m_send_window.buffer = TRY(ByteRingBuffer::create(s_send_window_buffer_size)); ~(vaddr_t)0,
s_recv_window_buffer_size,
PageTable::Flags::ReadWrite | PageTable::Flags::Present,
true, false
));
socket->m_recv_window.scale_shift = PAGE_SIZE_SHIFT; // use PAGE_SIZE windows
socket->m_send_window.buffer = TRY(VirtualRange::create_to_vaddr_range(
PageTable::kernel(),
KERNEL_OFFSET,
~(vaddr_t)0,
s_send_window_buffer_size,
PageTable::Flags::ReadWrite | PageTable::Flags::Present,
true, false
));
socket->m_thread = TRY(Thread::create_kernel( socket->m_thread = TRY(Thread::create_kernel(
[](void* socket_ptr) [](void* socket_ptr)
{ {
@ -94,13 +100,12 @@ namespace Kernel
return_inode->m_listen_parent = this; return_inode->m_listen_parent = this;
return_inode->m_connection_info.emplace(connection.target); return_inode->m_connection_info.emplace(connection.target);
return_inode->m_recv_window.start_seq = connection.target_start_seq; return_inode->m_recv_window.start_seq = connection.target_start_seq;
return_inode->m_send_window.scale_shift = connection.window_scale;
return_inode->m_send_window.mss = connection.maximum_seqment_size;
return_inode->m_next_flags = SYN | ACK; return_inode->m_next_flags = SYN | ACK;
return_inode->m_next_state = State::SynReceived; return_inode->m_next_state = State::SynReceived;
return_inode->m_mutex.unlock();
if (!return_inode->m_connection_info->has_window_scale) if (!return_inode->m_connection_info->has_window_scale)
return_inode->m_recv_window.scale_shift = 0; return_inode->m_recv_window.scale_shift = 0;
return_inode->m_mutex.unlock();
TRY(m_listen_children.emplace(listen_key, return_inode)); TRY(m_listen_children.emplace(listen_key, return_inode));
@ -192,7 +197,8 @@ namespace Kernel
BAN::ErrorOr<size_t> TCPSocket::recvmsg_impl(msghdr& message, int flags) BAN::ErrorOr<size_t> TCPSocket::recvmsg_impl(msghdr& message, int flags)
{ {
if (flags & ~(MSG_PEEK)) flags &= (MSG_OOB | MSG_PEEK | MSG_WAITALL);
if (flags != 0)
{ {
dwarnln("TODO: recvmsg with flags 0x{H}", flags); dwarnln("TODO: recvmsg with flags 0x{H}", flags);
return BAN::Error::from_errno(ENOTSUP); return BAN::Error::from_errno(ENOTSUP);
@ -200,14 +206,14 @@ namespace Kernel
if (CMSG_FIRSTHDR(&message)) if (CMSG_FIRSTHDR(&message))
{ {
dprintln_if(DEBUG_TCP, "ignoring recvmsg control message"); dwarnln("ignoring recvmsg control message");
message.msg_controllen = 0; message.msg_controllen = 0;
} }
if (!m_has_connected) if (!m_has_connected)
return BAN::Error::from_errno(ENOTCONN); return BAN::Error::from_errno(ENOTCONN);
while (m_recv_window.buffer->empty()) while (m_recv_window.data_size == 0)
{ {
if (m_state != State::Established) if (m_state != State::Established)
return return_with_maybe_zero(); return return_with_maybe_zero();
@ -217,34 +223,21 @@ namespace Kernel
message.msg_flags = 0; message.msg_flags = 0;
size_t total_recv = 0; size_t total_recv = 0;
for (int i = 0; i < message.msg_iovlen && total_recv < m_recv_window.buffer->size(); i++) for (int i = 0; i < message.msg_iovlen; i++)
{ {
auto& iov = message.msg_iov[i]; auto* recv_buffer = reinterpret_cast<uint8_t*>(m_recv_window.buffer->vaddr());
const size_t nrecv = BAN::Math::min(iov.iov_len, m_recv_window.buffer->size() - total_recv); const size_t nrecv = BAN::Math::min<size_t>(message.msg_iov[i].iov_len, m_recv_window.data_size);
memcpy(iov.iov_base, m_recv_window.buffer->get_data().data() + total_recv, nrecv); memcpy(message.msg_iov[i].iov_base, recv_buffer, nrecv);
total_recv += nrecv; total_recv += nrecv;
} m_recv_window.data_size -= nrecv;
m_recv_window.start_seq += nrecv;
if (m_recv_window.data_size == 0)
break;
if (!(flags & MSG_PEEK)) // TODO: use circular buffer to avoid this
{ memmove(recv_buffer, recv_buffer + nrecv, m_recv_window.data_size);
m_recv_window.buffer->pop(total_recv);
m_recv_window.start_seq += total_recv;
}
const size_t update_window_threshold = m_recv_window.buffer->capacity() / 8;
const bool should_update_window_size =
m_last_sent_window_size != m_recv_window.buffer->capacity() && (
(m_last_sent_window_size == 0) ||
(m_recv_window.buffer->empty()) ||
(m_last_sent_window_size + update_window_threshold <= m_recv_window.buffer->free())
);
if (should_update_window_size || m_should_send_zero_window)
{
m_should_send_window_update = true;
m_thread_blocker.unblock();
} }
return total_recv; return total_recv;
@ -264,7 +257,7 @@ namespace Kernel
if (!m_has_connected) if (!m_has_connected)
return BAN::Error::from_errno(ENOTCONN); return BAN::Error::from_errno(ENOTCONN);
while (m_send_window.buffer->full()) while (m_send_window.data_size == m_send_window.buffer->size())
{ {
if (m_state != State::Established) if (m_state != State::Established)
return return_with_maybe_zero(); return return_with_maybe_zero();
@ -274,14 +267,17 @@ namespace Kernel
} }
size_t total_sent = 0; size_t total_sent = 0;
for (int i = 0; i < message.msg_iovlen && !m_send_window.buffer->full(); i++) for (int i = 0; i < message.msg_iovlen; i++)
{ {
const auto& iov = message.msg_iov[i]; auto* send_buffer = reinterpret_cast<uint8_t*>(m_send_window.buffer->vaddr());
const size_t nsend = BAN::Math::min(iov.iov_len, m_send_window.buffer->free()); const size_t nsend = BAN::Math::min<size_t>(message.msg_iov[i].iov_len, m_send_window.buffer->size() - m_send_window.data_size);
m_send_window.buffer->push({ static_cast<const uint8_t*>(iov.iov_base), nsend }); memcpy(send_buffer + m_send_window.data_size, message.msg_iov[i].iov_base, nsend);
total_sent += nsend; total_sent += nsend;
m_send_window.data_size += nsend;
if (m_send_window.data_size == m_send_window.buffer->size())
break;
} }
m_thread_blocker.unblock(); m_thread_blocker.unblock();
@ -302,16 +298,12 @@ namespace Kernel
BAN::ErrorOr<void> TCPSocket::getsockopt_impl(int level, int option, void* value, socklen_t* value_len) BAN::ErrorOr<void> TCPSocket::getsockopt_impl(int level, int option, void* value, socklen_t* value_len)
{ {
int result; if (level != SOL_SOCKET)
return BAN::Error::from_errno(EINVAL);
switch (level) int result;
{
case SOL_SOCKET:
switch (option) switch (option)
{ {
case SO_KEEPALIVE:
result = m_keep_alive;
break;
case SO_ERROR: case SO_ERROR:
result = 0; result = 0;
break; break;
@ -319,27 +311,10 @@ namespace Kernel
result = m_send_window.scaled_size(); result = m_send_window.scaled_size();
break; break;
case SO_RCVBUF: case SO_RCVBUF:
result = m_recv_window.buffer->capacity(); result = m_recv_window.buffer->size();
break; break;
default: default:
dwarnln("getsockopt(SOL_SOCKET, {})", option); return BAN::Error::from_errno(ENOTSUP);
return BAN::Error::from_errno(ENOPROTOOPT);
}
break;
case IPPROTO_TCP:
switch (option)
{
case TCP_NODELAY:
result = m_no_delay;
break;
default:
dwarnln("getsockopt(IPPROTO_TCP, {})", option);
return BAN::Error::from_errno(ENOPROTOOPT);
}
break;
default:
dwarnln("getsockopt({}, {})", level, option);
return BAN::Error::from_errno(EINVAL);
} }
const size_t len = BAN::Math::min<size_t>(sizeof(result), *value_len); const size_t len = BAN::Math::min<size_t>(sizeof(result), *value_len);
@ -349,50 +324,12 @@ namespace Kernel
return {}; return {};
} }
BAN::ErrorOr<void> TCPSocket::setsockopt_impl(int level, int option, const void* value, socklen_t value_len)
{
switch (level)
{
case SOL_SOCKET:
switch (option)
{
case SO_KEEPALIVE:
if (value_len != sizeof(int))
return BAN::Error::from_errno(EINVAL);
m_keep_alive = *static_cast<const int*>(value);
break;
default:
dwarnln("setsockopt(SOL_SOCKET, {})", option);
return BAN::Error::from_errno(ENOPROTOOPT);
}
break;
case IPPROTO_TCP:
switch (option)
{
case TCP_NODELAY:
if (value_len != sizeof(int))
return BAN::Error::from_errno(EINVAL);
m_no_delay = *static_cast<const int*>(value);
break;
default:
dwarnln("setsockopt(IPPROTO_TCP, {})", option);
return BAN::Error::from_errno(ENOPROTOOPT);
}
break;
default:
dwarnln("setsockopt({}, {})", level, option);
return BAN::Error::from_errno(EINVAL);
}
return {};
}
BAN::ErrorOr<long> TCPSocket::ioctl_impl(int request, void* argument) BAN::ErrorOr<long> TCPSocket::ioctl_impl(int request, void* argument)
{ {
switch (request) switch (request)
{ {
case FIONREAD: case FIONREAD:
*static_cast<int*>(argument) = m_recv_window.buffer->size(); *static_cast<int*>(argument) = m_recv_window.data_size;
return 0; return 0;
} }
@ -405,14 +342,14 @@ namespace Kernel
return true; return true;
if (m_state == State::Listen) if (m_state == State::Listen)
return !m_pending_connections.empty(); return !m_pending_connections.empty();
return !m_recv_window.buffer->empty(); return m_recv_window.data_size > 0;
} }
bool TCPSocket::can_write_impl() const bool TCPSocket::can_write_impl() const
{ {
if (m_state != State::Established) if (m_state != State::Established)
return false; return false;
return !m_send_window.buffer->full(); return m_send_window.data_size < m_send_window.buffer->size();
} }
bool TCPSocket::has_hungup_impl() const bool TCPSocket::has_hungup_impl() const
@ -485,7 +422,7 @@ namespace Kernel
if (header.options[i] == TCPOption::NOP) if (header.options[i] == TCPOption::NOP)
continue; continue;
if (header.options[i] == TCPOption::MaximumSeqmentSize) if (header.options[i] == TCPOption::MaximumSeqmentSize)
result.maximum_seqment_size = BAN::network_endian_to_host(*reinterpret_cast<const uint16_t*>(&header.options[i + 2])); result.maximum_seqment_size = BAN::host_to_network_endian(*reinterpret_cast<const uint16_t*>(&header.options[i + 2]));
if (header.options[i] == TCPOption::WindowScale) if (header.options[i] == TCPOption::WindowScale)
result.window_scale = header.options[i + 2]; result.window_scale = header.options[i + 2];
if (header.options[i + 1] == 0) if (header.options[i + 1] == 0)
@ -496,28 +433,22 @@ namespace Kernel
return result; return result;
} }
void TCPSocket::get_protocol_header(BAN::ByteSpan header_buffer, BAN::ConstByteSpan payload, uint16_t dst_port, PseudoHeader pseudo_header) void TCPSocket::add_protocol_header(BAN::ByteSpan packet, uint16_t dst_port, PseudoHeader pseudo_header)
{ {
ASSERT(m_next_flags); ASSERT(m_next_flags);
ASSERT(m_mutex.locker() == Thread::current().tid()); ASSERT(m_mutex.locker() == Thread::current().tid());
ASSERT(header_buffer.size() == protocol_header_size());
m_last_sent_window_size = m_should_send_zero_window ? 0 : m_recv_window.buffer->free(); auto& header = packet.as<TCPHeader>();
memset(&header, 0, sizeof(TCPHeader));
auto& header = header_buffer.as<TCPHeader>(); memset(header.options, TCPOption::End, m_tcp_options_bytes);
header = {
.src_port = bound_port(),
.dst_port = dst_port,
.seq_number = m_send_window.current_seq + m_send_window.has_ghost_byte,
.ack_number = m_recv_window.start_seq + m_recv_window.buffer->size() + m_recv_window.has_ghost_byte,
.data_offset = (sizeof(TCPHeader) + m_tcp_options_bytes) / sizeof(uint32_t),
.flags = m_next_flags,
.window_size = BAN::Math::min<size_t>(0xFFFF, m_last_sent_window_size >> m_recv_window.scale_shift),
.checksum = 0,
.urgent_pointer = 0,
};
memset(header.options, 0, m_tcp_options_bytes);
header.src_port = bound_port();
header.dst_port = dst_port;
header.seq_number = m_send_window.current_seq + m_send_window.has_ghost_byte;
header.ack_number = m_recv_window.start_seq + m_recv_window.data_size + m_recv_window.has_ghost_byte;
header.data_offset = (sizeof(TCPHeader) + m_tcp_options_bytes) / sizeof(uint32_t);
header.window_size = BAN::Math::min<size_t>(0xFFFF, m_recv_window.buffer->size() >> m_recv_window.scale_shift);
header.flags = m_next_flags;
if (header.flags & FIN) if (header.flags & FIN)
m_send_window.has_ghost_byte = true; m_send_window.has_ghost_byte = true;
m_next_flags = 0; m_next_flags = 0;
@ -536,39 +467,24 @@ namespace Kernel
if (m_connection_info->has_window_scale) if (m_connection_info->has_window_scale)
add_tcp_header_option<4, TCPOption::WindowScale>(header, m_recv_window.scale_shift); add_tcp_header_option<4, TCPOption::WindowScale>(header, m_recv_window.scale_shift);
header.window_size = BAN::Math::min<size_t>(0xFFFF, m_recv_window.buffer->capacity()); header.window_size = BAN::Math::min<size_t>(0xFFFF, m_recv_window.buffer->size());
m_send_window.mss = 1440;
m_send_window.start_seq++; m_send_window.start_seq++;
m_send_window.current_seq = m_send_window.start_seq; m_send_window.current_seq = m_send_window.start_seq;
} }
const BAN::ConstByteSpan buffers[] { pseudo_header.extra = packet.size();
BAN::ConstByteSpan::from(pseudo_header), header.checksum = calculate_internet_checksum(packet, pseudo_header);
header_buffer,
payload,
};
header.checksum = calculate_internet_checksum({ buffers, sizeof(buffers) / sizeof(*buffers) });
dprintln_if(DEBUG_TCP, "sending {} {8b}", (uint8_t)m_state, header.flags); dprintln_if(DEBUG_TCP, "sending {} {8b}", (uint8_t)m_state, header.flags);
dprintln_if(DEBUG_TCP, " ack {}", (uint32_t)header.ack_number); dprintln_if(DEBUG_TCP, " {}", (uint32_t)header.ack_number);
dprintln_if(DEBUG_TCP, " seq {}", (uint32_t)header.seq_number); dprintln_if(DEBUG_TCP, " {}", (uint32_t)header.seq_number);
} }
void TCPSocket::receive_packet(BAN::ConstByteSpan buffer, const sockaddr* sender, socklen_t sender_len) void TCPSocket::receive_packet(BAN::ConstByteSpan buffer, const sockaddr* sender, socklen_t sender_len)
{ {
if (m_state == State::Listen) (void)sender_len;
{
auto socket =
[&]() -> BAN::RefPtr<TCPSocket> {
LockGuard _(m_mutex);
if (auto it = m_listen_children.find(ListenKey(sender, sender_len)); it != m_listen_children.end())
return it->value;
return {};
}();
if (socket)
return socket->receive_packet(buffer, sender, sender_len);
}
{ {
uint16_t checksum = 0; uint16_t checksum = 0;
@ -581,17 +497,14 @@ namespace Kernel
auto interface = interface_or_error.release_value(); auto interface = interface_or_error.release_value();
auto& addr_in = *reinterpret_cast<const sockaddr_in*>(sender); auto& addr_in = *reinterpret_cast<const sockaddr_in*>(sender);
const PseudoHeader pseudo_header { checksum = calculate_internet_checksum(buffer,
PseudoHeader {
.src_ipv4 = BAN::IPv4Address(addr_in.sin_addr.s_addr), .src_ipv4 = BAN::IPv4Address(addr_in.sin_addr.s_addr),
.dst_ipv4 = interface->get_ipv4_address(), .dst_ipv4 = interface->get_ipv4_address(),
.protocol = NetworkProtocol::TCP, .protocol = NetworkProtocol::TCP,
.length = buffer.size(), .extra = buffer.size()
}; }
const BAN::ConstByteSpan buffers[] { );
BAN::ConstByteSpan::from(pseudo_header),
buffer
};
checksum = calculate_internet_checksum({ buffers, sizeof(buffers) / sizeof(*buffers) });
} }
else else
{ {
@ -611,14 +524,11 @@ namespace Kernel
const bool hungup_before = has_hungup_impl(); const bool hungup_before = has_hungup_impl();
auto& header = buffer.as<const TCPHeader>(); auto& header = buffer.as<const TCPHeader>();
dprintln_if(DEBUG_TCP, "receiving {} {8b}", (uint8_t)m_state, header.flags); dprintln_if(DEBUG_TCP, "receiving {} {8b}", (uint8_t)m_state, header.flags);
dprintln_if(DEBUG_TCP, " ack {}", (uint32_t)header.ack_number); dprintln_if(DEBUG_TCP, " {}", (uint32_t)header.ack_number);
dprintln_if(DEBUG_TCP, " seq {}", (uint32_t)header.seq_number); dprintln_if(DEBUG_TCP, " {}", (uint32_t)header.seq_number);
m_send_window.non_scaled_size = header.window_size; m_send_window.non_scaled_size = header.window_size;
if (m_send_window.scaled_size() == 0)
m_send_window.had_zero_window = true;
bool check_payload = false; bool check_payload = false;
switch (m_state) switch (m_state)
@ -637,7 +547,8 @@ namespace Kernel
} }
auto options = parse_tcp_options(header); auto options = parse_tcp_options(header);
m_send_window.mss = options.maximum_seqment_size.value_or(s_default_mss); if (options.maximum_seqment_size.has_value())
m_send_window.mss = *options.maximum_seqment_size;
if (options.window_scale.has_value()) if (options.window_scale.has_value())
m_send_window.scale_shift = *options.window_scale; m_send_window.scale_shift = *options.window_scale;
else else
@ -662,34 +573,44 @@ namespace Kernel
m_has_connected = true; m_has_connected = true;
break; break;
case State::Listen: case State::Listen:
if (header.flags != SYN) if (header.flags == SYN)
dprintln_if(DEBUG_TCP, "Unexpected packet to listening socket"); {
else if (m_pending_connections.size() == m_pending_connections.capacity()) if (m_pending_connections.size() == m_pending_connections.capacity())
dprintln_if(DEBUG_TCP, "No storage to store pending connection"); dprintln_if(DEBUG_TCP, "No storage to store pending connection");
else else
{ {
const auto options = parse_tcp_options(header);
ConnectionInfo connection_info; ConnectionInfo connection_info;
memcpy(&connection_info.address, sender, sender_len); memcpy(&connection_info.address, sender, sender_len);
connection_info.address_len = sender_len; connection_info.address_len = sender_len;
connection_info.has_window_scale = options.window_scale.has_value(); connection_info.has_window_scale = parse_tcp_options(header).window_scale.has_value();
MUST(m_pending_connections.emplace( MUST(m_pending_connections.emplace(
connection_info, connection_info,
header.seq_number + 1, header.seq_number + 1
options.maximum_seqment_size.value_or(s_default_mss),
options.window_scale.value_or(0)
)); ));
epoll_notify(EPOLLIN); epoll_notify(EPOLLIN);
m_thread_blocker.unblock(); m_thread_blocker.unblock();
} }
}
else
{
auto it = m_listen_children.find(ListenKey(sender, sender_len));
if (it == m_listen_children.end())
{
dprintln_if(DEBUG_TCP, "Unexpected packet to listening socket");
break;
}
auto socket = it->value;
m_mutex.unlock();
socket->receive_packet(buffer, sender, sender_len);
m_mutex.lock();
}
return; return;
case State::Established: case State::Established:
check_payload = true; check_payload = true;
if (!(header.flags & FIN)) if (!(header.flags & FIN))
break; break;
if (m_recv_window.start_seq + m_recv_window.buffer->size() != header.seq_number) if (m_recv_window.start_seq + m_recv_window.data_size != header.seq_number)
break; break;
m_next_flags = FIN | ACK; m_next_flags = FIN | ACK;
m_next_state = State::LastAck; m_next_state = State::LastAck;
@ -738,9 +659,7 @@ namespace Kernel
break; break;
} }
const uint32_t expected_seq = m_recv_window.start_seq + m_recv_window.buffer->size() + m_recv_window.has_ghost_byte; if (header.seq_number != m_recv_window.start_seq + m_recv_window.data_size + m_recv_window.has_ghost_byte)
if (header.seq_number > expected_seq)
dprintln_if(DEBUG_TCP, "Missing packets"); dprintln_if(DEBUG_TCP, "Missing packets");
else if (check_payload) else if (check_payload)
{ {
@ -751,37 +670,28 @@ namespace Kernel
m_send_window.current_ack = header.ack_number; m_send_window.current_ack = header.ack_number;
auto payload = buffer.slice(header.data_offset * sizeof(uint32_t)); auto payload = buffer.slice(header.data_offset * sizeof(uint32_t));
if (payload.size() > 0)
if (header.seq_number < expected_seq)
{ {
const uint32_t already_received_bytes = expected_seq - header.seq_number; if (m_recv_window.data_size + payload.size() > m_recv_window.buffer->size())
if (already_received_bytes <= payload.size()) dprintln_if(DEBUG_TCP, "Cannot fit received bytes to window, waiting for retransmission");
payload = payload.slice(already_received_bytes);
else else
payload = {};
}
const bool can_receive_new_data = (payload.size() > 0 && !m_recv_window.buffer->full());
if (can_receive_new_data)
{ {
const size_t nrecv = BAN::Math::min(payload.size(), m_recv_window.buffer->free()); auto* buffer = reinterpret_cast<uint8_t*>(m_recv_window.buffer->vaddr());
m_recv_window.buffer->push(payload.slice(0, nrecv)); memcpy(buffer + m_recv_window.data_size, payload.data(), payload.size());
m_recv_window.data_size += payload.size();
epoll_notify(EPOLLIN); epoll_notify(EPOLLIN);
dprintln_if(DEBUG_TCP, "Received {} bytes", nrecv); dprintln_if(DEBUG_TCP, "Received {} bytes", payload.size());
}
// make sure zero window is reported if (m_next_flags == 0)
if (m_last_sent_window_size > 0 && m_recv_window.buffer->full())
m_should_send_zero_window = true;
else if (can_receive_new_data)
{ {
m_next_flags = ACK; m_next_flags = ACK;
m_next_state = m_state; m_next_state = m_state;
} }
} }
}
}
if (!hungup_before && has_hungup_impl()) if (!hungup_before && has_hungup_impl())
epoll_notify(EPOLLHUP); epoll_notify(EPOLLHUP);
@ -883,14 +793,21 @@ namespace Kernel
continue; continue;
} }
if (m_send_window.current_ack - m_send_window.has_ghost_byte > m_send_window.start_seq) if (m_send_window.data_size > 0 && m_send_window.current_ack - m_send_window.has_ghost_byte > m_send_window.start_seq)
{ {
const uint32_t acknowledged_bytes = m_send_window.current_ack - m_send_window.start_seq - m_send_window.has_ghost_byte; uint32_t acknowledged_bytes = m_send_window.current_ack - m_send_window.start_seq - m_send_window.has_ghost_byte;
ASSERT(acknowledged_bytes <= m_send_window.buffer->size()); ASSERT(acknowledged_bytes <= m_send_window.data_size);
m_send_window.data_size -= acknowledged_bytes;
m_send_window.start_seq += acknowledged_bytes; m_send_window.start_seq += acknowledged_bytes;
if (m_send_window.data_size > 0)
{
auto* send_buffer = reinterpret_cast<uint8_t*>(m_send_window.buffer->vaddr());
memmove(send_buffer, send_buffer + acknowledged_bytes, m_send_window.data_size);
}
m_send_window.sent_size -= acknowledged_bytes; m_send_window.sent_size -= acknowledged_bytes;
m_send_window.buffer->pop(acknowledged_bytes);
epoll_notify(EPOLLOUT); epoll_notify(EPOLLOUT);
@ -899,32 +816,26 @@ namespace Kernel
continue; continue;
} }
const bool should_retransmit = m_send_window.had_zero_window || (m_send_window.sent_size > 0 && current_ms >= m_send_window.last_send_ms + retransmit_timeout_ms); const bool should_retransmit = m_send_window.data_size > 0 && current_ms >= m_send_window.last_send_ms + retransmit_timeout_ms;
const bool can_send_new_data = (m_send_window.buffer->size() > m_send_window.sent_size && m_send_window.sent_size < m_send_window.scaled_size()); if (m_send_window.data_size > m_send_window.sent_size || should_retransmit)
if (m_send_window.scaled_size() > 0 && (should_retransmit || can_send_new_data))
{ {
m_send_window.had_zero_window = false;
ASSERT(m_connection_info.has_value()); ASSERT(m_connection_info.has_value());
auto* target_address = reinterpret_cast<const sockaddr*>(&m_connection_info->address); auto* target_address = reinterpret_cast<const sockaddr*>(&m_connection_info->address);
auto target_address_len = m_connection_info->address_len; auto target_address_len = m_connection_info->address_len;
const size_t send_offset = should_retransmit ? 0 : m_send_window.sent_size; const uint32_t send_base = should_retransmit ? 0 : m_send_window.sent_size;
const size_t total_send = BAN::Math::min<size_t>( const uint32_t total_send = BAN::Math::min<uint32_t>(m_send_window.data_size - send_base, m_send_window.scaled_size());
m_send_window.buffer->size() - send_offset,
m_send_window.scaled_size() - send_offset
);
m_send_window.current_seq = m_send_window.start_seq + send_offset; m_send_window.current_seq = m_send_window.start_seq + m_send_window.sent_size;
for (size_t i = 0; i < total_send;) auto* send_buffer = reinterpret_cast<const uint8_t*>(m_send_window.buffer->vaddr() + send_base);
for (uint32_t i = 0; i < total_send;)
{ {
const size_t to_send = BAN::Math::min<size_t>(total_send - i, m_send_window.mss); const uint32_t to_send = BAN::Math::min(total_send - i, m_send_window.mss);
auto message = m_send_window.buffer->get_data().slice(send_offset + i, to_send); auto message = BAN::ConstByteSpan(send_buffer + i, to_send);
m_next_flags = ACK; m_next_flags = ACK;
if (auto ret = m_network_layer.sendto(*this, message, target_address, target_address_len); ret.is_error()) if (auto ret = m_network_layer.sendto(*this, message, target_address, target_address_len); ret.is_error())
@ -935,10 +846,9 @@ namespace Kernel
dprintln_if(DEBUG_TCP, "Sent {} bytes", to_send); dprintln_if(DEBUG_TCP, "Sent {} bytes", to_send);
i += to_send; m_send_window.sent_size += to_send;
m_send_window.current_seq += to_send; m_send_window.current_seq += to_send;
if (send_offset + i > m_send_window.sent_size) i += to_send;
m_send_window.sent_size = send_offset + i;
} }
m_send_window.last_send_ms = current_ms; m_send_window.last_send_ms = current_ms;
@ -946,30 +856,6 @@ namespace Kernel
continue; continue;
} }
if (m_last_sent_window_size == 0)
m_should_send_zero_window = false;
if (m_should_send_zero_window || m_should_send_window_update)
{
ASSERT(m_connection_info.has_value());
auto* target_address = reinterpret_cast<const sockaddr*>(&m_connection_info->address);
auto target_address_len = m_connection_info->address_len;
m_next_flags = ACK;
if (auto ret = m_network_layer.sendto(*this, {}, target_address, target_address_len); ret.is_error())
dwarnln("{}", ret.error());
m_should_send_zero_window = false;
m_should_send_window_update = false;
if (m_last_sent_window_size == 0 && !m_recv_window.buffer->full())
{
m_next_flags = ACK;
if (auto ret = m_network_layer.sendto(*this, {}, target_address, target_address_len); ret.is_error())
dwarnln("{}", ret.error());
}
}
m_thread_blocker.unblock(); m_thread_blocker.unblock();
m_thread_blocker.block_with_wake_time_ms(current_ms + retransmit_timeout_ms, &m_mutex); m_thread_blocker.block_with_wake_time_ms(current_ms + retransmit_timeout_ms, &m_mutex);
} }

View File

@ -35,26 +35,13 @@ namespace Kernel
m_address_len = 0; m_address_len = 0;
} }
void UDPSocket::get_protocol_header(BAN::ByteSpan header_buffer, BAN::ConstByteSpan payload, uint16_t dst_port, PseudoHeader pseudo_header) void UDPSocket::add_protocol_header(BAN::ByteSpan packet, uint16_t dst_port, PseudoHeader)
{ {
ASSERT(header_buffer.size() == protocol_header_size()); auto& header = packet.as<UDPHeader>();
header.src_port = bound_port();
auto& header = header_buffer.as<UDPHeader>(); header.dst_port = dst_port;
header = { header.length = packet.size();
.src_port = bound_port(), header.checksum = 0;
.dst_port = dst_port,
.length = protocol_header_size() + payload.size(),
.checksum = 0,
};
const BAN::ConstByteSpan buffers[] {
BAN::ConstByteSpan::from(pseudo_header),
header_buffer,
payload,
};
header.checksum = calculate_internet_checksum({ buffers, sizeof(buffers) / sizeof(*buffers) });
if (header.checksum == 0)
header.checksum = 0xFFFF;
} }
void UDPSocket::receive_packet(BAN::ConstByteSpan packet, const sockaddr* sender, socklen_t sender_len) void UDPSocket::receive_packet(BAN::ConstByteSpan packet, const sockaddr* sender, socklen_t sender_len)
@ -225,11 +212,10 @@ namespace Kernel
BAN::ErrorOr<void> UDPSocket::getsockopt_impl(int level, int option, void* value, socklen_t* value_len) BAN::ErrorOr<void> UDPSocket::getsockopt_impl(int level, int option, void* value, socklen_t* value_len)
{ {
int result; if (level != SOL_SOCKET)
return BAN::Error::from_errno(EINVAL);
switch (level) int result;
{
case SOL_SOCKET:
switch (option) switch (option)
{ {
case SO_ERROR: case SO_ERROR:
@ -242,16 +228,7 @@ namespace Kernel
result = m_packet_buffer->size(); result = m_packet_buffer->size();
break; break;
default: default:
dwarnln("getsockopt(SOLSOCKET, {})", option); return BAN::Error::from_errno(ENOTSUP);
return BAN::Error::from_errno(ENOPROTOOPT);
}
break;
case IPPROTO_UDP:
dwarnln("getsockopt(IPPROTO_UDP, {})", option);
return BAN::Error::from_errno(ENOPROTOOPT);
default:
dwarnln("getsockopt({}, {})", level, option);
return BAN::Error::from_errno(EINVAL);
} }
const size_t len = BAN::Math::min<size_t>(sizeof(result), *value_len); const size_t len = BAN::Math::min<size_t>(sizeof(result), *value_len);
@ -261,27 +238,6 @@ namespace Kernel
return {}; return {};
} }
BAN::ErrorOr<void> UDPSocket::setsockopt_impl(int level, int option, const void* value, socklen_t value_len)
{
(void)value;
(void)value_len;
switch (level)
{
case SOL_SOCKET:
dwarnln("setsockopt(SOL_SOCKET, {})", option);
return BAN::Error::from_errno(ENOPROTOOPT);
case IPPROTO_UDP:
dwarnln("setsockopt(IPPROTO_UDP, {})", option);
return BAN::Error::from_errno(ENOPROTOOPT);
default:
dwarnln("setsockopt({}, {})", level, option);
return BAN::Error::from_errno(EINVAL);
}
return {};
}
BAN::ErrorOr<long> UDPSocket::ioctl_impl(int request, void* argument) BAN::ErrorOr<long> UDPSocket::ioctl_impl(int request, void* argument)
{ {
switch (request) switch (request)

View File

@ -707,10 +707,7 @@ namespace Kernel
BAN::ErrorOr<void> UnixDomainSocket::getsockopt_impl(int level, int option, void* value, socklen_t* value_len) BAN::ErrorOr<void> UnixDomainSocket::getsockopt_impl(int level, int option, void* value, socklen_t* value_len)
{ {
if (level != SOL_SOCKET) if (level != SOL_SOCKET)
{
dwarnln("getsockopt({}, {})", level, option);
return BAN::Error::from_errno(EINVAL); return BAN::Error::from_errno(EINVAL);
}
int result; int result;
switch (option) switch (option)
@ -739,10 +736,7 @@ namespace Kernel
BAN::ErrorOr<void> UnixDomainSocket::setsockopt_impl(int level, int option, const void* value, socklen_t value_len) BAN::ErrorOr<void> UnixDomainSocket::setsockopt_impl(int level, int option, const void* value, socklen_t value_len)
{ {
if (level != SOL_SOCKET) if (level != SOL_SOCKET)
{
dwarnln("setsockopt({}, {})", level, option);
return BAN::Error::from_errno(EINVAL); return BAN::Error::from_errno(EINVAL);
}
switch (option) switch (option)
{ {

View File

@ -5,7 +5,6 @@
#include <kernel/ELF.h> #include <kernel/ELF.h>
#include <kernel/Epoll.h> #include <kernel/Epoll.h>
#include <kernel/FS/DevFS/FileSystem.h> #include <kernel/FS/DevFS/FileSystem.h>
#include <kernel/FS/EventFD.h>
#include <kernel/FS/ProcFS/FileSystem.h> #include <kernel/FS/ProcFS/FileSystem.h>
#include <kernel/FS/VirtualFileSystem.h> #include <kernel/FS/VirtualFileSystem.h>
#include <kernel/IDT.h> #include <kernel/IDT.h>
@ -29,7 +28,6 @@
#include <pthread.h> #include <pthread.h>
#include <stdio.h> #include <stdio.h>
#include <sys/banan-os.h> #include <sys/banan-os.h>
#include <sys/eventfd.h>
#include <sys/futex.h> #include <sys/futex.h>
#include <sys/sysmacros.h> #include <sys/sysmacros.h>
#include <sys/wait.h> #include <sys/wait.h>
@ -381,7 +379,7 @@ namespace Kernel
const auto [master_addr, master_size] = master_tls; const auto [master_addr, master_size] = master_tls;
ASSERT(master_size % alignof(uthread) == 0); ASSERT(master_size % alignof(uthread) == 0);
const size_t tls_size = master_size + sizeof(uthread); const size_t tls_size = master_size + PAGE_SIZE;
auto region = TRY(MemoryBackedRegion::create( auto region = TRY(MemoryBackedRegion::create(
page_table, page_table,
@ -410,26 +408,28 @@ namespace Kernel
bytes_copied += to_copy; bytes_copied += to_copy;
} }
auto uthread = TRY(BAN::UniqPtr<struct uthread>::create()); const uthread uthread {
*uthread = {
.self = reinterpret_cast<struct uthread*>(region->vaddr() + master_size), .self = reinterpret_cast<struct uthread*>(region->vaddr() + master_size),
.master_tls_addr = reinterpret_cast<void*>(master_addr), .master_tls_addr = reinterpret_cast<void*>(master_addr),
.master_tls_size = master_size, .master_tls_size = master_size,
.master_tls_module_count = 1,
.dynamic_tls = nullptr,
.cleanup_stack = nullptr, .cleanup_stack = nullptr,
.id = 0, .id = 0,
.errno_ = 0, .errno_ = 0,
.cancel_type = 0, .cancel_type = 0,
.cancel_state = 0, .cancel_state = 0,
.canceled = 0, .canceled = 0,
.dtv = { 0, region->vaddr() }
}; };
const uintptr_t dtv[2] { 1, region->vaddr() };
TRY(region->copy_data_to_region( TRY(region->copy_data_to_region(
master_size, master_size,
reinterpret_cast<const uint8_t*>(uthread.ptr()), reinterpret_cast<const uint8_t*>(&uthread),
sizeof(struct uthread) sizeof(uthread)
));
TRY(region->copy_data_to_region(
master_size + sizeof(uthread),
reinterpret_cast<const uint8_t*>(&dtv),
sizeof(dtv)
)); ));
TLSResult result; TLSResult result;
@ -1658,6 +1658,12 @@ namespace Kernel
BAN::ErrorOr<long> Process::sys_getsockopt(int socket, int level, int option_name, void* user_option_value, socklen_t* user_option_len) BAN::ErrorOr<long> Process::sys_getsockopt(int socket, int level, int option_name, void* user_option_value, socklen_t* user_option_len)
{ {
if (level != SOL_SOCKET)
{
dwarnln("{}: getsockopt level {}", name(), level);
return BAN::Error::from_errno(EINVAL);
}
socklen_t option_len; socklen_t option_len;
TRY(read_from_user(user_option_len, &option_len, sizeof(socklen_t))); TRY(read_from_user(user_option_len, &option_len, sizeof(socklen_t)));
@ -1679,6 +1685,12 @@ namespace Kernel
BAN::ErrorOr<long> Process::sys_setsockopt(int socket, int level, int option_name, const void* user_option_value, socklen_t option_len) BAN::ErrorOr<long> Process::sys_setsockopt(int socket, int level, int option_name, const void* user_option_value, socklen_t option_len)
{ {
if (level != SOL_SOCKET)
{
dwarnln("{}: setsockopt level {}", name(), level);
return BAN::Error::from_errno(EINVAL);
}
if (option_len < 0) if (option_len < 0)
return BAN::Error::from_errno(EINVAL); return BAN::Error::from_errno(EINVAL);
@ -2162,27 +2174,6 @@ namespace Kernel
return TRY(static_cast<Epoll*>(epoll_inode.ptr())->wait(BAN::Span<epoll_event>(events, maxevents), waketime_ns)); return TRY(static_cast<Epoll*>(epoll_inode.ptr())->wait(BAN::Span<epoll_event>(events, maxevents), waketime_ns));
} }
BAN::ErrorOr<long> Process::sys_eventfd(unsigned int initval, int flags)
{
if (flags & ~(EFD_CLOEXEC | EFD_NONBLOCK | EFD_SEMAPHORE))
return BAN::Error::from_errno(EINVAL);
int oflags = 0;
if (flags & EFD_CLOEXEC)
oflags |= O_CLOEXEC;
if (flags & EFD_NONBLOCK)
oflags |= O_NONBLOCK;
const bool is_semaphore = !!(flags & EFD_SEMAPHORE);
return TRY(m_open_file_descriptors.open(
VirtualFileSystem::File {
TRY(EventFD::create(initval, is_semaphore)),
"<eventfd>"_sv
}, oflags
));
}
BAN::ErrorOr<long> Process::sys_pipe(int user_fildes[2]) BAN::ErrorOr<long> Process::sys_pipe(int user_fildes[2])
{ {
int fildes[2]; int fildes[2];
@ -2380,8 +2371,6 @@ namespace Kernel
TRY(read_string_from_user(user_path, path, PATH_MAX)); TRY(read_string_from_user(user_path, path, PATH_MAX));
auto new_cwd = TRY(find_file(AT_FDCWD, path, O_SEARCH)); auto new_cwd = TRY(find_file(AT_FDCWD, path, O_SEARCH));
if (!new_cwd.inode->mode().ifdir())
return BAN::Error::from_errno(ENOTDIR);
LockGuard _(m_process_lock); LockGuard _(m_process_lock);
m_working_directory = BAN::move(new_cwd); m_working_directory = BAN::move(new_cwd);
@ -2665,9 +2654,6 @@ namespace Kernel
for (size_t j = 0; j < new_regions.size(); j++) for (size_t j = 0; j < new_regions.size(); j++)
TRY(m_mapped_regions.insert(i + j + 1, BAN::move(new_regions[j]))); TRY(m_mapped_regions.insert(i + j + 1, BAN::move(new_regions[j])));
while (i + 1 < m_mapped_regions.size() && !m_mapped_regions[i + 1]->overlaps(vaddr, len))
i++;
continue; continue;
} }

View File

@ -73,9 +73,7 @@ namespace Kernel
: CharacterDevice(mode, uid, gid) : CharacterDevice(mode, uid, gid)
, m_termios(termios) , m_termios(termios)
, m_rdev(next_tty_rdev()) , m_rdev(next_tty_rdev())
{ { }
m_output.buffer = MUST(ByteRingBuffer::create(PAGE_SIZE));
}
BAN::RefPtr<TTY> TTY::current() BAN::RefPtr<TTY> TTY::current()
{ {
@ -206,7 +204,7 @@ namespace Kernel
} }
case FIONREAD: case FIONREAD:
{ {
*static_cast<int*>(argument) = m_output.flush ? m_output.buffer->size() : 0; *static_cast<int*>(argument) = m_output.flush ? m_output.bytes : 0;
return 0; return 0;
} }
case TIOCGWINSZ: case TIOCGWINSZ:
@ -234,13 +232,14 @@ namespace Kernel
return; return;
const char* ansi_c_str = LibInput::key_to_utf8_ansi(event.key, event.modifier); const char* ansi_c_str = LibInput::key_to_utf8_ansi(event.key, event.modifier);
if (ansi_c_str == nullptr) if (ansi_c_str)
return; {
auto* ptr = reinterpret_cast<const uint8_t*>(ansi_c_str);
while (*ansi_c_str) while (*ptr)
handle_input_byte(*ansi_c_str++); handle_input_byte(*ptr++);
after_write(); after_write();
} }
}
void TTY::handle_input_byte(uint8_t ch) void TTY::handle_input_byte(uint8_t ch)
{ {
@ -288,7 +287,7 @@ namespace Kernel
if (ch == m_termios.c_cc[VKILL] && (m_termios.c_lflag & ECHOK)) if (ch == m_termios.c_cc[VKILL] && (m_termios.c_lflag & ECHOK))
{ {
while (!m_output.buffer->empty() && m_output.buffer->back() != '\n') while (m_output.bytes > 0 && m_output.buffer[m_output.bytes - 1] != '\n')
do_backspace(); do_backspace();
return; return;
} }
@ -308,8 +307,12 @@ namespace Kernel
// TODO: terminal suspension with VSTOP/VSTART // TODO: terminal suspension with VSTOP/VSTART
if (should_append && !m_output.buffer->full()) if (should_append)
m_output.buffer->push({ &ch, 1 }); {
if (m_output.bytes >= m_output.buffer.size())
return;
m_output.buffer[m_output.bytes++] = ch;
}
if (should_append && (force_echo || (m_termios.c_lflag & ECHO))) if (should_append && (force_echo || (m_termios.c_lflag & ECHO)))
{ {
@ -347,22 +350,29 @@ namespace Kernel
void TTY::do_backspace() void TTY::do_backspace()
{ {
if (m_output.buffer->empty()) if (m_output.bytes > 0)
return;
const bool is_caret_notation =
(m_output.buffer->back() < 32) ||
(m_output.buffer->back() == 127);
// handle multibyte UTF8
while ((m_output.buffer->back() & 0xC0) == 0x80)
m_output.buffer->pop_back(1);
ASSERT(!m_output.buffer->empty());
m_output.buffer->pop_back(1);
if (is_caret_notation)
{ {
uint8_t last = m_output.buffer[m_output.bytes - 1];
// Multibyte UTF8
if ((last & 0xC0) == 0x80)
{
// NOTE: this should be valid UTF8 since keyboard input already 'validates' it
while ((m_output.buffer[m_output.bytes - 1] & 0xC0) == 0x80)
{
ASSERT(m_output.bytes > 0);
m_output.bytes--;
}
ASSERT(m_output.bytes > 0);
m_output.bytes--;
putchar('\b');
putchar(' ');
putchar('\b');
}
// Caret notation
else if (last < 32 || last == 127)
{
m_output.bytes--;
putchar('\b'); putchar('\b');
putchar('\b'); putchar('\b');
putchar(' '); putchar(' ');
@ -370,13 +380,16 @@ namespace Kernel
putchar('\b'); putchar('\b');
putchar('\b'); putchar('\b');
} }
// Ascii
else else
{ {
m_output.bytes--;
putchar('\b'); putchar('\b');
putchar(' '); putchar(' ');
putchar('\b'); putchar('\b');
} }
} }
}
bool TTY::putchar(uint8_t ch) bool TTY::putchar(uint8_t ch)
{ {
@ -398,7 +411,7 @@ namespace Kernel
while (!m_output.flush) while (!m_output.flush)
TRY(Thread::current().block_or_eintr_indefinite(m_output.thread_blocker, &m_mutex)); TRY(Thread::current().block_or_eintr_indefinite(m_output.thread_blocker, &m_mutex));
if (m_output.buffer->empty()) if (m_output.bytes == 0)
{ {
if (master_has_closed()) if (master_has_closed())
return 0; return 0;
@ -406,19 +419,19 @@ namespace Kernel
return 0; return 0;
} }
auto data = m_output.buffer->get_data(); const size_t max_to_copy = BAN::Math::min<size_t>(buffer.size(), m_output.bytes);
const size_t max_to_copy = BAN::Math::min<size_t>(buffer.size(), data.size());
size_t to_copy = max_to_copy; size_t to_copy = max_to_copy;
if (m_termios.c_lflag & ICANON) if (m_termios.c_lflag & ICANON)
for (to_copy = 1; to_copy < max_to_copy; to_copy++) for (to_copy = 1; to_copy < max_to_copy; to_copy++)
if (data[to_copy - 1] == NL) if (m_output.buffer[to_copy - 1] == NL)
break; break;
memcpy(buffer.data(), data.data(), to_copy); memcpy(buffer.data(), m_output.buffer.data(), to_copy);
m_output.buffer->pop(to_copy);
if (m_output.buffer->empty()) memmove(m_output.buffer.data(), m_output.buffer.data() + to_copy, m_output.bytes - to_copy);
m_output.bytes -= to_copy;
if (m_output.bytes == 0)
m_output.flush = false; m_output.flush = false;
m_output.thread_blocker.unblock(); m_output.thread_blocker.unblock();

View File

@ -3,7 +3,7 @@
NAME='cairo' NAME='cairo'
VERSION='1.18.4' VERSION='1.18.4'
DOWNLOAD_URL="https://cairographics.org/releases/cairo-$VERSION.tar.xz#445ed8208a6e4823de1226a74ca319d3600e83f6369f99b14265006599c32ccb" DOWNLOAD_URL="https://cairographics.org/releases/cairo-$VERSION.tar.xz#445ed8208a6e4823de1226a74ca319d3600e83f6369f99b14265006599c32ccb"
DEPENDENCIES=('libpng' 'pixman' 'fontconfig' 'glib' 'libX11' 'libXrender' 'libXext') DEPENDENCIES=('libpng' 'pixman' 'fontconfig' 'glib')
CONFIGURE_OPTIONS=( CONFIGURE_OPTIONS=(
'-Dprefix=/usr' '-Dprefix=/usr'
'-Dtests=disabled' '-Dtests=disabled'

View File

@ -1,29 +0,0 @@
#!/bin/bash ../install.sh
NAME='dbus'
VERSION='1.16.2'
DOWNLOAD_URL="https://dbus.freedesktop.org/releases/dbus/dbus-$VERSION.tar.xz#0ba2a1a4b16afe7bceb2c07e9ce99a8c2c3508e5dec290dbb643384bd6beb7e2"
DEPENDENCIES=('glib' 'expat')
CONFIGURE_OPTIONS=(
'-Dprefix=/usr'
'-Depoll=disabled' # linux only
'-Dintrusive_tests=false'
'-Dinstalled_tests=false'
'-Dmodular_tests=disabled'
)
configure() {
meson setup \
--reconfigure \
--cross-file "$MESON_CROSS_FILE" \
"${CONFIGURE_OPTIONS[@]}" \
build || exit 1
}
build() {
meson compile -C build || exit 1
}
install() {
meson install --destdir="$BANAN_SYSROOT" -C build || exit 1
}

View File

@ -1,13 +0,0 @@
diff -ruN dbus-1.16.2/tools/dbus-print-message.c dbus-1.16.2-banan_os/tools/dbus-print-message.c
--- dbus-1.16.2/tools/dbus-print-message.c 2025-02-27 18:29:06.000000000 +0200
+++ dbus-1.16.2-banan_os/tools/dbus-print-message.c 2026-02-21 23:23:51.987302740 +0200
@@ -31,7 +31,9 @@
#include <sys/un.h>
#include <unistd.h>
#include <netinet/in.h>
+#ifndef __banan_os__
#include <netinet/ip.h>
+#endif
#include <arpa/inet.h>
#endif

View File

@ -1,48 +0,0 @@
diff -ruN expat-2.7.1/configure expat-2.7.1-banan_os/configure
--- expat-2.7.1/configure 2025-03-27 21:46:37.000000000 +0200
+++ expat-2.7.1-banan_os/configure 2025-08-10 00:50:27.773898797 +0300
@@ -6679,6 +6679,10 @@
lt_cv_deplibs_check_method=pass_all
;;
+banan_os*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
beos*)
lt_cv_deplibs_check_method=pass_all
;;
@@ -12479,6 +12483,16 @@
esac
;;
+banan_os*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ dynamic_linker="$host_os DynamicLoader.so"
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
beos*)
library_names_spec='$libname$shared_ext'
dynamic_linker="$host_os ld.so"
@@ -18079,6 +18093,16 @@
esac
;;
+banan_os*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ dynamic_linker="$host_os DynamicLoader.so"
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
beos*)
library_names_spec='$libname$shared_ext'
dynamic_linker="$host_os ld.so"

View File

@ -1,47 +0,0 @@
#!/bin/bash ../install.sh
NAME='fontconfig'
VERSION='2.17.1'
DOWNLOAD_URL="https://gitlab.freedesktop.org/fontconfig/fontconfig/-/archive/$VERSION/fontconfig-$VERSION.tar.gz#82e73b26adad651b236e5f5d4b3074daf8ff0910188808496326bd3449e5261d"
DEPENDENCIES=('harfbuzz' 'freetype' 'expat' 'libiconv')
CONFIGURE_OPTIONS=(
'-Dprefix=/usr'
'-Dtests=disabled'
'-Dnls=disabled'
)
configure() {
meson setup \
--reconfigure \
--cross-file "$MESON_CROSS_FILE" \
"${CONFIGURE_OPTIONS[@]}" \
build || exit 1
}
build() {
meson compile -C build || exit 1
}
install() {
meson install --destdir="$BANAN_SYSROOT" -C build || exit 1
}
post_install() {
pushd .. &>/dev/null
local font_name='dejavu-fonts-ttf-2.37'
if [ ! -f "$font_name.tar.bz2" ]; then
wget "http://sourceforge.net/projects/dejavu/files/dejavu/2.37/$font_name.tar.bz2" || exit 1
fi
if [ ! -d "$font_name" ]; then
tar xf "$font_name.tar.bz2" || exit 1
fi
mkdir -p "$BANAN_SYSROOT/usr/share/fonts/TTF" || exit 1
cp "$font_name/ttf/"* "$BANAN_SYSROOT/usr/share/fonts/TTF/" || exit 1
cp "$font_name/fontconfig/"* "$BANAN_SYSROOT/usr/share/fontconfig/conf.avail/" || exit 1
popd &>/dev/null
}

View File

@ -1,6 +0,0 @@
#!/bin/bash ../install.sh
NAME='fribidi'
VERSION='1.0.16'
DOWNLOAD_URL="https://github.com/fribidi/fribidi/releases/download/v$VERSION/fribidi-$VERSION.tar.xz#1b1cde5b235d40479e91be2f0e88a309e3214c8ab470ec8a2744d82a5a9ea05c"
CONFIG_SUB=('config.sub')

View File

@ -1,20 +0,0 @@
diff -ruN fribidi-1.0.16/configure fribidi-1.0.16-banan_os/configure
--- fribidi-1.0.16/configure 2024-09-25 21:04:21.000000000 +0300
+++ fribidi-1.0.16-banan_os/configure 2025-11-05 20:51:12.227775953 +0200
@@ -11536,6 +11536,16 @@
esac
;;
+banan_os*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ dynamic_linker="$host_os DynamicLoader.so"
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
beos*)
library_names_spec='$libname$shared_ext'
dynamic_linker="$host_os ld.so"

View File

@ -1,27 +0,0 @@
#!/bin/bash ../install.sh
NAME='gdk-pixbuf'
VERSION='2.44.4'
DOWNLOAD_URL="https://gitlab.gnome.org/GNOME/gdk-pixbuf/-/archive/$VERSION/gdk-pixbuf-$VERSION.tar.gz#6de2f77d992155b4121d20036e7e986dfe595a0e654381cdd0d7257f493c208a"
DEPENDENCIES=('glib' 'libpng' 'libjpeg' 'libtiff' 'shared-mime-info')
CONFIGURE_OPTIONS=(
'-Dprefix=/usr'
'-Dtests=false'
'-Dman=false'
)
configure() {
meson setup \
--reconfigure \
--cross-file "$MESON_CROSS_FILE" \
"${CONFIGURE_OPTIONS[@]}" \
build || exit 1
}
build() {
meson compile -C build || exit 1
}
install() {
meson install --destdir="$BANAN_SYSROOT" -C build || exit 1
}

View File

@ -1,14 +1,13 @@
#!/bin/bash ../install.sh #!/bin/bash ../install.sh
NAME='git' NAME='git'
VERSION='2.53.0' VERSION='2.52.0'
DOWNLOAD_URL="https://www.kernel.org/pub/software/scm/git/git-$VERSION.tar.xz#5818bd7d80b061bbbdfec8a433d609dc8818a05991f731ffc4a561e2ca18c653" DOWNLOAD_URL="https://www.kernel.org/pub/software/scm/git/git-$VERSION.tar.xz#3cd8fee86f69a949cb610fee8cd9264e6873d07fa58411f6060b3d62729ed7c5"
DEPENDENCIES=('zlib' 'openssl' 'curl' 'libiconv') DEPENDENCIES=('zlib' 'openssl' 'curl')
CONFIGURE_OPTIONS=( CONFIGURE_OPTIONS=(
'--with-curl' '--with-curl'
'--with-openssl' '--with-openssl'
ac_cv_fread_reads_directories=no ac_cv_fread_reads_directories=no
ac_cv_iconv_omits_bom=no
ac_cv_lib_curl_curl_global_init=yes
ac_cv_snprintf_returns_bogus=no ac_cv_snprintf_returns_bogus=no
ac_cv_lib_curl_curl_global_init=yes
) )

View File

@ -1,30 +0,0 @@
#!/bin/bash ../install.sh
NAME='gtk'
VERSION='3.24.49'
DOWNLOAD_URL="https://gitlab.gnome.org/GNOME/gtk/-/archive/$VERSION/gtk-$VERSION.tar.gz#a2958d82986c81794e953a3762335fa7c78948706d23cced421f7245ca544cbc"
DEPENDENCIES=('glib' 'gdk-pixbuf' 'pango' 'libatk' 'libepoxy' 'libXrandr')
CONFIGURE_OPTIONS=(
'-Dprefix=/usr'
'-Dtests=false'
'-Dexamples=false'
'-Dintrospection=false'
'-Dx11_backend=true'
'-Dwayland_backend=false'
)
configure() {
meson setup \
--reconfigure \
--cross-file "$MESON_CROSS_FILE" \
"${CONFIGURE_OPTIONS[@]}" \
build || exit 1
}
build() {
meson compile -C build || exit 1
}
install() {
meson install --destdir="$BANAN_SYSROOT" -C build || exit 1
}

View File

@ -1,45 +0,0 @@
#!/bin/bash ../install.sh
NAME='icu'
VERSION='78.1'
DOWNLOAD_URL="https://github.com/unicode-org/icu/releases/download/release-$VERSION/icu4c-$VERSION-sources.tgz#6217f58ca39b23127605cfc6c7e0d3475fe4b0d63157011383d716cb41617886"
TAR_CONTENT='icu'
_DEPENDENCIES=('ca-certificates' 'openssl' 'zlib' 'zstd')
CONFIG_SUB=('source/config.sub')
CONFIGURE_OPTIONS=(
"--with-cross-build=$BANAN_PORT_DIR/icu/icu-$VERSION-$BANAN_ARCH/source/build-host"
'--disable-tests'
'--disable-samples'
)
pre_configure() {
unset CC CXX LD AS AR
mkdir -p source/build-host || exit 1
pushd source/build-host || exit 1
../configure --disable-tests --disable-samples || exit 1
make -j$(proc) || exit 1
popd >/dev/null || exit 1
pushd source >/dev/null || exit 1
}
post_configure() {
popd >/dev/null || exit 1
}
pre_build() {
pushd source >/dev/null || exit 1
}
post_build() {
popd >/dev/null || exit 1
}
pre_install() {
pushd source >/dev/null || exit 1
}
post_install() {
popd >/dev/null || exit 1
}

View File

@ -1,95 +0,0 @@
diff -ruN icu-78.1/source/config/mh-banan_os icu-78.1-banan_os/source/config/mh-banan_os
--- icu-78.1/source/config/mh-banan_os 1970-01-01 02:00:00.000000000 +0200
+++ icu-78.1-banan_os/source/config/mh-banan_os 2025-11-06 23:07:11.542495330 +0200
@@ -0,0 +1,80 @@
+## -*-makefile-*-
+## Copyright (C) 2016 and later: Unicode, Inc. and others.
+## License & terms of use: http://www.unicode.org/copyright.html
+## haiku-specific setup
+## Copyright (c) 2010-2012, International Business Machines Corporation and
+## others. All Rights Reserved.
+##
+
+## Commands to generate dependency files
+GEN_DEPS.c= $(CC) -E -MM $(DEFS) $(CPPFLAGS)
+GEN_DEPS.cc= $(CXX) -E -MM $(DEFS) $(CPPFLAGS)
+
+## Flags for position independent code
+SHAREDLIBCFLAGS = -fPIC
+SHAREDLIBCXXFLAGS = -fPIC
+SHAREDLIBCPPFLAGS = -DPIC
+
+## Additional flags when building libraries and with threads
+LIBCPPFLAGS =
+THREADSCPPFLAGS =
+
+#
+CPPFLAGS += -DU_CHARSET_IS_UTF8=1
+
+## Compiler switch to embed a runtime search path
+LD_RPATH=
+LD_RPATH_PRE = -Wl,-rpath,
+
+## Compiler switch to embed a library name
+LD_SONAME = -Wl,-soname -Wl,$(notdir $(MIDDLE_SO_TARGET))
+
+## Shared object suffix
+SO = so
+## Non-shared intermediate object suffix
+STATIC_O = ao
+
+## Compilation rules
+%.$(STATIC_O): $(srcdir)/%.c
+ $(COMPILE.c) $(STATICCPPFLAGS) $(STATICCFLAGS) -o $@ $<
+%.o: $(srcdir)/%.c
+ $(COMPILE.c) $(DYNAMICCPPFLAGS) $(DYNAMICCFLAGS) -o $@ $<
+
+%.$(STATIC_O): $(srcdir)/%.cpp
+ $(COMPILE.cc) $(STATICCPPFLAGS) $(STATICCXXFLAGS) -o $@ $<
+%.o: $(srcdir)/%.cpp
+ $(COMPILE.cc) $(DYNAMICCPPFLAGS) $(DYNAMICCXXFLAGS) -o $@ $<
+
+
+## Dependency rules
+%.d: $(srcdir)/%.c
+ @echo "generating dependency information for $<"
+ @$(SHELL) -ec '$(GEN_DEPS.c) $< \
+ | sed '\''s%\($*\)\.o[ :]*%\1.o $@ : %g'\'' > $@; \
+ [ -s $@ ] || rm -f $@'
+
+%.d: $(srcdir)/%.cpp
+ @echo "generating dependency information for $<"
+ @$(SHELL) -ec '$(GEN_DEPS.cc) $< \
+ | sed '\''s%\($*\)\.o[ :]*%\1.o $@ : %g'\'' > $@; \
+ [ -s $@ ] || rm -f $@'
+
+## Versioned libraries rules
+
+%.$(SO).$(SO_TARGET_VERSION_MAJOR): %.$(SO).$(SO_TARGET_VERSION)
+ $(RM) $@ && ln -s ${<F} $@
+%.$(SO): %.$(SO).$(SO_TARGET_VERSION_MAJOR)
+ $(RM) $@ && ln -s ${*F}.$(SO).$(SO_TARGET_VERSION) $@
+
+## Bind internal references
+
+# LDflags that pkgdata will use
+BIR_LDFLAGS= -Wl,-Bsymbolic
+
+# Dependencies [i.e. map files] for the final library
+BIR_DEPS=
+
+# Use LIBRARY_PATH instead of LD_LIBRARY_PATH
+LDLIBRARYPATH_ENVVAR= LIBRARY_PATH
+
+## End haiku-specific setup
diff -ruN icu-78.1/source/configure icu-78.1-banan_os/source/configure
--- icu-78.1/source/configure 2025-10-30 19:37:19.000000000 +0200
+++ icu-78.1-banan_os/source/configure 2025-11-06 23:06:17.308923216 +0200
@@ -5829,6 +5829,7 @@
*-apple-darwin*) icu_cv_host_frag=mh-darwin ;;
*-*-beos) icu_cv_host_frag=mh-beos ;;
*-*-haiku) icu_cv_host_frag=mh-haiku ;;
+*-*-banan_os) icu_cv_host_frag=mh-banan_os ;;
*-*-irix*) icu_cv_host_frag=mh-irix ;;
*-dec-osf*) icu_cv_host_frag=mh-alpha-osf ;;
*-*-nto*) icu_cv_host_frag=mh-qnx ;;

View File

@ -1,11 +0,0 @@
--- icu/source/common/unicode/ptypes.h 2025-10-30 19:37:19.000000000 +0200
+++ icu-78.1-x86_64/source/common/unicode/ptypes.h 2025-11-06 23:12:15.984514832 +0200
@@ -56,7 +56,7 @@
// implementations (looking at you, Apple, spring 2024) actually do this, so
// ICU4C must detect and deal with that.
#if !defined(__cplusplus) && !defined(U_IN_DOXYGEN)
-# if U_HAVE_CHAR16_T
+# if ! U_HAVE_CHAR16_T
# include <uchar.h>
# else
typedef uint16_t char16_t;

View File

@ -1,11 +0,0 @@
#!/bin/bash ../install.sh
NAME='libICE'
VERSION='1.1.2'
DOWNLOAD_URL="https://www.x.org/releases/individual/lib/libICE-$VERSION.tar.xz#974e4ed414225eb3c716985df9709f4da8d22a67a2890066bc6dfc89ad298625"
CONFIG_SUB=('config.sub')
DEPENDENCIES=('xorgproto' 'xtrans')
CONFIGURE_OPTIONS=(
'--enable-shared=yes'
'--enable-static=no'
)

View File

@ -1,31 +0,0 @@
diff -ruN libICE-1.1.2/configure libICE-1.1.2-banan_os/configure
--- libICE-1.1.2/configure 2024-12-13 23:40:33.000000000 +0200
+++ libICE-1.1.2-banan_os/configure 2025-11-16 23:38:24.456211241 +0200
@@ -6464,6 +6464,10 @@
lt_cv_deplibs_check_method=pass_all
;;
+banan_os*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
beos*)
lt_cv_deplibs_check_method=pass_all
;;
@@ -11969,6 +11973,16 @@
esac
;;
+banan_os*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ dynamic_linker="$host_os DynamicLoader.so"
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
beos*)
library_names_spec='$libname$shared_ext'
dynamic_linker="$host_os ld.so"

View File

@ -1,11 +0,0 @@
#!/bin/bash ../install.sh
NAME='libSM'
VERSION='1.2.6'
DOWNLOAD_URL="https://www.x.org/releases/individual/lib/libSM-$VERSION.tar.xz#be7c0abdb15cbfd29ac62573c1c82e877f9d4047ad15321e7ea97d1e43d835be"
CONFIG_SUB=('config.sub')
DEPENDENCIES=('libICE')
CONFIGURE_OPTIONS=(
'--enable-shared=yes'
'--enable-static=no'
)

View File

@ -1,31 +0,0 @@
diff -ruN libSM-1.2.6/configure libSM-1.2.6-banan_os/configure
--- libSM-1.2.6/configure 2025-03-09 03:46:18.000000000 +0200
+++ libSM-1.2.6-banan_os/configure 2025-11-16 23:36:16.733929290 +0200
@@ -6262,6 +6262,10 @@
lt_cv_deplibs_check_method=pass_all
;;
+banan_os*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
beos*)
lt_cv_deplibs_check_method=pass_all
;;
@@ -11797,6 +11801,16 @@
esac
;;
+banan_os*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ dynamic_linker="$host_os DynamicLoader.so"
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
beos*)
library_names_spec='$libname$shared_ext'
dynamic_linker="$host_os ld.so"

View File

@ -1,11 +0,0 @@
#!/bin/bash ../install.sh
NAME='libX11'
VERSION='1.8.12'
DOWNLOAD_URL="https://www.x.org/releases/individual/lib/libX11-$VERSION.tar.xz#fa026f9bb0124f4d6c808f9aef4057aad65e7b35d8ff43951cef0abe06bb9a9a"
CONFIG_SUB=('config.sub')
DEPENDENCIES=('xorgproto' 'xtrans' 'libxcb')
CONFIGURE_OPTIONS=(
'--enable-shared=yes'
'--enable-static=no'
)

View File

@ -1,31 +0,0 @@
diff -ruN libX11-1.8.12/configure libX11-1.8.12-banan_os/configure
--- libX11-1.8.12/configure 2025-03-09 01:53:09.000000000 +0200
+++ libX11-1.8.12-banan_os/configure 2025-11-13 20:07:46.592619585 +0200
@@ -6633,6 +6633,10 @@
lt_cv_deplibs_check_method=pass_all
;;
+banan_os*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
beos*)
lt_cv_deplibs_check_method=pass_all
;;
@@ -12138,6 +12142,16 @@
esac
;;
+banan_os*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ dynamic_linker="$host_os DynamicLoader.so"
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
beos*)
library_names_spec='$libname$shared_ext'
dynamic_linker="$host_os ld.so"

View File

@ -1,11 +0,0 @@
#!/bin/bash ../install.sh
NAME='libXau'
VERSION='1.0.12'
DOWNLOAD_URL="https://www.x.org/releases/individual/lib/libXau-$VERSION.tar.xz#74d0e4dfa3d39ad8939e99bda37f5967aba528211076828464d2777d477fc0fb"
CONFIG_SUB=('config.sub')
DEPENDENCIES=('xorgproto')
CONFIGURE_OPTIONS=(
'--enable-shared=yes'
'--enable-static=no'
)

View File

@ -1,31 +0,0 @@
diff -ruN libXau-1.0.12/configure libXau-1.0.12-banan_os/configure
--- libXau-1.0.12/configure 2024-12-14 03:33:02.000000000 +0200
+++ libXau-1.0.12-banan_os/configure 2025-11-13 20:00:35.574268731 +0200
@@ -6224,6 +6224,10 @@
lt_cv_deplibs_check_method=pass_all
;;
+banan_os*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
beos*)
lt_cv_deplibs_check_method=pass_all
;;
@@ -12060,6 +12064,16 @@
esac
;;
+banan_os*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ dynamic_linker="$host_os DynamicLoader.so"
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
beos*)
library_names_spec='$libname$shared_ext'
dynamic_linker="$host_os ld.so"

View File

@ -1,11 +0,0 @@
#!/bin/bash ../install.sh
NAME='libXaw'
VERSION='1.0.16'
DOWNLOAD_URL="https://www.x.org/releases/individual/lib/libXaw-$VERSION.tar.xz#731d572b54c708f81e197a6afa8016918e2e06dfd3025e066ca642a5b8c39c8f"
CONFIG_SUB=('config.sub')
DEPENDENCIES=('libX11' 'libXext' 'libXt' 'libXmu' 'libXpm')
CONFIGURE_OPTIONS=(
'--enable-shared=yes'
'--enable-static=no'
)

View File

@ -1,31 +0,0 @@
diff -ruN libXaw-1.0.16/configure libXaw-1.0.16-banan_os/configure
--- libXaw-1.0.16/configure 2024-03-10 19:39:54.000000000 +0200
+++ libXaw-1.0.16-banan_os/configure 2025-11-16 23:51:15.704550082 +0200
@@ -5977,6 +5977,10 @@
lt_cv_deplibs_check_method=pass_all
;;
+banan_os*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
beos*)
lt_cv_deplibs_check_method=pass_all
;;
@@ -11343,6 +11347,16 @@
esac
;;
+banan_os*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ dynamic_linker="$host_os DynamicLoader.so"
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
beos*)
library_names_spec='$libname$shared_ext'
dynamic_linker="$host_os ld.so"

View File

@ -1,11 +0,0 @@
#!/bin/bash ../install.sh
NAME='libXdmcp'
VERSION='1.1.5'
DOWNLOAD_URL="https://www.x.org/releases/individual/lib/libXdmcp-$VERSION.tar.xz#d8a5222828c3adab70adf69a5583f1d32eb5ece04304f7f8392b6a353aa2228c"
CONFIG_SUB=('config.sub')
DEPENDENCIES=('xorgproto')
CONFIGURE_OPTIONS=(
'--enable-shared=yes'
'--enable-static=no'
)

View File

@ -1,31 +0,0 @@
diff -ruN libXdmcp-1.1.5/configure libXdmcp-1.1.5-banan_os/configure
--- libXdmcp-1.1.5/configure 2024-03-02 23:37:19.000000000 +0200
+++ libXdmcp-1.1.5-banan_os/configure 2025-11-13 21:49:06.142805910 +0200
@@ -6247,6 +6247,10 @@
lt_cv_deplibs_check_method=pass_all
;;
+banan_os*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
beos*)
lt_cv_deplibs_check_method=pass_all
;;
@@ -11960,6 +11964,16 @@
esac
;;
+banan_os*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ dynamic_linker="$host_os DynamicLoader.so"
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
beos*)
library_names_spec='$libname$shared_ext'
dynamic_linker="$host_os ld.so"

View File

@ -1,12 +0,0 @@
#!/bin/bash ../install.sh
NAME='libXext'
VERSION='1.3.6'
DOWNLOAD_URL="https://www.x.org/releases/individual/lib/libXext-$VERSION.tar.xz#edb59fa23994e405fdc5b400afdf5820ae6160b94f35e3dc3da4457a16e89753"
CONFIG_SUB=('config.sub')
DEPENDENCIES=('libX11')
CONFIGURE_OPTIONS=(
'--enable-shared=yes'
'--enable-static=no'
'--disable-malloc0returnsnull'
)

View File

@ -1,31 +0,0 @@
diff -ruN libXext-1.3.6/configure libXext-1.3.6-banan_os/configure
--- libXext-1.3.6/configure 2024-02-04 23:42:50.000000000 +0200
+++ libXext-1.3.6-banan_os/configure 2025-11-16 23:30:16.532954111 +0200
@@ -6282,6 +6282,10 @@
lt_cv_deplibs_check_method=pass_all
;;
+banan_os*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
beos*)
lt_cv_deplibs_check_method=pass_all
;;
@@ -11663,6 +11667,16 @@
;;
esac
;;
+
+banan_os*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ dynamic_linker="$host_os DynamicLoader.so"
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
beos*)
library_names_spec='$libname$shared_ext'

View File

@ -1,11 +0,0 @@
#!/bin/bash ../install.sh
NAME='libXfixes'
VERSION='6.0.2'
DOWNLOAD_URL="https://www.x.org/releases/individual/lib/libXfixes-$VERSION.tar.xz#39f115d72d9c5f8111e4684164d3d68cc1fd21f9b27ff2401b08fddfc0f409ba"
CONFIG_SUB=('config.sub')
DEPENDENCIES=('libX11')
CONFIGURE_OPTIONS=(
'--enable-shared=yes'
'--enable-static=no'
)

View File

@ -1,31 +0,0 @@
diff -ruN libXfixes-6.0.2/configure libXfixes-6.0.2-banan_os/configure
--- libXfixes-6.0.2/configure 2025-09-02 02:25:56.000000000 +0300
+++ libXfixes-6.0.2-banan_os/configure 2025-11-16 23:59:00.284383978 +0200
@@ -6157,6 +6157,10 @@
lt_cv_deplibs_check_method=pass_all
;;
+banan_os*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
beos*)
lt_cv_deplibs_check_method=pass_all
;;
@@ -11692,6 +11696,16 @@
esac
;;
+banan_os*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ dynamic_linker="$host_os DynamicLoader.so"
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
beos*)
library_names_spec='$libname$shared_ext'
dynamic_linker="$host_os ld.so"

View File

@ -1,11 +0,0 @@
#!/bin/bash ../install.sh
NAME='libXfont2'
VERSION='2.0.7'
DOWNLOAD_URL="https://www.x.org/releases/individual/lib/libXfont2-$VERSION.tar.xz#8b7b82fdeba48769b69433e8e3fbb984a5f6bf368b0d5f47abeec49de3e58efb"
CONFIG_SUB=('config.sub')
DEPENDENCIES=('freetype' 'xorgproto' 'xtrans' 'libfontenc')
CONFIGURE_OPTIONS=(
'--enable-shared=yes'
'--enable-static=no'
)

View File

@ -1,31 +0,0 @@
diff -ruN libXfont2-2.0.7/configure libXfont2-2.0.7-banan_os/configure
--- libXfont2-2.0.7/configure 2024-08-02 02:38:54.000000000 +0300
+++ libXfont2-2.0.7-banan_os/configure 2025-11-13 20:21:21.333718050 +0200
@@ -6558,6 +6558,10 @@
lt_cv_deplibs_check_method=pass_all
;;
+banan_os*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
beos*)
lt_cv_deplibs_check_method=pass_all
;;
@@ -11940,6 +11944,16 @@
esac
;;
+banan_os*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ dynamic_linker="$host_os DynamicLoader.so"
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
beos*)
library_names_spec='$libname$shared_ext'
dynamic_linker="$host_os ld.so"

View File

@ -1,11 +0,0 @@
#!/bin/bash ../install.sh
NAME='libXft'
VERSION='2.3.9'
DOWNLOAD_URL="https://www.x.org/releases/individual/lib/libXft-$VERSION.tar.xz#60a25b78945ed6932635b3bb1899a517d31df7456e69867ffba27f89ff3976f5"
CONFIG_SUB=('config.sub')
DEPENDENCIES=('libXrender' 'libX11' 'freetype' 'fontconfig')
CONFIGURE_OPTIONS=(
'--enable-shared=yes'
'--enable-static=no'
)

View File

@ -1,31 +0,0 @@
diff -ruN libXft-2.3.9/configure libXft-2.3.9-banan_os/configure
--- libXft-2.3.9/configure 2025-04-20 18:10:46.000000000 +0300
+++ libXft-2.3.9-banan_os/configure 2025-11-17 01:42:42.971908492 +0200
@@ -5873,6 +5873,10 @@
lt_cv_deplibs_check_method=pass_all
;;
+banan_os*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
beos*)
lt_cv_deplibs_check_method=pass_all
;;
@@ -11239,6 +11243,16 @@
esac
;;
+banan_os*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ dynamic_linker="$host_os DynamicLoader.so"
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
beos*)
library_names_spec='$libname$shared_ext'
dynamic_linker="$host_os ld.so"

View File

@ -1,12 +0,0 @@
#!/bin/bash ../install.sh
NAME='libXi'
VERSION='1.8.2'
DOWNLOAD_URL="https://www.x.org/releases/individual/lib/libXi-$VERSION.tar.xz#d0e0555e53d6e2114eabfa44226ba162d2708501a25e18d99cfb35c094c6c104"
CONFIG_SUB=('config.sub')
DEPENDENCIES=('libX11' 'libXext' 'libXfixes')
CONFIGURE_OPTIONS=(
'--enable-shared=yes'
'--enable-static=no'
'--disable-malloc0returnsnull'
)

View File

@ -1,31 +0,0 @@
diff -ruN libXi-1.8.2/configure libXi-1.8.2-banan_os/configure
--- libXi-1.8.2/configure 2024-09-05 04:19:46.000000000 +0300
+++ libXi-1.8.2-banan_os/configure 2025-11-16 23:54:14.061298859 +0200
@@ -6020,6 +6020,10 @@
lt_cv_deplibs_check_method=pass_all
;;
+banan_os*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
beos*)
lt_cv_deplibs_check_method=pass_all
;;
@@ -11377,6 +11381,16 @@
esac
;;
+banan_os*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ dynamic_linker="$host_os DynamicLoader.so"
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
beos*)
library_names_spec='$libname$shared_ext'
dynamic_linker="$host_os ld.so"

View File

@ -1,11 +0,0 @@
#!/bin/bash ../install.sh
NAME='libXmu'
VERSION='1.2.1'
DOWNLOAD_URL="https://www.x.org/releases/individual/lib/libXmu-$VERSION.tar.xz#fcb27793248a39e5fcc5b9c4aec40cc0734b3ca76aac3d7d1c264e7f7e14e8b2"
CONFIG_SUB=('config.sub')
DEPENDENCIES=('libXt' 'libXext' 'libX11')
CONFIGURE_OPTIONS=(
'--enable-shared=yes'
'--enable-static=no'
)

View File

@ -1,31 +0,0 @@
diff -ruN libXmu-1.2.1/configure libXmu-1.2.1-banan_os/configure
--- libXmu-1.2.1/configure 2024-04-16 23:02:25.000000000 +0300
+++ libXmu-1.2.1-banan_os/configure 2025-11-16 23:42:28.961754856 +0200
@@ -6165,6 +6165,10 @@
lt_cv_deplibs_check_method=pass_all
;;
+banan_os*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
beos*)
lt_cv_deplibs_check_method=pass_all
;;
@@ -11492,6 +11496,16 @@
esac
;;
+banan_os*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ dynamic_linker="$host_os DynamicLoader.so"
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
beos*)
library_names_spec='$libname$shared_ext'
dynamic_linker="$host_os ld.so"

View File

@ -1,11 +0,0 @@
#!/bin/bash ../install.sh
NAME='libXpm'
VERSION='3.5.17'
DOWNLOAD_URL="https://www.x.org/releases/individual/lib/libXpm-$VERSION.tar.xz#64b31f81019e7d388c822b0b28af8d51c4622b83f1f0cb6fa3fc95e271226e43"
CONFIG_SUB=('config.sub')
DEPENDENCIES=('libX11')
CONFIGURE_OPTIONS=(
'--enable-shared=yes'
'--enable-static=no'
)

View File

@ -1,31 +0,0 @@
diff -ruN libXpm-3.5.17/configure libXpm-3.5.17-banan_os/configure
--- libXpm-3.5.17/configure 2023-10-03 19:12:11.000000000 +0300
+++ libXpm-3.5.17-banan_os/configure 2025-11-16 23:46:08.171880860 +0200
@@ -5897,6 +5897,10 @@
lt_cv_deplibs_check_method=pass_all
;;
+banan_os*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
beos*)
lt_cv_deplibs_check_method=pass_all
;;
@@ -11254,6 +11258,16 @@
esac
;;
+banan_os*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ dynamic_linker="$host_os DynamicLoader.so"
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
beos*)
library_names_spec='$libname$shared_ext'
dynamic_linker="$host_os ld.so"

View File

@ -1,11 +0,0 @@
#!/bin/bash ../install.sh
NAME='libXrandr'
VERSION='1.5.5'
DOWNLOAD_URL="https://xorg.freedesktop.org/archive/individual/lib/libXrandr-$VERSION.tar.xz#72b922c2e765434e9e9f0960148070bd4504b288263e2868a4ccce1b7cf2767a"
CONFIG_SUB=('config.sub')
DEPENDENCIES=('libX11' 'libXext' 'libXrender')
CONFIGURE_OPTIONS=(
'--enable-shared=yes'
'--enable-static=no'
)

View File

@ -1,31 +0,0 @@
diff -ruN libXrandr-1.5.5/configure libXrandr-1.5.5-banan_os/configure
--- libXrandr-1.5.5/configure 2026-01-26 02:25:38.000000000 +0200
+++ libXrandr-1.5.5-banan_os/configure 2026-02-21 23:34:03.906187857 +0200
@@ -6162,6 +6162,10 @@
lt_cv_deplibs_check_method=pass_all
;;
+banan_os*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
beos*)
lt_cv_deplibs_check_method=pass_all
;;
@@ -11697,6 +11701,16 @@
esac
;;
+banan_os*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ dynamic_linker="$host_os DynamicLoader.so"
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
beos*)
library_names_spec='$libname$shared_ext'
dynamic_linker="$host_os ld.so"

View File

@ -1,11 +0,0 @@
#!/bin/bash ../install.sh
NAME='libXrender'
VERSION='0.9.12'
DOWNLOAD_URL="https://www.x.org/releases/individual/lib/libXrender-$VERSION.tar.xz#b832128da48b39c8d608224481743403ad1691bf4e554e4be9c174df171d1b97"
CONFIG_SUB=('config.sub')
DEPENDENCIES=('libX11')
CONFIGURE_OPTIONS=(
'--enable-shared=yes'
'--enable-static=no'
)

View File

@ -1,31 +0,0 @@
diff -ruN libXrender-0.9.12/configure libXrender-0.9.12-banan_os/configure
--- libXrender-0.9.12/configure 2024-12-13 23:07:57.000000000 +0200
+++ libXrender-0.9.12-banan_os/configure 2025-11-17 00:04:56.995318198 +0200
@@ -6035,6 +6035,10 @@
lt_cv_deplibs_check_method=pass_all
;;
+banan_os*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
beos*)
lt_cv_deplibs_check_method=pass_all
;;
@@ -11570,6 +11574,16 @@
esac
;;
+banan_os*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ dynamic_linker="$host_os DynamicLoader.so"
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
beos*)
library_names_spec='$libname$shared_ext'
dynamic_linker="$host_os ld.so"

View File

@ -1,11 +0,0 @@
#!/bin/bash ../install.sh
NAME='libXt'
VERSION='1.3.1'
DOWNLOAD_URL="https://www.x.org/releases/individual/lib/libXt-$VERSION.tar.xz#e0a774b33324f4d4c05b199ea45050f87206586d81655f8bef4dba434d931288"
CONFIG_SUB=('config.sub')
DEPENDENCIES=('libSM' 'libICE' 'libX11')
CONFIGURE_OPTIONS=(
'--enable-shared=yes'
'--enable-static=no'
)

View File

@ -1,31 +0,0 @@
diff -ruN libXt-1.3.1/configure libXt-1.3.1-banan_os/configure
--- libXt-1.3.1/configure 2024-11-17 06:44:13.000000000 +0200
+++ libXt-1.3.1-banan_os/configure 2025-11-16 23:33:28.525874895 +0200
@@ -6313,6 +6313,10 @@
lt_cv_deplibs_check_method=pass_all
;;
+banan_os*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
beos*)
lt_cv_deplibs_check_method=pass_all
;;
@@ -11695,6 +11699,16 @@
esac
;;
+banan_os*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ dynamic_linker="$host_os DynamicLoader.so"
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
beos*)
library_names_spec='$libname$shared_ext'
dynamic_linker="$host_os ld.so"

View File

@ -1,11 +0,0 @@
#!/bin/bash ../install.sh
NAME='libXtst'
VERSION='1.2.5'
DOWNLOAD_URL="https://xorg.freedesktop.org/archive/individual/lib/libXtst-$VERSION.tar.xz#b50d4c25b97009a744706c1039c598f4d8e64910c9fde381994e1cae235d9242"
CONFIG_SUB=('config.sub')
DEPENDENCIES=('libX11' 'libXext' 'libXi')
CONFIGURE_OPTIONS=(
'--enable-shared=yes'
'--enable-static=no'
)

View File

@ -1,31 +0,0 @@
diff -ruN libXtst-1.2.5/configure libXtst-1.2.5-banan_os/configure
--- libXtst-1.2.5/configure 2024-08-02 03:27:45.000000000 +0300
+++ libXtst-1.2.5-banan_os/configure 2026-02-21 23:29:27.999396388 +0200
@@ -6194,6 +6194,10 @@
lt_cv_deplibs_check_method=pass_all
;;
+banan_os*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
beos*)
lt_cv_deplibs_check_method=pass_all
;;
@@ -11606,6 +11610,16 @@
esac
;;
+banan_os*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ dynamic_linker="$host_os DynamicLoader.so"
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
beos*)
library_names_spec='$libname$shared_ext'
dynamic_linker="$host_os ld.so"

View File

@ -1,26 +0,0 @@
#!/bin/bash ../install.sh
NAME='libatk'
VERSION='2.56.6'
DOWNLOAD_URL="https://gitlab.gnome.org/GNOME/at-spi2-core/-/archive/$VERSION/at-spi2-core-$VERSION.tar.gz#49b1a640d50a95389a31672a0a077f0c20e8e222322cbd0228d3fa597686819d"
TAR_CONTENT="at-spi2-core-$VERSION"
DEPENDENCIES=('glib' 'dbus' 'libxml2' 'libX11' 'libXtst')
CONFIGURE_OPTIONS=(
'-Dprefix=/usr'
)
configure() {
meson setup \
--reconfigure \
--cross-file "$MESON_CROSS_FILE" \
"${CONFIGURE_OPTIONS[@]}" \
build || exit 1
}
build() {
meson compile -C build || exit 1
}
install() {
meson install --destdir="$BANAN_SYSROOT" -C build || exit 1
}

View File

@ -1,27 +0,0 @@
#!/bin/bash ../install.sh
NAME='libepoxy'
VERSION='1.5.10'
DOWNLOAD_URL="https://download.gnome.org/sources/libepoxy/1.5/libepoxy-$VERSION.tar.xz#072cda4b59dd098bba8c2363a6247299db1fa89411dc221c8b81b8ee8192e623"
DEPENDENCIES=('mesa' 'libX11')
CONFIGURE_OPTIONS=(
'-Dprefix=/usr'
'-Dtests=false'
'-Degl=no'
)
configure() {
meson setup \
--reconfigure \
--cross-file "$MESON_CROSS_FILE" \
"${CONFIGURE_OPTIONS[@]}" \
build || exit 1
}
build() {
meson compile -C build || exit 1
}
install() {
meson install --destdir="$BANAN_SYSROOT" -C build || exit 1
}

View File

@ -1,23 +0,0 @@
--- libepoxy-1.5.10/src/dispatch_common.c 2022-02-17 14:56:12.000000000 +0200
+++ libepoxy-1.5.10-banan_os/src/dispatch_common.c 2025-11-11 18:35:23.194563757 +0200
@@ -164,7 +164,9 @@
#include <windows.h>
#else
#include <dlfcn.h>
+#ifndef __banan_os__
#include <err.h>
+#endif
#include <pthread.h>
#endif
#include <string.h>
@@ -306,8 +308,10 @@
pthread_mutex_lock(&api.mutex);
if (!*handle) {
int flags = RTLD_LAZY | RTLD_LOCAL;
+#ifdef RTLD_NOLOAD
if (!load)
flags |= RTLD_NOLOAD;
+#endif
*handle = dlopen(lib_name, flags);
if (!*handle) {

View File

@ -1,11 +0,0 @@
#!/bin/bash ../install.sh
NAME='libfontenc'
VERSION='1.1.8'
DOWNLOAD_URL="https://www.x.org/releases/individual/lib/libfontenc-$VERSION.tar.xz#7b02c3d405236e0d86806b1de9d6868fe60c313628b38350b032914aa4fd14c6"
CONFIG_SUB=('config.sub')
DEPENDENCIES=('zlib' 'xorgproto')
CONFIGURE_OPTIONS=(
'--enable-shared=yes'
'--enable-static=no'
)

View File

@ -1,31 +0,0 @@
diff -ruN libfontenc-1.1.8/configure libfontenc-1.1.8-banan_os/configure
--- libfontenc-1.1.8/configure 2024-03-02 20:32:14.000000000 +0200
+++ libfontenc-1.1.8-banan_os/configure 2025-11-13 20:25:22.782104114 +0200
@@ -6145,6 +6145,10 @@
lt_cv_deplibs_check_method=pass_all
;;
+banan_os*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
beos*)
lt_cv_deplibs_check_method=pass_all
;;
@@ -11527,6 +11531,16 @@
esac
;;
+banan_os*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ dynamic_linker="$host_os DynamicLoader.so"
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
beos*)
library_names_spec='$libname$shared_ext'
dynamic_linker="$host_os ld.so"

View File

@ -1,5 +0,0 @@
#!/bin/bash ../install.sh
NAME='libpthread-stubs'
VERSION='0.5'
DOWNLOAD_URL="https://www.x.org/releases/individual/lib/libpthread-stubs-$VERSION.tar.xz#59da566decceba7c2a7970a4a03b48d9905f1262ff94410a649224e33d2442bc"

View File

@ -1,11 +0,0 @@
#!/bin/bash ../install.sh
NAME='libxcb'
VERSION='1.17.0'
DOWNLOAD_URL="https://www.x.org/releases/individual/lib/libxcb-$VERSION.tar.xz#599ebf9996710fea71622e6e184f3a8ad5b43d0e5fa8c4e407123c88a59a6d55"
CONFIG_SUB=('config.sub' 'build-aux/config.sub')
DEPENDENCIES=('xcb-proto' 'libXau' 'libXdmcp' 'libpthread-stubs')
CONFIGURE_OPTIONS=(
'--enable-shared=yes'
'--enable-static=no'
)

View File

@ -1,31 +0,0 @@
diff -ruN libxcb-1.17.0/configure libxcb-1.17.0-banan_os/configure
--- libxcb-1.17.0/configure 2024-04-15 18:09:34.000000000 +0300
+++ libxcb-1.17.0-banan_os/configure 2025-11-13 19:58:33.829610129 +0200
@@ -6886,6 +6886,10 @@
lt_cv_deplibs_check_method=pass_all
;;
+banan_os*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
beos*)
lt_cv_deplibs_check_method=pass_all
;;
@@ -12538,6 +12542,16 @@
esac
;;
+banan_os*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ dynamic_linker="$host_os DynamicLoader.so"
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
beos*)
library_names_spec='$libname$shared_ext'
dynamic_linker="$host_os ld.so"

View File

@ -1,11 +0,0 @@
#!/bin/bash ../install.sh
NAME='libxkbfile'
VERSION='1.1.3'
DOWNLOAD_URL="https://www.x.org/releases/individual/lib/libxkbfile-$VERSION.tar.xz#a9b63eea997abb9ee6a8b4fbb515831c841f471af845a09de443b28003874bec"
CONFIG_SUB=('config.sub')
DEPENDENCIES=('libX11' 'xkeyboard-config')
CONFIGURE_OPTIONS=(
'--enable-shared=yes'
'--enable-static=no'
)

View File

@ -1,31 +0,0 @@
diff -ruN libxkbfile-1.1.3/configure libxkbfile-1.1.3-banan_os/configure
--- libxkbfile-1.1.3/configure 2024-02-05 00:14:27.000000000 +0200
+++ libxkbfile-1.1.3-banan_os/configure 2025-11-13 20:14:55.314294954 +0200
@@ -5944,6 +5944,10 @@
lt_cv_deplibs_check_method=pass_all
;;
+banan_os*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
beos*)
lt_cv_deplibs_check_method=pass_all
;;
@@ -11356,6 +11360,16 @@
esac
;;
+banan_os*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ dynamic_linker="$host_os DynamicLoader.so"
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
beos*)
library_names_spec='$libname$shared_ext'
dynamic_linker="$host_os ld.so"

Some files were not shown because too many files have changed in this diff Show More