Changeset 137f8aa in mainline
- Timestamp:
- 2010-10-15T20:53:02Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- b01f878
- Parents:
- 25d2de69
- Location:
- uspace/lib/net
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/net/generic/socket_core.c
r25d2de69 r137f8aa 27 27 */ 28 28 29 /** @addtogroup socket30 * 29 /** @addtogroup libnet 30 * @{ 31 31 */ 32 32 33 33 /** @file 34 * Socket common core implementation. 35 */ 34 * Socket common core implementation. 35 */ 36 37 #include <socket_core.h> 38 #include <packet_client.h> 39 #include <packet_remote.h> 36 40 37 41 #include <net/socket_codes.h> 38 42 #include <net/in.h> 39 43 #include <net/inet.h> 44 #include <net/packet.h> 45 #include <net/modules.h> 40 46 41 47 #include <stdint.h> … … 46 52 #include <adt/dynamic_fifo.h> 47 53 #include <adt/int_map.h> 48 #include <net/packet.h> 49 #include <packet_client.h> 50 #include <packet_remote.h> 51 #include <net/modules.h> 52 #include <socket_core.h> 53 54 /** Maximum number of random attempts to find a new socket identifier before switching to the sequence. 55 */ 56 #define SOCKET_ID_TRIES 100 57 58 /** Bound port sockets. 59 */ 60 struct socket_port{ 61 /** The bound sockets map. 62 */ 54 55 /** 56 * Maximum number of random attempts to find a new socket identifier before 57 * switching to the sequence. 58 */ 59 #define SOCKET_ID_TRIES 100 60 61 /** Bound port sockets.*/ 62 struct socket_port { 63 /** The bound sockets map. */ 63 64 socket_port_map_t map; 64 /** The bound sockets count. 65 */ 65 /** The bound sockets count. */ 66 66 int count; 67 67 }; … … 74 74 75 75 /** Destroys the socket. 76 * If the socket is bound, the port is released. 77 * Releases all buffered packets, calls the release function and removes the socket from the local sockets. 78 * @param[in] packet_phone The packet server phone to release buffered packets. 79 * @param[in] socket The socket to be destroyed. 80 * @param[in,out] local_sockets The local sockets to be updated. 81 * @param[in,out] global_sockets The global sockets to be updated. 82 * @param[in] socket_release The client release callback function. 83 */ 84 static 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)){ 76 * 77 * If the socket is bound, the port is released. 78 * Releases all buffered packets, calls the release function and removes the 79 * socket from the local sockets. 80 * 81 * @param[in] packet_phone The packet server phone to release buffered packets. 82 * @param[in] socket The socket to be destroyed. 83 * @param[in,out] local_sockets The local sockets to be updated. 84 * @param[in,out] global_sockets The global sockets to be updated. 85 * @param[in] socket_release The client release callback function. 86 */ 87 static void 88 socket_destroy_core(int packet_phone, socket_core_ref socket, 89 socket_cores_ref local_sockets, socket_ports_ref global_sockets, 90 void (* socket_release)(socket_core_ref socket)) 91 { 85 92 int packet_id; 86 93 87 94 // if bound 88 if (socket->port){95 if (socket->port) { 89 96 // release the port 90 97 socket_port_release(global_sockets, socket); 91 98 } 99 92 100 // release all received packets 93 while ((packet_id = dyn_fifo_pop(&socket->received)) >= 0){101 while ((packet_id = dyn_fifo_pop(&socket->received)) >= 0) 94 102 pq_release_remote(packet_phone, packet_id); 95 } 103 96 104 dyn_fifo_destroy(&socket->received); 97 105 dyn_fifo_destroy(&socket->accepted); 98 if(socket_release){ 106 107 if (socket_release) 99 108 socket_release(socket); 100 } 109 101 110 socket_cores_exclude(local_sockets, socket->socket_id); 102 111 } 103 112 104 void socket_cores_release(int packet_phone, socket_cores_ref local_sockets, socket_ports_ref global_sockets, void (*socket_release)(socket_core_ref socket)){ 105 if(socket_cores_is_valid(local_sockets)){ 106 int index; 107 108 local_sockets->magic = 0; 109 for(index = 0; index < local_sockets->next; ++ index){ 110 if(socket_cores_item_is_valid(&(local_sockets->items[index]))){ 111 local_sockets->items[index].magic = 0; 112 if(local_sockets->items[index].value){ 113 socket_destroy_core(packet_phone, local_sockets->items[index].value, local_sockets, global_sockets, socket_release); 114 free(local_sockets->items[index].value); 115 local_sockets->items[index].value = NULL; 116 } 113 /** Destroys local sockets. 114 * 115 * Releases all buffered packets and calls the release function for each of the 116 * sockets. 117 * 118 * @param[in] packet_phone The packet server phone to release buffered packets. 119 * @param[in] local_sockets The local sockets to be destroyed. 120 * @param[in,out] global_sockets The global sockets to be updated. 121 * @param[in] socket_release The client release callback function. 122 */ 123 void 124 socket_cores_release(int packet_phone, socket_cores_ref local_sockets, 125 socket_ports_ref global_sockets, 126 void (* socket_release)(socket_core_ref socket)) 127 { 128 int index; 129 130 if (!socket_cores_is_valid(local_sockets)) 131 return; 132 133 local_sockets->magic = 0; 134 135 for (index = 0; index < local_sockets->next; ++index) { 136 if (socket_cores_item_is_valid(&local_sockets->items[index])) { 137 local_sockets->items[index].magic = 0; 138 139 if (local_sockets->items[index].value) { 140 socket_destroy_core(packet_phone, 141 local_sockets->items[index].value, 142 local_sockets, global_sockets, 143 socket_release); 144 free(local_sockets->items[index].value); 145 local_sockets->items[index].value = NULL; 117 146 } 118 147 } 119 free(local_sockets->items); 120 } 148 } 149 150 free(local_sockets->items); 121 151 } 122 152 123 153 /** Adds the socket to a socket port. 124 * @param[in,out] socket_port The socket port structure. 125 * @param[in] socket The socket to be added. 126 * @param[in] key The socket key identifier. 127 * @param[in] key_length The socket key length. 128 * @returns EOK on success. 129 * @returns ENOMEM if there is not enough memory left. 130 */ 131 static int socket_port_add_core(socket_port_ref socket_port, socket_core_ref socket, const char * key, size_t key_length){ 154 * 155 * @param[in,out] socket_port The socket port structure. 156 * @param[in] socket The socket to be added. 157 * @param[in] key The socket key identifier. 158 * @param[in] key_length The socket key length. 159 * @returns EOK on success. 160 * @returns ENOMEM if there is not enough memory left. 161 */ 162 static int 163 socket_port_add_core(socket_port_ref socket_port, socket_core_ref socket, 164 const char *key, size_t key_length) 165 { 132 166 ERROR_DECLARE; 133 167 134 socket_core_ref * 168 socket_core_ref *socket_ref; 135 169 136 170 // create a wrapper 137 171 socket_ref = malloc(sizeof(*socket_ref)); 138 if (! socket_ref){172 if (!socket_ref) 139 173 return ENOMEM; 140 } 174 141 175 *socket_ref = socket; 142 176 // add the wrapper 143 if(ERROR_OCCURRED(socket_port_map_add(&socket_port->map, key, key_length, socket_ref))){ 177 if (ERROR_OCCURRED(socket_port_map_add(&socket_port->map, key, 178 key_length, socket_ref))) { 144 179 free(socket_ref); 145 180 return ERROR_CODE; 146 181 } 147 ++ socket_port->count; 182 183 ++socket_port->count; 148 184 socket->key = key; 149 185 socket->key_length = key_length; 186 150 187 return EOK; 151 188 } 152 189 153 190 /** Binds the socket to the port. 154 * The SOCKET_MAP_KEY_LISTENING key identifier is used. 155 * @param[in] global_sockets The global sockets to be updated. 156 * @param[in] socket The socket to be added. 157 * @param[in] port The port number to be bound to. 158 * @returns EOK on success. 159 * @returns ENOMEM if there is not enough memory left. 160 * @returns Other error codes as defined for the socket_ports_add() function. 161 */ 162 static int socket_bind_insert(socket_ports_ref global_sockets, socket_core_ref socket, int port){ 191 * 192 * The SOCKET_MAP_KEY_LISTENING key identifier is used. 193 * 194 * @param[in] global_sockets The global sockets to be updated. 195 * @param[in] socket The socket to be added. 196 * @param[in] port The port number to be bound to. 197 * @returns EOK on success. 198 * @returns ENOMEM if there is not enough memory left. 199 * @returns Other error codes as defined for the 200 * socket_ports_add() function. 201 */ 202 static int 203 socket_bind_insert(socket_ports_ref global_sockets, socket_core_ref socket, 204 int port) 205 { 163 206 ERROR_DECLARE; 164 207 … … 167 210 // create a wrapper 168 211 socket_port = malloc(sizeof(*socket_port)); 169 if (! socket_port){212 if (!socket_port) 170 213 return ENOMEM; 171 } 214 172 215 socket_port->count = 0; 173 if(ERROR_OCCURRED(socket_port_map_initialize(&socket_port->map)) 174 || ERROR_OCCURRED(socket_port_add_core(socket_port, socket, SOCKET_MAP_KEY_LISTENING, 0))){ 216 if (ERROR_OCCURRED(socket_port_map_initialize(&socket_port->map)) || 217 ERROR_OCCURRED(socket_port_add_core(socket_port, socket, 218 SOCKET_MAP_KEY_LISTENING, 0))) { 175 219 socket_port_map_destroy(&socket_port->map); 176 220 free(socket_port); 177 221 return ERROR_CODE; 178 222 } 223 179 224 // register the incomming port 180 225 ERROR_CODE = socket_ports_add(global_sockets, port, socket_port); 181 if (ERROR_CODE < 0){226 if (ERROR_CODE < 0) { 182 227 socket_port_map_destroy(&socket_port->map); 183 228 free(socket_port); 184 229 return ERROR_CODE; 185 230 } 231 186 232 socket->port = port; 187 233 return EOK; 188 234 } 189 235 190 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){ 236 /** Binds the socket to the port. 237 * 238 * The address port is used if set, a free port is used if not. 239 * 240 * @param[in] local_sockets The local sockets to be searched. 241 * @param[in,out] global_sockets The global sockets to be updated. 242 * @param[in] socket_id The new socket identifier. 243 * @param[in] addr The address to be bound to. 244 * @param[in] addrlen The address length. 245 * @param[in] free_ports_start The minimum free port. 246 * @param[in] free_ports_end The maximum free port. 247 * @param[in] last_used_port The last used free port. 248 * @returns EOK on success. 249 * @returns ENOTSOCK if the socket was not found. 250 * @returns EAFNOSUPPORT if the address family is not supported. 251 * @returns EADDRINUSE if the port is already in use. 252 * @returns Other error codes as defined for the 253 * socket_bind_free_port() function. 254 * @returns Other error codes as defined for the 255 * socket_bind_insert() function. 256 */ 257 int 258 socket_bind(socket_cores_ref local_sockets, socket_ports_ref global_sockets, 259 int socket_id, void *addr, size_t addrlen, int free_ports_start, 260 int free_ports_end, int last_used_port) 261 { 191 262 socket_core_ref socket; 192 263 socket_port_ref socket_port; 193 struct sockaddr * 194 struct sockaddr_in * 195 196 if (addrlen < sizeof(struct sockaddr)){264 struct sockaddr *address; 265 struct sockaddr_in *address_in; 266 267 if (addrlen < sizeof(struct sockaddr)) 197 268 return EINVAL; 198 } 269 199 270 address = (struct sockaddr *) addr; 200 switch(address->sa_family){ 201 case AF_INET: 202 if(addrlen != sizeof(struct sockaddr_in)){ 203 return EINVAL; 204 } 205 address_in = (struct sockaddr_in *) addr; 206 // find the socket 207 socket = socket_cores_find(local_sockets, socket_id); 208 if(! socket){ 209 return ENOTSOCK; 210 } 211 // bind a free port? 212 if(address_in->sin_port <= 0){ 213 return socket_bind_free_port(global_sockets, socket, free_ports_start, free_ports_end, last_used_port); 214 } 215 // try to find the port 216 socket_port = socket_ports_find(global_sockets, ntohs(address_in->sin_port)); 217 if(socket_port){ 218 // already used 219 return EADDRINUSE; 220 } 221 // if bound 222 if(socket->port){ 223 // release the port 224 socket_port_release(global_sockets, socket); 225 } 226 socket->port = -1; 227 return socket_bind_insert(global_sockets, socket, ntohs(address_in->sin_port)); 228 break; 271 switch (address->sa_family) { 272 case AF_INET: 273 if (addrlen != sizeof(struct sockaddr_in)) 274 return EINVAL; 275 276 address_in = (struct sockaddr_in *) addr; 277 // find the socket 278 socket = socket_cores_find(local_sockets, socket_id); 279 if (!socket) 280 return ENOTSOCK; 281 282 // bind a free port? 283 if (address_in->sin_port <= 0) 284 return socket_bind_free_port(global_sockets, socket, 285 free_ports_start, free_ports_end, last_used_port); 286 287 // try to find the port 288 socket_port = socket_ports_find(global_sockets, 289 ntohs(address_in->sin_port)); 290 if (socket_port) { 291 // already used 292 return EADDRINUSE; 293 } 294 295 // if bound 296 if (socket->port) { 297 // release the port 298 socket_port_release(global_sockets, socket); 299 } 300 socket->port = -1; 301 302 return socket_bind_insert(global_sockets, socket, 303 ntohs(address_in->sin_port)); 304 305 case AF_INET6: 229 306 // TODO IPv6 230 } 307 break; 308 } 309 231 310 return EAFNOSUPPORT; 232 311 } 233 312 234 int socket_bind_free_port(socket_ports_ref global_sockets, socket_core_ref socket, int free_ports_start, int free_ports_end, int last_used_port){ 313 /** Binds the socket to a free port. 314 * 315 * The first free port is used. 316 * 317 * @param[in,out] global_sockets The global sockets to be updated. 318 * @param[in,out] socket The socket to be bound. 319 * @param[in] free_ports_start The minimum free port. 320 * @param[in] free_ports_end The maximum free port. 321 * @param[in] last_used_port The last used free port. 322 * @returns EOK on success. 323 * @returns ENOTCONN if no free port was found. 324 * @returns Other error codes as defined for the 325 * socket_bind_insert() function. 326 */ 327 int 328 socket_bind_free_port(socket_ports_ref global_sockets, socket_core_ref socket, 329 int free_ports_start, int free_ports_end, int last_used_port) 330 { 235 331 int index; 236 332 237 333 // from the last used one 238 334 index = last_used_port; 239 do{ 240 ++ index; 335 336 do { 337 ++index; 338 241 339 // til the range end 242 if (index >= free_ports_end){340 if (index >= free_ports_end) { 243 341 // start from the range beginning 244 342 index = free_ports_start - 1; 245 do {246 ++ 343 do { 344 ++index; 247 345 // til the last used one 248 if (index >= last_used_port){346 if (index >= last_used_port) { 249 347 // none found 250 348 return ENOTCONN; 251 349 } 252 }while(socket_ports_find(global_sockets, index) != NULL); 350 } while (socket_ports_find(global_sockets, index)); 351 253 352 // found, break immediately 254 353 break; 255 354 } 256 }while(socket_ports_find(global_sockets, index) != NULL); 355 356 } while (socket_ports_find(global_sockets, index)); 357 257 358 return socket_bind_insert(global_sockets, socket, index); 258 359 } 259 360 260 361 /** Tries to find a new free socket identifier. 261 * @param[in] local_sockets The local sockets to be searched. 262 * @param[in] positive A value indicating whether a positive identifier is requested. A negative identifier is requested if set to false. 263 * @returns The new socket identifier. 264 * @returns ELIMIT if there is no socket identifier available. 265 */ 266 static int socket_generate_new_id(socket_cores_ref local_sockets, int positive){ 362 * 363 * @param[in] local_sockets The local sockets to be searched. 364 * @param[in] positive A value indicating whether a positive identifier is 365 * requested. A negative identifier is requested if set to 366 * false. 367 * @returns The new socket identifier. 368 * @returns ELIMIT if there is no socket identifier available. 369 */ 370 static int socket_generate_new_id(socket_cores_ref local_sockets, int positive) 371 { 267 372 int socket_id; 268 373 int count; … … 270 375 count = 0; 271 376 // socket_id = socket_globals.last_id; 272 do {273 if (count < SOCKET_ID_TRIES){377 do { 378 if (count < SOCKET_ID_TRIES) { 274 379 socket_id = rand() % INT_MAX; 275 ++ 276 } else if(count == SOCKET_ID_TRIES){380 ++count; 381 } else if (count == SOCKET_ID_TRIES) { 277 382 socket_id = 1; 278 ++ 383 ++count; 279 384 // only this branch for last_id 280 } else{281 if (socket_id < INT_MAX){385 } else { 386 if (socket_id < INT_MAX) { 282 387 ++ socket_id; 283 /* } else if(socket_globals.last_id){388 /* } else if(socket_globals.last_id) { 284 389 * socket_globals.last_id = 0; 285 390 * socket_id = 1; 286 */ } else{391 */ } else { 287 392 return ELIMIT; 288 393 } 289 394 } 290 }while(socket_cores_find(local_sockets, ((positive ? 1 : -1) * socket_id))); 395 } while (socket_cores_find(local_sockets, 396 ((positive ? 1 : -1) * socket_id))); 397 291 398 // last_id = socket_id 292 399 return socket_id; 293 400 } 294 401 295 int socket_create(socket_cores_ref local_sockets, int app_phone, void * specific_data, int * socket_id){ 402 /** Creates a new socket. 403 * 404 * @param[in,out] local_sockets The local sockets to be updated. 405 * @param[in] app_phone The application phone. 406 * @param[in] specific_data The socket specific data. 407 * @param[in,out] socket_id The new socket identifier. A new identifier is 408 * chosen if set to zero or negative. A negative identifier 409 * is chosen if set to negative. 410 * @returns EOK on success. 411 * @returns EINVAL if the socket_id parameter is NULL. 412 * @returns ENOMEM if there is not enough memory left. 413 */ 414 int 415 socket_create(socket_cores_ref local_sockets, int app_phone, 416 void *specific_data, int *socket_id) 417 { 296 418 ERROR_DECLARE; 297 419 … … 300 422 int positive; 301 423 302 if (! socket_id){424 if (!socket_id) 303 425 return EINVAL; 304 }426 305 427 // store the socket 306 if (*socket_id <= 0){428 if (*socket_id <= 0) { 307 429 positive = (*socket_id == 0); 308 430 *socket_id = socket_generate_new_id(local_sockets, positive); 309 if(*socket_id <= 0){ 310 return * socket_id; 311 } 312 if(! positive){ 431 if (*socket_id <= 0) 432 return *socket_id; 433 if (!positive) 313 434 *socket_id *= -1; 314 } 315 }else if(socket_cores_find(local_sockets, * socket_id)){ 435 } else if(socket_cores_find(local_sockets, *socket_id)) { 316 436 return EEXIST; 317 437 } 438 318 439 socket = (socket_core_ref) malloc(sizeof(*socket)); 319 if (! socket){440 if (!socket) 320 441 return ENOMEM; 321 }442 322 443 // initialize 323 444 socket->phone = app_phone; … … 326 447 socket->key_length = 0; 327 448 socket->specific_data = specific_data; 328 if(ERROR_OCCURRED(dyn_fifo_initialize(&socket->received, SOCKET_INITIAL_RECEIVED_SIZE))){ 449 if (ERROR_OCCURRED(dyn_fifo_initialize(&socket->received, 450 SOCKET_INITIAL_RECEIVED_SIZE))) { 329 451 free(socket); 330 452 return ERROR_CODE; 331 453 } 332 if(ERROR_OCCURRED(dyn_fifo_initialize(&socket->accepted, SOCKET_INITIAL_ACCEPTED_SIZE))){ 454 if (ERROR_OCCURRED(dyn_fifo_initialize(&socket->accepted, 455 SOCKET_INITIAL_ACCEPTED_SIZE))) { 333 456 dyn_fifo_destroy(&socket->received); 334 457 free(socket); 335 458 return ERROR_CODE; 336 459 } 337 socket->socket_id = * 460 socket->socket_id = *socket_id; 338 461 res = socket_cores_add(local_sockets, socket->socket_id, socket); 339 if (res < 0){462 if (res < 0) { 340 463 dyn_fifo_destroy(&socket->received); 341 464 dyn_fifo_destroy(&socket->accepted); … … 343 466 return res; 344 467 } 468 345 469 return EOK; 346 470 } 347 471 348 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)){ 472 /** Destroys the socket. 473 * 474 * If the socket is bound, the port is released. 475 * Releases all buffered packets, calls the release function and removes the 476 * socket from the local sockets. 477 * 478 * @param[in] packet_phone The packet server phone to release buffered packets. 479 * @param[in] socket_id The socket identifier. 480 * @param[in,out] local_sockets The local sockets to be updated. 481 * @param[in,out] global_sockets The global sockets to be updated. 482 * @param[in] socket_release The client release callback function. 483 * @returns EOK on success. 484 * @returns ENOTSOCK if the socket is not found. 485 */ 486 int 487 socket_destroy(int packet_phone, int socket_id, socket_cores_ref local_sockets, 488 socket_ports_ref global_sockets, 489 void (*socket_release)(socket_core_ref socket)) 490 { 349 491 socket_core_ref socket; 350 492 int accepted_id; … … 352 494 // find the socket 353 495 socket = socket_cores_find(local_sockets, socket_id); 354 if (! socket){496 if (!socket) 355 497 return ENOTSOCK; 356 }498 357 499 // destroy all accepted sockets 358 while((accepted_id = dyn_fifo_pop(&socket->accepted)) >= 0){ 359 socket_destroy(packet_phone, accepted_id, local_sockets, global_sockets, socket_release); 360 } 361 socket_destroy_core(packet_phone, socket, local_sockets, global_sockets, socket_release); 500 while ((accepted_id = dyn_fifo_pop(&socket->accepted)) >= 0) 501 socket_destroy(packet_phone, accepted_id, local_sockets, 502 global_sockets, socket_release); 503 504 socket_destroy_core(packet_phone, socket, local_sockets, global_sockets, 505 socket_release); 506 362 507 return EOK; 363 508 } 364 509 365 int socket_reply_packets(packet_t packet, size_t * length){ 510 /** Replies the packet or the packet queue data to the application via the 511 * socket. 512 * 513 * Uses the current message processing fibril. 514 * 515 * @param[in] packet The packet to be transfered. 516 * @param[out] length The total data length. 517 * @returns EOK on success. 518 * @returns EBADMEM if the length parameter is NULL. 519 * @returns ENOMEM if there is not enough memory left. 520 * @returns Other error codes as defined for the data_reply() 521 * function. 522 */ 523 int socket_reply_packets(packet_t packet, size_t *length) 524 { 366 525 ERROR_DECLARE; 367 526 368 527 packet_t next_packet; 369 528 size_t fragments; 370 size_t * 529 size_t *lengths; 371 530 size_t index; 372 531 373 if (! length){532 if (!length) 374 533 return EBADMEM; 375 } 534 376 535 next_packet = pq_next(packet); 377 if (! next_packet){536 if (!next_packet) { 378 537 // write all if only one fragment 379 ERROR_PROPAGATE(data_reply(packet_get_data(packet), packet_get_data_length(packet))); 538 ERROR_PROPAGATE(data_reply(packet_get_data(packet), 539 packet_get_data_length(packet))); 380 540 // store the total length 381 541 *length = packet_get_data_length(packet); 382 } else{542 } else { 383 543 // count the packet fragments 384 544 fragments = 1; 385 545 next_packet = pq_next(packet); 386 while ((next_packet = pq_next(next_packet))){387 ++ 388 }546 while ((next_packet = pq_next(next_packet))) 547 ++fragments; 548 389 549 // compute and store the fragment lengths 390 lengths = (size_t *) malloc(sizeof(size_t) * fragments + sizeof(size_t)); 391 if(! lengths){ 550 lengths = (size_t *) malloc(sizeof(size_t) * fragments + 551 sizeof(size_t)); 552 if (!lengths) 392 553 return ENOMEM; 393 }554 394 555 lengths[0] = packet_get_data_length(packet); 395 556 lengths[fragments] = lengths[0]; 396 557 next_packet = pq_next(packet); 397 for(index = 1; index < fragments; ++ index){ 558 559 for (index = 1; index < fragments; ++index) { 398 560 lengths[index] = packet_get_data_length(next_packet); 399 561 lengths[fragments] += lengths[index]; 400 562 next_packet = pq_next(packet); 401 }while(next_packet); 563 } 564 402 565 // write the fragment lengths 403 ERROR_PROPAGATE(data_reply(lengths, sizeof(int) * (fragments + 1))); 566 ERROR_PROPAGATE(data_reply(lengths, 567 sizeof(int) * (fragments + 1))); 404 568 next_packet = packet; 569 405 570 // write the fragments 406 for(index = 0; index < fragments; ++ index){ 407 ERROR_PROPAGATE(data_reply(packet_get_data(next_packet), lengths[index])); 571 for (index = 0; index < fragments; ++index) { 572 ERROR_PROPAGATE(data_reply(packet_get_data(next_packet), 573 lengths[index])); 408 574 next_packet = pq_next(next_packet); 409 }while(next_packet); 575 } 576 410 577 // store the total length 411 578 *length = lengths[fragments]; 412 579 free(lengths); 413 580 } 581 414 582 return EOK; 415 583 } 416 584 417 socket_core_ref socket_port_find(socket_ports_ref global_sockets, int port, const char * key, size_t key_length){ 585 /** Finds the bound port socket. 586 * 587 * @param[in] global_sockets The global sockets to be searched. 588 * @param[in] port The port number. 589 * @param[in] key The socket key identifier. 590 * @param[in] key_length The socket key length. 591 * @returns The found socket. 592 * @returns NULL if no socket was found. 593 */ 594 socket_core_ref 595 socket_port_find(socket_ports_ref global_sockets, int port, const char *key, 596 size_t key_length) 597 { 418 598 socket_port_ref socket_port; 419 socket_core_ref * 599 socket_core_ref *socket_ref; 420 600 421 601 socket_port = socket_ports_find(global_sockets, port); 422 if(socket_port && (socket_port->count > 0)){ 423 socket_ref = socket_port_map_find(&socket_port->map, key, key_length); 424 if(socket_ref){ 425 return * socket_ref; 426 } 427 } 602 if (socket_port && (socket_port->count > 0)) { 603 socket_ref = socket_port_map_find(&socket_port->map, key, 604 key_length); 605 if (socket_ref) 606 return *socket_ref; 607 } 608 428 609 return NULL; 429 610 } 430 611 431 void socket_port_release(socket_ports_ref global_sockets, socket_core_ref socket){ 612 /** Releases the socket port. 613 * 614 * If the socket is bound the port entry is released. 615 * If there are no more port entries the port is release. 616 * 617 * @param[in] global_sockets The global sockets to be updated. 618 * @param[in] socket The socket to be unbound. 619 */ 620 void 621 socket_port_release(socket_ports_ref global_sockets, socket_core_ref socket) 622 { 432 623 socket_port_ref socket_port; 433 socket_core_ref * socket_ref; 434 435 if(socket->port){ 436 // find ports 437 socket_port = socket_ports_find(global_sockets, socket->port); 438 if(socket_port){ 439 // find the socket 440 socket_ref = socket_port_map_find(&socket_port->map, socket->key, socket->key_length); 441 if(socket_ref){ 442 -- socket_port->count; 443 // release if empty 444 if(socket_port->count <= 0){ 445 // destroy the map 446 socket_port_map_destroy(&socket_port->map); 447 // release the port 448 socket_ports_exclude(global_sockets, socket->port); 449 }else{ 450 // remove 451 socket_port_map_exclude(&socket_port->map, socket->key, socket->key_length); 452 } 624 socket_core_ref *socket_ref; 625 626 if (!socket->port) 627 return; 628 629 // find ports 630 socket_port = socket_ports_find(global_sockets, socket->port); 631 if (socket_port) { 632 // find the socket 633 socket_ref = socket_port_map_find(&socket_port->map, 634 socket->key, socket->key_length); 635 636 if (socket_ref) { 637 --socket_port->count; 638 639 // release if empty 640 if (socket_port->count <= 0) { 641 // destroy the map 642 socket_port_map_destroy(&socket_port->map); 643 // release the port 644 socket_ports_exclude(global_sockets, 645 socket->port); 646 } else { 647 // remove 648 socket_port_map_exclude(&socket_port->map, 649 socket->key, socket->key_length); 453 650 } 454 651 } 455 socket->port = 0; 456 socket->key = NULL; 457 socket->key_length = 0; 458 } 459 } 460 461 int socket_port_add(socket_ports_ref global_sockets, int port, socket_core_ref socket, const char * key, size_t key_length){ 652 } 653 654 socket->port = 0; 655 socket->key = NULL; 656 socket->key_length = 0; 657 } 658 659 /** Adds the socket to an already bound port. 660 * 661 * @param[in] global_sockets The global sockets to be updated. 662 * @param[in] port The port number to be bound to. 663 * @param[in] socket The socket to be added. 664 * @param[in] key The socket key identifier. 665 * @param[in] key_length The socket key length. 666 * @returns EOK on success. 667 * @returns ENOENT if the port is not already used. 668 * @returns Other error codes as defined for the 669 * socket_port_add_core() function. 670 */ 671 int 672 socket_port_add(socket_ports_ref global_sockets, int port, 673 socket_core_ref socket, const char *key, size_t key_length) 674 { 462 675 ERROR_DECLARE; 463 676 … … 466 679 // find ports 467 680 socket_port = socket_ports_find(global_sockets, port); 468 if (! socket_port){681 if (!socket_port) 469 682 return ENOENT; 470 }683 471 684 // add the socket 472 ERROR_PROPAGATE(socket_port_add_core(socket_port, socket, key, key_length)); 685 ERROR_PROPAGATE(socket_port_add_core(socket_port, socket, key, 686 key_length)); 687 473 688 socket->port = port; 474 689 return EOK; -
uspace/lib/net/include/socket_core.h
r25d2de69 r137f8aa 27 27 */ 28 28 29 /** @addtogroup socket29 /** @addtogroup libnet 30 30 * @{ 31 31 */ 32 32 33 33 /** @file 34 * 34 * Socket common core. 35 35 */ 36 36 37 #ifndef __NET_SOCKET_CORE_H__38 #define __NET_SOCKET_CORE_H__37 #ifndef LIBNET_SOCKET_CORE_H_ 38 #define LIBNET_SOCKET_CORE_H_ 39 39 40 40 #include <sys/types.h> 41 42 #include <net/in.h>43 #include <net/device.h>44 41 #include <adt/generic_char_map.h> 45 42 #include <adt/dynamic_fifo.h> 46 43 #include <adt/int_map.h> 44 #include <net/in.h> 45 #include <net/device.h> 47 46 #include <net/packet.h> 48 47 49 /** Initial size of the received packet queue. 50 */ 48 /** Initial size of the received packet queue. */ 51 49 #define SOCKET_INITIAL_RECEIVED_SIZE 4 52 50 53 /** Maximum size of the received packet queue. 54 */ 55 #define SOCKET_MAX_RECEIVED_SIZE 0 51 /** Maximum size of the received packet queue. */ 52 #define SOCKET_MAX_RECEIVED_SIZE 0 56 53 57 /** Initial size of the sockets for acceptance queue. 58 */ 54 /** Initial size of the sockets for acceptance queue. */ 59 55 #define SOCKET_INITIAL_ACCEPTED_SIZE 1 60 56 61 /** Maximum size of the sockets for acceptance queue. 62 */ 63 #define SOCKET_MAX_ACCEPTEDED_SIZE 0 57 /** Maximum size of the sockets for acceptance queue. */ 58 #define SOCKET_MAX_ACCEPTEDED_SIZE 0 64 59 65 /** Listening sockets' port map key. 66 */ 60 /** Listening sockets' port map key. */ 67 61 #define SOCKET_MAP_KEY_LISTENING "L" 68 62 69 63 /** Type definition of the socket core. 70 * 64 * @see socket_core 71 65 */ 72 typedef struct socket_core 66 typedef struct socket_core socket_core_t; 73 67 74 68 /** Type definition of the socket core pointer. 75 * 69 * @see socket_core 76 70 */ 77 typedef socket_core_t * 71 typedef socket_core_t *socket_core_ref; 78 72 79 73 /** Type definition of the socket port. 80 * 74 * @see socket_port 81 75 */ 82 typedef struct socket_port 76 typedef struct socket_port socket_port_t; 83 77 84 78 /** Type definition of the socket port pointer. 85 * 79 * @see socket_port 86 80 */ 87 typedef socket_port_t * 81 typedef socket_port_t *socket_port_ref; 88 82 89 /** Socket core. 90 */ 91 struct socket_core{ 92 /** Socket identifier. 93 */ 83 /** Socket core. */ 84 struct socket_core { 85 /** Socket identifier. */ 94 86 int socket_id; 95 /** Client application phone. 96 */ 87 /** Client application phone. */ 97 88 int phone; 98 /** Bound port. 99 */ 89 /** Bound port. */ 100 90 int port; 101 /** Received packets queue. 102 */ 91 /** Received packets queue. */ 103 92 dyn_fifo_t received; 104 /** Sockets for acceptance queue. 105 */ 93 /** Sockets for acceptance queue. */ 106 94 dyn_fifo_t accepted; 107 /** Protocol specific data. 108 */ 109 void * specific_data; 110 /** Socket ports map key. 111 */ 112 const char * key; 113 /** Length of the Socket ports map key. 114 */ 95 /** Protocol specific data. */ 96 void *specific_data; 97 /** Socket ports map key. */ 98 const char *key; 99 /** Length of the Socket ports map key. */ 115 100 size_t key_length; 116 101 }; 117 102 118 103 /** Sockets map. 119 * 104 * The key is the socket identifier. 120 105 */ 121 106 INT_MAP_DECLARE(socket_cores, socket_core_t); 122 107 123 108 /** Bount port sockets map. 124 * The listening socket has the SOCKET_MAP_KEY_LISTENING key identifier whereas the other use the remote addresses. 109 * 110 * The listening socket has the SOCKET_MAP_KEY_LISTENING key identifier whereas 111 * the other use the remote addresses. 125 112 */ 126 113 GENERIC_CHAR_MAP_DECLARE(socket_port_map, socket_core_ref); 127 114 128 115 /** Ports map. 129 * 116 * The key is the port number. 130 117 */ 131 118 INT_MAP_DECLARE(socket_ports, socket_port_t); 132 119 133 /** Destroys local sockets. 134 * Releases all buffered packets and calls the release function for each of the sockets. 135 * @param[in] packet_phone The packet server phone to release buffered packets. 136 * @param[in] local_sockets The local sockets to be destroyed. 137 * @param[in,out] global_sockets The global sockets to be updated. 138 * @param[in] socket_release The client release callback function. 139 */ 140 extern void socket_cores_release(int packet_phone, socket_cores_ref local_sockets, socket_ports_ref global_sockets, void (*socket_release)(socket_core_ref socket)); 141 142 /** Binds the socket to the port. 143 * The address port is used if set, a free port is used if not. 144 * @param[in] local_sockets The local sockets to be searched. 145 * @param[in,out] global_sockets The global sockets to be updated. 146 * @param[in] socket_id The new socket identifier. 147 * @param[in] addr The address to be bound to. 148 * @param[in] addrlen The address length. 149 * @param[in] free_ports_start The minimum free port. 150 * @param[in] free_ports_end The maximum free port. 151 * @param[in] last_used_port The last used free port. 152 * @returns EOK on success. 153 * @returns ENOTSOCK if the socket was not found. 154 * @returns EAFNOSUPPORT if the address family is not supported. 155 * @returns EADDRINUSE if the port is already in use. 156 * @returns Other error codes as defined for the socket_bind_free_port() function. 157 * @returns Other error codes as defined for the socket_bind_insert() function. 158 */ 159 extern 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); 160 161 /** Binds the socket to a free port. 162 * The first free port is used. 163 * @param[in,out] global_sockets The global sockets to be updated. 164 * @param[in,out] socket The socket to be bound. 165 * @param[in] free_ports_start The minimum free port. 166 * @param[in] free_ports_end The maximum free port. 167 * @param[in] last_used_port The last used free port. 168 * @returns EOK on success. 169 * @returns ENOTCONN if no free port was found. 170 * @returns Other error codes as defined for the socket_bind_insert() function. 171 */ 172 extern int socket_bind_free_port(socket_ports_ref global_sockets, socket_core_ref socket, int free_ports_start, int free_ports_end, int last_used_port); 173 174 /** Creates a new socket. 175 * @param[in,out] local_sockets The local sockets to be updated. 176 * @param[in] app_phone The application phone. 177 * @param[in] specific_data The socket specific data. 178 * @param[in,out] socket_id The new socket identifier. A new identifier is chosen if set to zero (0) or negative. A negative identifier is chosen if set to negative. 179 * @returns EOK on success. 180 * @returns EINVAL if the socket_id parameter is NULL. 181 * @returns ENOMEM if there is not enough memory left. 182 */ 183 extern int socket_create(socket_cores_ref local_sockets, int app_phone, void * specific_data, int * socket_id); 184 185 /** Destroys the socket. 186 * If the socket is bound, the port is released. 187 * Releases all buffered packets, calls the release function and removes the socket from the local sockets. 188 * @param[in] packet_phone The packet server phone to release buffered packets. 189 * @param[in] socket_id The socket identifier. 190 * @param[in,out] local_sockets The local sockets to be updated. 191 * @param[in,out] global_sockets The global sockets to be updated. 192 * @param[in] socket_release The client release callback function. 193 * @returns EOK on success. 194 * @returns ENOTSOCK if the socket is not found. 195 */ 196 extern 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)); 197 198 /** Replies the packet or the packet queue data to the application via the socket. 199 * Uses the current message processing fibril. 200 * @param[in] packet The packet to be transfered. 201 * @param[out] length The total data length. 202 * @returns EOK on success. 203 * @returns EBADMEM if the length parameter is NULL. 204 * @returns ENOMEM if there is not enough memory left. 205 * @returns Other error codes as defined for the data_reply() function. 206 */ 207 extern int socket_reply_packets(packet_t packet, size_t * length); 208 209 /** Finds the bound port socket. 210 * @param[in] global_sockets The global sockets to be searched. 211 * @param[in] port The port number. 212 * @param[in] key The socket key identifier. 213 * @param[in] key_length The socket key length. 214 * @returns The found socket. 215 * @returns NULL if no socket was found. 216 */ 217 extern socket_core_ref socket_port_find(socket_ports_ref global_sockets, int port, const char * key, size_t key_length); 218 219 /** Releases the socket port. 220 * If the socket is bound the port entry is released. 221 * If there are no more port entries the port is release. 222 * @param[in] global_sockets The global sockets to be updated. 223 * @param[in] socket The socket to be unbound. 224 */ 225 extern void socket_port_release(socket_ports_ref global_sockets, socket_core_ref socket); 226 227 /** Adds the socket to an already bound port. 228 * @param[in] global_sockets The global sockets to be updated. 229 * @param[in] port The port number to be bound to. 230 * @param[in] socket The socket to be added. 231 * @param[in] key The socket key identifier. 232 * @param[in] key_length The socket key length. 233 * @returns EOK on success. 234 * @returns ENOENT if the port is not already used. 235 * @returns Other error codes as defined for the socket_port_add_core() function. 236 */ 237 extern int socket_port_add(socket_ports_ref global_sockets, int port, socket_core_ref socket, const char * key, size_t key_length); 120 extern void socket_cores_release(int, socket_cores_ref, socket_ports_ref, 121 void (*)(socket_core_ref)); 122 extern int socket_bind(socket_cores_ref, socket_ports_ref, int, void *, size_t, 123 int, int, int); 124 extern int socket_bind_free_port(socket_ports_ref, socket_core_ref, int, int, 125 int); 126 extern int socket_create(socket_cores_ref, int, void *, int *); 127 extern int socket_destroy(int, int, socket_cores_ref, socket_ports_ref, 128 void (*)(socket_core_ref)); 129 extern int socket_reply_packets(packet_t, size_t *); 130 extern socket_core_ref socket_port_find(socket_ports_ref, int, const char *, 131 size_t); 132 extern void socket_port_release(socket_ports_ref, socket_core_ref); 133 extern int socket_port_add(socket_ports_ref, int, socket_core_ref, 134 const char *, size_t); 238 135 239 136 #endif
Note:
See TracChangeset
for help on using the changeset viewer.