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
This commit is contained in:
parent
effe53fae9
commit
bfb45f717c
@ -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
|
||||
|
288
headers/private/net/ProtocolUtilities.h
Normal file
288
headers/private/net/ProtocolUtilities.h
Normal file
@ -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 <lock.h>
|
||||
#include <util/AutoLock.h>
|
||||
#include <util/DoublyLinkedList.h>
|
||||
|
||||
#include <net_buffer.h>
|
||||
#include <net_socket.h>
|
||||
#include <net_stack.h>
|
||||
|
||||
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<typename LockingBase = BenaphoreLocking,
|
||||
typename ModuleBundle = NetModuleBundle>
|
||||
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<net_buffer> NetBufferLink;
|
||||
typedef DoublyLinkedList<net_buffer, NetBufferLink> BufferList;
|
||||
|
||||
status_t fStatus;
|
||||
net_socket *fSocket;
|
||||
sem_id fNotify;
|
||||
BufferList fBuffers;
|
||||
size_t fCurrentBytes;
|
||||
mutable LockType fLock;
|
||||
};
|
||||
|
||||
|
||||
#define DECL_DATAGRAM_SOCKET(args) \
|
||||
template<typename LockingBase, typename ModuleBundle> args \
|
||||
DatagramSocket<LockingBase, ModuleBundle>
|
||||
|
||||
|
||||
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
|
@ -13,6 +13,7 @@
|
||||
#include <net_protocol.h>
|
||||
#include <net_stack.h>
|
||||
#include <NetBufferUtilities.h>
|
||||
#include <ProtocolUtilities.h>
|
||||
|
||||
#include <ByteOrder.h>
|
||||
#include <KernelExport.h>
|
||||
@ -110,22 +111,9 @@ class FragmentPacket {
|
||||
|
||||
typedef DoublyLinkedList<class RawSocket> RawSocketList;
|
||||
|
||||
class RawSocket : public DoublyLinkedListLinkImpl<RawSocket> {
|
||||
class RawSocket : public DoublyLinkedListLinkImpl<RawSocket>, 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);
|
||||
|
@ -22,6 +22,7 @@
|
||||
|
||||
#include <NetBufferUtilities.h>
|
||||
#include <NetUtilities.h>
|
||||
#include <ProtocolUtilities.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <new>
|
||||
@ -29,9 +30,6 @@
|
||||
#include <string.h>
|
||||
#include <utility>
|
||||
|
||||
// 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<uint16, offsetof(udp_header, udp_checksum)>
|
||||
|
||||
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;
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include <util/AutoLock.h>
|
||||
|
||||
#include <KernelExport.h>
|
||||
#include <ProtocolUtilities.h>
|
||||
|
||||
#include <net/if_types.h>
|
||||
#include <new>
|
||||
@ -28,12 +29,18 @@
|
||||
#include <sys/sockio.h>
|
||||
|
||||
|
||||
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<BenaphoreLocking, LocalStackBundle> 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;
|
||||
|
@ -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,
|
||||
|
@ -14,10 +14,12 @@
|
||||
#include <net_datalink_protocol.h>
|
||||
#include <net_protocol.h>
|
||||
#include <net_socket.h>
|
||||
#include <net_stack.h>
|
||||
|
||||
|
||||
#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;
|
||||
|
Loading…
Reference in New Issue
Block a user