diff --git a/headers/private/net/ProtocolUtilities.h b/headers/private/net/ProtocolUtilities.h index 8dad93e869..f418bbb45c 100644 --- a/headers/private/net/ProtocolUtilities.h +++ b/headers/private/net/ProtocolUtilities.h @@ -114,7 +114,7 @@ public: status_t Enqueue(net_buffer* buffer); net_buffer* Dequeue(bool clone); - status_t BlockingDequeue(bool clone, bigtime_t timeout, + status_t BlockingDequeue(bool peek, bigtime_t timeout, net_buffer** _buffer); void Clear(); @@ -122,24 +122,27 @@ public: status_t SocketDequeue(uint32 flags, net_buffer** _buffer); + bool IsEmpty() const { return fBuffers.IsEmpty(); } ssize_t AvailableData() const; void WakeAll(); + void NotifyOne(); protected: - virtual status_t _SocketStatus() const; + virtual status_t SocketStatus(bool peek) const; +private: status_t _Enqueue(net_buffer* buffer); status_t _SocketEnqueue(net_buffer* buffer); - net_buffer* _Dequeue(bool clone); + net_buffer* _Dequeue(bool peek); void _Clear(); status_t _Wait(bigtime_t timeout); void _NotifyOneReader(bool notifySocket); - bool _IsEmpty() const { return fBuffers.IsEmpty(); } bigtime_t _SocketTimeout(uint32 flags) const; +protected: typedef typename LockingBase::Type LockType; typedef typename LockingBase::AutoLocker AutoLocker; typedef DoublyLinkedListCLink NetBufferLink; @@ -249,27 +252,31 @@ DECL_DATAGRAM_SOCKET(inline net_buffer*)::_Dequeue(bool clone) } -DECL_DATAGRAM_SOCKET(inline status_t)::BlockingDequeue(bool clone, +DECL_DATAGRAM_SOCKET(inline status_t)::BlockingDequeue(bool peek, bigtime_t timeout, net_buffer** _buffer) { AutoLocker _(fLock); bool waited = false; while (fBuffers.IsEmpty()) { - status_t status = _SocketStatus(); - if (status < B_OK) + status_t status = SocketStatus(peek); + if (status != B_OK) { + if (peek) + _NotifyOneReader(false); + return status; + } + + status = _Wait(timeout); + if (status != B_OK) return status; - if ((status = _Wait(timeout)) < 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. + *_buffer = _Dequeue(peek); + if (peek && waited) { + // There is a new buffer in the list; but since we are only peeking, + // notify the next waiting reader. _NotifyOneReader(false); } @@ -307,7 +314,7 @@ DECL_DATAGRAM_SOCKET(inline void)::_Clear() DECL_DATAGRAM_SOCKET(inline ssize_t)::AvailableData() const { AutoLocker _(fLock); - status_t status = _SocketStatus(); + status_t status = SocketStatus(true); if (status < B_OK) return status; @@ -315,9 +322,15 @@ DECL_DATAGRAM_SOCKET(inline ssize_t)::AvailableData() const } -DECL_DATAGRAM_SOCKET(inline status_t)::_SocketStatus() const +DECL_DATAGRAM_SOCKET(inline status_t)::SocketStatus(bool peek) const { - return B_OK; + if (peek) + return fSocket->error; + + status_t status = fSocket->error; + fSocket->error = B_OK; + + return status; } @@ -338,14 +351,22 @@ DECL_DATAGRAM_SOCKET(inline void)::WakeAll() } +DECL_DATAGRAM_SOCKET(inline void)::NotifyOne() +{ + release_sem_etc(fNotify, 1, B_RELEASE_IF_WAITING_ONLY + | B_DO_NOT_RESCHEDULE); +} + + DECL_DATAGRAM_SOCKET(inline void)::_NotifyOneReader(bool notifySocket) { release_sem_etc(fNotify, 1, B_RELEASE_IF_WAITING_ONLY | B_DO_NOT_RESCHEDULE); - if (notifySocket) + if (notifySocket) { ModuleBundle::Stack()->notify_socket(fSocket, B_SELECT_READ, fCurrentBytes); + } } diff --git a/src/add-ons/kernel/network/stack/link.cpp b/src/add-ons/kernel/network/stack/link.cpp index 21919d208b..101b1f259b 100644 --- a/src/add-ons/kernel/network/stack/link.cpp +++ b/src/add-ons/kernel/network/stack/link.cpp @@ -40,22 +40,26 @@ typedef DatagramSocket LocalDatagramSocket; class LinkProtocol : public net_protocol, public LocalDatagramSocket { public: - LinkProtocol(net_socket* socket); - ~LinkProtocol(); + LinkProtocol(net_socket* socket); + virtual ~LinkProtocol(); - status_t StartMonitoring(const char* deviceName); - status_t StopMonitoring(); + status_t StartMonitoring(const char* deviceName); + status_t StopMonitoring(); + +protected: + status_t SocketStatus(bool peek) const; private: - status_t _SocketStatus() const; - status_t _Unregister(); + status_t _Unregister(); - static status_t _MonitorData(net_device_monitor* monitor, - net_buffer* buffer); - static void _MonitorEvent(net_device_monitor* monitor, int32 event); + static status_t _MonitorData(net_device_monitor* monitor, + net_buffer* buffer); + static void _MonitorEvent(net_device_monitor* monitor, + int32 event); - net_device_monitor fMonitor; - net_device_interface* fMonitoredDevice; +private: + net_device_monitor fMonitor; + net_device_interface* fMonitoredDevice; }; @@ -115,13 +119,15 @@ LinkProtocol::StopMonitoring() status_t -LinkProtocol::_SocketStatus() const +LinkProtocol::SocketStatus(bool peek) const { if (fMonitoredDevice == NULL) return ENODEV; - return LocalDatagramSocket::_SocketStatus(); + + return LocalDatagramSocket::SocketStatus(peek); } + status_t LinkProtocol::_Unregister() { @@ -153,7 +159,7 @@ LinkProtocol::_MonitorEvent(net_device_monitor* monitor, int32 event) MutexLocker _(protocol->fLock); protocol->_Unregister(); - if (protocol->_IsEmpty()) { + if (protocol->IsEmpty()) { protocol->WakeAll(); notify_socket(protocol->socket, B_SELECT_READ, ENODEV); }