Rev 3886 | Rev 3912 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
| Rev 3886 | Rev 3901 | ||
|---|---|---|---|
| Line 25... | Line 25... | ||
| 25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
| 26 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
26 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 27 | */ |
27 | */ |
| 28 | 28 | ||
| 29 | /** @addtogroup net |
29 | /** @addtogroup net |
| 30 | * @{ |
30 | * @{ |
| 31 | */ |
31 | */ |
| 32 | 32 | ||
| 33 | /** @file |
33 | /** @file |
| 34 | */ |
34 | */ |
| 35 | 35 | ||
| 36 | #include <errno.h> |
36 | #include <errno.h> |
| 37 | #include <unistd.h> |
37 | #include <malloc.h> |
| - | 38 | //#include <stdio.h> |
|
| 38 | #include <string.h> |
39 | #include <string.h> |
| 39 | 40 | ||
| 40 | #include <ipc/ipc.h> |
- | |
| 41 | #include <sys/mman.h> |
41 | #include <sys/mman.h> |
| 42 | 42 | ||
| 43 | #include "../../err.h" |
43 | #include "../../err.h" |
| 44 | 44 | ||
| - | 45 | #include "../generic_field.h" |
|
| - | 46 | ||
| - | 47 | #include "packet_header.h" |
|
| 45 | #include "packet.h" |
48 | #include "packet.h" |
| 46 | 49 | ||
| - | 50 | // TODO power of 2 aritmetic => div and mod speedup? |
|
| 47 | #define PACKET_MAGIC_VALUE 0x11227788 |
51 | #define PACKET_MAP_SIZE 100 |
| 48 | 52 | ||
| 49 | struct packet{ |
- | |
| 50 | size_t length; |
- | |
| 51 | size_t max_prefix; |
- | |
| 52 | size_t max_content; |
- | |
| 53 | size_t data_start; |
- | |
| 54 | size_t data_end; |
- | |
| 55 | int magic_value; |
- | |
| 56 | }; |
- | |
| 57 | - | ||
| 58 | int packet_is_valid( packet_t packet ); |
- | |
| 59 | - | ||
| 60 | packet_t packet_create( size_t max_prefix, size_t max_content, size_t max_sufix ){ |
53 | #define PACKET_MAP_PAGE( packet_id ) ((( packet_id ) - 1 ) / PACKET_MAP_SIZE ) |
| 61 | size_t length; |
- | |
| 62 | packet_t packet; |
- | |
| 63 | - | ||
| 64 | length = max_prefix + max_content + max_sufix; |
- | |
| 65 | packet = ( packet_t ) mmap( NULL, sizeof( struct packet ) + length, PROTO_READ | PROTO_WRITE, MAP_SHARED | MAP_ANONYMOUS, 0, 0 ); |
- | |
| 66 | if( packet == MAP_FAILED ) return NULL; |
- | |
| 67 | packet->length = length; |
- | |
| 68 | packet->max_prefix = max_prefix; |
- | |
| 69 | packet->max_content = max_content; |
- | |
| 70 | packet->data_start = sizeof( struct packet ) + packet->max_prefix; |
54 | #define PACKET_MAP_INDEX( packet_id ) ((( packet_id ) - 1 ) % PACKET_MAP_SIZE ) |
| 71 | packet->data_end = packet->data_start; |
- | |
| 72 | packet->magic_value = PACKET_MAGIC_VALUE; |
- | |
| 73 | return packet; |
- | |
| 74 | } |
- | |
| 75 | 55 | ||
| 76 | int packet_is_valid( packet_t packet ){ |
- | |
| 77 | return packet && ( packet->magic_value == PACKET_MAGIC_VALUE ); |
- | |
| 78 | } |
- | |
| 79 | 56 | ||
| 80 | packet_t packet_copy( packet_t packet ){ |
57 | int packet_destroy( packet_t packet ); |
| 81 | packet_t new; |
- | |
| 82 | 58 | ||
| 83 | if( ! packet_is_valid( packet )) return NULL; |
59 | typedef packet_t packet_map_t[ PACKET_MAP_SIZE ]; |
| 84 | new = ( packet_t ) mmap( NULL, packet->length, PROTO_READ | PROTO_WRITE, MAP_SHARED | MAP_ANONYMOUS, 0, 0 ); |
- | |
| 85 | if( new == MAP_FAILED ) return NULL; |
60 | typedef packet_map_t * packet_map_ref; |
| - | 61 | ||
| 86 | memcpy( new, packet, packet->length ); |
62 | GENERIC_FIELD_DECLARE( gpm, packet_map_t ); |
| 87 | return new; |
- | |
| 88 | } |
63 | |
| - | 64 | GENERIC_FIELD_IMPLEMENT( gpm, packet_map_t ); |
|
| 89 | 65 | ||
| - | 66 | static struct{ |
|
| - | 67 | // TODO lock |
|
| - | 68 | gpm_t map; |
|
| - | 69 | } pm_globals; |
|
| - | 70 | ||
| 90 | int packet_copy_data( packet_t packet, void * data, size_t length ){ |
71 | int packet_destroy( packet_t packet ){ |
| 91 | if( ! packet_is_valid( packet )) return EINVAL; |
72 | if( ! packet_is_valid( packet )) return EINVAL; |
| 92 | if( packet->data_start + length >= (( size_t ) packet ) + packet->length ) return ENOMEM; |
- | |
| 93 | memcpy( packet + packet->data_start, data, length ); |
73 | return munmap( packet, packet->length ); |
| 94 | if( packet->data_start + length > packet->data_end ){ |
- | |
| 95 | packet->data_end = packet->data_start + length; |
- | |
| 96 | } |
- | |
| 97 | return EOK; |
- | |
| 98 | } |
74 | } |
| 99 | 75 | ||
| 100 | void * packet_prepend( packet_t packet, size_t length ){ |
- | |
| 101 | if(( ! packet_is_valid( packet )) || ( packet->data_start - sizeof( struct packet ) < length )) return NULL; |
- | |
| 102 | packet->data_start -= length; |
- | |
| 103 | return packet + packet->data_start; |
- | |
| 104 | } |
- | |
| 105 | - | ||
| 106 | void * packet_append( packet_t packet, size_t length ){ |
- | |
| 107 | if(( ! packet_is_valid( packet )) || ( packet->data_end + length >= (( size_t ) packet ) + packet->length )) return NULL; |
- | |
| 108 | packet->data_end += length; |
76 | int pm_init( void ){ |
| 109 | return packet + packet->data_end - length; |
77 | return gpm_initialize( & pm_globals.map ); |
| 110 | } |
- | |
| 111 | - | ||
| 112 | int packet_trim( packet_t packet, size_t prefix, size_t sufix ){ |
- | |
| 113 | if(( ! packet_is_valid( packet )) || ( prefix + sufix > packet->data_end - packet->data_start )) return EINVAL; |
- | |
| 114 | packet->data_start += prefix; |
- | |
| 115 | packet->data_end -= sufix; |
- | |
| 116 | return EOK; |
- | |
| 117 | } |
78 | } |
| 118 | 79 | ||
| 119 | int packet_send( packet_t packet, int phone ){ |
80 | packet_t pm_find( packet_id_t packet_id ){ |
| - | 81 | packet_map_ref map; |
|
| - | 82 | ||
| 120 | if( ! packet_is_valid( packet )) return EINVAL; |
83 | if( ! packet_id ) return NULL; |
| - | 84 | if( packet_id > PACKET_MAP_SIZE * gpm_count( & pm_globals.map )) return NULL; |
|
| 121 | return ipc_share_out_start( phone, packet, PROTO_READ | PROTO_WRITE ); |
85 | map = gpm_get_index( & pm_globals.map, PACKET_MAP_PAGE( packet_id )); |
| - | 86 | if( ! map ) return NULL; |
|
| - | 87 | return ( * map )[ PACKET_MAP_INDEX( packet_id ) ]; |
|
| 122 | } |
88 | } |
| 123 | 89 | ||
| 124 | int packet_receive( packet_ref packet ){ |
90 | int pm_add( packet_t packet ){ |
| 125 | ERROR_DECLARE; |
91 | ERROR_DECLARE; |
| 126 | 92 | ||
| 127 | ipc_callid_t callid; |
93 | packet_map_ref map; |
| 128 | size_t size; |
- | |
| 129 | int flags; |
- | |
| 130 | 94 | ||
| 131 | if( ! packet ) return EINVAL; |
95 | if(( ! packet_is_valid( packet )) || ( gpm_count( & pm_globals.map ) < -1 )) return EINVAL; |
| 132 | if( ! ipc_share_out_receive( & callid, & size, & flags )) return EINVAL; |
96 | if( PACKET_MAP_PAGE( packet->packet_id ) < gpm_count( & pm_globals.map )){ |
| - | 97 | map = gpm_get_index( & pm_globals.map, PACKET_MAP_PAGE( packet->packet_id )); |
|
| - | 98 | }else{ |
|
| - | 99 | do{ |
|
| 133 | * packet = ( packet_t ) as_get_mappable_page( size ); |
100 | map = ( packet_map_ref ) malloc( sizeof( packet_map_t )); |
| 134 | if( !( * packet )) return ENOMEM; |
101 | if( ! map ) return ENOMEM; |
| - | 102 | memset( map, 0, sizeof( packet_map_t )); |
|
| 135 | if( ERROR_OCCURED( ipc_share_out_finalize( callid, * packet ))){ |
103 | if(( ERROR_CODE = gpm_add( & pm_globals.map, map )) < 0 ){ |
| 136 | munmap( * packet, size ); |
104 | free( map ); |
| 137 | return ERROR_CODE; |
105 | return ERROR_CODE; |
| - | 106 | } |
|
| - | 107 | }while( PACKET_MAP_PAGE( packet->packet_id ) >= gpm_count( & pm_globals.map )); |
|
| 138 | } |
108 | } |
| - | 109 | ( * map )[ PACKET_MAP_INDEX( packet->packet_id ) ] = packet; |
|
| 139 | return EOK; |
110 | return EOK; |
| 140 | } |
111 | } |
| 141 | 112 | ||
| 142 | int packet_destroy( packet_t packet ){ |
113 | void pm_destroy( void ){ |
| - | 114 | int count; |
|
| - | 115 | int index; |
|
| - | 116 | packet_map_ref map; |
|
| - | 117 | packet_t packet; |
|
| - | 118 | ||
| - | 119 | count = gpm_count( & pm_globals.map ); |
|
| - | 120 | while( count > 0 ){ |
|
| - | 121 | map = gpm_get_index( & pm_globals.map, count - 1 ); |
|
| - | 122 | for( index = PACKET_MAP_SIZE - 1; index >= 0; -- index ){ |
|
| - | 123 | packet = ( * map )[ index ]; |
|
| 143 | if( ! packet_is_valid( packet )) return EINVAL; |
124 | if( packet_is_valid( packet )){ |
| 144 | return munmap( packet, sizeof( struct packet ) + packet->length ); |
125 | munmap( packet, packet->length ); |
| - | 126 | } |
|
| - | 127 | } |
|
| - | 128 | } |
|
| - | 129 | gpm_destroy( & pm_globals.map ); |
|
| 145 | } |
130 | } |
| 146 | 131 | ||
| 147 | size_t packet_get_data_length( packet_t packet ){ |
132 | packet_t pq_add( packet_t first, packet_t packet, int order, size_t metric ){ |
| - | 133 | packet_t item; |
|
| - | 134 | ||
| 148 | if( ! packet_is_valid( packet )) return 0; |
135 | if( ! packet_is_valid( packet )) return NULL; |
| - | 136 | pq_set( packet, order, metric ); |
|
| - | 137 | if( packet_is_valid( first )){ |
|
| - | 138 | item = first; |
|
| - | 139 | do{ |
|
| - | 140 | if( item->order < order ){ |
|
| - | 141 | if( item->next ){ |
|
| - | 142 | item = pm_find( item->next ); |
|
| - | 143 | }else{ |
|
| - | 144 | item->next = packet->packet_id; |
|
| 149 | return packet->data_end - packet->data_start; |
145 | packet->previous = item->packet_id; |
| - | 146 | return first; |
|
| - | 147 | } |
|
| - | 148 | }else{ |
|
| - | 149 | packet->previous = item->previous; |
|
| - | 150 | packet->next = item->packet_id; |
|
| - | 151 | item->previous = packet->packet_id; |
|
| - | 152 | item = pm_find( packet->previous ); |
|
| - | 153 | if( item ) item->next = packet->packet_id; |
|
| - | 154 | return item; |
|
| - | 155 | } |
|
| - | 156 | }while( packet_is_valid( item )); |
|
| - | 157 | } |
|
| - | 158 | return packet; |
|
| 150 | } |
159 | } |
| 151 | 160 | ||
| 152 | void * packet_get_data( packet_t packet ){ |
161 | packet_t pq_detach( packet_t packet ){ |
| - | 162 | packet_t next; |
|
| - | 163 | packet_t previous; |
|
| - | 164 | ||
| 153 | if( ! packet_is_valid( packet )) return NULL; |
165 | if( ! packet_is_valid( packet )) return NULL; |
| 154 | return packet + packet->data_start; |
166 | next = pm_find( packet->next ); |
| - | 167 | if( next ){ |
|
| - | 168 | next->previous = packet->previous; |
|
| - | 169 | previous = pm_find( next->previous ); |
|
| - | 170 | if( previous ){ |
|
| - | 171 | previous->next = next->packet_id; |
|
| - | 172 | } |
|
| - | 173 | } |
|
| - | 174 | packet->previous = 0; |
|
| - | 175 | packet->next = 0; |
|
| - | 176 | return next; |
|
| - | 177 | } |
|
| - | 178 | ||
| - | 179 | int pq_set( packet_t packet, int order, size_t metric ){ |
|
| - | 180 | if( ! packet_is_valid( packet )) return EINVAL; |
|
| - | 181 | packet->order = order; |
|
| - | 182 | packet->metric = metric; |
|
| - | 183 | return EOK; |
|
| - | 184 | } |
|
| - | 185 | ||
| - | 186 | void pq_destroy( packet_t first, void ( * packet_release )( packet_t packet )){ |
|
| - | 187 | packet_t actual; |
|
| - | 188 | packet_t next; |
|
| - | 189 | ||
| - | 190 | actual = first; |
|
| - | 191 | while( packet_is_valid( actual )){ |
|
| - | 192 | next = pm_find( actual->next ); |
|
| - | 193 | actual->next = 0; |
|
| - | 194 | actual->previous = 0; |
|
| - | 195 | if( packet_release ) packet_release( actual ); |
|
| - | 196 | actual = next; |
|
| - | 197 | } |
|
| 155 | } |
198 | } |
| 156 | 199 | ||
| 157 | /** @} |
200 | /** @} |
| 158 | */ |
201 | */ |