Moved the container management for ancillary data from the net_buffer
module to the stack module. There's a dedicated struct ancillary_data_container, now. One can just set the container on a net_buffer. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@25292 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
110d4031fb
commit
49e00d1f99
@ -37,11 +37,7 @@ typedef struct net_buffer {
|
||||
uint8 protocol;
|
||||
} net_buffer;
|
||||
|
||||
typedef struct ancillary_data_header {
|
||||
int level;
|
||||
int type;
|
||||
size_t len;
|
||||
} ancillary_data_header;
|
||||
struct ancillary_data_container;
|
||||
|
||||
struct net_buffer_module_info {
|
||||
module_info info;
|
||||
@ -74,16 +70,11 @@ struct net_buffer_module_info {
|
||||
|
||||
status_t (*associate_data)(net_buffer *buffer, void *data);
|
||||
|
||||
status_t (*attach_ancillary_data)(net_buffer *buffer,
|
||||
const ancillary_data_header *header, const void *data,
|
||||
void (*destructor)(const ancillary_data_header*, void*),
|
||||
void **_allocatedData);
|
||||
status_t (*detach_ancillary_data)(net_buffer *buffer, void *data,
|
||||
bool destroy);
|
||||
void (*set_ancillary_data)(net_buffer *buffer,
|
||||
ancillary_data_container *container);
|
||||
ancillary_data_container* (*get_ancillary_data)(net_buffer *buffer);
|
||||
void * (*transfer_ancillary_data)(net_buffer *from,
|
||||
net_buffer *to);
|
||||
void * (*next_ancillary_data)(net_buffer *buffer,
|
||||
void *previousData, ancillary_data_header *_header);
|
||||
|
||||
status_t (*direct_access)(net_buffer *buffer, uint32 offset,
|
||||
size_t bytes, void **_data);
|
||||
|
@ -16,6 +16,9 @@
|
||||
#define LEVEL_DRIVER_IOCTL 0x0f000000
|
||||
#define LEVEL_MASK 0x0fffffff
|
||||
|
||||
struct ancillary_data_container;
|
||||
struct ancillary_data_header;
|
||||
|
||||
typedef struct net_protocol {
|
||||
struct net_protocol *next;
|
||||
struct net_protocol_module_info *module;
|
||||
@ -69,8 +72,8 @@ struct net_protocol_module_info {
|
||||
status_t (*error_reply)(net_protocol *self, net_buffer *causedError,
|
||||
uint32 code, void *errorData);
|
||||
|
||||
status_t (*attach_ancillary_data)(net_protocol *self, net_buffer *buffer,
|
||||
const cmsghdr *header);
|
||||
status_t (*add_ancillary_data)(net_protocol *self,
|
||||
ancillary_data_container *container, const cmsghdr *header);
|
||||
ssize_t (*process_ancillary_data)(net_protocol *self,
|
||||
const ancillary_data_header *header, const void *data,
|
||||
void *buffer, size_t bufferSize);
|
||||
|
@ -24,6 +24,8 @@ struct net_domain;
|
||||
struct net_socket;
|
||||
struct net_timer;
|
||||
|
||||
typedef struct ancillary_data_container ancillary_data_container;
|
||||
|
||||
struct net_fifo {
|
||||
benaphore lock;
|
||||
sem_id notify;
|
||||
@ -64,6 +66,12 @@ struct net_device_monitor {
|
||||
void (*event)(struct net_device_monitor *monitor, int32 event);
|
||||
};
|
||||
|
||||
typedef struct ancillary_data_header {
|
||||
int level;
|
||||
int type;
|
||||
size_t len;
|
||||
} ancillary_data_header;
|
||||
|
||||
struct net_stack_module_info {
|
||||
module_info info;
|
||||
|
||||
@ -139,6 +147,21 @@ struct net_stack_module_info {
|
||||
bool (*is_restarted_syscall)(void);
|
||||
void (*store_syscall_restart_timeout)(bigtime_t timeout);
|
||||
bigtime_t (*restore_syscall_restart_timeout)(void);
|
||||
|
||||
// ancillary data
|
||||
ancillary_data_container* (*create_ancillary_data_container)();
|
||||
void (*delete_ancillary_data_container)(
|
||||
ancillary_data_container* container);
|
||||
status_t (*add_ancillary_data)(ancillary_data_container *container,
|
||||
const ancillary_data_header *header, const void *data,
|
||||
void (*destructor)(const ancillary_data_header*, void*),
|
||||
void **_allocatedData);
|
||||
status_t (*remove_ancillary_data)(ancillary_data_container *container,
|
||||
void *data, bool destroy);
|
||||
void* (*move_ancillary_data)(ancillary_data_container *from,
|
||||
ancillary_data_container *to);
|
||||
void* (*next_ancillary_data)(ancillary_data_container *container,
|
||||
void *previousData, ancillary_data_header *_header);
|
||||
};
|
||||
|
||||
#endif // NET_STACK_H
|
||||
|
@ -268,11 +268,11 @@ unix_error_reply(net_protocol *protocol, net_buffer *causedError, uint32 code,
|
||||
|
||||
|
||||
status_t
|
||||
unix_attach_ancillary_data(net_protocol *self, net_buffer *buffer,
|
||||
unix_add_ancillary_data(net_protocol *self, ancillary_data_container *container,
|
||||
const cmsghdr *header)
|
||||
{
|
||||
TRACE("[%ld] unix_attach_ancillary_data(%p, %p, %p (level: %d, type: %d, "
|
||||
"len: %d))\n", find_thread(NULL), self, buffer, header,
|
||||
TRACE("[%ld] unix_add_ancillary_data(%p, %p, %p (level: %d, type: %d, "
|
||||
"len: %d))\n", find_thread(NULL), self, container, header,
|
||||
header->cmsg_level, header->cmsg_type, (int)header->cmsg_len);
|
||||
|
||||
// we support only SCM_RIGHTS
|
||||
@ -302,17 +302,17 @@ unix_attach_ancillary_data(net_protocol *self, net_buffer *buffer,
|
||||
}
|
||||
}
|
||||
|
||||
// attach the ancillary data to the buffer
|
||||
// attach the ancillary data to the container
|
||||
if (error == B_OK) {
|
||||
ancillary_data_header header;
|
||||
header.level = SOL_SOCKET;
|
||||
header.type = SCM_RIGHTS;
|
||||
header.len = count * sizeof(file_descriptor*);
|
||||
|
||||
TRACE("[%ld] unix_attach_ancillary_data(): attaching %d FDs to "
|
||||
"buffer\n", find_thread(NULL), count);
|
||||
TRACE("[%ld] unix_add_ancillary_data(): adding %d FDs to "
|
||||
"container\n", find_thread(NULL), count);
|
||||
|
||||
error = gBufferModule->attach_ancillary_data(buffer, &header,
|
||||
error = gStackModule->add_ancillary_data(container, &header,
|
||||
descriptors, destroy_scm_rights_descriptors, NULL);
|
||||
}
|
||||
|
||||
@ -468,7 +468,7 @@ net_protocol_module_info gUnixModule = {
|
||||
unix_deliver_data,
|
||||
unix_error,
|
||||
unix_error_reply,
|
||||
unix_attach_ancillary_data,
|
||||
unix_add_ancillary_data,
|
||||
unix_process_ancillary_data
|
||||
};
|
||||
|
||||
|
@ -15,6 +15,7 @@ UseHeaders $(TARGET_PRIVATE_KERNEL_HEADERS) : true ;
|
||||
UsePrivateHeaders net ;
|
||||
|
||||
KernelAddon stack :
|
||||
ancillary_data.cpp
|
||||
datalink.cpp
|
||||
domains.cpp
|
||||
interfaces.cpp
|
||||
|
203
src/add-ons/kernel/network/stack/ancillary_data.cpp
Normal file
203
src/add-ons/kernel/network/stack/ancillary_data.cpp
Normal file
@ -0,0 +1,203 @@
|
||||
/*
|
||||
* Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
#include "ancillary_data.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <new>
|
||||
|
||||
#include <util/DoublyLinkedList.h>
|
||||
|
||||
|
||||
#define MAX_ANCILLARY_DATA_SIZE 128
|
||||
|
||||
|
||||
struct ancillary_data : DoublyLinkedListLinkImpl<ancillary_data> {
|
||||
void* Data()
|
||||
{
|
||||
return (char*)this + _ALIGN(sizeof(ancillary_data));
|
||||
}
|
||||
|
||||
static ancillary_data* FromData(void* data)
|
||||
{
|
||||
return (ancillary_data*)((char*)data - _ALIGN(sizeof(ancillary_data)));
|
||||
}
|
||||
|
||||
ancillary_data_header header;
|
||||
void (*destructor)(const ancillary_data_header*, void*);
|
||||
};
|
||||
|
||||
typedef DoublyLinkedList<ancillary_data> ancillary_data_list;
|
||||
|
||||
struct ancillary_data_container {
|
||||
ancillary_data_list data_list;
|
||||
};
|
||||
|
||||
|
||||
ancillary_data_container*
|
||||
create_ancillary_data_container()
|
||||
{
|
||||
return new(std::nothrow) ancillary_data_container;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
delete_ancillary_data_container(ancillary_data_container* container)
|
||||
{
|
||||
if (container == NULL)
|
||||
return;
|
||||
|
||||
while (ancillary_data* data = container->data_list.RemoveHead()) {
|
||||
if (data->destructor != NULL)
|
||||
data->destructor(&data->header, data->Data());
|
||||
free(data);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
Adds ancillary data to the given container.
|
||||
|
||||
\param container The container.
|
||||
\param header Description of the data.
|
||||
\param data If not \c NULL, the data are copied into the allocated storage.
|
||||
\param destructor If not \c NULL, this function will be invoked with the
|
||||
data as parameter when the container is destroyed.
|
||||
\param _allocatedData Will be set to the storage allocated for the data.
|
||||
\return \c B_OK when everything goes well, another error code otherwise.
|
||||
*/
|
||||
status_t
|
||||
add_ancillary_data(ancillary_data_container* container,
|
||||
const ancillary_data_header* header, const void* data,
|
||||
void (*destructor)(const ancillary_data_header*, void*),
|
||||
void** _allocatedData)
|
||||
{
|
||||
// check parameters
|
||||
if (header == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
if (header->len > MAX_ANCILLARY_DATA_SIZE)
|
||||
return ENOBUFS;
|
||||
|
||||
// allocate buffer
|
||||
void *dataBuffer = malloc(_ALIGN(sizeof(ancillary_data)) + header->len);
|
||||
if (dataBuffer == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
// init and attach the structure
|
||||
ancillary_data *ancillaryData = new(dataBuffer) ancillary_data;
|
||||
ancillaryData->header = *header;
|
||||
ancillaryData->destructor = destructor;
|
||||
|
||||
container->data_list.Add(ancillaryData);
|
||||
|
||||
if (data != NULL)
|
||||
memcpy(ancillaryData->Data(), data, header->len);
|
||||
|
||||
if (_allocatedData != NULL)
|
||||
*_allocatedData = ancillaryData->Data();
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
Removes ancillary data from the given container. The associated memory is
|
||||
freed, i.e. the \a data pointer must no longer be used after calling this
|
||||
function. Depending on \a destroy, the destructor is invoked before freeing
|
||||
the data.
|
||||
|
||||
\param container The container.
|
||||
\param data Pointer to the data to be removed (as returned by
|
||||
add_ancillary_data() or next_ancillary_data()).
|
||||
\param destroy If \c true, the destructor, if one was passed to
|
||||
add_ancillary_data(), is invoked for the data.
|
||||
\return \c B_OK when everything goes well, another error code otherwise.
|
||||
*/
|
||||
status_t
|
||||
remove_ancillary_data(ancillary_data_container* container, void* data,
|
||||
bool destroy)
|
||||
{
|
||||
if (data == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
ancillary_data *ancillaryData = ancillary_data::FromData(data);
|
||||
|
||||
container->data_list.Remove(ancillaryData);
|
||||
|
||||
if (destroy && ancillaryData->destructor != NULL) {
|
||||
ancillaryData->destructor(&ancillaryData->header,
|
||||
ancillaryData->Data());
|
||||
}
|
||||
|
||||
free(ancillaryData);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
Moves all ancillary data from container \c from to the end of the list of
|
||||
ancillary data of container \c to.
|
||||
|
||||
\param from The container from which to remove the ancillary data.
|
||||
\param to The container to which to add the ancillary data.
|
||||
\return A pointer to the first of the moved ancillary data, if any, \c NULL
|
||||
otherwise.
|
||||
*/
|
||||
void *
|
||||
move_ancillary_data(ancillary_data_container* from,
|
||||
ancillary_data_container* to)
|
||||
{
|
||||
if (from == NULL || to == NULL)
|
||||
return NULL;
|
||||
|
||||
ancillary_data *ancillaryData = from->data_list.Head();
|
||||
to->data_list.MoveFrom(&from->data_list);
|
||||
|
||||
return ancillaryData != NULL ? ancillaryData->Data() : NULL;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
Returns the next ancillary data. When iterating through the data, initially
|
||||
a \c NULL pointer shall be passed as \a previousData, subsequently the
|
||||
previously returned data pointer. After the last item, \c NULL is returned.
|
||||
|
||||
Note, that it is not safe to call remove_ancillary_data() for a data item
|
||||
and then pass that pointer to this function. First get the next item, then
|
||||
remove the previous one.
|
||||
|
||||
\param container The container.
|
||||
\param previousData The pointer to the previous data returned by this
|
||||
function. Initially \c NULL shall be passed.
|
||||
\param header Pointer to allocated storage into which the data description
|
||||
is written. May be \c NULL.
|
||||
\return A pointer to the next ancillary data in the container. \c NULL after
|
||||
the last one.
|
||||
*/
|
||||
void*
|
||||
next_ancillary_data(ancillary_data_container* container, void* previousData,
|
||||
ancillary_data_header* _header)
|
||||
{
|
||||
ancillary_data *ancillaryData;
|
||||
|
||||
if (previousData == NULL) {
|
||||
ancillaryData = container->data_list.Head();
|
||||
} else {
|
||||
ancillaryData = ancillary_data::FromData(previousData);
|
||||
ancillaryData = container->data_list.GetNext(ancillaryData);
|
||||
}
|
||||
|
||||
if (ancillaryData == NULL)
|
||||
return NULL;
|
||||
|
||||
if (_header != NULL)
|
||||
*_header = ancillaryData->header;
|
||||
|
||||
return ancillaryData->Data();
|
||||
}
|
29
src/add-ons/kernel/network/stack/ancillary_data.h
Normal file
29
src/add-ons/kernel/network/stack/ancillary_data.h
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef NET_ANCILLARY_DATA_H
|
||||
#define NET_ANCILLARY_DATA_H
|
||||
|
||||
#include <net_stack.h>
|
||||
|
||||
|
||||
struct ancillary_data_container;
|
||||
|
||||
ancillary_data_container* create_ancillary_data_container();
|
||||
void delete_ancillary_data_container(ancillary_data_container* container);
|
||||
|
||||
status_t add_ancillary_data(ancillary_data_container* container,
|
||||
const ancillary_data_header* header, const void* data,
|
||||
void (*destructor)(const ancillary_data_header*, void*),
|
||||
void** _allocatedData);
|
||||
status_t remove_ancillary_data(ancillary_data_container* container, void* data,
|
||||
bool destroy);
|
||||
void* move_ancillary_data(ancillary_data_container* from,
|
||||
ancillary_data_container* to);
|
||||
|
||||
void* next_ancillary_data(ancillary_data_container* container,
|
||||
void* previousData, ancillary_data_header* _header);
|
||||
|
||||
|
||||
#endif // NET_ANCILLARY_DATA_H
|
@ -25,6 +25,8 @@
|
||||
#include <sys/param.h>
|
||||
#include <sys/uio.h>
|
||||
|
||||
#include "ancillary_data.h"
|
||||
|
||||
#include "paranoia_config.h"
|
||||
|
||||
|
||||
@ -121,30 +123,11 @@ struct data_node {
|
||||
}
|
||||
};
|
||||
|
||||
#define MAX_ANCILLARY_DATA_SIZE 128
|
||||
|
||||
struct ancillary_data : DoublyLinkedListLinkImpl<ancillary_data> {
|
||||
void* Data()
|
||||
{
|
||||
return (char*)this + _ALIGN(sizeof(ancillary_data));
|
||||
}
|
||||
|
||||
static ancillary_data* FromData(void* data)
|
||||
{
|
||||
return (ancillary_data*)((char*)data - _ALIGN(sizeof(ancillary_data)));
|
||||
}
|
||||
|
||||
ancillary_data_header header;
|
||||
void (*destructor)(const ancillary_data_header*, void*);
|
||||
};
|
||||
|
||||
typedef DoublyLinkedList<ancillary_data> ancillary_data_list;
|
||||
|
||||
struct net_buffer_private : net_buffer {
|
||||
struct list buffers;
|
||||
data_header *allocation_header; // the current place where we
|
||||
// allocate header space (nodes,...)
|
||||
ancillary_data_list ancillary_data;
|
||||
ancillary_data_container* ancillary_data;
|
||||
|
||||
struct {
|
||||
struct sockaddr_storage source;
|
||||
@ -1021,7 +1004,7 @@ create_buffer(size_t headerSpace)
|
||||
list_init(&buffer->buffers);
|
||||
list_add_item(&buffer->buffers, node);
|
||||
|
||||
new(&buffer->ancillary_data) ancillary_data_list;
|
||||
buffer->ancillary_data = NULL;
|
||||
|
||||
buffer->source = (sockaddr *)&buffer->storage.source;
|
||||
buffer->destination = (sockaddr *)&buffer->storage.destination;
|
||||
@ -1063,11 +1046,7 @@ free_buffer(net_buffer *_buffer)
|
||||
remove_data_node(node);
|
||||
}
|
||||
|
||||
while (ancillary_data* data = buffer->ancillary_data.RemoveHead()) {
|
||||
if (data->destructor != NULL)
|
||||
data->destructor(&data->header, data->Data());
|
||||
free(data);
|
||||
}
|
||||
delete_ancillary_data_container(buffer->ancillary_data);
|
||||
|
||||
release_data_header(buffer->allocation_header);
|
||||
|
||||
@ -1873,89 +1852,17 @@ append_cloned_data(net_buffer *_buffer, net_buffer *_source, uint32 offset,
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
Attaches ancillary data to the given buffer. The data are completely
|
||||
orthogonal to the data the buffer stores.
|
||||
|
||||
\param buffer The buffer.
|
||||
\param header Description of the data.
|
||||
\param data If not \c NULL, the data are copied into the allocated storage.
|
||||
\param destructor If not \c NULL, this function will be invoked with the
|
||||
data as parameter when the buffer is destroyed.
|
||||
\param _allocatedData Will be set to the storage allocated for the data.
|
||||
\return \c B_OK when everything goes well, another error code otherwise.
|
||||
*/
|
||||
static status_t
|
||||
attach_ancillary_data(net_buffer *_buffer, const ancillary_data_header *header,
|
||||
const void *data, void (*destructor)(const ancillary_data_header*, void*),
|
||||
void **_allocatedData)
|
||||
void
|
||||
set_ancillary_data(net_buffer *buffer, ancillary_data_container *container)
|
||||
{
|
||||
// TODO: Obviously it would be nice to allocate the memory for the
|
||||
// ancillary data in the buffer.
|
||||
net_buffer_private *buffer = (net_buffer_private *)_buffer;
|
||||
|
||||
// check parameters
|
||||
if (header == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
if (header->len > MAX_ANCILLARY_DATA_SIZE)
|
||||
return ENOBUFS;
|
||||
|
||||
// allocate buffer
|
||||
void *dataBuffer = malloc(_ALIGN(sizeof(ancillary_data)) + header->len);
|
||||
if (dataBuffer == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
// init and attach the structure
|
||||
ancillary_data *ancillaryData = new(dataBuffer) ancillary_data;
|
||||
ancillaryData->header = *header;
|
||||
ancillaryData->destructor = destructor;
|
||||
|
||||
buffer->ancillary_data.Add(ancillaryData);
|
||||
|
||||
if (data != NULL)
|
||||
memcpy(ancillaryData->Data(), data, header->len);
|
||||
|
||||
if (_allocatedData != NULL)
|
||||
*_allocatedData = ancillaryData->Data();
|
||||
|
||||
return B_OK;
|
||||
((net_buffer_private*)buffer)->ancillary_data = container;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
Detaches ancillary data from the given buffer. The associated memory is
|
||||
free, i.e. the \a data pointer must no longer be used after calling this
|
||||
function. Depending on \a destroy, the destructor is invoked before freeing
|
||||
the data.
|
||||
|
||||
\param buffer The buffer.
|
||||
\param data Pointer to the data to be removed (as returned by
|
||||
attach_ancillary_data() or next_ancillary_data()).
|
||||
\param destroy If \c true, the destructor, if one was passed to
|
||||
attach_ancillary_data(), is invoked for the data.
|
||||
\return \c B_OK when everything goes well, another error code otherwise.
|
||||
*/
|
||||
static status_t
|
||||
detach_ancillary_data(net_buffer *_buffer, void *data, bool destroy)
|
||||
ancillary_data_container*
|
||||
get_ancillary_data(net_buffer *buffer)
|
||||
{
|
||||
net_buffer_private *buffer = (net_buffer_private *)_buffer;
|
||||
|
||||
if (data == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
ancillary_data *ancillaryData = ancillary_data::FromData(data);
|
||||
|
||||
buffer->ancillary_data.Remove(ancillaryData);
|
||||
|
||||
if (destroy && ancillaryData->destructor != NULL) {
|
||||
ancillaryData->destructor(&ancillaryData->header,
|
||||
ancillaryData->Data());
|
||||
}
|
||||
|
||||
free(ancillaryData);
|
||||
|
||||
return B_OK;
|
||||
return ((net_buffer_private*)buffer)->ancillary_data;
|
||||
}
|
||||
|
||||
|
||||
@ -1965,7 +1872,7 @@ detach_ancillary_data(net_buffer *_buffer, void *data, bool destroy)
|
||||
transfers or copies ancillary data from one buffer to another.
|
||||
|
||||
\param from The buffer from which to remove the ancillary data.
|
||||
\param to The buffer to which to add teh ancillary data.
|
||||
\param to The buffer to which to add the ancillary data.
|
||||
\return A pointer to the first of the moved ancillary data, if any, \c NULL
|
||||
otherwise.
|
||||
*/
|
||||
@ -1978,52 +1885,23 @@ transfer_ancillary_data(net_buffer *_from, net_buffer *_to)
|
||||
if (from == NULL || to == NULL)
|
||||
return NULL;
|
||||
|
||||
ancillary_data *ancillaryData = from->ancillary_data.Head();
|
||||
to->ancillary_data.MoveFrom(&from->ancillary_data);
|
||||
|
||||
return ancillaryData != NULL ? ancillaryData->Data() : NULL;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
Returns the next ancillary data. When iterating over the data, initially
|
||||
a \c NULL pointer shall be passed as \a previousData, subsequently the
|
||||
previously returned data pointer. After the last item, \c NULL is returned.
|
||||
|
||||
Note, that it is not safe to call detach_ancillary_data() for a data item
|
||||
and then pass that pointer to this function. First get the next item, then
|
||||
detach the previous one.
|
||||
|
||||
\param buffer The buffer.
|
||||
\param previousData The pointer to the previous data returned by this
|
||||
function. Initially \c NULL shall be passed.
|
||||
\param header Pointer to allocated storage into which the data description
|
||||
is written. May be \c NULL.
|
||||
\return A pointer to the next ancillary data in the buffer. \c NULL after
|
||||
the last one.
|
||||
*/
|
||||
static void*
|
||||
next_ancillary_data(net_buffer *_buffer, void *previousData,
|
||||
ancillary_data_header *_header)
|
||||
{
|
||||
net_buffer_private *buffer = (net_buffer_private *)_buffer;
|
||||
|
||||
ancillary_data *ancillaryData;
|
||||
|
||||
if (previousData == NULL) {
|
||||
ancillaryData = buffer->ancillary_data.Head();
|
||||
} else {
|
||||
ancillaryData = ancillary_data::FromData(previousData);
|
||||
ancillaryData = buffer->ancillary_data.GetNext(ancillaryData);
|
||||
}
|
||||
|
||||
if (ancillaryData == NULL)
|
||||
if (from->ancillary_data == NULL)
|
||||
return NULL;
|
||||
|
||||
if (_header != NULL)
|
||||
*_header = ancillaryData->header;
|
||||
if (to->ancillary_data == NULL) {
|
||||
// no ancillary data in the target buffer
|
||||
to->ancillary_data = from->ancillary_data;
|
||||
from->ancillary_data = NULL;
|
||||
return next_ancillary_data(to->ancillary_data, NULL, NULL);
|
||||
}
|
||||
|
||||
return ancillaryData->Data();
|
||||
// both have ancillary data
|
||||
void *data = move_ancillary_data(from->ancillary_data,
|
||||
to->ancillary_data);
|
||||
delete_ancillary_data_container(from->ancillary_data);
|
||||
from->ancillary_data = NULL;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
@ -2228,10 +2106,9 @@ net_buffer_module_info gNetBufferModule = {
|
||||
|
||||
NULL, // associate_data
|
||||
|
||||
attach_ancillary_data,
|
||||
detach_ancillary_data,
|
||||
set_ancillary_data,
|
||||
get_ancillary_data,
|
||||
transfer_ancillary_data,
|
||||
next_ancillary_data,
|
||||
|
||||
direct_access,
|
||||
read_data,
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include <net_stack.h>
|
||||
#include <net_stat.h>
|
||||
|
||||
#include "ancillary_data.h"
|
||||
#include "utility.h"
|
||||
|
||||
|
||||
@ -134,8 +135,8 @@ err1:
|
||||
|
||||
|
||||
static status_t
|
||||
attach_ancillary_data(net_socket *socket, net_buffer *buffer, void *data,
|
||||
size_t dataLen)
|
||||
add_ancillary_data(net_socket *socket, ancillary_data_container* container,
|
||||
void *data, size_t dataLen)
|
||||
{
|
||||
cmsghdr *header = (cmsghdr*)data;
|
||||
|
||||
@ -143,11 +144,11 @@ attach_ancillary_data(net_socket *socket, net_buffer *buffer, void *data,
|
||||
if (header->cmsg_len < sizeof(cmsghdr) || header->cmsg_len > dataLen)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
if (socket->first_info->attach_ancillary_data == NULL)
|
||||
if (socket->first_info->add_ancillary_data == NULL)
|
||||
return EOPNOTSUPP;
|
||||
|
||||
status_t status = socket->first_info->attach_ancillary_data(
|
||||
socket->first_protocol, buffer, header);
|
||||
status_t status = socket->first_info->add_ancillary_data(
|
||||
socket->first_protocol, container, header);
|
||||
if (status != B_OK)
|
||||
return status;
|
||||
|
||||
@ -160,17 +161,20 @@ attach_ancillary_data(net_socket *socket, net_buffer *buffer, void *data,
|
||||
|
||||
|
||||
static status_t
|
||||
process_ancillary_data(net_socket *socket, net_buffer *buffer, msghdr *_header)
|
||||
process_ancillary_data(net_socket *socket, ancillary_data_container* container,
|
||||
msghdr *_header)
|
||||
{
|
||||
if (container == NULL)
|
||||
return B_OK;
|
||||
|
||||
uint8 *dataBuffer = (uint8*)_header->msg_control;
|
||||
int dataBufferLen = _header->msg_controllen;
|
||||
|
||||
ancillary_data_header header;
|
||||
void *data = NULL;
|
||||
|
||||
while ((data = gNetBufferModule.next_ancillary_data(buffer, data, &header))
|
||||
!= NULL) {
|
||||
|
||||
while ((data = next_ancillary_data(container, data, &header)) != NULL) {
|
||||
if (socket->first_info->process_ancillary_data == NULL)
|
||||
return EOPNOTSUPP;
|
||||
|
||||
@ -943,7 +947,8 @@ socket_receive(net_socket *socket, msghdr *header, void *data, size_t length,
|
||||
// process ancillary data
|
||||
if (header != NULL) {
|
||||
if (buffer != NULL && header->msg_control != NULL) {
|
||||
status = process_ancillary_data(socket, buffer, header);
|
||||
status = process_ancillary_data(socket,
|
||||
gNetBufferModule.get_ancillary_data(buffer), header);
|
||||
if (status != B_OK) {
|
||||
gNetBufferModule.free(buffer);
|
||||
return status;
|
||||
@ -1129,8 +1134,15 @@ socket_send(net_socket *socket, msghdr *header, const void *data, size_t length,
|
||||
// attach ancillary data to the first buffer
|
||||
status_t status = B_OK;
|
||||
if (ancillaryData != NULL) {
|
||||
status = attach_ancillary_data(socket, buffer, ancillaryData,
|
||||
ancillaryDataLen);
|
||||
ancillary_data_container *container
|
||||
= create_ancillary_data_container();
|
||||
if (container != NULL) {
|
||||
gNetBufferModule.set_ancillary_data(buffer, container);
|
||||
status = add_ancillary_data(socket, container, ancillaryData,
|
||||
ancillaryDataLen);
|
||||
} else
|
||||
status = B_NO_MEMORY;
|
||||
|
||||
ancillaryData = NULL;
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,7 @@
|
||||
*/
|
||||
|
||||
|
||||
#include "ancillary_data.h"
|
||||
#include "domains.h"
|
||||
#include "interfaces.h"
|
||||
#include "link.h"
|
||||
@ -922,6 +923,13 @@ net_stack_module_info gNetStackModule = {
|
||||
is_restarted_syscall,
|
||||
store_syscall_restart_timeout,
|
||||
restore_syscall_restart_timeout,
|
||||
|
||||
create_ancillary_data_container,
|
||||
delete_ancillary_data_container,
|
||||
add_ancillary_data,
|
||||
remove_ancillary_data,
|
||||
move_ancillary_data,
|
||||
next_ancillary_data
|
||||
};
|
||||
|
||||
module_info *modules[] = {
|
||||
|
Loading…
Reference in New Issue
Block a user