Rev 4730 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 4730 | Rev 4738 | ||
---|---|---|---|
Line 45... | Line 45... | ||
45 | #include "../structures/dynamic_fifo.h" |
45 | #include "../structures/dynamic_fifo.h" |
46 | #include "../structures/int_map.h" |
46 | #include "../structures/int_map.h" |
47 | #include "../structures/packet/packet.h" |
47 | #include "../structures/packet/packet.h" |
48 | #include "../structures/packet/packet_client.h" |
48 | #include "../structures/packet/packet_client.h" |
49 | 49 | ||
- | 50 | #include "../modules.h" |
|
- | 51 | ||
50 | #include "socket_core.h" |
52 | #include "socket_core.h" |
51 | 53 | ||
- | 54 | /** \todo |
|
- | 55 | */ |
|
- | 56 | struct socket_port{ |
|
- | 57 | socket_port_map_t map; |
|
- | 58 | int count; |
|
- | 59 | }; |
|
- | 60 | ||
- | 61 | /** \todo |
|
- | 62 | */ |
|
52 | int socket_bind_insert( socket_ports_ref global_sockets, socket_core_ref socket, int port ); |
63 | int socket_bind_insert( socket_ports_ref global_sockets, socket_core_ref socket, int port ); |
53 | 64 | ||
- | 65 | /** \todo |
|
- | 66 | */ |
|
- | 67 | void socket_destroy_core( int packet_phone, socket_core_ref socket, socket_cores_ref local_sockets, socket_ports_ref global_sockets, void ( * socket_release )( socket_core_ref socket )); |
|
- | 68 | ||
- | 69 | /** \todo |
|
- | 70 | */ |
|
- | 71 | int socket_port_add_core( socket_port_ref socket_port, socket_core_ref socket, const char * key, size_t key_length ); |
|
- | 72 | ||
54 | INT_MAP_IMPLEMENT( socket_cores, socket_core_t ); |
73 | INT_MAP_IMPLEMENT( socket_cores, socket_core_t ); |
55 | 74 | ||
- | 75 | GENERIC_CHAR_MAP_IMPLEMENT( socket_port_map, socket_core_ref ); |
|
- | 76 | ||
56 | INT_MAP_IMPLEMENT( socket_ports, socket_core_ref ); |
77 | INT_MAP_IMPLEMENT( socket_ports, socket_port_t ); |
- | 78 | ||
- | 79 | void socket_cores_release( int packet_phone, socket_cores_ref local_sockets, socket_ports_ref global_sockets, void ( * socket_release )( socket_core_ref socket )){ |
|
- | 80 | if( socket_cores_is_valid( local_sockets )){ |
|
- | 81 | int index; |
|
- | 82 | ||
- | 83 | local_sockets->magic = 0; |
|
- | 84 | for( index = 0; index < local_sockets->next; ++ index ){ |
|
- | 85 | if( socket_cores_item_is_valid( &( local_sockets->items[ index ] ))){ |
|
- | 86 | local_sockets->items[ index ].magic = 0; |
|
- | 87 | if( local_sockets->items[ index ].value ){ |
|
- | 88 | socket_destroy_core( packet_phone, local_sockets->items[ index ].value, local_sockets, global_sockets, socket_release ); |
|
- | 89 | free( local_sockets->items[ index ].value ); |
|
- | 90 | local_sockets->items[ index ].value = NULL; |
|
- | 91 | } |
|
- | 92 | } |
|
- | 93 | } |
|
- | 94 | free( local_sockets->items ); |
|
- | 95 | } |
|
- | 96 | } |
|
- | 97 | ||
- | 98 | void socket_destroy_core( int packet_phone, socket_core_ref socket, socket_cores_ref local_sockets, socket_ports_ref global_sockets, void ( * socket_release )( socket_core_ref socket )){ |
|
- | 99 | int packet_id; |
|
- | 100 | ||
- | 101 | // if bound |
|
- | 102 | if( socket->port ){ |
|
- | 103 | // release the port |
|
- | 104 | socket_port_release( global_sockets, socket ); |
|
- | 105 | } |
|
- | 106 | // release all received packets |
|
- | 107 | while(( packet_id = dyn_fifo_pop( & socket->received )) >= 0 ){ |
|
- | 108 | pq_release( packet_phone, packet_id ); |
|
- | 109 | } |
|
- | 110 | dyn_fifo_destroy( & socket->received ); |
|
- | 111 | dyn_fifo_destroy( & socket->accepted ); |
|
- | 112 | if( socket_release ){ |
|
- | 113 | socket_release( socket ); |
|
- | 114 | } |
|
- | 115 | socket_cores_exclude( local_sockets, socket->socket_id ); |
|
- | 116 | } |
|
57 | 117 | ||
58 | int socket_bind( socket_cores_ref local_sockets, socket_ports_ref global_sockets, int socket_id, void * addr, size_t addrlen, int free_ports_start, int free_ports_end, int last_used_port ){ |
118 | int socket_bind( socket_cores_ref local_sockets, socket_ports_ref global_sockets, int socket_id, void * addr, size_t addrlen, int free_ports_start, int free_ports_end, int last_used_port ){ |
59 | socket_core_ref socket; |
119 | socket_core_ref socket; |
60 | socket_core_ref * socket_pointer; |
120 | socket_port_ref socket_port; |
61 | struct sockaddr * address; |
121 | struct sockaddr * address; |
62 | struct sockaddr_in * address_in; |
122 | struct sockaddr_in * address_in; |
63 | 123 | ||
64 | if( addrlen < sizeof( struct sockaddr )) return EINVAL; |
124 | if( addrlen < sizeof( struct sockaddr )) return EINVAL; |
65 | address = ( struct sockaddr * ) addr; |
125 | address = ( struct sockaddr * ) addr; |
Line 73... | Line 133... | ||
73 | // bind a free port? |
133 | // bind a free port? |
74 | if( address_in->sin_port <= 0 ){ |
134 | if( address_in->sin_port <= 0 ){ |
75 | return socket_bind_free_port( global_sockets, socket, free_ports_start, free_ports_end, last_used_port ); |
135 | return socket_bind_free_port( global_sockets, socket, free_ports_start, free_ports_end, last_used_port ); |
76 | } |
136 | } |
77 | // try to find the port |
137 | // try to find the port |
78 | socket_pointer = socket_ports_find( global_sockets, address_in->sin_port ); |
138 | socket_port = socket_ports_find( global_sockets, ntohs( address_in->sin_port )); |
79 | if( socket_pointer ){ |
139 | if( socket_port ){ |
80 | // already used |
140 | // already used |
81 | return EADDRINUSE; |
141 | return EADDRINUSE; |
82 | } |
142 | } |
83 | // unbind if bound |
143 | // if bound |
- | 144 | if( socket->port ){ |
|
- | 145 | // release the port |
|
84 | socket_ports_exclude( global_sockets, socket->port ); |
146 | socket_port_release( global_sockets, socket ); |
- | 147 | } |
|
85 | socket->port = -1; |
148 | socket->port = -1; |
86 | return socket_bind_insert( global_sockets, socket, address_in->sin_port ); |
149 | return socket_bind_insert( global_sockets, socket, ntohs( address_in->sin_port )); |
87 | break; |
150 | break; |
88 | // TODO IPv6 |
151 | // TODO IPv6 |
89 | } |
152 | } |
90 | return EAFNOSUPPORT; |
153 | return EAFNOSUPPORT; |
91 | } |
154 | } |
Line 117... | Line 180... | ||
117 | } |
180 | } |
118 | 181 | ||
119 | int socket_bind_insert( socket_ports_ref global_sockets, socket_core_ref socket, int port ){ |
182 | int socket_bind_insert( socket_ports_ref global_sockets, socket_core_ref socket, int port ){ |
120 | ERROR_DECLARE; |
183 | ERROR_DECLARE; |
121 | 184 | ||
122 | socket_core_ref * socket_pointer; |
185 | socket_port_ref socket_port; |
123 | 186 | ||
124 | // create a wrapper |
187 | // create a wrapper |
125 | socket_pointer = ( socket_core_ref * ) malloc( sizeof( socket_core_ref )); |
188 | socket_port = malloc( sizeof( * socket_port )); |
126 | if( ! socket_pointer ) return ENOMEM; |
189 | if( ! socket_port ) return ENOMEM; |
127 | * socket_pointer = socket; |
190 | socket_port->count = 0; |
- | 191 | if( ERROR_OCCURRED( socket_port_map_initialize( & socket_port->map )) |
|
- | 192 | || ERROR_OCCURRED( socket_port_add_core( socket_port, socket, SOCKET_MAP_KEY_LISTENING, 0 ))){ |
|
- | 193 | socket_port_map_destroy( & socket_port->map ); |
|
- | 194 | free( socket_port ); |
|
- | 195 | return ERROR_CODE; |
|
- | 196 | } |
|
128 | // register the incomming port |
197 | // register the incomming port |
129 | ERROR_CODE = socket_ports_add( global_sockets, port, socket_pointer ); |
198 | ERROR_CODE = socket_ports_add( global_sockets, port, socket_port ); |
130 | if( ERROR_CODE < 0 ){ |
199 | if( ERROR_CODE < 0 ){ |
- | 200 | socket_port_map_destroy( & socket_port->map ); |
|
131 | free( socket_pointer ); |
201 | free( socket_port ); |
132 | return ERROR_CODE; |
202 | return ERROR_CODE; |
133 | } |
203 | } |
134 | socket->port = port; |
204 | socket->port = port; |
135 | return EOK; |
205 | return EOK; |
136 | } |
206 | } |
Line 145... | Line 215... | ||
145 | socket = ( socket_core_ref ) malloc( sizeof( * socket )); |
215 | socket = ( socket_core_ref ) malloc( sizeof( * socket )); |
146 | if( ! socket ) return ENOMEM; |
216 | if( ! socket ) return ENOMEM; |
147 | // initialize |
217 | // initialize |
148 | socket->phone = app_phone; |
218 | socket->phone = app_phone; |
149 | socket->port = -1; |
219 | socket->port = -1; |
- | 220 | socket->key = NULL; |
|
- | 221 | socket->key_length = 0; |
|
150 | socket->specific_data = specific_data; |
222 | socket->specific_data = specific_data; |
151 | if( ERROR_OCCURRED( dyn_fifo_initialize( & socket->received, SOCKET_INITIAL_RECEIVED_SIZE ))){ |
223 | if( ERROR_OCCURRED( dyn_fifo_initialize( & socket->received, SOCKET_INITIAL_RECEIVED_SIZE ))){ |
152 | free( socket ); |
224 | free( socket ); |
153 | return ERROR_CODE; |
225 | return ERROR_CODE; |
154 | } |
226 | } |
Line 170... | Line 242... | ||
170 | // return the socket identifier |
242 | // return the socket identifier |
171 | * socket_id = socket->socket_id; |
243 | * socket_id = socket->socket_id; |
172 | return EOK; |
244 | return EOK; |
173 | } |
245 | } |
174 | 246 | ||
175 | int socket_destroy( int packet_phone, int socket_id, socket_cores_ref local_sockets, socket_ports_ref global_sockets ){ |
247 | int socket_destroy( int packet_phone, int socket_id, socket_cores_ref local_sockets, socket_ports_ref global_sockets, void ( * socket_release )( socket_core_ref socket )){ |
176 | socket_core_ref socket; |
248 | socket_core_ref socket; |
177 | int accepted_id; |
249 | int accepted_id; |
178 | int packet_id; |
- | |
179 | 250 | ||
180 | // find the socket |
251 | // find the socket |
181 | socket = socket_cores_find( local_sockets, socket_id ); |
252 | socket = socket_cores_find( local_sockets, socket_id ); |
182 | if( ! socket ) return ENOTSOCK; |
253 | if( ! socket ) return ENOTSOCK; |
183 | socket_ports_exclude( global_sockets, socket->port ); |
- | |
184 | // destroy all accepted sockets |
254 | // destroy all accepted sockets |
185 | while(( accepted_id = dyn_fifo_pop( & socket->accepted )) >= 0 ){ |
255 | while(( accepted_id = dyn_fifo_pop( & socket->accepted )) >= 0 ){ |
186 | socket_destroy( packet_phone, accepted_id, local_sockets, global_sockets ); |
256 | socket_destroy( packet_phone, accepted_id, local_sockets, global_sockets, socket_release ); |
187 | } |
257 | } |
- | 258 | socket_destroy_core( packet_phone, socket, local_sockets, global_sockets, socket_release ); |
|
188 | // release all received packets |
259 | return EOK; |
- | 260 | } |
|
- | 261 | ||
189 | while(( packet_id = dyn_fifo_pop( & socket->received )) >= 0 ){ |
262 | int socket_reply_packets( packet_t packet, size_t * length ){ |
- | 263 | ERROR_DECLARE; |
|
- | 264 | ||
190 | pq_release( packet_phone, packet_id ); |
265 | packet_t next_packet; |
- | 266 | size_t fragments; |
|
- | 267 | size_t * lengths; |
|
- | 268 | size_t index; |
|
- | 269 | ||
- | 270 | if( ! length ){ |
|
- | 271 | return EINVAL; |
|
191 | } |
272 | } |
- | 273 | next_packet = pq_next( packet ); |
|
- | 274 | if( ! next_packet ){ |
|
- | 275 | // write all if only one fragment |
|
- | 276 | ERROR_PROPAGATE( data_reply( packet_get_data( packet ), packet_get_data_length( packet ))); |
|
- | 277 | // store the total length |
|
- | 278 | * length = packet_get_data_length( packet ); |
|
- | 279 | }else{ |
|
- | 280 | // count the packet fragments |
|
- | 281 | fragments = 1; |
|
- | 282 | next_packet = pq_next( packet ); |
|
- | 283 | while(( next_packet = pq_next( next_packet ))){ |
|
- | 284 | ++ fragments; |
|
- | 285 | } |
|
- | 286 | // compute and store the fragment lengths |
|
- | 287 | lengths = ( size_t * ) malloc( sizeof( size_t ) * fragments + sizeof( size_t )); |
|
- | 288 | if( ! lengths ) return ENOMEM; |
|
- | 289 | lengths[ 0 ] = packet_get_data_length( packet ); |
|
- | 290 | lengths[ fragments ] = lengths[ 0 ]; |
|
- | 291 | next_packet = pq_next( packet ); |
|
- | 292 | for( index = 1; index < fragments; ++ index ){ |
|
- | 293 | lengths[ index ] = packet_get_data_length( next_packet ); |
|
- | 294 | lengths[ fragments ] += lengths[ index ]; |
|
- | 295 | next_packet = pq_next( packet ); |
|
- | 296 | }while( next_packet ); |
|
- | 297 | // write the fragment lengths |
|
- | 298 | ERROR_PROPAGATE( data_reply( lengths, sizeof( int ) * ( fragments + 1 ))); |
|
- | 299 | next_packet = packet; |
|
- | 300 | // write the fragments |
|
- | 301 | for( index = 0; index < fragments; ++ index ){ |
|
- | 302 | ERROR_PROPAGATE( data_reply( packet_get_data( next_packet ), lengths[ index ] )); |
|
- | 303 | next_packet = pq_next( next_packet ); |
|
- | 304 | }while( next_packet ); |
|
- | 305 | // store the total length |
|
- | 306 | * length = lengths[ fragments ]; |
|
- | 307 | free( lengths ); |
|
- | 308 | } |
|
- | 309 | return EOK; |
|
- | 310 | } |
|
- | 311 | ||
- | 312 | socket_core_ref socket_port_find( socket_ports_ref global_sockets, int port, const char * key, size_t key_length ){ |
|
- | 313 | socket_port_ref socket_port; |
|
- | 314 | socket_core_ref * socket_ref; |
|
- | 315 | ||
- | 316 | socket_port = socket_ports_find( global_sockets, port ); |
|
192 | dyn_fifo_destroy( & socket->received ); |
317 | if( socket_port && ( socket_port->count > 0 )){ |
- | 318 | socket_ref = socket_port_map_find( & socket_port->map, key, key_length ); |
|
- | 319 | if( socket_ref ){ |
|
- | 320 | return * socket_ref; |
|
- | 321 | } |
|
- | 322 | } |
|
- | 323 | return NULL; |
|
- | 324 | } |
|
- | 325 | ||
- | 326 | void socket_port_release( socket_ports_ref global_sockets, socket_core_ref socket ){ |
|
- | 327 | socket_port_ref socket_port; |
|
- | 328 | socket_core_ref * socket_ref; |
|
- | 329 | ||
- | 330 | if( socket->port ){ |
|
- | 331 | // find ports |
|
- | 332 | socket_port = socket_ports_find( global_sockets, socket->port ); |
|
- | 333 | if( socket_port ){ |
|
- | 334 | // find the socket |
|
- | 335 | socket_ref = socket_port_map_find( & socket_port->map, socket->key, socket->key_length ); |
|
- | 336 | if( socket_ref ){ |
|
- | 337 | -- socket_port->count; |
|
- | 338 | // release if empty |
|
- | 339 | if( socket_port->count <= 0 ){ |
|
- | 340 | // destroy the map |
|
193 | dyn_fifo_destroy( & socket->accepted ); |
341 | socket_port_map_destroy( & socket_port->map ); |
- | 342 | // release the port |
|
194 | socket_cores_exclude( local_sockets, socket_id ); |
343 | socket_ports_exclude( global_sockets, socket->port ); |
- | 344 | }else{ |
|
- | 345 | // remove |
|
- | 346 | socket_port_map_exclude( & socket_port->map, socket->key, socket->key_length ); |
|
- | 347 | } |
|
- | 348 | } |
|
- | 349 | } |
|
- | 350 | socket->port = 0; |
|
- | 351 | socket->key = NULL; |
|
- | 352 | socket->key_length = 0; |
|
- | 353 | } |
|
- | 354 | } |
|
- | 355 | ||
- | 356 | int socket_port_add( socket_ports_ref global_sockets, int port, socket_core_ref socket, const char * key, size_t key_length ){ |
|
- | 357 | ERROR_DECLARE; |
|
- | 358 | ||
- | 359 | socket_port_ref socket_port; |
|
- | 360 | ||
- | 361 | // find ports |
|
- | 362 | socket_port = socket_ports_find( global_sockets, port ); |
|
- | 363 | if( ! socket_port ) return ENOENT; |
|
- | 364 | // add the socket |
|
- | 365 | ERROR_PROPAGATE( socket_port_add_core( socket_port, socket, key, key_length )); |
|
- | 366 | socket->port = port; |
|
- | 367 | return EOK; |
|
- | 368 | } |
|
- | 369 | ||
- | 370 | int socket_port_add_core( socket_port_ref socket_port, socket_core_ref socket, const char * key, size_t key_length ){ |
|
- | 371 | ERROR_DECLARE; |
|
- | 372 | ||
- | 373 | socket_core_ref * socket_ref; |
|
- | 374 | ||
- | 375 | // create a wrapper |
|
- | 376 | socket_ref = malloc( sizeof( * socket_ref )); |
|
- | 377 | if( ! socket_ref ) return ENOMEM; |
|
- | 378 | * socket_ref = socket; |
|
- | 379 | // add the wrapper |
|
- | 380 | if( ERROR_OCCURRED( socket_port_map_add( & socket_port->map, key, key_length, socket_ref ))){ |
|
- | 381 | free( socket_ref ); |
|
- | 382 | return ERROR_CODE; |
|
- | 383 | } |
|
- | 384 | ++ socket_port->count; |
|
- | 385 | socket->key = key; |
|
- | 386 | socket->key_length = key_length; |
|
195 | return EOK; |
387 | return EOK; |
196 | } |
388 | } |
197 | 389 | ||
198 | /** @} |
390 | /** @} |
199 | */ |
391 | */ |