prepared the ipv4 multicast code for full multicast support.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@20945 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -85,6 +85,8 @@ public:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Iterator GetIterator() const { return HashTable::GetIterator(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void _Insert(ValueType **table, size_t tableSize, ValueType *value)
|
void _Insert(ValueType **table, size_t tableSize, ValueType *value)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
#include "multicast.h"
|
#include "multicast.h"
|
||||||
|
|
||||||
#include <net_datalink.h>
|
#include <net_datalink.h>
|
||||||
|
#include <net_datalink_protocol.h>
|
||||||
#include <net_protocol.h>
|
#include <net_protocol.h>
|
||||||
#include <net_stack.h>
|
#include <net_stack.h>
|
||||||
#include <NetBufferUtilities.h>
|
#include <NetBufferUtilities.h>
|
||||||
@@ -22,7 +23,7 @@
|
|||||||
#include <util/list.h>
|
#include <util/list.h>
|
||||||
#include <util/khash.h>
|
#include <util/khash.h>
|
||||||
#include <util/DoublyLinkedList.h>
|
#include <util/DoublyLinkedList.h>
|
||||||
#include <util/OpenHashTable.h>
|
#include <util/MultiHashTable.h>
|
||||||
|
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <netinet/ip.h>
|
#include <netinet/ip.h>
|
||||||
@@ -30,6 +31,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
|
||||||
//#define TRACE_IPV4
|
//#define TRACE_IPV4
|
||||||
@@ -118,48 +120,6 @@ class FragmentPacket {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class MulticastGroup {
|
|
||||||
public:
|
|
||||||
MulticastGroup(const in_addr &address);
|
|
||||||
|
|
||||||
status_t Deliver(net_protocol_module_info *module, net_buffer *buffer,
|
|
||||||
bool raw);
|
|
||||||
|
|
||||||
void Add(IPv4Multicast::GroupState *groupState);
|
|
||||||
void Remove(IPv4Multicast::GroupState *groupState);
|
|
||||||
bool IsEmpty() const { return fLinks.IsEmpty(); }
|
|
||||||
|
|
||||||
struct HashDefinition {
|
|
||||||
typedef void ParentType;
|
|
||||||
typedef const in_addr KeyType;
|
|
||||||
typedef MulticastGroup ValueType;
|
|
||||||
|
|
||||||
size_t HashKey(const in_addr &address) const
|
|
||||||
{ return address.s_addr; }
|
|
||||||
size_t Hash(MulticastGroup *group) const
|
|
||||||
{ return HashKey(group->fMulticastAddress); }
|
|
||||||
bool Compare(const in_addr &address, MulticastGroup *group) const
|
|
||||||
{ return group->fMulticastAddress.s_addr == address.s_addr; }
|
|
||||||
HashTableLink<MulticastGroup> *GetLink(MulticastGroup *group) const
|
|
||||||
{ return &group->fLink; }
|
|
||||||
};
|
|
||||||
|
|
||||||
void DumpInternalState() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
// for g++ 2.95
|
|
||||||
friend class HashDefinition;
|
|
||||||
|
|
||||||
typedef DoublyLinkedList<IPv4Multicast::GroupState> Links;
|
|
||||||
|
|
||||||
in_addr fMulticastAddress;
|
|
||||||
Links fLinks;
|
|
||||||
|
|
||||||
HashTableLink<MulticastGroup> fLink;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class RawSocket : public DoublyLinkedListLinkImpl<RawSocket>, public DatagramSocket<> {
|
class RawSocket : public DoublyLinkedListLinkImpl<RawSocket>, public DatagramSocket<> {
|
||||||
public:
|
public:
|
||||||
RawSocket(net_socket *socket);
|
RawSocket(net_socket *socket);
|
||||||
@@ -167,8 +127,29 @@ class RawSocket : public DoublyLinkedListLinkImpl<RawSocket>, public DatagramSoc
|
|||||||
|
|
||||||
typedef DoublyLinkedList<RawSocket> RawSocketList;
|
typedef DoublyLinkedList<RawSocket> RawSocketList;
|
||||||
|
|
||||||
|
typedef MulticastGroupInterface<IPv4Multicast> IPv4GroupInterface;
|
||||||
typedef MulticastFilter<IPv4Multicast> IPv4MulticastFilter;
|
typedef MulticastFilter<IPv4Multicast> IPv4MulticastFilter;
|
||||||
|
|
||||||
|
struct MulticastStateHash {
|
||||||
|
typedef void ParentType;
|
||||||
|
typedef std::pair<const in_addr *, uint32> KeyType;
|
||||||
|
typedef IPv4GroupInterface ValueType;
|
||||||
|
|
||||||
|
size_t HashKey(const KeyType &key) const
|
||||||
|
{ return key.first->s_addr ^ key.second; }
|
||||||
|
size_t Hash(ValueType *value) const
|
||||||
|
{ return HashKey(std::make_pair(&value->Address(),
|
||||||
|
value->Interface()->index)); }
|
||||||
|
bool Compare(const KeyType &key, ValueType *value) const
|
||||||
|
{ return value->Interface()->index == key.second
|
||||||
|
&& value->Address().s_addr == key.first->s_addr; }
|
||||||
|
bool CompareValues(ValueType *value1, ValueType *value2) const
|
||||||
|
{ return value1->Interface()->index == value2->Interface()->index
|
||||||
|
&& value1->Address().s_addr == value2->Address().s_addr; }
|
||||||
|
HashTableLink<ValueType> *GetLink(ValueType *value) const { return value; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
struct ipv4_protocol : net_protocol {
|
struct ipv4_protocol : net_protocol {
|
||||||
ipv4_protocol()
|
ipv4_protocol()
|
||||||
: multicast_filter(this) {}
|
: multicast_filter(this) {}
|
||||||
@@ -205,8 +186,10 @@ static benaphore sRawSocketsLock;
|
|||||||
static benaphore sFragmentLock;
|
static benaphore sFragmentLock;
|
||||||
static hash_table *sFragmentHash;
|
static hash_table *sFragmentHash;
|
||||||
static benaphore sMulticastGroupsLock;
|
static benaphore sMulticastGroupsLock;
|
||||||
typedef OpenHashTable<MulticastGroup::HashDefinition> MulticastGroups;
|
|
||||||
static MulticastGroups *sMulticastGroups;
|
typedef MultiHashTable<MulticastStateHash> MulticastState;
|
||||||
|
static MulticastState *sMulticastState;
|
||||||
|
|
||||||
static net_protocol_module_info *sReceivingProtocol[256];
|
static net_protocol_module_info *sReceivingProtocol[256];
|
||||||
static benaphore sReceivingProtocolLock;
|
static benaphore sReceivingProtocolLock;
|
||||||
|
|
||||||
@@ -461,73 +444,6 @@ FragmentPacket::StaleTimer(struct net_timer *timer, void *data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
MulticastGroup::MulticastGroup(const in_addr &address)
|
|
||||||
: fMulticastAddress(address)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
MulticastGroup::Deliver(net_protocol_module_info *module, net_buffer *buffer,
|
|
||||||
bool deliverToRaw)
|
|
||||||
{
|
|
||||||
Links::Iterator iterator = fLinks.GetIterator();
|
|
||||||
|
|
||||||
while (iterator.HasNext()) {
|
|
||||||
IPv4Multicast::GroupState *groupState = iterator.Next();
|
|
||||||
|
|
||||||
if (deliverToRaw && groupState->Socket()->raw == NULL)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (groupState->FilterAccepts(buffer)) {
|
|
||||||
// as Multicast filters are installed with an IPv4 protocol
|
|
||||||
// reference, we need to go and find the appropriate instance
|
|
||||||
// related to the 'receiving protocol' with module 'module'.
|
|
||||||
net_protocol *proto = groupState->Socket()->socket->first_protocol;
|
|
||||||
|
|
||||||
while (proto && proto->module != module)
|
|
||||||
proto = proto->next;
|
|
||||||
|
|
||||||
if (proto)
|
|
||||||
module->deliver_data(proto, buffer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
MulticastGroup::Add(IPv4Multicast::GroupState *groupState)
|
|
||||||
{
|
|
||||||
fLinks.Add(groupState);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
MulticastGroup::Remove(IPv4Multicast::GroupState *groupState)
|
|
||||||
{
|
|
||||||
fLinks.Remove(groupState);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
MulticastGroup::DumpInternalState() const
|
|
||||||
{
|
|
||||||
char addrBuf[64];
|
|
||||||
|
|
||||||
kprintf("group %s (%p)\n", print_address(&fMulticastAddress, addrBuf,
|
|
||||||
sizeof(addrBuf)), this);
|
|
||||||
|
|
||||||
Links::ConstIterator it = fLinks.GetIterator();
|
|
||||||
while (it.HasNext()) {
|
|
||||||
IPv4Multicast::GroupState *group = it.Next();
|
|
||||||
|
|
||||||
kprintf(" socket %p\n", group->Socket());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark -
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
@@ -730,12 +646,37 @@ deliver_multicast(net_protocol_module_info *module, net_buffer *buffer,
|
|||||||
|
|
||||||
BenaphoreLocker _(sMulticastGroupsLock);
|
BenaphoreLocker _(sMulticastGroupsLock);
|
||||||
|
|
||||||
MulticastGroup *group = sMulticastGroups->Lookup(
|
sockaddr_in *multicastAddr = (sockaddr_in *)&buffer->destination;
|
||||||
((sockaddr_in *)&buffer->destination)->sin_addr);
|
|
||||||
if (group == NULL)
|
|
||||||
return B_OK;
|
|
||||||
|
|
||||||
return group->Deliver(module, buffer, deliverToRaw);
|
MulticastState::Iterator it = sMulticastState->Lookup(std::make_pair(
|
||||||
|
&multicastAddr->sin_addr, buffer->interface->index));
|
||||||
|
|
||||||
|
while (it.HasNext()) {
|
||||||
|
IPv4GroupInterface *state = it.Next();
|
||||||
|
|
||||||
|
if (state->Interface()->index != buffer->interface->index
|
||||||
|
|| state->Address().s_addr != multicastAddr->sin_addr.s_addr)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (deliverToRaw && state->Parent()->Socket()->raw == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (state->FilterAccepts(buffer)) {
|
||||||
|
// as Multicast filters are installed with an IPv4 protocol
|
||||||
|
// reference, we need to go and find the appropriate instance
|
||||||
|
// related to the 'receiving protocol' with module 'module'.
|
||||||
|
net_protocol *proto =
|
||||||
|
state->Parent()->Socket()->socket->first_protocol;
|
||||||
|
|
||||||
|
while (proto && proto->module != module)
|
||||||
|
proto = proto->next;
|
||||||
|
|
||||||
|
if (proto)
|
||||||
|
module->deliver_data(proto, buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -770,40 +711,42 @@ raw_receive_data(net_buffer *buffer)
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
IPv4Multicast::JoinGroup(GroupState *groupState)
|
IPv4Multicast::JoinGroup(IPv4GroupInterface *state)
|
||||||
{
|
{
|
||||||
BenaphoreLocker _(sMulticastGroupsLock);
|
BenaphoreLocker _(sMulticastGroupsLock);
|
||||||
|
|
||||||
MulticastGroup *group = sMulticastGroups->Lookup(groupState->Address());
|
sockaddr_in groupAddr;
|
||||||
if (group == NULL) {
|
memset(&groupAddr, 0, sizeof(groupAddr));
|
||||||
group = new (std::nothrow) MulticastGroup(groupState->Address());
|
groupAddr.sin_addr = state->Address();
|
||||||
if (group == NULL)
|
|
||||||
return B_NO_MEMORY;
|
|
||||||
|
|
||||||
sMulticastGroups->Insert(group);
|
net_interface *intf = state->Interface();
|
||||||
}
|
|
||||||
|
|
||||||
group->Add(groupState);
|
status_t status =
|
||||||
|
intf->first_protocol->module->join_multicast(intf->first_protocol,
|
||||||
|
(sockaddr *)&groupAddr);
|
||||||
|
if (status < B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
sMulticastState->Insert(state);
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
IPv4Multicast::LeaveGroup(GroupState *groupState)
|
IPv4Multicast::LeaveGroup(IPv4GroupInterface *state)
|
||||||
{
|
{
|
||||||
BenaphoreLocker _(sMulticastGroupsLock);
|
BenaphoreLocker _(sMulticastGroupsLock);
|
||||||
|
|
||||||
MulticastGroup *group = sMulticastGroups->Lookup(groupState->Address());
|
sMulticastState->Remove(state);
|
||||||
if (group == NULL)
|
|
||||||
return ENOENT;
|
|
||||||
|
|
||||||
group->Remove(groupState);
|
sockaddr_in groupAddr;
|
||||||
if (group->IsEmpty()) {
|
memset(&groupAddr, 0, sizeof(groupAddr));
|
||||||
sMulticastGroups->Remove(group);
|
groupAddr.sin_addr = state->Address();
|
||||||
delete group;
|
|
||||||
}
|
|
||||||
|
|
||||||
return B_OK;
|
net_interface *intf = state->Interface();
|
||||||
|
|
||||||
|
return intf->first_protocol->module->join_multicast(intf->first_protocol,
|
||||||
|
(sockaddr *)&groupAddr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -838,22 +781,22 @@ fill_sockaddr_in(sockaddr_in *target, in_addr_t address)
|
|||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
ipv4_delta_group(IPv4MulticastFilter::GroupState *group, int option,
|
ipv4_delta_group(IPv4GroupInterface *group, int option,
|
||||||
net_interface *interface, const in_addr *sourceAddr)
|
net_interface *interface, const in_addr *sourceAddr)
|
||||||
{
|
{
|
||||||
switch (option) {
|
switch (option) {
|
||||||
case IP_ADD_MEMBERSHIP:
|
case IP_ADD_MEMBERSHIP:
|
||||||
return group->Add(interface);
|
return group->Add();
|
||||||
case IP_DROP_MEMBERSHIP:
|
case IP_DROP_MEMBERSHIP:
|
||||||
return group->Drop(interface);
|
return group->Drop();
|
||||||
case IP_BLOCK_SOURCE:
|
case IP_BLOCK_SOURCE:
|
||||||
return group->BlockSource(interface, *sourceAddr);
|
return group->BlockSource(*sourceAddr);
|
||||||
case IP_UNBLOCK_SOURCE:
|
case IP_UNBLOCK_SOURCE:
|
||||||
return group->UnblockSource(interface, *sourceAddr);
|
return group->UnblockSource(*sourceAddr);
|
||||||
case IP_ADD_SOURCE_MEMBERSHIP:
|
case IP_ADD_SOURCE_MEMBERSHIP:
|
||||||
return group->AddSSM(interface, *sourceAddr);
|
return group->AddSSM(*sourceAddr);
|
||||||
case IP_DROP_SOURCE_MEMBERSHIP:
|
case IP_DROP_SOURCE_MEMBERSHIP:
|
||||||
return group->DropSSM(interface, *sourceAddr);
|
return group->DropSSM(*sourceAddr);
|
||||||
}
|
}
|
||||||
|
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
@@ -866,22 +809,21 @@ ipv4_delta_membership(ipv4_protocol *protocol, int option,
|
|||||||
const in_addr *sourceAddr)
|
const in_addr *sourceAddr)
|
||||||
{
|
{
|
||||||
IPv4MulticastFilter &filter = protocol->multicast_filter;
|
IPv4MulticastFilter &filter = protocol->multicast_filter;
|
||||||
IPv4MulticastFilter::GroupState *group = NULL;
|
IPv4GroupInterface *state = NULL;
|
||||||
|
status_t status = B_OK;
|
||||||
|
|
||||||
switch (option) {
|
switch (option) {
|
||||||
case IP_ADD_MEMBERSHIP:
|
case IP_ADD_MEMBERSHIP:
|
||||||
case IP_ADD_SOURCE_MEMBERSHIP:
|
case IP_ADD_SOURCE_MEMBERSHIP:
|
||||||
group = filter.GetGroup(*groupAddr, true);
|
status = filter.GetState(*groupAddr, interface, state, true);
|
||||||
if (group == NULL)
|
|
||||||
return ENOBUFS;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IP_DROP_MEMBERSHIP:
|
case IP_DROP_MEMBERSHIP:
|
||||||
case IP_BLOCK_SOURCE:
|
case IP_BLOCK_SOURCE:
|
||||||
case IP_UNBLOCK_SOURCE:
|
case IP_UNBLOCK_SOURCE:
|
||||||
case IP_DROP_SOURCE_MEMBERSHIP:
|
case IP_DROP_SOURCE_MEMBERSHIP:
|
||||||
group = filter.GetGroup(*groupAddr, false);
|
filter.GetState(*groupAddr, interface, state, false);
|
||||||
if (group == NULL) {
|
if (state == NULL) {
|
||||||
if (option == IP_DROP_MEMBERSHIP
|
if (option == IP_DROP_MEMBERSHIP
|
||||||
|| option == IP_DROP_SOURCE_MEMBERSHIP)
|
|| option == IP_DROP_SOURCE_MEMBERSHIP)
|
||||||
return EADDRNOTAVAIL;
|
return EADDRNOTAVAIL;
|
||||||
@@ -891,10 +833,11 @@ ipv4_delta_membership(ipv4_protocol *protocol, int option,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t status = ipv4_delta_group(group, option, interface, sourceAddr);
|
if (status < B_OK)
|
||||||
|
return status;
|
||||||
filter.ReturnGroup(group);
|
|
||||||
|
|
||||||
|
status = ipv4_delta_group(state, option, interface, sourceAddr);
|
||||||
|
filter.ReturnState(state);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1590,10 +1533,17 @@ ipv4_error_reply(net_protocol *protocol, net_buffer *causedError, uint32 code,
|
|||||||
static int
|
static int
|
||||||
dump_ipv4_multicast(int argc, char *argv[])
|
dump_ipv4_multicast(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
MulticastGroups::Iterator it = sMulticastGroups->GetIterator();
|
MulticastState::Iterator it = sMulticastState->GetIterator();
|
||||||
|
|
||||||
while (it.HasNext())
|
while (it.HasNext()) {
|
||||||
it.Next()->DumpInternalState();
|
IPv4GroupInterface *state = it.Next();
|
||||||
|
|
||||||
|
char addrBuf[64];
|
||||||
|
|
||||||
|
kprintf("%p: group <%s, %s> sock %p\n", state,
|
||||||
|
state->Interface()->name, print_address(&state->Address(),
|
||||||
|
addrBuf, sizeof(addrBuf)), state->Parent()->Socket());
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -1623,11 +1573,11 @@ init_ipv4()
|
|||||||
if (status < B_OK)
|
if (status < B_OK)
|
||||||
goto err3;
|
goto err3;
|
||||||
|
|
||||||
sMulticastGroups = new MulticastGroups();
|
sMulticastState = new MulticastState();
|
||||||
if (sMulticastGroups == NULL)
|
if (sMulticastState == NULL)
|
||||||
goto err4;
|
goto err4;
|
||||||
|
|
||||||
status = sMulticastGroups->InitCheck();
|
status = sMulticastState->InitCheck();
|
||||||
if (status < B_OK)
|
if (status < B_OK)
|
||||||
goto err5;
|
goto err5;
|
||||||
|
|
||||||
@@ -1659,7 +1609,7 @@ init_ipv4()
|
|||||||
err6:
|
err6:
|
||||||
hash_uninit(sFragmentHash);
|
hash_uninit(sFragmentHash);
|
||||||
err5:
|
err5:
|
||||||
delete sMulticastGroups;
|
delete sMulticastState;
|
||||||
err4:
|
err4:
|
||||||
benaphore_destroy(&sReceivingProtocolLock);
|
benaphore_destroy(&sReceivingProtocolLock);
|
||||||
err3:
|
err3:
|
||||||
@@ -1688,7 +1638,7 @@ uninit_ipv4()
|
|||||||
gStackModule->unregister_domain(sDomain);
|
gStackModule->unregister_domain(sDomain);
|
||||||
benaphore_unlock(&sReceivingProtocolLock);
|
benaphore_unlock(&sReceivingProtocolLock);
|
||||||
|
|
||||||
delete sMulticastGroups;
|
delete sMulticastState;
|
||||||
hash_uninit(sFragmentHash);
|
hash_uninit(sFragmentHash);
|
||||||
|
|
||||||
benaphore_destroy(&sMulticastGroupsLock);
|
benaphore_destroy(&sMulticastGroupsLock);
|
||||||
|
|||||||
@@ -23,227 +23,120 @@ operator==(const in_addr &a1, const in_addr &a2)
|
|||||||
using std::nothrow;
|
using std::nothrow;
|
||||||
|
|
||||||
|
|
||||||
template<typename AddressType>
|
|
||||||
MulticastGroupInterfaceState<AddressType>::MulticastGroupInterfaceState(
|
|
||||||
net_interface *interface)
|
|
||||||
: fInterface(interface)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<typename AddressType>
|
|
||||||
MulticastGroupInterfaceState<AddressType>::~MulticastGroupInterfaceState()
|
|
||||||
{
|
|
||||||
typename SourceList::Iterator iterator = fSources.GetIterator();
|
|
||||||
while (iterator.HasNext()) {
|
|
||||||
_Remove(iterator.Next());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<typename AddressType> status_t
|
|
||||||
MulticastGroupInterfaceState<AddressType>::Add(const AddressType &address)
|
|
||||||
{
|
|
||||||
return _Get(address, true) ? B_OK : ENOBUFS;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<typename AddressType> status_t
|
|
||||||
MulticastGroupInterfaceState<AddressType>::Remove(const AddressType &address)
|
|
||||||
{
|
|
||||||
Source *state = _Get(address, false);
|
|
||||||
if (state == NULL)
|
|
||||||
return EADDRNOTAVAIL;
|
|
||||||
|
|
||||||
_Remove(state);
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<typename AddressType> typename MulticastGroupInterfaceState<AddressType>::Source *
|
|
||||||
MulticastGroupInterfaceState<AddressType>::_Get(const AddressType &address,
|
|
||||||
bool create)
|
|
||||||
{
|
|
||||||
typename SourceList::Iterator iterator = fSources.GetIterator();
|
|
||||||
while (iterator.HasNext()) {
|
|
||||||
Source *state = iterator.Next();
|
|
||||||
if (state->address == address)
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!create)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
Source *state = new (nothrow) Source;
|
|
||||||
if (state) {
|
|
||||||
state->address = address;
|
|
||||||
fSources.Add(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<typename AddressType> void
|
|
||||||
MulticastGroupInterfaceState<AddressType>::_Remove(Source *state)
|
|
||||||
{
|
|
||||||
fSources.Remove(state);
|
|
||||||
delete state;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<typename Addressing>
|
template<typename Addressing>
|
||||||
MulticastGroupState<Addressing>::MulticastGroupState(ProtocolType *socket,
|
MulticastGroupInterface<Addressing>::MulticastGroupInterface(Filter *parent,
|
||||||
const AddressType &address)
|
const AddressType &address, net_interface *interface)
|
||||||
: fSocket(socket), fMulticastAddress(address), fFilterMode(kInclude)
|
: fParent(parent), fMulticastAddress(address), fInterface(interface)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<typename Addressing>
|
template<typename Addressing>
|
||||||
MulticastGroupState<Addressing>::~MulticastGroupState()
|
MulticastGroupInterface<Addressing>::~MulticastGroupInterface()
|
||||||
{
|
{
|
||||||
Clear();
|
Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<typename Addressing> status_t
|
template<typename Addressing> status_t
|
||||||
MulticastGroupState<Addressing>::Add(net_interface *interface)
|
MulticastGroupInterface<Addressing>::Add()
|
||||||
{
|
{
|
||||||
if (fFilterMode == kInclude && !fInterfaces.IsEmpty())
|
if (fFilterMode == kInclude && !fAddresses.IsEmpty())
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
|
|
||||||
fFilterMode = kExclude;
|
fFilterMode = kExclude;
|
||||||
|
|
||||||
return _GetInterface(interface, true) != NULL ? B_OK : ENOBUFS;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<typename Addressing> status_t
|
|
||||||
MulticastGroupState<Addressing>::Drop(net_interface *interface)
|
|
||||||
{
|
|
||||||
InterfaceState *state = _GetInterface(interface, false);
|
|
||||||
if (state == NULL)
|
|
||||||
return EADDRNOTAVAIL;
|
|
||||||
|
|
||||||
_RemoveInterface(state);
|
|
||||||
|
|
||||||
if (fInterfaces.IsEmpty())
|
|
||||||
fFilterMode = kInclude;
|
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<typename Addressing> status_t
|
template<typename Addressing> status_t
|
||||||
MulticastGroupState<Addressing>::BlockSource(net_interface *interface,
|
MulticastGroupInterface<Addressing>::Drop()
|
||||||
|
{
|
||||||
|
fAddresses.Clear();
|
||||||
|
fFilterMode = kInclude;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<typename Addressing> status_t
|
||||||
|
MulticastGroupInterface<Addressing>::BlockSource(
|
||||||
const AddressType &sourceAddress)
|
const AddressType &sourceAddress)
|
||||||
{
|
{
|
||||||
if (fFilterMode != kExclude)
|
if (fFilterMode != kExclude)
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
|
|
||||||
InterfaceState *state = _GetInterface(interface, false);
|
fAddresses.Add(sourceAddress);
|
||||||
if (state == NULL)
|
return B_OK;
|
||||||
return EINVAL;
|
|
||||||
|
|
||||||
return state->Add(sourceAddress);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<typename Addressing> status_t
|
template<typename Addressing> status_t
|
||||||
MulticastGroupState<Addressing>::UnblockSource(net_interface *interface,
|
MulticastGroupInterface<Addressing>::UnblockSource(
|
||||||
const AddressType &sourceAddress)
|
const AddressType &sourceAddress)
|
||||||
{
|
{
|
||||||
if (fFilterMode != kExclude)
|
if (fFilterMode != kExclude)
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
|
|
||||||
InterfaceState *state = _GetInterface(interface, false);
|
if (!fAddresses.Has(sourceAddress))
|
||||||
if (state == NULL)
|
|
||||||
return EINVAL;
|
|
||||||
|
|
||||||
return state->Remove(sourceAddress);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Addressing> status_t
|
|
||||||
MulticastGroupState<Addressing>::AddSSM(net_interface *interface,
|
|
||||||
const AddressType &sourceAddress)
|
|
||||||
{
|
|
||||||
if (fFilterMode == kExclude)
|
|
||||||
return EINVAL;
|
|
||||||
|
|
||||||
InterfaceState *state = _GetInterface(interface, true);
|
|
||||||
if (state == NULL)
|
|
||||||
return ENOBUFS;
|
|
||||||
|
|
||||||
return state->Add(sourceAddress);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<typename Addressing> status_t
|
|
||||||
MulticastGroupState<Addressing>::DropSSM(net_interface *interface,
|
|
||||||
const AddressType &sourceAddress)
|
|
||||||
{
|
|
||||||
if (fFilterMode == kExclude)
|
|
||||||
return EINVAL;
|
|
||||||
|
|
||||||
InterfaceState *state = _GetInterface(interface, false);
|
|
||||||
if (state == NULL)
|
|
||||||
return EADDRNOTAVAIL;
|
return EADDRNOTAVAIL;
|
||||||
|
|
||||||
return state->Remove(sourceAddress);
|
fAddresses.Add(sourceAddress);
|
||||||
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<typename Addressing> void
|
template<typename Addressing> status_t
|
||||||
MulticastGroupState<Addressing>::Clear()
|
MulticastGroupInterface<Addressing>::AddSSM(const AddressType &sourceAddress)
|
||||||
{
|
{
|
||||||
typename InterfaceList::Iterator iterator = fInterfaces.GetIterator();
|
if (fFilterMode == kExclude)
|
||||||
while (iterator.HasNext())
|
return EINVAL;
|
||||||
_RemoveInterface(iterator.Next());
|
|
||||||
|
fAddresses.Add(sourceAddress);
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<typename Addressing> status_t
|
||||||
|
MulticastGroupInterface<Addressing>::DropSSM(const AddressType &sourceAddress)
|
||||||
|
{
|
||||||
|
if (fFilterMode == kExclude)
|
||||||
|
return EINVAL;
|
||||||
|
|
||||||
|
if (!fAddresses.Has(sourceAddress))
|
||||||
|
return EADDRNOTAVAIL;
|
||||||
|
|
||||||
|
fAddresses.Add(sourceAddress);
|
||||||
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<typename Addressing> bool
|
template<typename Addressing> bool
|
||||||
MulticastGroupState<Addressing>::FilterAccepts(net_buffer *buffer)
|
MulticastGroupInterface<Addressing>::IsEmpty() const
|
||||||
{
|
{
|
||||||
InterfaceState *state = _GetInterface(buffer->interface, false);
|
return fFilterMode == kInclude && fAddresses.IsEmpty();
|
||||||
if (state == NULL)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
bool has = state->Contains(Addressing::AddressFromSockAddr(
|
|
||||||
(sockaddr *)&buffer->source));
|
|
||||||
|
|
||||||
return (has && fFilterMode == kInclude) || (!has && fFilterMode == kExclude);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<typename Addressing> typename MulticastGroupState<Addressing>::InterfaceState *
|
|
||||||
MulticastGroupState<Addressing>::_GetInterface(net_interface *interface,
|
|
||||||
bool create)
|
|
||||||
{
|
|
||||||
typename InterfaceList::Iterator iterator = fInterfaces.GetIterator();
|
|
||||||
while (iterator.HasNext()) {
|
|
||||||
InterfaceState *state = iterator.Next();
|
|
||||||
if (state->Interface() == interface)
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!create)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
InterfaceState *state = new (nothrow) InterfaceState(interface);
|
|
||||||
if (state)
|
|
||||||
fInterfaces.Add(state);
|
|
||||||
|
|
||||||
return state;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<typename Addressing> void
|
template<typename Addressing> void
|
||||||
MulticastGroupState<Addressing>::_RemoveInterface(InterfaceState *state)
|
MulticastGroupInterface<Addressing>::Clear()
|
||||||
{
|
{
|
||||||
fInterfaces.Remove(state);
|
if (IsEmpty())
|
||||||
delete state;
|
return;
|
||||||
|
|
||||||
|
fFilterMode = kInclude;
|
||||||
|
fAddresses.Clear();
|
||||||
|
Addressing::LeaveGroup(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<typename Addressing> bool
|
||||||
|
MulticastGroupInterface<Addressing>::FilterAccepts(net_buffer *buffer) const
|
||||||
|
{
|
||||||
|
bool has = fAddresses.Has(Addressing::AddressFromSockAddr(
|
||||||
|
(sockaddr *)&buffer->source));
|
||||||
|
|
||||||
|
return (has && fFilterMode == kInclude)
|
||||||
|
|| (!has && fFilterMode == kExclude);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -262,56 +155,58 @@ MulticastFilter<Addressing>::~MulticastFilter()
|
|||||||
if (!iterator.HasNext())
|
if (!iterator.HasNext())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
GroupState *state = iterator.Next();
|
GroupInterface *state = iterator.Next();
|
||||||
state->Clear();
|
state->Clear();
|
||||||
_ReturnGroup(state);
|
_ReturnState(state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<typename Addressing> typename MulticastFilter<Addressing>::GroupState *
|
template<typename Addressing> status_t
|
||||||
MulticastFilter<Addressing>::GetGroup(const AddressType &groupAddress,
|
MulticastFilter<Addressing>::GetState(const AddressType &groupAddress,
|
||||||
bool create)
|
net_interface *interface, GroupInterface* &state, bool create)
|
||||||
{
|
{
|
||||||
GroupState *state = fStates.Lookup(groupAddress);
|
state = fStates.Lookup(std::make_pair(&groupAddress, interface->index));
|
||||||
if (state)
|
|
||||||
return state;
|
|
||||||
|
|
||||||
if (create) {
|
if (state == NULL && create) {
|
||||||
state = new (nothrow) GroupState(fParent, groupAddress);
|
state = new (nothrow) GroupInterface(this, groupAddress, interface);
|
||||||
if (state) {
|
if (state == NULL)
|
||||||
if (fStates.Insert(state) >= B_OK) {
|
return B_NO_MEMORY;
|
||||||
if (Addressing::JoinGroup(state) >= B_OK)
|
|
||||||
return state;
|
|
||||||
|
|
||||||
fStates.Remove(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
status_t status = fStates.Insert(state);
|
||||||
|
if (status < B_OK) {
|
||||||
delete state;
|
delete state;
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
status = Addressing::JoinGroup(state);
|
||||||
|
if (status < B_OK) {
|
||||||
|
fStates.Remove(state);
|
||||||
|
delete state;
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<typename Addressing> void
|
template<typename Addressing> void
|
||||||
MulticastFilter<Addressing>::ReturnGroup(GroupState *group)
|
MulticastFilter<Addressing>::ReturnState(GroupInterface *state)
|
||||||
{
|
{
|
||||||
if (group->IsEmpty())
|
if (state->IsEmpty())
|
||||||
_ReturnGroup(group);
|
_ReturnState(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<typename Addressing> void
|
template<typename Addressing> void
|
||||||
MulticastFilter<Addressing>::_ReturnGroup(GroupState *group)
|
MulticastFilter<Addressing>::_ReturnState(GroupInterface *state)
|
||||||
{
|
{
|
||||||
Addressing::LeaveGroup(group);
|
fStates.Remove(state);
|
||||||
fStates.Remove(group);
|
delete state;
|
||||||
delete group;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// IPv4 explicit template instantiation
|
// IPv4 explicit template instantiation
|
||||||
template class MulticastFilter<IPv4Multicast>;
|
template class MulticastFilter<IPv4Multicast>;
|
||||||
template class MulticastGroupState<IPv4Multicast>;
|
template class MulticastGroupInterface<IPv4Multicast>;
|
||||||
template class MulticastGroupInterfaceState<in_addr>;
|
|
||||||
|
|||||||
@@ -12,25 +12,28 @@
|
|||||||
#include <util/DoublyLinkedList.h>
|
#include <util/DoublyLinkedList.h>
|
||||||
#include <util/OpenHashTable.h>
|
#include <util/OpenHashTable.h>
|
||||||
|
|
||||||
|
#include <net_datalink.h>
|
||||||
|
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
struct net_buffer;
|
struct net_buffer;
|
||||||
struct net_interface;
|
|
||||||
struct net_protocol;
|
struct net_protocol;
|
||||||
|
|
||||||
// This code is template'ized as it is reusable for IPv6
|
// This code is template'ized as it is reusable for IPv6
|
||||||
|
|
||||||
template<typename Addressing> class MulticastFilter;
|
template<typename Addressing> class MulticastFilter;
|
||||||
template<typename Addressing> class MulticastGroupState;
|
template<typename Addressing> class MulticastGroupInterface;
|
||||||
|
|
||||||
// TODO move this elsewhere...
|
// TODO move this elsewhere...
|
||||||
struct IPv4Multicast {
|
struct IPv4Multicast {
|
||||||
typedef struct in_addr AddressType;
|
typedef struct in_addr AddressType;
|
||||||
typedef struct ipv4_protocol ProtocolType;
|
typedef struct ipv4_protocol ProtocolType;
|
||||||
typedef MulticastGroupState<IPv4Multicast> GroupState;
|
typedef MulticastGroupInterface<IPv4Multicast> GroupInterface;
|
||||||
|
|
||||||
static status_t JoinGroup(GroupState *);
|
static status_t JoinGroup(GroupInterface *);
|
||||||
static status_t LeaveGroup(GroupState *);
|
static status_t LeaveGroup(GroupInterface *);
|
||||||
|
|
||||||
static const in_addr &AddressFromSockAddr(const sockaddr *sockaddr)
|
static const in_addr &AddressFromSockAddr(const sockaddr *sockaddr)
|
||||||
{ return ((const sockaddr_in *)sockaddr)->sin_addr; }
|
{ return ((const sockaddr_in *)sockaddr)->sin_addr; }
|
||||||
@@ -39,106 +42,131 @@ struct IPv4Multicast {
|
|||||||
};
|
};
|
||||||
|
|
||||||
template<typename AddressType>
|
template<typename AddressType>
|
||||||
struct MulticastSource
|
class AddressSet {
|
||||||
: DoublyLinkedListLinkImpl< MulticastSource<AddressType> > {
|
|
||||||
AddressType address;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename AddressType>
|
|
||||||
class MulticastGroupInterfaceState
|
|
||||||
: public DoublyLinkedListLinkImpl< MulticastGroupInterfaceState<AddressType> > {
|
|
||||||
public:
|
public:
|
||||||
MulticastGroupInterfaceState(net_interface *interface);
|
struct ContainedAddress : DoublyLinkedListLinkImpl<ContainedAddress> {
|
||||||
~MulticastGroupInterfaceState();
|
AddressType address;
|
||||||
|
|
||||||
net_interface *Interface() const { return fInterface; }
|
|
||||||
|
|
||||||
status_t Add(const AddressType &address);
|
|
||||||
status_t Remove(const AddressType &address);
|
|
||||||
|
|
||||||
bool Contains(const AddressType &address)
|
|
||||||
{ return _Get(address, false) != NULL; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
typedef MulticastSource<AddressType> Source;
|
|
||||||
typedef DoublyLinkedList<Source> SourceList;
|
|
||||||
|
|
||||||
Source *_Get(const AddressType &address, bool create);
|
|
||||||
void _Remove(Source *state);
|
|
||||||
|
|
||||||
net_interface *fInterface;
|
|
||||||
// TODO make this an hash table as well
|
|
||||||
SourceList fSources;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename Addressing>
|
|
||||||
class MulticastGroupState
|
|
||||||
: public DoublyLinkedListLinkImpl< MulticastGroupState<Addressing> > {
|
|
||||||
public:
|
|
||||||
typedef MulticastGroupState<Addressing> ThisType;
|
|
||||||
typedef HashTableLink<ThisType> HashLink;
|
|
||||||
typedef typename Addressing::AddressType AddressType;
|
|
||||||
typedef typename Addressing::ProtocolType ProtocolType;
|
|
||||||
|
|
||||||
MulticastGroupState(ProtocolType *parent, const AddressType &address);
|
|
||||||
~MulticastGroupState();
|
|
||||||
|
|
||||||
ProtocolType *Socket() const { return fSocket; }
|
|
||||||
|
|
||||||
const AddressType &Address() const { return fMulticastAddress; }
|
|
||||||
bool IsEmpty() const
|
|
||||||
{ return fFilterMode == kInclude && fInterfaces.IsEmpty(); }
|
|
||||||
|
|
||||||
status_t Add(net_interface *interface);
|
|
||||||
status_t Drop(net_interface *interface);
|
|
||||||
status_t BlockSource(net_interface *interface,
|
|
||||||
const AddressType &sourceAddress);
|
|
||||||
status_t UnblockSource(net_interface *interface,
|
|
||||||
const AddressType &sourceAddress);
|
|
||||||
status_t AddSSM(net_interface *interface,
|
|
||||||
const AddressType &sourceAddress);
|
|
||||||
status_t DropSSM(net_interface *interface,
|
|
||||||
const AddressType &sourceAddress);
|
|
||||||
|
|
||||||
void Clear();
|
|
||||||
|
|
||||||
bool FilterAccepts(net_buffer *buffer);
|
|
||||||
|
|
||||||
struct HashDefinition {
|
|
||||||
typedef void ParentType;
|
|
||||||
typedef typename MulticastGroupState::AddressType KeyType;
|
|
||||||
typedef typename MulticastGroupState::ThisType ValueType;
|
|
||||||
typedef typename MulticastGroupState::HashLink HashLink;
|
|
||||||
|
|
||||||
size_t HashKey(const KeyType &key) const
|
|
||||||
{ return Addressing::HashAddress(key); }
|
|
||||||
size_t Hash(ValueType *value) const
|
|
||||||
{ return HashKey(value->Address()); }
|
|
||||||
bool Compare(const KeyType &key, ValueType *value) const
|
|
||||||
{ return key == value->Address(); }
|
|
||||||
HashLink *GetLink(ValueType *value) const { return &value->fHashLink; }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
~AddressSet() { Clear(); }
|
||||||
|
|
||||||
|
status_t Add(const AddressType &address)
|
||||||
|
{
|
||||||
|
if (Has(address))
|
||||||
|
return B_OK;
|
||||||
|
|
||||||
|
ContainedAddress *container = new ContainedAddress();
|
||||||
|
if (container == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
container->address = address;
|
||||||
|
fAddresses.Add(container);
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Remove(const AddressType &address)
|
||||||
|
{
|
||||||
|
ContainedAddress *container = _Get(address);
|
||||||
|
if (container == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
fAddresses.Remove(container);
|
||||||
|
delete container;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Has(const AddressType &address) const
|
||||||
|
{
|
||||||
|
return _Get(address) != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsEmpty() const { return fAddresses.IsEmpty(); }
|
||||||
|
|
||||||
|
void Clear()
|
||||||
|
{
|
||||||
|
while (!fAddresses.IsEmpty())
|
||||||
|
Remove(fAddresses.Head()->address);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// for g++ 2.95
|
typedef DoublyLinkedList<ContainedAddress> AddressList;
|
||||||
friend class HashDefinition;
|
|
||||||
|
|
||||||
typedef MulticastGroupInterfaceState<AddressType> InterfaceState;
|
ContainedAddress *_Get(const AddressType &address) const
|
||||||
typedef DoublyLinkedList<InterfaceState> InterfaceList;
|
{
|
||||||
|
AddressList::ConstIterator it = fAddresses.GetIterator();
|
||||||
|
while (it.HasNext()) {
|
||||||
|
ContainedAddress *container = it.Next();
|
||||||
|
if (container->address == address)
|
||||||
|
return container;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
InterfaceState *_GetInterface(net_interface *interface, bool create);
|
AddressList fAddresses;
|
||||||
void _RemoveInterface(InterfaceState *state);
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template<typename Addressing>
|
||||||
|
class MulticastGroupInterface
|
||||||
|
: public HashTableLink< MulticastGroupInterface<Addressing> > {
|
||||||
|
public:
|
||||||
|
typedef MulticastGroupInterface<Addressing> ThisType;
|
||||||
|
typedef HashTableLink<ThisType> HashLink;
|
||||||
|
typedef typename Addressing::AddressType AddressType;
|
||||||
|
typedef MulticastFilter<Addressing> Filter;
|
||||||
|
|
||||||
enum FilterMode {
|
enum FilterMode {
|
||||||
kInclude,
|
kInclude,
|
||||||
kExclude
|
kExclude
|
||||||
};
|
};
|
||||||
|
|
||||||
ProtocolType *fSocket;
|
MulticastGroupInterface(Filter *parent, const AddressType &address,
|
||||||
|
net_interface *interface);
|
||||||
|
~MulticastGroupInterface();
|
||||||
|
|
||||||
|
Filter *Parent() const { return fParent; }
|
||||||
|
|
||||||
|
const AddressType &Address() const { return fMulticastAddress; }
|
||||||
|
net_interface *Interface() const { return fInterface; }
|
||||||
|
|
||||||
|
status_t Add();
|
||||||
|
status_t Drop();
|
||||||
|
status_t BlockSource(const AddressType &sourceAddress);
|
||||||
|
status_t UnblockSource(const AddressType &sourceAddress);
|
||||||
|
status_t AddSSM(const AddressType &sourceAddress);
|
||||||
|
status_t DropSSM(const AddressType &sourceAddress);
|
||||||
|
|
||||||
|
bool IsEmpty() const;
|
||||||
|
void Clear();
|
||||||
|
|
||||||
|
bool FilterAccepts(net_buffer *buffer) const;
|
||||||
|
|
||||||
|
struct HashDefinition {
|
||||||
|
typedef void ParentType;
|
||||||
|
typedef std::pair<const AddressType *, uint32> KeyType;
|
||||||
|
typedef ThisType ValueType;
|
||||||
|
|
||||||
|
size_t HashKey(const KeyType &key) const
|
||||||
|
{ return Addressing::HashAddress(*key.first) ^ key.second; }
|
||||||
|
size_t Hash(ValueType *value) const
|
||||||
|
{ return HashKey(std::make_pair(&value->Address(),
|
||||||
|
value->Interface()->index)); }
|
||||||
|
bool Compare(const KeyType &key, ValueType *value) const
|
||||||
|
{ return value->Interface()->index == key.second
|
||||||
|
&& value->Address().s_addr == key.first->s_addr; }
|
||||||
|
HashLink *GetLink(ValueType *value) const { return &value->fLink; }
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
// for g++ 2.95
|
||||||
|
friend class HashDefinition;
|
||||||
|
|
||||||
|
Filter *fParent;
|
||||||
AddressType fMulticastAddress;
|
AddressType fMulticastAddress;
|
||||||
|
net_interface *fInterface;
|
||||||
FilterMode fFilterMode;
|
FilterMode fFilterMode;
|
||||||
InterfaceList fInterfaces;
|
AddressSet<AddressType> fAddresses;
|
||||||
HashLink fHashLink;
|
HashLink fLink;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Addressing>
|
template<typename Addressing>
|
||||||
@@ -146,21 +174,22 @@ class MulticastFilter {
|
|||||||
public:
|
public:
|
||||||
typedef typename Addressing::AddressType AddressType;
|
typedef typename Addressing::AddressType AddressType;
|
||||||
typedef typename Addressing::ProtocolType ProtocolType;
|
typedef typename Addressing::ProtocolType ProtocolType;
|
||||||
typedef MulticastGroupState<Addressing> GroupState;
|
typedef MulticastGroupInterface<Addressing> GroupInterface;
|
||||||
|
|
||||||
MulticastFilter(ProtocolType *parent);
|
MulticastFilter(ProtocolType *parent);
|
||||||
~MulticastFilter();
|
~MulticastFilter();
|
||||||
|
|
||||||
ProtocolType *Parent() const { return fParent; }
|
ProtocolType *Socket() const { return fParent; }
|
||||||
|
|
||||||
GroupState *GetGroup(const AddressType &groupAddress, bool create);
|
status_t GetState(const AddressType &groupAddress,
|
||||||
void ReturnGroup(GroupState *group);
|
net_interface *interface, GroupInterface* &state, bool create);
|
||||||
|
void ReturnState(GroupInterface *state);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef typename GroupState::HashDefinition GroupHashDefinition;
|
typedef typename GroupInterface::HashDefinition HashDefinition;
|
||||||
typedef OpenHashTable<GroupHashDefinition> States;
|
typedef OpenHashTable<HashDefinition> States;
|
||||||
|
|
||||||
void _ReturnGroup(GroupState *group);
|
void _ReturnState(GroupInterface *state);
|
||||||
|
|
||||||
ProtocolType *fParent;
|
ProtocolType *fParent;
|
||||||
States fStates;
|
States fStates;
|
||||||
|
|||||||
@@ -804,7 +804,7 @@ interface_protocol_join_multicast(net_datalink_protocol *_protocol,
|
|||||||
const sockaddr *address)
|
const sockaddr *address)
|
||||||
{
|
{
|
||||||
// TODO
|
// TODO
|
||||||
return EINVAL;
|
return ENOTSUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -813,7 +813,7 @@ interface_protocol_leave_multicast(net_datalink_protocol *_protocol,
|
|||||||
const sockaddr *address)
|
const sockaddr *address)
|
||||||
{
|
{
|
||||||
// TODO
|
// TODO
|
||||||
return EINVAL;
|
return ENOTSUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user