33,10 → 33,126 |
/** @file |
*/ |
|
#include <errno.h> |
#include <unistd.h> |
#include <string.h> |
|
#include <ipc/ipc.h> |
#include <sys/mman.h> |
|
#include "err.h" |
|
#include "packet.h" |
|
#define PACKET_MAGIC_VALUE 0x11227788 |
|
struct packet{ |
void * start; |
size_t length; |
size_t max_prefix; |
size_t max_content; |
size_t data_start; |
size_t data_end; |
int magic_value; |
}; |
|
int packet_is_valid( packet_t packet ); |
|
packet_t packet_create( size_t max_prefix, size_t max_content, size_t max_sufix ){ |
size_t length; |
packet_t packet; |
|
length = max_prefix + max_content + max_sufix; |
packet = ( packet_t ) mmap( NULL, sizeof( struct packet ) + length, PROTO_READ | PROTO_WRITE, MAP_SHARED | MAP_ANONYMOUS, 0, 0 ); |
if( packet == MAP_FAILED ) return NULL; |
packet->length = length; |
packet->max_prefix = max_prefix; |
packet->max_content = max_content; |
packet->data_start = sizeof( struct packet ) + packet->max_prefix; |
packet->data_end = packet->data_start; |
packet->magic_value = PACKET_MAGIC_VALUE; |
return packet; |
} |
|
int packet_is_valid( packet_t packet ){ |
return packet && ( packet->magic_value == PACKET_MAGIC_VALUE ); |
} |
|
packet_t packet_copy( packet_t packet ){ |
packet_t new; |
|
if( ! packet_is_valid( packet )) return NULL; |
new = ( packet_t ) mmap( NULL, packet->length, PROTO_READ | PROTO_WRITE, MAP_SHARED | MAP_ANONYMOUS, 0, 0 ); |
if( new == MAP_FAILED ) return NULL; |
memcpy( new, packet, packet->length ); |
return new; |
} |
|
int packet_copy_data( packet_t packet, void * data, size_t length ){ |
if( ! packet_is_valid( packet )) return EINVAL; |
if( packet->data_start + length >= (( size_t ) packet ) + packet->length ) return ENOMEM; |
memcpy( packet + packet->data_start, data, length ); |
if( packet->data_start + length > packet->data_end ){ |
packet->data_end = packet->data_start + length; |
} |
return EOK; |
} |
|
void * packet_prepend( packet_t packet, size_t length ){ |
if(( ! packet_is_valid( packet )) || ( packet->data_start - sizeof( struct packet ) < length )) return NULL; |
packet->data_start -= length; |
return packet + packet->data_start; |
} |
|
void * packet_append( packet_t packet, size_t length ){ |
if(( ! packet_is_valid( packet )) || ( packet->data_end + length >= (( size_t ) packet ) + packet->length )) return NULL; |
packet->data_end += length; |
return packet + packet->data_end - length; |
} |
|
int packet_trim( packet_t packet, size_t prefix, size_t sufix ){ |
if(( ! packet_is_valid( packet )) || ( prefix + sufix > packet->data_end - packet->data_start )) return EINVAL; |
packet->data_start += prefix; |
packet->data_end -= sufix; |
return EOK; |
} |
|
int packet_send( packet_t packet, int phone ){ |
if( ! packet_is_valid( packet )) return EINVAL; |
return ipc_share_out_start( phone, packet, PROTO_READ | PROTO_WRITE ); |
} |
|
int packet_receive( packet_ref packet ){ |
ERROR_DECLARE; |
|
ipc_callid_t callid; |
size_t size; |
int flags; |
|
if( ! packet ) return EINVAL; |
if( ! ipc_share_out_receive( & callid, & size, & flags )) return EINVAL; |
* packet = ( packet_t ) as_get_mappable_page( size ); |
if( !( * packet )) return ENOMEM; |
if( ERROR_OCCURED( ipc_share_out_finalize( callid, * packet ))){ |
munmap( * packet, size ); |
return ERROR_CODE; |
} |
return EOK; |
} |
|
int packet_destroy( packet_t packet ){ |
if( ! packet_is_valid( packet )) return EINVAL; |
return munmap( packet, sizeof( struct packet ) + packet->length ); |
} |
|
size_t packet_get_data_length( packet_t packet ){ |
if( ! packet_is_valid( packet )) return 0; |
return packet->data_end - packet->data_start; |
} |
|
void * packet_get_data( packet_t packet ){ |
if( ! packet_is_valid( packet )) return NULL; |
return packet + packet->data_start; |
} |
|
/** @} |
*/ |