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 | */ |