glued the multicast filter handling to the receive path: we are now capable of receiving multicast frames in datagram sockets.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@20695 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -55,8 +55,9 @@ struct net_protocol_module_info {
|
||||
size_t (*get_mtu)(net_protocol *self, const struct sockaddr *address);
|
||||
|
||||
status_t (*receive_data)(net_buffer *data);
|
||||
status_t (*error)(uint32 code, net_buffer *data);
|
||||
status_t (*deliver_data)(net_protocol *protocol, net_buffer *data);
|
||||
|
||||
status_t (*error)(uint32 code, net_buffer *data);
|
||||
status_t (*error_reply)(net_protocol *self, net_buffer *causedError,
|
||||
uint32 code, void *errorData);
|
||||
};
|
||||
|
||||
@@ -342,6 +342,7 @@ net_protocol_module_info sICMPModule = {
|
||||
icmp_get_domain,
|
||||
icmp_get_mtu,
|
||||
icmp_receive_data,
|
||||
NULL,
|
||||
icmp_error,
|
||||
icmp_error_reply,
|
||||
};
|
||||
|
||||
@@ -117,9 +117,15 @@ class FragmentPacket {
|
||||
|
||||
class MulticastGroup {
|
||||
public:
|
||||
typedef MulticastGroupLink<IPv4Multicast> Link;
|
||||
|
||||
MulticastGroup(const in_addr &address);
|
||||
|
||||
status_t Deliver(net_buffer *buffer);
|
||||
status_t Deliver(net_protocol_module_info *module, net_buffer *buffer);
|
||||
|
||||
void Add(Link *link);
|
||||
void Remove(Link *link);
|
||||
bool IsEmpty() const { return fLinks.IsEmpty(); }
|
||||
|
||||
static uint32 Hash(void *address, const void *key, uint32 range);
|
||||
static int Compare(void *address, const void *key);
|
||||
@@ -128,8 +134,12 @@ public:
|
||||
static const int kMaxGroups = 64;
|
||||
|
||||
private:
|
||||
typedef DoublyLinkedListCLink<Link> LinkLink;
|
||||
typedef DoublyLinkedList<Link, LinkLink> Links;
|
||||
|
||||
MulticastGroup *fNext;
|
||||
in_addr fMulticastAddress;
|
||||
Links fLinks;
|
||||
};
|
||||
|
||||
class RawSocket : public DoublyLinkedListLinkImpl<RawSocket>, public DatagramSocket<> {
|
||||
@@ -139,9 +149,11 @@ class RawSocket : public DoublyLinkedListLinkImpl<RawSocket>, public DatagramSoc
|
||||
|
||||
typedef DoublyLinkedList<RawSocket> RawSocketList;
|
||||
|
||||
typedef MulticastFilter<IPv4Multicast> IPv4MulticastFilter;
|
||||
|
||||
struct ipv4_protocol : net_protocol {
|
||||
ipv4_protocol(net_socket *socket)
|
||||
: multicast_filter(socket) {}
|
||||
ipv4_protocol()
|
||||
: multicast_filter(this) {}
|
||||
|
||||
RawSocket *raw;
|
||||
uint8 service_type;
|
||||
@@ -149,7 +161,7 @@ struct ipv4_protocol : net_protocol {
|
||||
uint8 multicast_time_to_live;
|
||||
uint32 flags;
|
||||
|
||||
MulticastFilter<in_addr> multicast_filter;
|
||||
IPv4MulticastFilter multicast_filter;
|
||||
};
|
||||
|
||||
// protocol flags
|
||||
@@ -424,9 +436,35 @@ MulticastGroup::MulticastGroup(const in_addr &address)
|
||||
|
||||
|
||||
status_t
|
||||
MulticastGroup::Deliver(net_buffer *buffer)
|
||||
MulticastGroup::Deliver(net_protocol_module_info *module, net_buffer *buffer)
|
||||
{
|
||||
return B_ERROR;
|
||||
if (module->deliver_data == NULL)
|
||||
return B_OK;
|
||||
|
||||
Links::Iterator iterator = fLinks.GetIterator();
|
||||
|
||||
while (iterator.HasNext()) {
|
||||
Link *link = iterator.Next();
|
||||
|
||||
if (link->group->FilterAccepts(buffer))
|
||||
module->deliver_data(link->group->Socket(), buffer);
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
MulticastGroup::Add(Link *link)
|
||||
{
|
||||
fLinks.Add(link);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
MulticastGroup::Remove(Link *link)
|
||||
{
|
||||
fLinks.Remove(link);
|
||||
}
|
||||
|
||||
|
||||
@@ -669,7 +707,7 @@ raw_receive_data(net_buffer *buffer)
|
||||
|
||||
|
||||
static status_t
|
||||
deliver_multicast(net_buffer *buffer)
|
||||
deliver_multicast(net_protocol_module_info *module, net_buffer *buffer)
|
||||
{
|
||||
BenaphoreLocker _(sMulticastGroupsLock);
|
||||
|
||||
@@ -678,9 +716,54 @@ deliver_multicast(net_buffer *buffer)
|
||||
if (group == NULL)
|
||||
return B_OK;
|
||||
|
||||
// RAW sockets will be registered just like any other
|
||||
// TODO fix sending multicast to RAW sockets, right now
|
||||
// they are receiving the frames without the IP header
|
||||
|
||||
return group->Deliver(buffer);
|
||||
return group->Deliver(module, buffer);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
IPv4Multicast::JoinGroup(const in_addr &groupAddr, MulticastGroup::Link *link)
|
||||
{
|
||||
BenaphoreLocker _(sMulticastGroupsLock);
|
||||
|
||||
MulticastGroup *group = (MulticastGroup *)hash_lookup(sMulticastGroups,
|
||||
&groupAddr);
|
||||
if (group == NULL) {
|
||||
group = new (std::nothrow) MulticastGroup(groupAddr);
|
||||
if (group == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
status_t status = hash_insert(sMulticastGroups, group);
|
||||
if (status < B_OK) {
|
||||
delete group;
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
group->Add(link);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
IPv4Multicast::LeaveGroup(const in_addr &groupAddr, MulticastGroup::Link *link)
|
||||
{
|
||||
BenaphoreLocker _(sMulticastGroupsLock);
|
||||
|
||||
MulticastGroup *group = (MulticastGroup *)hash_lookup(sMulticastGroups,
|
||||
&groupAddr);
|
||||
if (group == NULL)
|
||||
return ENOENT;
|
||||
|
||||
group->Remove(link);
|
||||
if (group->IsEmpty()) {
|
||||
hash_remove(sMulticastGroups, group);
|
||||
delete group;
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -715,7 +798,7 @@ fill_sockaddr_in(sockaddr_in *target, in_addr_t address)
|
||||
|
||||
|
||||
static status_t
|
||||
ipv4_delta_group(MulticastFilter<in_addr>::GroupState *group, int option,
|
||||
ipv4_delta_group(IPv4MulticastFilter::GroupState *group, int option,
|
||||
net_interface *interface, const in_addr *sourceAddr)
|
||||
{
|
||||
switch (option) {
|
||||
@@ -742,8 +825,8 @@ ipv4_delta_membership(ipv4_protocol *protocol, int option,
|
||||
net_interface *interface, const in_addr *groupAddr,
|
||||
const in_addr *sourceAddr)
|
||||
{
|
||||
MulticastFilter<in_addr> &filter = protocol->multicast_filter;
|
||||
MulticastFilter<in_addr>::GroupState *group = NULL;
|
||||
IPv4MulticastFilter &filter = protocol->multicast_filter;
|
||||
IPv4MulticastFilter::GroupState *group = NULL;
|
||||
|
||||
switch (option) {
|
||||
case IP_ADD_MEMBERSHIP:
|
||||
@@ -833,7 +916,7 @@ ipv4_generic_delta_membership(ipv4_protocol *protocol, int option,
|
||||
net_protocol *
|
||||
ipv4_init_protocol(net_socket *socket)
|
||||
{
|
||||
ipv4_protocol *protocol = new (std::nothrow) ipv4_protocol(socket);
|
||||
ipv4_protocol *protocol = new (std::nothrow) ipv4_protocol();
|
||||
if (protocol == NULL)
|
||||
return NULL;
|
||||
|
||||
@@ -1412,19 +1495,12 @@ ipv4_receive_data(net_buffer *buffer)
|
||||
}
|
||||
}
|
||||
|
||||
if (buffer->flags & MSG_MCAST) {
|
||||
// Unfortunely historical reasons dictate that the IP multicast
|
||||
// model be a little different from the unicast one. We deliver
|
||||
// this frame directly to all sockets registered with interest
|
||||
// for this multicast group.
|
||||
return deliver_multicast(buffer);
|
||||
}
|
||||
|
||||
// Since the buffer might have been changed (reassembled fragment)
|
||||
// we must no longer access bufferHeader or header anymore after
|
||||
// this point
|
||||
|
||||
raw_receive_data(buffer);
|
||||
if (!(buffer->flags & MSG_MCAST))
|
||||
raw_receive_data(buffer);
|
||||
|
||||
gBufferModule->remove_header(buffer, headerLength);
|
||||
// the header is of variable size and may include IP options
|
||||
@@ -1436,10 +1512,30 @@ ipv4_receive_data(net_buffer *buffer)
|
||||
return EAFNOSUPPORT;
|
||||
}
|
||||
|
||||
if (buffer->flags & MSG_MCAST) {
|
||||
// Unfortunely historical reasons dictate that the IP multicast
|
||||
// model be a little different from the unicast one. We deliver
|
||||
// this frame directly to all sockets registered with interest
|
||||
// for this multicast group.
|
||||
return deliver_multicast(module, buffer);
|
||||
}
|
||||
|
||||
return module->receive_data(buffer);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
ipv4_deliver_data(net_protocol *_protocol, net_buffer *buffer)
|
||||
{
|
||||
ipv4_protocol *protocol = (ipv4_protocol *)_protocol;
|
||||
|
||||
if (protocol->raw == NULL)
|
||||
return B_ERROR;
|
||||
|
||||
return protocol->raw->SocketEnqueue(buffer);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
ipv4_error(uint32 code, net_buffer *data)
|
||||
{
|
||||
@@ -1591,6 +1687,7 @@ net_protocol_module_info gIPv4Module = {
|
||||
ipv4_get_domain,
|
||||
ipv4_get_mtu,
|
||||
ipv4_receive_data,
|
||||
ipv4_deliver_data,
|
||||
ipv4_error,
|
||||
ipv4_error_reply,
|
||||
};
|
||||
|
||||
@@ -8,12 +8,14 @@
|
||||
|
||||
#include "multicast.h"
|
||||
|
||||
#include <net_buffer.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include <new>
|
||||
|
||||
template class MulticastFilter<in_addr>;
|
||||
template class MulticastGroupState<in_addr>;
|
||||
template class MulticastFilter<IPv4Multicast>;
|
||||
template class MulticastGroupState<IPv4Multicast>;
|
||||
template class MulticastGroupInterfaceState<in_addr>;
|
||||
|
||||
static inline bool
|
||||
@@ -94,25 +96,23 @@ MulticastGroupInterfaceState<AddressType>::_Remove(Source *state)
|
||||
}
|
||||
|
||||
|
||||
template<typename AddressType>
|
||||
MulticastGroupState<AddressType>::MulticastGroupState(
|
||||
MulticastFilter<AddressType> *parent, const AddressType &address)
|
||||
: fParent(parent), fMulticastAddress(address), fFilterMode(kInclude)
|
||||
template<typename Addressing>
|
||||
MulticastGroupState<Addressing>::MulticastGroupState(net_protocol *socket,
|
||||
const AddressType &address)
|
||||
: fSocket(socket), fMulticastAddress(address), fFilterMode(kInclude)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
template<typename AddressType>
|
||||
MulticastGroupState<AddressType>::~MulticastGroupState()
|
||||
template<typename Addressing>
|
||||
MulticastGroupState<Addressing>::~MulticastGroupState()
|
||||
{
|
||||
InterfaceList::Iterator iterator = fInterfaces.GetIterator();
|
||||
while (iterator.HasNext())
|
||||
_RemoveInterface(iterator.Next());
|
||||
Clear();
|
||||
}
|
||||
|
||||
|
||||
template<typename AddressType> status_t
|
||||
MulticastGroupState<AddressType>::Add(net_interface *interface)
|
||||
template<typename Addressing> status_t
|
||||
MulticastGroupState<Addressing>::Add(net_interface *interface)
|
||||
{
|
||||
if (fFilterMode == kInclude && !fInterfaces.IsEmpty())
|
||||
return EINVAL;
|
||||
@@ -123,8 +123,8 @@ MulticastGroupState<AddressType>::Add(net_interface *interface)
|
||||
}
|
||||
|
||||
|
||||
template<typename AddressType> status_t
|
||||
MulticastGroupState<AddressType>::Drop(net_interface *interface)
|
||||
template<typename Addressing> status_t
|
||||
MulticastGroupState<Addressing>::Drop(net_interface *interface)
|
||||
{
|
||||
InterfaceState *state = _GetInterface(interface, false);
|
||||
if (state == NULL)
|
||||
@@ -139,8 +139,8 @@ MulticastGroupState<AddressType>::Drop(net_interface *interface)
|
||||
}
|
||||
|
||||
|
||||
template<typename AddressType> status_t
|
||||
MulticastGroupState<AddressType>::BlockSource(net_interface *interface,
|
||||
template<typename Addressing> status_t
|
||||
MulticastGroupState<Addressing>::BlockSource(net_interface *interface,
|
||||
const AddressType &sourceAddress)
|
||||
{
|
||||
if (fFilterMode != kExclude)
|
||||
@@ -154,8 +154,8 @@ MulticastGroupState<AddressType>::BlockSource(net_interface *interface,
|
||||
}
|
||||
|
||||
|
||||
template<typename AddressType> status_t
|
||||
MulticastGroupState<AddressType>::UnblockSource(net_interface *interface,
|
||||
template<typename Addressing> status_t
|
||||
MulticastGroupState<Addressing>::UnblockSource(net_interface *interface,
|
||||
const AddressType &sourceAddress)
|
||||
{
|
||||
if (fFilterMode != kExclude)
|
||||
@@ -168,8 +168,8 @@ MulticastGroupState<AddressType>::UnblockSource(net_interface *interface,
|
||||
return state->Remove(sourceAddress);
|
||||
}
|
||||
|
||||
template<typename AddressType> status_t
|
||||
MulticastGroupState<AddressType>::AddSSM(net_interface *interface,
|
||||
template<typename Addressing> status_t
|
||||
MulticastGroupState<Addressing>::AddSSM(net_interface *interface,
|
||||
const AddressType &sourceAddress)
|
||||
{
|
||||
if (fFilterMode == kExclude)
|
||||
@@ -183,8 +183,8 @@ MulticastGroupState<AddressType>::AddSSM(net_interface *interface,
|
||||
}
|
||||
|
||||
|
||||
template<typename AddressType> status_t
|
||||
MulticastGroupState<AddressType>::DropSSM(net_interface *interface,
|
||||
template<typename Addressing> status_t
|
||||
MulticastGroupState<Addressing>::DropSSM(net_interface *interface,
|
||||
const AddressType &sourceAddress)
|
||||
{
|
||||
if (fFilterMode == kExclude)
|
||||
@@ -198,8 +198,31 @@ MulticastGroupState<AddressType>::DropSSM(net_interface *interface,
|
||||
}
|
||||
|
||||
|
||||
template<typename AddressType> MulticastGroupState<AddressType>::InterfaceState *
|
||||
MulticastGroupState<AddressType>::_GetInterface(net_interface *interface,
|
||||
template<typename Addressing> void
|
||||
MulticastGroupState<Addressing>::Clear()
|
||||
{
|
||||
InterfaceList::Iterator iterator = fInterfaces.GetIterator();
|
||||
while (iterator.HasNext())
|
||||
_RemoveInterface(iterator.Next());
|
||||
}
|
||||
|
||||
|
||||
template<typename Addressing> bool
|
||||
MulticastGroupState<Addressing>::FilterAccepts(net_buffer *buffer)
|
||||
{
|
||||
InterfaceState *state = _GetInterface(buffer->interface, false);
|
||||
if (state == NULL)
|
||||
return false;
|
||||
|
||||
bool has = state->Contains(*Addressing::AddressFromSockAddr(
|
||||
(sockaddr *)&buffer->source));
|
||||
|
||||
return (has && fFilterMode == kInclude) || (!has && fFilterMode == kExclude);
|
||||
}
|
||||
|
||||
|
||||
template<typename Addressing> MulticastGroupState<Addressing>::InterfaceState *
|
||||
MulticastGroupState<Addressing>::_GetInterface(net_interface *interface,
|
||||
bool create)
|
||||
{
|
||||
InterfaceList::Iterator iterator = fInterfaces.GetIterator();
|
||||
@@ -220,35 +243,35 @@ MulticastGroupState<AddressType>::_GetInterface(net_interface *interface,
|
||||
}
|
||||
|
||||
|
||||
template<typename AddressType> void
|
||||
MulticastGroupState<AddressType>::_RemoveInterface(InterfaceState *state)
|
||||
template<typename Addressing> void
|
||||
MulticastGroupState<Addressing>::_RemoveInterface(InterfaceState *state)
|
||||
{
|
||||
fInterfaces.Remove(state);
|
||||
delete state;
|
||||
}
|
||||
|
||||
|
||||
template<typename AddressType>
|
||||
MulticastFilter<AddressType>::MulticastFilter(net_socket *socket)
|
||||
template<typename Addressing>
|
||||
MulticastFilter<Addressing>::MulticastFilter(net_protocol *socket)
|
||||
: fParent(socket)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
template<typename AddressType>
|
||||
MulticastFilter<AddressType>::~MulticastFilter()
|
||||
template<typename Addressing>
|
||||
MulticastFilter<Addressing>::~MulticastFilter()
|
||||
{
|
||||
States::Iterator iterator = fStates.GetIterator();
|
||||
while (iterator.HasNext()) {
|
||||
GroupState *state = iterator.Next();
|
||||
fStates.Remove(state);
|
||||
delete state;
|
||||
state->Clear();
|
||||
ReturnGroup(state);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<typename AddressType> MulticastFilter<AddressType>::GroupState *
|
||||
MulticastFilter<AddressType>::GetGroup(const AddressType &groupAddress,
|
||||
template<typename Addressing> MulticastFilter<Addressing>::GroupState *
|
||||
MulticastFilter<Addressing>::GetGroup(const AddressType &groupAddress,
|
||||
bool create)
|
||||
{
|
||||
States::Iterator iterator = fStates.GetIterator();
|
||||
@@ -262,17 +285,26 @@ MulticastFilter<AddressType>::GetGroup(const AddressType &groupAddress,
|
||||
if (!create)
|
||||
return NULL;
|
||||
|
||||
GroupState *state = new (nothrow) GroupState(this, groupAddress);
|
||||
if (state)
|
||||
GroupState *state = new (nothrow) GroupState(fParent, groupAddress);
|
||||
if (state) {
|
||||
if (Addressing::JoinGroup(groupAddress, state->ProtocolLink()) < B_OK) {
|
||||
delete state;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fStates.Add(state);
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
|
||||
template<typename AddressType> void
|
||||
MulticastFilter<AddressType>::ReturnGroup(GroupState *group)
|
||||
template<typename Addressing> void
|
||||
MulticastFilter<Addressing>::ReturnGroup(GroupState *group)
|
||||
{
|
||||
if (group->IsEmpty()) {
|
||||
Addressing::LeaveGroup(group->Address(), group->ProtocolLink());
|
||||
|
||||
fStates.Remove(group);
|
||||
delete group;
|
||||
}
|
||||
|
||||
@@ -12,10 +12,30 @@
|
||||
#include <util/DoublyLinkedList.h>
|
||||
#include <util/list.h>
|
||||
|
||||
struct net_interface;
|
||||
struct net_socket;
|
||||
#include <netinet/in.h>
|
||||
|
||||
template<typename AddressType> class MulticastFilter;
|
||||
struct net_buffer;
|
||||
struct net_interface;
|
||||
struct net_protocol;
|
||||
|
||||
// This code is template'ized as it is reusable for IPv6
|
||||
|
||||
template<typename Addressing> class MulticastFilter;
|
||||
template<typename Addressing> struct MulticastGroupLink;
|
||||
template<typename Addressing> class MulticastGroupState;
|
||||
|
||||
// TODO move this elsewhere...
|
||||
struct IPv4Multicast {
|
||||
typedef struct in_addr AddressType;
|
||||
|
||||
static status_t JoinGroup(const in_addr &, MulticastGroupLink<IPv4Multicast> *);
|
||||
static status_t LeaveGroup(const in_addr &, MulticastGroupLink<IPv4Multicast> *);
|
||||
|
||||
static in_addr *AddressFromSockAddr(sockaddr *sockaddr)
|
||||
{
|
||||
return &((sockaddr_in *)sockaddr)->sin_addr;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename AddressType>
|
||||
struct MulticastSource {
|
||||
@@ -34,6 +54,9 @@ public:
|
||||
status_t Add(const AddressType &address);
|
||||
status_t Remove(const AddressType &address);
|
||||
|
||||
bool Contains(const AddressType &address)
|
||||
{ return _Get(address, false) != NULL; }
|
||||
|
||||
list_link link;
|
||||
private:
|
||||
typedef MulticastSource<AddressType> Source;
|
||||
@@ -48,13 +71,22 @@ private:
|
||||
SourceList fSources;
|
||||
};
|
||||
|
||||
template<typename AddressType>
|
||||
template<typename Addressing>
|
||||
struct MulticastGroupLink {
|
||||
MulticastGroupState<Addressing> *group;
|
||||
list_link link;
|
||||
};
|
||||
|
||||
template<typename Addressing>
|
||||
class MulticastGroupState {
|
||||
public:
|
||||
MulticastGroupState(MulticastFilter<AddressType> *parent,
|
||||
const AddressType &address);
|
||||
typedef typename Addressing::AddressType AddressType;
|
||||
|
||||
MulticastGroupState(net_protocol *parent, const AddressType &address);
|
||||
~MulticastGroupState();
|
||||
|
||||
net_protocol *Socket() const { return fSocket; }
|
||||
|
||||
const AddressType &Address() const { return fMulticastAddress; }
|
||||
bool IsEmpty() const
|
||||
{ return fFilterMode == kInclude && fInterfaces.IsEmpty(); }
|
||||
@@ -70,6 +102,12 @@ public:
|
||||
status_t DropSSM(net_interface *interface,
|
||||
const AddressType &sourceAddress);
|
||||
|
||||
void Clear();
|
||||
|
||||
bool FilterAccepts(net_buffer *buffer);
|
||||
|
||||
MulticastGroupLink<Addressing> *ProtocolLink() { return &fInternalLink; }
|
||||
|
||||
list_link link;
|
||||
private:
|
||||
typedef MulticastGroupInterfaceState<AddressType> InterfaceState;
|
||||
@@ -84,21 +122,23 @@ private:
|
||||
kExclude
|
||||
};
|
||||
|
||||
MulticastFilter<AddressType> *fParent;
|
||||
net_protocol *fSocket;
|
||||
AddressType fMulticastAddress;
|
||||
FilterMode fFilterMode;
|
||||
InterfaceList fInterfaces;
|
||||
MulticastGroupLink<Addressing> fInternalLink;
|
||||
};
|
||||
|
||||
template<typename AddressType>
|
||||
template<typename Addressing>
|
||||
class MulticastFilter {
|
||||
public:
|
||||
typedef MulticastGroupState<AddressType> GroupState;
|
||||
typedef typename Addressing::AddressType AddressType;
|
||||
typedef MulticastGroupState<Addressing> GroupState;
|
||||
|
||||
MulticastFilter(net_socket *parent);
|
||||
MulticastFilter(net_protocol *parent);
|
||||
~MulticastFilter();
|
||||
|
||||
net_socket *Parent() const { return fParent; }
|
||||
net_protocol *Parent() const { return fParent; }
|
||||
|
||||
GroupState *GetGroup(const AddressType &groupAddress, bool create);
|
||||
void ReturnGroup(GroupState *group);
|
||||
@@ -107,7 +147,7 @@ private:
|
||||
typedef DoublyLinkedListCLink<GroupState> GroupStateLink;
|
||||
typedef DoublyLinkedList<GroupState, GroupStateLink> States;
|
||||
|
||||
net_socket *fParent;
|
||||
net_protocol *fParent;
|
||||
|
||||
// TODO change this into an hash table or tree
|
||||
States fStates;
|
||||
|
||||
@@ -718,6 +718,7 @@ net_protocol_module_info sTCPModule = {
|
||||
tcp_get_domain,
|
||||
tcp_get_mtu,
|
||||
tcp_receive_data,
|
||||
NULL,
|
||||
tcp_error,
|
||||
tcp_error_reply,
|
||||
};
|
||||
|
||||
@@ -82,6 +82,7 @@ public:
|
||||
net_buffer **_buffer);
|
||||
|
||||
status_t StoreData(net_buffer *buffer);
|
||||
status_t DeliverData(net_buffer *buffer);
|
||||
|
||||
net_domain * Domain() const
|
||||
{
|
||||
@@ -179,6 +180,7 @@ public:
|
||||
~UdpEndpointManager();
|
||||
|
||||
status_t ReceiveData(net_buffer *buffer);
|
||||
status_t Deframe(net_buffer *buffer);
|
||||
|
||||
UdpDomainSupport *OpenEndpoint(UdpEndpoint *endpoint);
|
||||
status_t FreeEndpoint(UdpDomainSupport *domain);
|
||||
@@ -544,8 +546,40 @@ UdpEndpointManager::InitCheck() const
|
||||
status_t
|
||||
UdpEndpointManager::ReceiveData(net_buffer *buffer)
|
||||
{
|
||||
status_t status = Deframe(buffer);
|
||||
if (status < B_OK)
|
||||
return status;
|
||||
|
||||
TRACE_EPM("ReceiveData(%p [%ld bytes])", buffer, buffer->size);
|
||||
|
||||
net_domain *domain = buffer->interface->domain;
|
||||
|
||||
BenaphoreLocker _(fLock);
|
||||
|
||||
UdpDomainSupport *domainSupport = _GetDomain(domain, false);
|
||||
if (domainSupport == NULL) {
|
||||
// we don't instantiate domain supports in the
|
||||
// RX path as we are only interested in delivering
|
||||
// data to existing sockets.
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
status = domainSupport->DemuxIncomingBuffer(buffer);
|
||||
if (status < B_OK) {
|
||||
TRACE_EPM(" ReceiveData(): no endpoint.");
|
||||
// TODO: send ICMP-error
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
UdpEndpointManager::Deframe(net_buffer *buffer)
|
||||
{
|
||||
TRACE_EPM("Deframe(%p [%ld bytes])", buffer, buffer->size);
|
||||
|
||||
NetBufferHeaderReader<udp_header> bufferHeader(buffer);
|
||||
if (bufferHeader.Status() < B_OK)
|
||||
return bufferHeader.Status();
|
||||
@@ -556,7 +590,7 @@ UdpEndpointManager::ReceiveData(net_buffer *buffer)
|
||||
struct sockaddr *destination = (struct sockaddr *)&buffer->destination;
|
||||
|
||||
if (buffer->interface == NULL || buffer->interface->domain == NULL) {
|
||||
TRACE_EPM(" ReceiveData(): UDP packed dropped as there was no domain "
|
||||
TRACE_EPM(" Deframe(): UDP packed dropped as there was no domain "
|
||||
"specified (interface %p).", buffer->interface);
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
@@ -564,18 +598,16 @@ UdpEndpointManager::ReceiveData(net_buffer *buffer)
|
||||
net_domain *domain = buffer->interface->domain;
|
||||
net_address_module_info *addressModule = domain->address_module;
|
||||
|
||||
BenaphoreLocker _(fLock);
|
||||
|
||||
addressModule->set_port(source, header.source_port);
|
||||
addressModule->set_port(destination, header.destination_port);
|
||||
|
||||
TRACE_EPM(" ReceiveData(): data from %s to %s",
|
||||
TRACE_EPM(" Deframe(): data from %s to %s",
|
||||
AddressString(domain, source, true).Data(),
|
||||
AddressString(domain, destination, true).Data());
|
||||
|
||||
uint16 udpLength = ntohs(header.udp_length);
|
||||
if (udpLength > buffer->size) {
|
||||
TRACE_EPM(" ReceiveData(): buffer is too short, expected %hu.",
|
||||
TRACE_EPM(" Deframe(): buffer is too short, expected %hu.",
|
||||
udpLength);
|
||||
return B_MISMATCHED_VALUES;
|
||||
}
|
||||
@@ -596,7 +628,7 @@ UdpEndpointManager::ReceiveData(net_buffer *buffer)
|
||||
<< Checksum::BufferHelper(buffer, gBufferModule);
|
||||
uint16 sum = udpChecksum;
|
||||
if (sum != 0) {
|
||||
TRACE_EPM(" ReceiveData(): bad checksum 0x%hx.", sum);
|
||||
TRACE_EPM(" Deframe(): bad checksum 0x%hx.", sum);
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
}
|
||||
@@ -604,22 +636,7 @@ UdpEndpointManager::ReceiveData(net_buffer *buffer)
|
||||
bufferHeader.Remove();
|
||||
// remove UDP-header from buffer before passing it on
|
||||
|
||||
UdpDomainSupport *domainSupport = _GetDomain(domain, false);
|
||||
if (domainSupport == NULL) {
|
||||
// we don't instantiate domain supports in the
|
||||
// RX path as we are only interested in delivering
|
||||
// data to existing sockets.
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
status_t status = domainSupport->DemuxIncomingBuffer(buffer);
|
||||
if (status < B_OK) {
|
||||
TRACE_EPM(" ReceiveData(): no endpoint.");
|
||||
// TODO: send ICMP-error
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
return B_ERROR;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -937,6 +954,25 @@ UdpEndpoint::StoreData(net_buffer *buffer)
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
UdpEndpoint::DeliverData(net_buffer *_buffer)
|
||||
{
|
||||
net_buffer *buffer = gBufferModule->clone(_buffer, false);
|
||||
if (buffer == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
status_t status = sUdpEndpointManager->Deframe(buffer);
|
||||
if (status < B_OK) {
|
||||
gBufferModule->free(buffer);
|
||||
return status;
|
||||
}
|
||||
|
||||
// we call Enqueue() instead of SocketEnqueue() as there is
|
||||
// no need to clone the buffer again.
|
||||
return Enqueue(buffer);
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - protocol interface
|
||||
|
||||
|
||||
@@ -1093,6 +1129,13 @@ udp_receive_data(net_buffer *buffer)
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
udp_deliver_data(net_protocol *protocol, net_buffer *buffer)
|
||||
{
|
||||
return ((UdpEndpoint *)protocol)->DeliverData(buffer);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
udp_error(uint32 code, net_buffer *data)
|
||||
{
|
||||
@@ -1204,6 +1247,7 @@ net_protocol_module_info sUDPModule = {
|
||||
udp_get_domain,
|
||||
udp_get_mtu,
|
||||
udp_receive_data,
|
||||
udp_deliver_data,
|
||||
udp_error,
|
||||
udp_error_reply,
|
||||
};
|
||||
|
||||
@@ -510,6 +510,7 @@ net_protocol_module_info gLinkModule = {
|
||||
link_get_domain,
|
||||
link_get_mtu,
|
||||
link_receive_data,
|
||||
NULL,
|
||||
link_error,
|
||||
link_error_reply,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user