some NetBufferUtility revamp.

- introduced base NetBufferFieldReader which deals with obtaining a continuguous field to deal with.
 - renamed Detach() to Sync() to better express the fact that we may be writing to the buffer.
 - Fixed IPv4's and ICMP's checksum calculation as it assumed the underlying header was contiguous.
 - ICMP is now able to reply to ICMP Echo Requests which were split across data nodes.
 - in split_buffer(), make sure we were able to trim() the new buffer before damaging the original one.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@20657 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Hugo Santos
2007-04-11 16:40:40 +00:00
parent 453fb26fda
commit 87001e059c
8 changed files with 153 additions and 142 deletions
+90 -87
View File
@@ -16,94 +16,26 @@ class NetBufferModuleGetter {
static net_buffer_module_info *Get() { return gBufferModule; }
};
//! A class to retrieve and remove a header from a buffer
template<typename Type, typename Module = NetBufferModuleGetter > class NetBufferHeader {
//! A class to access a field safely across node boundaries
template<typename Type, int Offset, typename Module = NetBufferModuleGetter>
class NetBufferFieldReader {
public:
NetBufferHeader(net_buffer *buffer)
NetBufferFieldReader(net_buffer *buffer)
:
fBuffer(buffer)
fBuffer(buffer),
fStatus(B_BAD_VALUE)
{
}
~NetBufferHeader()
{
Remove();
}
status_t
Status()
{
return fBuffer->size < sizeof(Type) ? B_BAD_VALUE : B_OK;
}
status_t
SetTo(net_buffer *buffer)
{
fBuffer = buffer;
return Status();
}
Type &
Data()
{
Type *data;
if (Module::Get()->direct_access(fBuffer, 0, sizeof(Type),
(void **)&data) == B_OK)
return *data;
Module::Get()->read(fBuffer, 0, &fDataBuffer, sizeof(Type));
return fDataBuffer;
}
void
Remove()
{
Remove(sizeof(Type));
}
void
Remove(size_t bytes)
{
if (fBuffer != NULL) {
Module::Get()->remove_header(fBuffer, bytes);
fBuffer = NULL;
if ((Offset + sizeof(Type)) <= buffer->size) {
fStatus = Module::Get()->direct_access(fBuffer, Offset,
sizeof(Type), (void **)&fData);
if (fStatus != B_OK) {
fData = NULL;
fStatus = Module::Get()->read(fBuffer, Offset,
&fDataBuffer, sizeof(Type));
}
}
}
void
Detach()
{
fBuffer = NULL;
}
private:
net_buffer *fBuffer;
Type fDataBuffer;
};
//! A class to access a header safely across data node boundaries
template<typename Type, typename Module = NetBufferModuleGetter>
class NetBufferSafeHeader {
public:
NetBufferSafeHeader(net_buffer *buffer)
:
fBuffer(buffer)
{
fStatus = Module::Get()->direct_access(fBuffer, 0,
sizeof(Type), (void **)&fData);
if (fStatus != B_OK) {
fData = NULL;
fStatus = Module::Get()->read(fBuffer, 0, &fDataBuffer,
sizeof(Type));
}
}
~NetBufferSafeHeader()
{
if (fBuffer != NULL)
Detach();
}
status_t
Status()
{
@@ -119,16 +51,33 @@ class NetBufferSafeHeader {
return fDataBuffer;
}
void
Detach()
Type *
operator->()
{
return &Data();
}
Type &
operator*()
{
return Data();
}
void
Sync()
{
if (fBuffer == NULL)
return;
if (fData == NULL)
Module::Get()->write(fBuffer, 0, &fDataBuffer, sizeof(Type));
Module::Get()->write(fBuffer, Offset, &fDataBuffer,
sizeof(Type));
fBuffer = NULL;
}
protected:
NetBufferSafeHeader() {}
NetBufferFieldReader() {}
net_buffer *fBuffer;
status_t fStatus;
@@ -136,9 +85,58 @@ class NetBufferSafeHeader {
Type fDataBuffer;
};
template<typename Type, int Offset, typename Module = NetBufferModuleGetter>
class NetBufferField : public NetBufferFieldReader<Type, Offset, Module> {
public:
NetBufferField(net_buffer *buffer)
: NetBufferFieldReader<Type, Offset, Module>(buffer)
{}
~NetBufferField()
{
Sync();
}
};
template<typename Type, typename Module = NetBufferModuleGetter>
class NetBufferHeaderReader : public NetBufferFieldReader<Type, 0, Module> {
public:
NetBufferHeaderReader(net_buffer *buffer)
: NetBufferFieldReader<Type, 0, Module>(buffer)
{}
void
Remove()
{
Remove(sizeof(Type));
}
void
Remove(size_t bytes)
{
if (fBuffer != NULL) {
Module::Get()->remove_header(fBuffer, bytes);
fBuffer = NULL;
}
}
};
template<typename Type, typename Module = NetBufferModuleGetter>
class NetBufferHeaderRemover : public NetBufferHeaderReader<Type, Module> {
public:
NetBufferHeaderRemover(net_buffer *buffer)
: NetBufferHeaderReader<Type, Module>(buffer)
{}
~NetBufferHeaderRemover()
{
Remove();
}
};
//! A class to add a header to a buffer
template<typename Type, typename Module = NetBufferModuleGetter>
class NetBufferPrepend : public NetBufferSafeHeader<Type, Module> {
class NetBufferPrepend : public NetBufferFieldReader<Type, 0, Module> {
public:
NetBufferPrepend(net_buffer *buffer, size_t size = 0)
{
@@ -150,6 +148,11 @@ class NetBufferPrepend : public NetBufferSafeHeader<Type, Module> {
fStatus = Module::Get()->prepend_size(buffer, size, (void **)&fData);
}
~NetBufferPrepend()
{
Sync();
}
};
#endif // NET_BUFFER_UTILITIES_H