* deliver_multicast() now returns whether or not it delivered the buffer,

instead of always returning B_OK.
* deliver_multicast() now takes the protocol restriction of a raw socket into
  account.
* raw_receive_data() now correctly returns whether a buffer was delivered (due
  to the protocol restriction, this wasn't the case before).
* ipv4_receive_data() leaked all multicast buffers.
* Some minor cleanup.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@37648 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2010-07-21 13:11:58 +00:00
parent 1978fb81ee
commit aea00dc3bc
1 changed files with 68 additions and 50 deletions

View File

@ -69,7 +69,7 @@ struct ipv4_packet_key {
class FragmentPacket {
public:
FragmentPacket(const ipv4_packet_key &key);
FragmentPacket(const ipv4_packet_key& key);
~FragmentPacket();
status_t AddFragment(uint16 start, uint16 end,
@ -80,7 +80,8 @@ public:
{ return fReceivedLastFragment
&& fBytesLeft == 0; }
static uint32 Hash(void* _packet, const void* _key, uint32 range);
static uint32 Hash(void* _packet, const void* _key,
uint32 range);
static int Compare(void* _packet, const void* _key);
static int32 NextOffset()
{ return offsetof(FragmentPacket, fNext); }
@ -133,7 +134,7 @@ struct ipv4_protocol : net_protocol {
{
}
RawSocket *raw;
RawSocket* raw;
uint8 service_type;
uint8 time_to_live;
uint8 multicast_time_to_live;
@ -660,12 +661,15 @@ send_fragments(ipv4_protocol* protocol, struct net_route* route,
}
static status_t
/*! Delivers the provided \a buffer to all listeners of this multicast group.
Does not take over ownership of the buffer.
*/
static bool
deliver_multicast(net_protocol_module_info* module, net_buffer* buffer,
bool deliverToRaw)
{
if (module->deliver_data == NULL)
return B_OK;
return false;
MutexLocker _(sMulticastGroupsLock);
@ -674,32 +678,41 @@ deliver_multicast(net_protocol_module_info* module, net_buffer* buffer,
MulticastState::ValueIterator it = sMulticastState->Lookup(std::make_pair(
&multicastAddr->sin_addr, buffer->interface->index));
size_t count = 0;
while (it.HasNext()) {
IPv4GroupInterface* state = it.Next();
if (deliverToRaw && state->Parent()->Socket()->raw == NULL)
ipv4_protocol* ipProtocol = state->Parent()->Socket();
if (deliverToRaw && (ipProtocol->raw == NULL
|| ipProtocol->socket->protocol != buffer->protocol))
continue;
if (state->FilterAccepts(buffer)) {
// as Multicast filters are installed with an IPv4 protocol
net_protocol* protocol = ipProtocol;
if (protocol->module != module) {
// 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* protocol
= state->Parent()->Socket()->socket->first_protocol;
net_protocol* protocol = ipProtocol->socket->first_protocol;
while (protocol != NULL && protocol->module != module)
protocol = protocol->next;
}
if (protocol != NULL)
if (protocol != NULL) {
module->deliver_data(protocol, buffer);
count++;
}
}
}
return B_OK;
return count > 0;
}
/*! Delivers the buffer to all listening raw sockets.
/*! Delivers the buffer to all listening raw sockets without taking ownership of
the provided \a buffer.
Returns \c true if there was any receiver, \c false if not.
*/
static bool
@ -712,25 +725,28 @@ raw_receive_data(net_buffer* buffer)
TRACE("RawReceiveData(%i)", buffer->protocol);
if (buffer->flags & MSG_MCAST) {
if ((buffer->flags & MSG_MCAST) != 0) {
// we need to call deliver_multicast here separately as
// buffer still has the IP header, and it won't in the
// next call. This isn't very optimized but works for now.
// A better solution would be to hold separate hash tables
// and lists for RAW and non-RAW sockets.
deliver_multicast(&gIPv4Module, buffer, true);
} else {
return deliver_multicast(&gIPv4Module, buffer, true);
}
RawSocketList::Iterator iterator = sRawSockets.GetIterator();
size_t count = 0;
while (iterator.HasNext()) {
RawSocket* raw = iterator.Next();
if (raw->Socket()->protocol == buffer->protocol)
if (raw->Socket()->protocol == buffer->protocol) {
raw->SocketEnqueue(buffer);
count++;
}
}
return true;
return count > 0;
}
@ -1637,11 +1653,13 @@ ipv4_receive_data(net_buffer* buffer)
}
if ((buffer->flags & MSG_MCAST) != 0) {
// Unfortunely historical reasons dictate that the IP multicast
// Unfortunately 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, false);
deliver_multicast(module, buffer, false);
gBufferModule->free(buffer);
return B_OK;
}
return module->receive_data(buffer);