Rev 3886 | Rev 3914 | 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 | */ |