From bfb45f717c648c5cd68e84c8ca1f805d099ba3c5 Mon Sep 17 00:00:00 2001 From: Hugo Santos Date: Fri, 13 Apr 2007 00:55:32 +0000 Subject: [PATCH] introduced a new helper class DatagramSocket which provides a consistent base interface and functionality for the implementation of datagram-based sockets. - made the ipv4 raw, udp and link protocols use DatagramSocket. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@20672 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/private/net/NetBufferUtilities.h | 2 +- headers/private/net/ProtocolUtilities.h | 288 ++++++++++++++++++ .../kernel/network/protocols/ipv4/ipv4.cpp | 101 ++---- .../kernel/network/protocols/udp/udp.cpp | 57 +--- src/add-ons/kernel/network/stack/link.cpp | 74 ++--- src/add-ons/kernel/network/stack/stack.cpp | 4 +- .../kernel/network/stack/stack_private.h | 2 + 7 files changed, 355 insertions(+), 173 deletions(-) create mode 100644 headers/private/net/ProtocolUtilities.h diff --git a/headers/private/net/NetBufferUtilities.h b/headers/private/net/NetBufferUtilities.h index 2072800790..4101f89cc8 100644 --- a/headers/private/net/NetBufferUtilities.h +++ b/headers/private/net/NetBufferUtilities.h @@ -1,5 +1,5 @@ /* - * Copyright 2006, Haiku, Inc. All Rights Reserved. + * Copyright 2006-2007, Haiku, Inc. All Rights Reserved. * Distributed under the terms of the MIT License. */ #ifndef NET_BUFFER_UTILITIES_H diff --git a/headers/private/net/ProtocolUtilities.h b/headers/private/net/ProtocolUtilities.h new file mode 100644 index 0000000000..4ddbb5f54f --- /dev/null +++ b/headers/private/net/ProtocolUtilities.h @@ -0,0 +1,288 @@ +/* + * Copyright 2007, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Hugo Santos, hugosantos@gmail.com + */ + +#ifndef PROTOCOL_UTILITIES_H +#define PROTOCOL_UTILITIES_H + +#include +#include +#include + +#include +#include +#include + +class BenaphoreLocking { +public: + typedef benaphore Type; + typedef BenaphoreLocker AutoLocker; + + static status_t Init(benaphore *lock, const char *name) + { return benaphore_init(lock, name); } + static void Destroy(benaphore *lock) { benaphore_destroy(lock); } + static status_t Lock(benaphore *lock) { return benaphore_lock(lock); } + static status_t Unlock(benaphore *lock) { return benaphore_unlock(lock); } +}; + + +extern net_stack_module_info *gStackModule; +extern net_buffer_module_info *gBufferModule; + +class NetModuleBundle { +public: + static net_stack_module_info *Stack() { return gStackModule; } + static net_buffer_module_info *Buffer() { return gBufferModule; } +}; + + +template +class DatagramSocket { +public: + DatagramSocket(const char *name, net_socket *socket); + ~DatagramSocket(); + + status_t InitCheck() const; + + status_t Enqueue(net_buffer *buffer); + status_t EnqueueClone(net_buffer *buffer); + net_buffer *Dequeue(bool clone); + status_t BlockingDequeue(bool clone, bigtime_t timeout, + net_buffer **_buffer); + status_t SocketDequeue(uint32 flags, net_buffer **_buffer); + void Clear(); + + size_t AvailableData() const; + + void WakeAll(); + +protected: + status_t _Enqueue(net_buffer *buffer); + status_t _EnqueueClone(net_buffer *buffer); + net_buffer *_Dequeue(bool clone); + void _Clear(); + + status_t _Wait(bigtime_t timeout); + void _NotifyOneReader(bool notifySocket); + + bool _IsEmpty() const { return fBuffers.IsEmpty(); } + bigtime_t _SocketTimeout(uint32 flags) const; + + typedef typename LockingBase::Type LockType; + typedef typename LockingBase::AutoLocker AutoLocker; + typedef DoublyLinkedListCLink NetBufferLink; + typedef DoublyLinkedList BufferList; + + status_t fStatus; + net_socket *fSocket; + sem_id fNotify; + BufferList fBuffers; + size_t fCurrentBytes; + mutable LockType fLock; +}; + + +#define DECL_DATAGRAM_SOCKET(args) \ + template args \ + DatagramSocket + + +DECL_DATAGRAM_SOCKET(inline)::DatagramSocket(const char *name, + net_socket *socket) + : fSocket(socket), fCurrentBytes(0) +{ + fStatus = LockingBase::Init(&fLock, name); + if (fStatus >= B_OK) + fNotify = create_sem(0, name); +} + + +DECL_DATAGRAM_SOCKET(inline)::~DatagramSocket() +{ + _Clear(); + + if (fStatus >= B_OK) { + delete_sem(fNotify); + LockingBase::Destroy(&fLock); + } +} + + +DECL_DATAGRAM_SOCKET(inline status_t)::InitCheck() const +{ + if (fStatus < 0) + return fStatus; + return fNotify; +} + + +DECL_DATAGRAM_SOCKET(inline status_t)::Enqueue(net_buffer *buffer) +{ + AutoLocker _(fLock); + return _Enqueue(buffer); +} + + +DECL_DATAGRAM_SOCKET(inline status_t)::_Enqueue(net_buffer *buffer) +{ + if (fSocket->receive.buffer_size > 0 + && (fCurrentBytes + buffer->size) > fSocket->receive.buffer_size) + return ENOBUFS; + + fBuffers.Add(buffer); + fCurrentBytes += buffer->size; + + _NotifyOneReader(true); + + return B_OK; +} + + +DECL_DATAGRAM_SOCKET(inline status_t)::EnqueueClone(net_buffer *_buffer) +{ + AutoLocker _(fLock); + return _EnqueueClone(_buffer); +} + + +DECL_DATAGRAM_SOCKET(inline status_t)::_EnqueueClone(net_buffer *_buffer) +{ + net_buffer *buffer = ModuleBundle::Buffer()->clone(_buffer, false); + if (buffer == NULL) + return B_NO_MEMORY; + + status_t status = _Enqueue(buffer); + if (status < B_OK) + ModuleBundle::Buffer()->free(buffer); + + return status; +} + + +DECL_DATAGRAM_SOCKET(inline net_buffer *)::Dequeue(bool clone) +{ + AutoLocker _(fLock); + return _Dequeue(clone); +} + + +DECL_DATAGRAM_SOCKET(inline net_buffer *)::_Dequeue(bool clone) +{ + if (fBuffers.IsEmpty()) + return NULL; + + if (clone) + return ModuleBundle::Buffer()->clone(fBuffers.Head(), false); + + net_buffer *buffer = fBuffers.RemoveHead(); + fCurrentBytes -= buffer->size; + + return buffer; +} + + +DECL_DATAGRAM_SOCKET(inline status_t)::BlockingDequeue(bool clone, + bigtime_t timeout, net_buffer **_buffer) +{ + AutoLocker _(fLock); + + bool waited = false; + + while (fBuffers.IsEmpty()) { + status_t status = _Wait(timeout); + if (status < B_OK) + return status; + waited = true; + } + + *_buffer = _Dequeue(clone); + if (clone && waited) { + // we were signalled there was a new buffer in the + // list; but since we are cloning, notify the next + // waiting reader. + _NotifyOneReader(false); + } + + if (*_buffer == NULL) + return B_NO_MEMORY; + + return B_OK; +} + + +DECL_DATAGRAM_SOCKET(inline status_t)::SocketDequeue(uint32 flags, + net_buffer **_buffer) +{ + return BlockingDequeue(flags & MSG_PEEK, _SocketTimeout(flags), _buffer); +} + + +DECL_DATAGRAM_SOCKET(inline void)::Clear() +{ + AutoLocker _(fLock); + _Clear(); +} + + +DECL_DATAGRAM_SOCKET(inline void)::_Clear() +{ + BufferList::Iterator it = fBuffers.GetIterator(); + while (it.HasNext()) + ModuleBundle::Buffer()->free(it.Next()); + fCurrentBytes = 0; +} + + +DECL_DATAGRAM_SOCKET(inline size_t)::AvailableData() const +{ + AutoLocker _(fLock); + return fCurrentBytes; +} + + +DECL_DATAGRAM_SOCKET(inline status_t)::_Wait(bigtime_t timeout) +{ + LockingBase::Unlock(&fLock); + status_t status = acquire_sem_etc(fNotify, 1, B_CAN_INTERRUPT + | B_ABSOLUTE_TIMEOUT, timeout); + LockingBase::Lock(&fLock); + + return status; +} + + +DECL_DATAGRAM_SOCKET(inline void)::WakeAll() +{ + release_sem_etc(fNotify, 0, B_RELEASE_ALL); +} + + +DECL_DATAGRAM_SOCKET(inline void)::_NotifyOneReader(bool notifySocket) +{ + release_sem_etc(fNotify, 1, B_RELEASE_IF_WAITING_ONLY + | B_DO_NOT_RESCHEDULE); + + if (notifySocket) + ModuleBundle::Stack()->notify_socket(fSocket, B_SELECT_READ, + fCurrentBytes); +} + + +DECL_DATAGRAM_SOCKET(inline bigtime_t)::_SocketTimeout(uint32 flags) const +{ + bigtime_t timeout = fSocket->receive.timeout; + + if (flags & MSG_DONTWAIT) + timeout = 0; + else if (timeout != 0 && timeout != B_INFINITE_TIMEOUT) + timeout += system_time(); + + return timeout; +} + +#endif diff --git a/src/add-ons/kernel/network/protocols/ipv4/ipv4.cpp b/src/add-ons/kernel/network/protocols/ipv4/ipv4.cpp index 1a083d012b..962c629295 100644 --- a/src/add-ons/kernel/network/protocols/ipv4/ipv4.cpp +++ b/src/add-ons/kernel/network/protocols/ipv4/ipv4.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -110,22 +111,9 @@ class FragmentPacket { typedef DoublyLinkedList RawSocketList; -class RawSocket : public DoublyLinkedListLinkImpl { +class RawSocket : public DoublyLinkedListLinkImpl, public DatagramSocket<> { public: RawSocket(net_socket *socket); - ~RawSocket(); - - status_t InitCheck(); - - status_t Read(size_t numBytes, uint32 flags, bigtime_t timeout, - net_buffer **_buffer); - ssize_t BytesAvailable(); - - status_t Write(net_buffer *buffer); - - private: - net_socket *fSocket; - net_fifo fFifo; }; struct ipv4_protocol : net_protocol { @@ -142,10 +130,11 @@ struct ipv4_protocol : net_protocol { extern net_protocol_module_info gIPv4Module; // we need this in ipv4_std_ops() for registering the AF_INET domain +net_stack_module_info *gStackModule; +net_buffer_module_info *gBufferModule; + static struct net_domain *sDomain; static net_datalink_module_info *sDatalinkModule; -static net_stack_module_info *sStackModule; -struct net_buffer_module_info *gBufferModule; static int32 sPacketID; static RawSocketList sRawSockets; static benaphore sRawSocketsLock; @@ -156,56 +145,8 @@ static benaphore sReceivingProtocolLock; RawSocket::RawSocket(net_socket *socket) - : - fSocket(socket) + : DatagramSocket<>("ipv4 raw socket", socket) { - status_t status = sStackModule->init_fifo(&fFifo, "ipv4 raw socket", 65536); - if (status < B_OK) - fFifo.notify = status; -} - - -RawSocket::~RawSocket() -{ - if (fFifo.notify >= B_OK) - sStackModule->uninit_fifo(&fFifo); -} - - -status_t -RawSocket::InitCheck() -{ - return fFifo.notify >= B_OK ? B_OK : fFifo.notify; -} - - -status_t -RawSocket::Read(size_t numBytes, uint32 flags, bigtime_t timeout, - net_buffer **_buffer) -{ - net_buffer *buffer; - status_t status = sStackModule->fifo_dequeue_buffer(&fFifo, - flags, timeout, &buffer); - if (status < B_OK) - return status; - - *_buffer = buffer; - return B_OK; -} - - -ssize_t -RawSocket::BytesAvailable() -{ - return fFifo.current_bytes; -} - - -status_t -RawSocket::Write(net_buffer *source) -{ - return sStackModule->fifo_socket_enqueue_buffer(&fFifo, fSocket, - B_SELECT_READ, source); } @@ -218,14 +159,14 @@ FragmentPacket::FragmentPacket(const ipv4_packet_key &key) fReceivedLastFragment(false), fBytesLeft(IP_MAXPACKET) { - sStackModule->init_timer(&fTimer, StaleTimer, this); + gStackModule->init_timer(&fTimer, StaleTimer, this); } FragmentPacket::~FragmentPacket() { // cancel the kill timer - sStackModule->set_timer(&fTimer, -1); + gStackModule->set_timer(&fTimer, -1); // delete all fragments net_buffer *buffer; @@ -240,7 +181,7 @@ FragmentPacket::AddFragment(uint16 start, uint16 end, net_buffer *buffer, bool lastFragment) { // restart the timer - sStackModule->set_timer(&fTimer, FRAGMENT_TIMEOUT); + gStackModule->set_timer(&fTimer, FRAGMENT_TIMEOUT); if (start >= end) { // invalid fragment @@ -595,7 +536,7 @@ send_fragments(ipv4_protocol *protocol, struct net_route *route, header->fragment_offset = htons((lastFragment ? 0 : IP_MORE_FRAGMENTS) | (fragmentOffset >> 3)); header->checksum = 0; - header->checksum = sStackModule->checksum((uint8 *)header, headerLength); + header->checksum = gStackModule->checksum((uint8 *)header, headerLength); // TODO: compute the checksum only for those parts that changed? dprintf(" send fragment of %ld bytes (%ld bytes left)\n", fragmentLength, bytesLeft); @@ -644,10 +585,8 @@ raw_receive_data(net_buffer *buffer) RawSocketList::Iterator iterator = sRawSockets.GetIterator(); - while (iterator.HasNext()) { - RawSocket *raw = iterator.Next(); - raw->Write(buffer); - } + while (iterator.HasNext()) + iterator.Next()->EnqueueClone(buffer); } @@ -664,7 +603,7 @@ receiving_protocol(uint8 protocol) if (module != NULL) return module; - if (sStackModule->get_domain_receiving_protocol(sDomain, protocol, &module) == B_OK) + if (gStackModule->get_domain_receiving_protocol(sDomain, protocol, &module) == B_OK) sReceivingProtocol[protocol] = module; return module; @@ -1016,7 +955,7 @@ ipv4_read_data(net_protocol *_protocol, size_t numBytes, uint32 flags, return B_ERROR; TRACE(("read is waiting for data...\n")); - return raw->Read(numBytes, flags, protocol->socket->receive.timeout, _buffer); + return raw->SocketDequeue(flags, _buffer); } @@ -1028,7 +967,7 @@ ipv4_read_avail(net_protocol *_protocol) if (raw == NULL) return B_ERROR; - return raw->BytesAvailable(); + return raw->AvailableData(); } @@ -1175,7 +1114,7 @@ ipv4_error_reply(net_protocol *protocol, net_buffer *causedError, uint32 code, status_t init_ipv4() { - status_t status = get_module(NET_STACK_MODULE_NAME, (module_info **)&sStackModule); + status_t status = get_module(NET_STACK_MODULE_NAME, (module_info **)&gStackModule); if (status < B_OK) return status; status = get_module(NET_BUFFER_MODULE_NAME, (module_info **)&gBufferModule); @@ -1209,12 +1148,12 @@ init_ipv4() // so we have to do it here, manually // TODO: for modules, this shouldn't be required - status = sStackModule->register_domain_protocols(AF_INET, SOCK_RAW, 0, + status = gStackModule->register_domain_protocols(AF_INET, SOCK_RAW, 0, "network/protocols/ipv4/v1", NULL); if (status < B_OK) goto err7; - status = sStackModule->register_domain(AF_INET, "internet", &gIPv4Module, + status = gStackModule->register_domain(AF_INET, "internet", &gIPv4Module, &gIPv4AddressModule, &sDomain); if (status < B_OK) goto err7; @@ -1247,10 +1186,10 @@ uninit_ipv4() // put all the domain receiving protocols we gathered so far for (uint32 i = 0; i < 256; i++) { if (sReceivingProtocol[i] != NULL) - sStackModule->put_domain_receiving_protocol(sDomain, i); + gStackModule->put_domain_receiving_protocol(sDomain, i); } - sStackModule->unregister_domain(sDomain); + gStackModule->unregister_domain(sDomain); benaphore_unlock(&sReceivingProtocolLock); hash_uninit(sFragmentHash); diff --git a/src/add-ons/kernel/network/protocols/udp/udp.cpp b/src/add-ons/kernel/network/protocols/udp/udp.cpp index 3d3a9a4c50..e89d980998 100644 --- a/src/add-ons/kernel/network/protocols/udp/udp.cpp +++ b/src/add-ons/kernel/network/protocols/udp/udp.cpp @@ -22,6 +22,7 @@ #include #include +#include #include #include @@ -29,9 +30,6 @@ #include #include -// TODO move the locking from the FIFO to the whole Endpoint -// much like we did with the LinkProtocol. - //#define TRACE_UDP #ifdef TRACE_UDP # define TRACE_BLOCK(x) dump_block x @@ -64,12 +62,9 @@ typedef NetBufferField class UdpDomainSupport; -class UdpEndpoint : public net_protocol { +class UdpEndpoint : public net_protocol, public DatagramSocket<> { public: UdpEndpoint(net_socket *socket); - ~UdpEndpoint(); - - status_t InitCheck() const; status_t Bind(sockaddr *newAddr); status_t Unbind(sockaddr *newAddr); @@ -110,8 +105,6 @@ private: bool fActive; // an active UdpEndpoint is part of the endpoint // hash (and it is bound and optionally connected) - net_fifo fFifo; - // storage space for incoming data }; @@ -208,9 +201,9 @@ private: static UdpEndpointManager *sUdpEndpointManager; +net_stack_module_info *gStackModule; net_buffer_module_info *gBufferModule; static net_datalink_module_info *sDatalinkModule; -static net_stack_module_info *sStackModule; // #pragma mark - @@ -707,27 +700,10 @@ UdpEndpointManager::_GetDomain(net_domain *domain, bool create) UdpEndpoint::UdpEndpoint(net_socket *socket) : + DatagramSocket<>("udp endpoint", socket), fDomain(NULL), fActive(false) { - status_t status = sStackModule->init_fifo(&fFifo, "UDP endpoint fifo", - socket->receive.buffer_size); - if (status < B_OK) - fFifo.notify = status; -} - - -UdpEndpoint::~UdpEndpoint() -{ - if (fFifo.notify >= B_OK) - sStackModule->uninit_fifo(&fFifo); -} - - -status_t -UdpEndpoint::InitCheck() const -{ - return fFifo.notify; } @@ -945,9 +921,9 @@ UdpEndpoint::SendData(net_buffer *buffer) ssize_t UdpEndpoint::BytesAvailable() { - // TODO protect this call - TRACE_EP("BytesAvailable(): %lu", fFifo.current_bytes); - return fFifo.current_bytes; + size_t bytes = AvailableData(); + TRACE_EP("BytesAvailable(): %lu", bytes); + return bytes; } @@ -956,16 +932,12 @@ UdpEndpoint::FetchData(size_t numBytes, uint32 flags, net_buffer **_buffer) { TRACE_EP("FetchData(%ld, 0x%lx)", numBytes, flags); - net_buffer *buffer; - - status_t status = sStackModule->fifo_dequeue_buffer(&fFifo, flags, - socket->receive.timeout, &buffer); + status_t status = SocketDequeue(flags, _buffer); TRACE_EP(" FetchData(): returned from fifo status=0x%lx", status); if (status < B_OK) return status; - TRACE_EP(" FetchData(): returns buffer with %ld bytes", buffer->size); - *_buffer = buffer; + TRACE_EP(" FetchData(): returns buffer with %ld bytes", (*_buffer)->size); return B_OK; } @@ -975,8 +947,7 @@ UdpEndpoint::StoreData(net_buffer *buffer) { TRACE_EP("StoreData(%p [%ld bytes])", buffer, buffer->size); - return sStackModule->fifo_socket_enqueue_buffer(&fFifo, socket, - B_SELECT_READ, buffer); + return EnqueueClone(buffer); } @@ -1160,7 +1131,7 @@ init_udp() status_t status; TRACE_EPM("init_udp()"); - status = get_module(NET_STACK_MODULE_NAME, (module_info **)&sStackModule); + status = get_module(NET_STACK_MODULE_NAME, (module_info **)&gStackModule); if (status < B_OK) return status; status = get_module(NET_BUFFER_MODULE_NAME, (module_info **)&gBufferModule); @@ -1179,20 +1150,20 @@ init_udp() if (status != B_OK) goto err3; - status = sStackModule->register_domain_protocols(AF_INET, SOCK_DGRAM, IPPROTO_IP, + status = gStackModule->register_domain_protocols(AF_INET, SOCK_DGRAM, IPPROTO_IP, "network/protocols/udp/v1", "network/protocols/ipv4/v1", NULL); if (status < B_OK) goto err4; - status = sStackModule->register_domain_protocols(AF_INET, SOCK_DGRAM, IPPROTO_UDP, + status = gStackModule->register_domain_protocols(AF_INET, SOCK_DGRAM, IPPROTO_UDP, "network/protocols/udp/v1", "network/protocols/ipv4/v1", NULL); if (status < B_OK) goto err4; - status = sStackModule->register_domain_receiving_protocol(AF_INET, IPPROTO_UDP, + status = gStackModule->register_domain_receiving_protocol(AF_INET, IPPROTO_UDP, "network/protocols/udp/v1"); if (status < B_OK) goto err4; diff --git a/src/add-ons/kernel/network/stack/link.cpp b/src/add-ons/kernel/network/stack/link.cpp index 6cb0feb015..0e5a316eaf 100644 --- a/src/add-ons/kernel/network/stack/link.cpp +++ b/src/add-ons/kernel/network/stack/link.cpp @@ -20,6 +20,7 @@ #include #include +#include #include #include @@ -28,12 +29,18 @@ #include -class LinkProtocol : public net_protocol { +class LocalStackBundle { public: - LinkProtocol(); - ~LinkProtocol(); + static net_stack_module_info *Stack() { return &gNetStackModule; } + static net_buffer_module_info *Buffer() { return &gNetBufferModule; } +}; - status_t InitCheck() const; +typedef DatagramSocket LocalDatagramSocket; + +class LinkProtocol : public net_protocol, public LocalDatagramSocket { +public: + LinkProtocol(net_socket *socket); + ~LinkProtocol(); status_t StartMonitoring(const char *); status_t StopMonitoring(); @@ -42,12 +49,8 @@ public: ssize_t ReadAvail() const; private: - status_t _Enqueue(net_buffer *buffer); status_t _Unregister(); - mutable benaphore fLock; - Fifo fFifo; - net_device_monitor fMonitor; net_device_interface *fMonitoredDevice; @@ -59,11 +62,9 @@ private: struct net_domain *sDomain; -LinkProtocol::LinkProtocol() - : fFifo("packet monitor fifo", 65536) +LinkProtocol::LinkProtocol(net_socket *socket) + : LocalDatagramSocket("packet capture", socket) { - benaphore_init(&fLock, "packet monitor lock"); - fMonitor.cookie = this; fMonitor.receive = _MonitorData; fMonitor.event = _MonitorEvent; @@ -77,15 +78,6 @@ LinkProtocol::~LinkProtocol() unregister_device_monitor(fMonitoredDevice->device, &fMonitor); put_device_interface(fMonitoredDevice); } - - benaphore_destroy(&fLock); -} - - -status_t -LinkProtocol::InitCheck() const -{ - return fLock.sem >= 0 && fFifo.InitCheck(); } @@ -127,26 +119,24 @@ LinkProtocol::ReadData(size_t numBytes, uint32 flags, net_buffer **_buffer) { BenaphoreLocker _(fLock); - bigtime_t timeout = socket->receive.timeout; + bool clone = flags & MSG_PEEK; + bigtime_t timeout = _SocketTimeout(flags); - if (timeout == 0) - flags |= MSG_DONTWAIT; - else if (timeout != B_INFINITE_TIMEOUT) - timeout += system_time(); - - while (fFifo.IsEmpty()) { + bool waited = false; + while (_IsEmpty()) { if (fMonitoredDevice == NULL) return ENODEV; - status_t status = B_WOULD_BLOCK; - if ((flags & MSG_DONTWAIT) == 0) - status = fFifo.Wait(&fLock, timeout); - + status_t status = _Wait(timeout); if (status < B_OK) return status; + waited = true; } - *_buffer = fFifo.Dequeue(flags & MSG_PEEK); + *_buffer = _Dequeue(clone); + if (clone && waited) + _NotifyOneReader(false); + return *_buffer ? B_OK : B_NO_MEMORY; } @@ -157,7 +147,7 @@ LinkProtocol::ReadAvail() const BenaphoreLocker _(fLock); if (fMonitoredDevice == NULL) return ENODEV; - return fFifo.current_bytes; + return fCurrentBytes; } @@ -176,18 +166,10 @@ LinkProtocol::_Unregister() } -status_t -LinkProtocol::_Enqueue(net_buffer *buffer) -{ - BenaphoreLocker _(fLock); - return fFifo.EnqueueAndNotify(buffer, socket, B_SELECT_READ); -} - - status_t LinkProtocol::_MonitorData(net_device_monitor *monitor, net_buffer *packet) { - return ((LinkProtocol *)monitor->cookie)->_Enqueue(packet); + return ((LinkProtocol *)monitor->cookie)->EnqueueClone(packet); } @@ -200,8 +182,8 @@ LinkProtocol::_MonitorEvent(net_device_monitor *monitor, int32 event) BenaphoreLocker _(protocol->fLock); protocol->_Unregister(); - if (protocol->fFifo.IsEmpty()) { - protocol->fFifo.WakeAll(); + if (protocol->_IsEmpty()) { + protocol->WakeAll(); notify_socket(protocol->socket, B_SELECT_READ, ENODEV); } } @@ -214,7 +196,7 @@ LinkProtocol::_MonitorEvent(net_device_monitor *monitor, int32 event) net_protocol * link_init_protocol(net_socket *socket) { - LinkProtocol *protocol = new (std::nothrow) LinkProtocol(); + LinkProtocol *protocol = new (std::nothrow) LinkProtocol(socket); if (protocol && protocol->InitCheck() < B_OK) { delete protocol; return NULL; diff --git a/src/add-ons/kernel/network/stack/stack.cpp b/src/add-ons/kernel/network/stack/stack.cpp index 2c68ae04e3..b8799497ef 100644 --- a/src/add-ons/kernel/network/stack/stack.cpp +++ b/src/add-ons/kernel/network/stack/stack.cpp @@ -888,7 +888,7 @@ stack_std_ops(int32 op, ...) } -static net_stack_module_info sNetStackModule = { +net_stack_module_info gNetStackModule = { { NET_STACK_MODULE_NAME, 0, @@ -939,7 +939,7 @@ static module_info sNetStarterModule = { }; module_info *modules[] = { - (module_info *)&sNetStackModule, + (module_info *)&gNetStackModule, (module_info *)&sNetStarterModule, (module_info *)&gNetBufferModule, (module_info *)&gNetSocketModule, diff --git a/src/add-ons/kernel/network/stack/stack_private.h b/src/add-ons/kernel/network/stack/stack_private.h index 5e2e906199..6b1d826fa0 100644 --- a/src/add-ons/kernel/network/stack/stack_private.h +++ b/src/add-ons/kernel/network/stack/stack_private.h @@ -14,10 +14,12 @@ #include #include #include +#include #define NET_STARTER_MODULE_NAME "network/stack/starter/v1" +extern net_stack_module_info gNetStackModule; extern net_buffer_module_info gNetBufferModule; extern net_socket_module_info gNetSocketModule; extern net_datalink_module_info gNetDatalinkModule;