* 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:
parent
1978fb81ee
commit
aea00dc3bc
|
@ -69,7 +69,7 @@ struct ipv4_packet_key {
|
||||||
|
|
||||||
class FragmentPacket {
|
class FragmentPacket {
|
||||||
public:
|
public:
|
||||||
FragmentPacket(const ipv4_packet_key &key);
|
FragmentPacket(const ipv4_packet_key& key);
|
||||||
~FragmentPacket();
|
~FragmentPacket();
|
||||||
|
|
||||||
status_t AddFragment(uint16 start, uint16 end,
|
status_t AddFragment(uint16 start, uint16 end,
|
||||||
|
@ -80,7 +80,8 @@ public:
|
||||||
{ return fReceivedLastFragment
|
{ return fReceivedLastFragment
|
||||||
&& fBytesLeft == 0; }
|
&& 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 int Compare(void* _packet, const void* _key);
|
||||||
static int32 NextOffset()
|
static int32 NextOffset()
|
||||||
{ return offsetof(FragmentPacket, fNext); }
|
{ return offsetof(FragmentPacket, fNext); }
|
||||||
|
@ -133,7 +134,7 @@ struct ipv4_protocol : net_protocol {
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
RawSocket *raw;
|
RawSocket* raw;
|
||||||
uint8 service_type;
|
uint8 service_type;
|
||||||
uint8 time_to_live;
|
uint8 time_to_live;
|
||||||
uint8 multicast_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,
|
deliver_multicast(net_protocol_module_info* module, net_buffer* buffer,
|
||||||
bool deliverToRaw)
|
bool deliverToRaw)
|
||||||
{
|
{
|
||||||
if (module->deliver_data == NULL)
|
if (module->deliver_data == NULL)
|
||||||
return B_OK;
|
return false;
|
||||||
|
|
||||||
MutexLocker _(sMulticastGroupsLock);
|
MutexLocker _(sMulticastGroupsLock);
|
||||||
|
|
||||||
|
@ -674,32 +678,41 @@ deliver_multicast(net_protocol_module_info* module, net_buffer* buffer,
|
||||||
MulticastState::ValueIterator it = sMulticastState->Lookup(std::make_pair(
|
MulticastState::ValueIterator it = sMulticastState->Lookup(std::make_pair(
|
||||||
&multicastAddr->sin_addr, buffer->interface->index));
|
&multicastAddr->sin_addr, buffer->interface->index));
|
||||||
|
|
||||||
|
size_t count = 0;
|
||||||
|
|
||||||
while (it.HasNext()) {
|
while (it.HasNext()) {
|
||||||
IPv4GroupInterface* state = it.Next();
|
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;
|
continue;
|
||||||
|
|
||||||
if (state->FilterAccepts(buffer)) {
|
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
|
// reference, we need to go and find the appropriate instance
|
||||||
// related to the 'receiving protocol' with module 'module'.
|
// related to the 'receiving protocol' with module 'module'.
|
||||||
net_protocol* protocol
|
net_protocol* protocol = ipProtocol->socket->first_protocol;
|
||||||
= state->Parent()->Socket()->socket->first_protocol;
|
|
||||||
|
|
||||||
while (protocol != NULL && protocol->module != module)
|
while (protocol != NULL && protocol->module != module)
|
||||||
protocol = protocol->next;
|
protocol = protocol->next;
|
||||||
|
}
|
||||||
|
|
||||||
if (protocol != NULL)
|
if (protocol != NULL) {
|
||||||
module->deliver_data(protocol, buffer);
|
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.
|
Returns \c true if there was any receiver, \c false if not.
|
||||||
*/
|
*/
|
||||||
static bool
|
static bool
|
||||||
|
@ -712,25 +725,28 @@ raw_receive_data(net_buffer* buffer)
|
||||||
|
|
||||||
TRACE("RawReceiveData(%i)", buffer->protocol);
|
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
|
// we need to call deliver_multicast here separately as
|
||||||
// buffer still has the IP header, and it won't in the
|
// buffer still has the IP header, and it won't in the
|
||||||
// next call. This isn't very optimized but works for now.
|
// next call. This isn't very optimized but works for now.
|
||||||
// A better solution would be to hold separate hash tables
|
// A better solution would be to hold separate hash tables
|
||||||
// and lists for RAW and non-RAW sockets.
|
// and lists for RAW and non-RAW sockets.
|
||||||
deliver_multicast(&gIPv4Module, buffer, true);
|
return deliver_multicast(&gIPv4Module, buffer, true);
|
||||||
} else {
|
}
|
||||||
|
|
||||||
RawSocketList::Iterator iterator = sRawSockets.GetIterator();
|
RawSocketList::Iterator iterator = sRawSockets.GetIterator();
|
||||||
|
size_t count = 0;
|
||||||
|
|
||||||
while (iterator.HasNext()) {
|
while (iterator.HasNext()) {
|
||||||
RawSocket* raw = iterator.Next();
|
RawSocket* raw = iterator.Next();
|
||||||
|
|
||||||
if (raw->Socket()->protocol == buffer->protocol)
|
if (raw->Socket()->protocol == buffer->protocol) {
|
||||||
raw->SocketEnqueue(buffer);
|
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) {
|
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
|
// model be a little different from the unicast one. We deliver
|
||||||
// this frame directly to all sockets registered with interest
|
// this frame directly to all sockets registered with interest
|
||||||
// for this multicast group.
|
// 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);
|
return module->receive_data(buffer);
|
||||||
|
|
Loading…
Reference in New Issue