1 /* 2 * Copyright 2007, Haiku, Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Hugo Santos, hugosantos@gmail.com 7 */ 8 #ifndef _PRIVATE_MULTICAST_H_ 9 #define _PRIVATE_MULTICAST_H_ 10 11 12 #include <util/DoublyLinkedList.h> 13 #include <util/OpenHashTable.h> 14 15 #include <net_datalink.h> 16 17 #include <netinet/in.h> 18 19 #include <utility> 20 21 22 struct net_buffer; 23 struct net_protocol; 24 25 // This code is template'ized as it is reusable for IPv6 26 27 template<typename Addressing> class MulticastFilter; 28 template<typename Addressing> class MulticastGroupInterface; 29 30 // TODO move this elsewhere... 31 struct IPv4Multicast { 32 typedef struct in_addr AddressType; 33 typedef struct ipv4_protocol ProtocolType; 34 typedef MulticastGroupInterface<IPv4Multicast> GroupInterface; 35 36 static status_t JoinGroup(GroupInterface *); 37 static status_t LeaveGroup(GroupInterface *); 38 39 static const in_addr &AddressFromSockAddr(const sockaddr *sockaddr) 40 { return ((const sockaddr_in *)sockaddr)->sin_addr; } 41 static size_t HashAddress(const in_addr &address) 42 { return address.s_addr; } 43 }; 44 45 template<typename AddressType> 46 class AddressSet { 47 struct ContainedAddress : DoublyLinkedListLinkImpl<ContainedAddress> { 48 AddressType address; 49 }; 50 51 typedef DoublyLinkedList<ContainedAddress> AddressList; 52 53 public: 54 AddressSet() 55 : fCount(0) {} 56 57 ~AddressSet() { Clear(); } 58 59 status_t Add(const AddressType &address) 60 { 61 if (Has(address)) 62 return B_OK; 63 64 ContainedAddress *container = new ContainedAddress(); 65 if (container == NULL) 66 return B_NO_MEMORY; 67 68 container->address = address; 69 fAddresses.Add(container); 70 71 return B_OK; 72 } 73 74 void Remove(const AddressType &address) 75 { 76 ContainedAddress *container = _Get(address); 77 if (container == NULL) 78 return; 79 80 fAddresses.Remove(container); 81 delete container; 82 } 83 84 bool Has(const AddressType &address) const 85 { 86 return _Get(address) != NULL; 87 } 88 89 bool IsEmpty() const { return fAddresses.IsEmpty(); } 90 91 void Clear() 92 { 93 while (!fAddresses.IsEmpty()) 94 Remove(fAddresses.Head()->address); 95 } 96 97 class Iterator { 98 public: 99 Iterator(const AddressList &addresses) 100 : fBaseIterator(addresses.GetIterator()) {} 101 102 bool HasNext() const { return fBaseIterator.HasNext(); } 103 AddressType &Next() { return fBaseIterator.Next()->address; } 104 105 private: 106 typename AddressList::ConstIterator fBaseIterator; 107 }; 108 109 Iterator GetIterator() const { return Iterator(fAddresses); } 110 111 private: 112 ContainedAddress *_Get(const AddressType &address) const 113 { 114 typename AddressList::ConstIterator it = fAddresses.GetIterator(); 115 while (it.HasNext()) { 116 ContainedAddress *container = it.Next(); 117 if (container->address == address) 118 return container; 119 } 120 return NULL; 121 } 122 123 AddressList fAddresses; 124 int fCount; 125 }; 126 127 128 template<typename Addressing> 129 class MulticastGroupInterface 130 : public HashTableLink< MulticastGroupInterface<Addressing> > { 131 public: 132 typedef MulticastGroupInterface<Addressing> ThisType; 133 typedef HashTableLink<ThisType> HashLink; 134 typedef typename Addressing::AddressType AddressType; 135 typedef MulticastFilter<Addressing> Filter; 136 typedef AddressSet<AddressType> AddressSet; 137 138 enum FilterMode { 139 kInclude, 140 kExclude 141 }; 142 143 MulticastGroupInterface(Filter *parent, const AddressType &address, 144 net_interface *interface); 145 ~MulticastGroupInterface(); 146 147 Filter *Parent() const { return fParent; } 148 149 const AddressType &Address() const { return fMulticastAddress; } 150 net_interface *Interface() const { return fInterface; } 151 152 status_t Add(); 153 status_t Drop(); 154 status_t BlockSource(const AddressType &sourceAddress); 155 status_t UnblockSource(const AddressType &sourceAddress); 156 status_t AddSSM(const AddressType &sourceAddress); 157 status_t DropSSM(const AddressType &sourceAddress); 158 159 bool IsEmpty() const; 160 void Clear(); 161 162 FilterMode Mode() const { return fFilterMode; } 163 const AddressSet &Sources() const { return fAddresses; } 164 165 bool FilterAccepts(net_buffer *buffer) const; 166 167 struct HashDefinition { 168 typedef std::pair<const AddressType *, uint32> KeyType; 169 typedef ThisType ValueType; 170 171 size_t HashKey(const KeyType &key) const 172 { return Addressing::HashAddress(*key.first) ^ key.second; } 173 size_t Hash(ValueType *value) const 174 { return HashKey(std::make_pair(&value->Address(), 175 value->Interface()->index)); } 176 bool Compare(const KeyType &key, ValueType *value) const 177 { return value->Interface()->index == key.second 178 && value->Address().s_addr == key.first->s_addr; } 179 HashLink *GetLink(ValueType *value) const { return &value->fLink; } 180 }; 181 182 private: 183 // for g++ 2.95 184 friend class HashDefinition; 185 186 Filter *fParent; 187 AddressType fMulticastAddress; 188 net_interface *fInterface; 189 FilterMode fFilterMode; 190 AddressSet fAddresses; 191 HashLink fLink; 192 }; 193 194 template<typename Addressing> 195 class MulticastFilter { 196 public: 197 typedef typename Addressing::AddressType AddressType; 198 typedef typename Addressing::ProtocolType ProtocolType; 199 typedef MulticastGroupInterface<Addressing> GroupInterface; 200 201 MulticastFilter(ProtocolType *parent); 202 ~MulticastFilter(); 203 204 ProtocolType *Socket() const { return fParent; } 205 206 status_t GetState(const AddressType &groupAddress, 207 net_interface *interface, GroupInterface* &state, bool create); 208 void ReturnState(GroupInterface *state); 209 210 private: 211 typedef typename GroupInterface::HashDefinition HashDefinition; 212 typedef OpenHashTable<HashDefinition> States; 213 214 void _ReturnState(GroupInterface *state); 215 216 ProtocolType *fParent; 217 States fStates; 218 }; 219 220 #endif 221