Rev 4708 | Rev 4729 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
| Rev 4708 | Rev 4726 | ||
|---|---|---|---|
| Line 79... | Line 79... | ||
| 79 | * @see socket |
79 | * @see socket |
| 80 | */ |
80 | */ |
| 81 | typedef socket_t * socket_ref; |
81 | typedef socket_t * socket_ref; |
| 82 | 82 | ||
| 83 | /** Socket specific data. |
83 | /** Socket specific data. |
| - | 84 | * Each socket lock locks only its structure part and any number of them may be locked simultaneously. |
|
| 84 | */ |
85 | */ |
| 85 | struct socket{ |
86 | struct socket{ |
| 86 | /** Socket identifier. |
87 | /** Socket identifier. |
| 87 | */ |
88 | */ |
| 88 | int socket_id; |
89 | int socket_id; |
| Line 95... | Line 96... | ||
| 95 | /** Underlying protocol header size. |
96 | /** Underlying protocol header size. |
| 96 | * Sending and receiving optimalization. |
97 | * Sending and receiving optimalization. |
| 97 | */ |
98 | */ |
| 98 | size_t header_size; |
99 | size_t header_size; |
| 99 | /** Packet data fragment size. |
100 | /** Packet data fragment size. |
| 100 | * Sending and receiving optimalization. |
101 | * Sending optimalization. |
| 101 | */ |
102 | */ |
| 102 | size_t data_fragment_size; |
103 | size_t data_fragment_size; |
| - | 104 | /** Sending safety lock. |
|
| - | 105 | * Locks the header_size and data_fragment_size attributes. |
|
| - | 106 | */ |
|
| - | 107 | fibril_rwlock_t sending_lock; |
|
| 103 | /** Received packets queue. |
108 | /** Received packets queue. |
| 104 | */ |
109 | */ |
| 105 | dyn_fifo_t received; |
110 | dyn_fifo_t received; |
| 106 | /** Received packets safety lock. |
111 | /** Received packets safety lock. |
| - | 112 | * Used for receiving and receive notifications. |
|
| - | 113 | * Locks the received attribute. |
|
| 107 | */ |
114 | */ |
| 108 | fibril_mutex_t receive_lock; |
115 | fibril_mutex_t receive_lock; |
| 109 | /** Received packets signaling. |
116 | /** Received packets signaling. |
| - | 117 | * Signaled upon receive notification. |
|
| 110 | */ |
118 | */ |
| 111 | fibril_condvar_t receive_signal; |
119 | fibril_condvar_t receive_signal; |
| 112 | /** Waiting sockets queue. |
120 | /** Waiting sockets queue. |
| 113 | */ |
121 | */ |
| 114 | dyn_fifo_t accepted; |
122 | dyn_fifo_t accepted; |
| 115 | /** Waiting sockets safety lock. |
123 | /** Waiting sockets safety lock. |
| - | 124 | * Used for accepting and accept notifications. |
|
| - | 125 | * Locks the accepted attribute. |
|
| 116 | */ |
126 | */ |
| 117 | fibril_mutex_t accept_lock; |
127 | fibril_mutex_t accept_lock; |
| 118 | /** Waiting sockets signaling. |
128 | /** Waiting sockets signaling. |
| - | 129 | * Signaled upon accept notification. |
|
| 119 | */ |
130 | */ |
| 120 | fibril_condvar_t accept_signal; |
131 | fibril_condvar_t accept_signal; |
| - | 132 | /** The number of blocked functions called. |
|
| - | 133 | * Used while waiting for the received packets or accepted sockets. |
|
| - | 134 | */ |
|
| - | 135 | int blocked; |
|
| 121 | }; |
136 | }; |
| 122 | 137 | ||
| 123 | /** Sockets map. |
138 | /** Sockets map. |
| 124 | * Maps socket identifiers to the socket specific data. |
139 | * Maps socket identifiers to the socket specific data. |
| 125 | * @see int_map.h |
140 | * @see int_map.h |
| 126 | */ |
141 | */ |
| 127 | INT_MAP_DECLARE( sockets, socket_t ); |
142 | INT_MAP_DECLARE( sockets, socket_t ); |
| 128 | 143 | ||
| 129 | /** Socket client library global data. |
144 | /** Socket client library global data. |
| 130 | */ |
145 | */ |
| 131 | static struct{ |
146 | static struct socket_client_globals { |
| 132 | /** TCP module phone. |
147 | /** TCP module phone. |
| 133 | */ |
148 | */ |
| 134 | int tcp_phone; |
149 | int tcp_phone; |
| 135 | /** UDP module phone. |
150 | /** UDP module phone. |
| 136 | */ |
151 | */ |
| 137 | int udp_phone; |
152 | int udp_phone; |
| 138 | /** Active sockets. |
153 | /** Active sockets. |
| 139 | */ |
154 | */ |
| 140 | sockets_ref sockets; |
155 | sockets_ref sockets; |
| - | 156 | /** Safety lock. |
|
| - | 157 | * Write lock is used only for adding or removing sockets. |
|
| - | 158 | * When locked for writing, no other socket locks need to be locked. |
|
| - | 159 | * When locked for reading, any other socket locks may be locked. |
|
| - | 160 | * No socket lock may be locked if this lock is unlocked. |
|
| - | 161 | */ |
|
| - | 162 | fibril_rwlock_t lock; |
|
| 141 | } socket_globals = { -1, -1, NULL }; |
163 | } socket_globals = { |
| - | 164 | .tcp_phone = -1, |
|
| - | 165 | .udp_phone = -1, |
|
| - | 166 | .sockets = NULL, |
|
| - | 167 | .lock = { |
|
| - | 168 | .readers = 0, |
|
| - | 169 | .writers = 0, |
|
| - | 170 | .waiters = { |
|
| - | 171 | .prev = & socket_globals.lock.waiters, |
|
| - | 172 | .next = & socket_globals.lock.waiters |
|
| - | 173 | } |
|
| - | 174 | } |
|
| - | 175 | }; |
|
| 142 | 176 | ||
| 143 | INT_MAP_IMPLEMENT( sockets, socket_t ); |
177 | INT_MAP_IMPLEMENT( sockets, socket_t ); |
| 144 | 178 | ||
| 145 | /** Returns the TCP module phone. |
179 | /** Returns the TCP module phone. |
| 146 | * Connects to the TCP module if necessary. |
180 | * Connects to the TCP module if necessary. |
| Line 259... | Line 293... | ||
| 259 | dyn_fifo_initialize( & socket->accepted, SOCKET_INITIAL_ACCEPTED_SIZE ); |
293 | dyn_fifo_initialize( & socket->accepted, SOCKET_INITIAL_ACCEPTED_SIZE ); |
| 260 | fibril_mutex_initialize( & socket->receive_lock ); |
294 | fibril_mutex_initialize( & socket->receive_lock ); |
| 261 | fibril_condvar_initialize( & socket->receive_signal ); |
295 | fibril_condvar_initialize( & socket->receive_signal ); |
| 262 | fibril_mutex_initialize( & socket->accept_lock ); |
296 | fibril_mutex_initialize( & socket->accept_lock ); |
| 263 | fibril_condvar_initialize( & socket->accept_signal ); |
297 | fibril_condvar_initialize( & socket->accept_signal ); |
| - | 298 | fibril_rwlock_initialize( & socket->sending_lock ); |
|
| 264 | } |
299 | } |
| 265 | 300 | ||
| 266 | void socket_connection( ipc_callid_t iid, ipc_call_t * icall ){ |
301 | void socket_connection( ipc_callid_t iid, ipc_call_t * icall ){ |
| 267 | ERROR_DECLARE; |
302 | ERROR_DECLARE; |
| 268 | 303 | ||
| Line 273... | Line 308... | ||
| 273 | 308 | ||
| 274 | while( true ){ |
309 | while( true ){ |
| 275 | 310 | ||
| 276 | callid = async_get_call( & call ); |
311 | callid = async_get_call( & call ); |
| 277 | switch( IPC_GET_METHOD( call )){ |
312 | switch( IPC_GET_METHOD( call )){ |
| - | 313 | // TODO remember the data_fragment_size |
|
| 278 | case NET_SOCKET_RECEIVED: |
314 | case NET_SOCKET_RECEIVED: |
| - | 315 | fibril_rwlock_read_lock( & socket_globals.lock ); |
|
| 279 | // find the socket |
316 | // find the socket |
| 280 | socket = sockets_find( socket_get_sockets(), SOCKET_GET_SOCKET_ID( call )); |
317 | socket = sockets_find( socket_get_sockets(), SOCKET_GET_SOCKET_ID( call )); |
| 281 | if( ! socket ){ |
318 | if( ! socket ){ |
| 282 | ERROR_CODE = ENOTSOCK; |
319 | ERROR_CODE = ENOTSOCK; |
| 283 | break; |
- | |
| 284 | } |
320 | }else{ |
| 285 | fibril_mutex_lock( & socket->receive_lock ); |
321 | fibril_mutex_lock( & socket->receive_lock ); |
| 286 | // push the number of received packet fragments |
322 | // push the number of received packet fragments |
| 287 | if( ! ERROR_OCCURRED( dyn_fifo_push( & socket->received, SOCKET_GET_DATA_FRAGMENTS( call ), SOCKET_MAX_RECEIVED_SIZE ))){ |
323 | if( ! ERROR_OCCURRED( dyn_fifo_push( & socket->received, SOCKET_GET_DATA_FRAGMENTS( call ), SOCKET_MAX_RECEIVED_SIZE ))){ |
| 288 | // signal the received packet |
324 | // signal the received packet |
| 289 | fibril_condvar_signal( & socket->receive_signal ); |
325 | fibril_condvar_signal( & socket->receive_signal ); |
| - | 326 | } |
|
| - | 327 | fibril_mutex_unlock( & socket->receive_lock ); |
|
| 290 | } |
328 | } |
| 291 | fibril_mutex_unlock( & socket->receive_lock ); |
329 | fibril_rwlock_read_unlock( & socket_globals.lock ); |
| 292 | break; |
330 | break; |
| 293 | case NET_SOCKET_ACCEPTED: |
331 | case NET_SOCKET_ACCEPTED: |
| - | 332 | fibril_rwlock_read_lock( & socket_globals.lock ); |
|
| 294 | // find the socket |
333 | // find the socket |
| 295 | socket = sockets_find( socket_get_sockets(), SOCKET_GET_SOCKET_ID( call )); |
334 | socket = sockets_find( socket_get_sockets(), SOCKET_GET_SOCKET_ID( call )); |
| 296 | if( ! socket ){ |
335 | if( ! socket ){ |
| 297 | ERROR_CODE = ENOTSOCK; |
336 | ERROR_CODE = ENOTSOCK; |
| 298 | break; |
- | |
| 299 | } |
- | |
| 300 | // create a new scoket |
- | |
| 301 | new_socket = ( socket_ref ) malloc( sizeof( socket_t )); |
- | |
| 302 | if( ! new_socket ){ |
- | |
| 303 | ERROR_CODE = ENOMEM; |
- | |
| 304 | break; |
- | |
| 305 | } |
- | |
| 306 | socket_initialize( new_socket, SOCKET_GET_SOCKET_ID( call ), socket->phone, socket->service ); |
- | |
| 307 | ERROR_CODE = sockets_add( socket_get_sockets(), new_socket->socket_id, new_socket ); |
- | |
| 308 | if( ERROR_CODE < 0 ){ |
- | |
| 309 | free( new_socket ); |
- | |
| 310 | }else{ |
337 | }else{ |
| 311 | // push the new socket identifier |
338 | // create a new scoket |
| 312 | fibril_mutex_lock( & socket->accept_lock ); |
- | |
| 313 | if( ERROR_OCCURRED( dyn_fifo_push( & socket->accepted, new_socket->socket_id, SOCKET_MAX_ACCEPTED_SIZE ))){ |
- | |
| 314 | sockets_exclude( socket_get_sockets(), new_socket->socket_id ); |
339 | new_socket = ( socket_ref ) malloc( sizeof( socket_t )); |
| 315 | free( new_socket ); |
340 | if( ! new_socket ){ |
| - | 341 | ERROR_CODE = ENOMEM; |
|
| 316 | }else{ |
342 | }else{ |
| - | 343 | socket_initialize( new_socket, SOCKET_GET_SOCKET_ID( call ), socket->phone, socket->service ); |
|
| - | 344 | ERROR_CODE = sockets_add( socket_get_sockets(), new_socket->socket_id, new_socket ); |
|
| - | 345 | if( ERROR_CODE < 0 ){ |
|
| - | 346 | free( new_socket ); |
|
| - | 347 | }else{ |
|
| - | 348 | // push the new socket identifier |
|
| - | 349 | fibril_mutex_lock( & socket->accept_lock ); |
|
| - | 350 | if( ERROR_OCCURRED( dyn_fifo_push( & socket->accepted, new_socket->socket_id, SOCKET_MAX_ACCEPTED_SIZE ))){ |
|
| - | 351 | sockets_exclude( socket_get_sockets(), new_socket->socket_id ); |
|
| - | 352 | free( new_socket ); |
|
| - | 353 | }else{ |
|
| 317 | // signal the accepted socket |
354 | // signal the accepted socket |
| 318 | fibril_condvar_signal( & socket->accept_signal ); |
355 | fibril_condvar_signal( & socket->accept_signal ); |
| - | 356 | } |
|
| - | 357 | fibril_mutex_unlock( & socket->accept_lock ); |
|
| - | 358 | ERROR_CODE = EOK; |
|
| - | 359 | } |
|
| 319 | } |
360 | } |
| 320 | fibril_mutex_unlock( & socket->accept_lock ); |
- | |
| 321 | ERROR_CODE = EOK; |
- | |
| 322 | } |
361 | } |
| - | 362 | fibril_rwlock_read_unlock( & socket_globals.lock ); |
|
| 323 | break; |
363 | break; |
| - | 364 | // TODO obsolete? |
|
| 324 | case NET_SOCKET_DATA_FRAGMENT_SIZE: |
365 | case NET_SOCKET_DATA_FRAGMENT_SIZE: |
| - | 366 | fibril_rwlock_read_lock( & socket_globals.lock ); |
|
| 325 | // find the socket |
367 | // find the socket |
| 326 | socket = sockets_find( socket_get_sockets(), SOCKET_GET_SOCKET_ID( call )); |
368 | socket = sockets_find( socket_get_sockets(), SOCKET_GET_SOCKET_ID( call )); |
| 327 | if( ! socket ){ |
369 | if( ! socket ){ |
| 328 | ERROR_CODE = ENOTSOCK; |
370 | ERROR_CODE = ENOTSOCK; |
| 329 | break; |
371 | }else{ |
| - | 372 | fibril_rwlock_write_lock( & socket->sending_lock ); |
|
| - | 373 | // set the data fragment size |
|
| - | 374 | socket->data_fragment_size = SOCKET_GET_DATA_FRAGMENT_SIZE( call ); |
|
| - | 375 | fibril_rwlock_write_unlock( & socket->sending_lock ); |
|
| - | 376 | ERROR_CODE = EOK; |
|
| 330 | } |
377 | } |
| 331 | // set the data fragment size |
- | |
| 332 | socket->data_fragment_size = SOCKET_GET_DATA_FRAGMENT_SIZE( call ); |
378 | fibril_rwlock_read_unlock( & socket_globals.lock ); |
| 333 | ERROR_CODE = EOK; |
- | |
| 334 | break; |
379 | break; |
| 335 | default: |
380 | default: |
| 336 | ERROR_CODE = ENOTSUP; |
381 | ERROR_CODE = ENOTSUP; |
| 337 | } |
382 | } |
| 338 | ipc_answer_0( callid, ( ipcarg_t ) ERROR_CODE ); |
383 | ipc_answer_0( callid, ( ipcarg_t ) ERROR_CODE ); |
| Line 393... | Line 438... | ||
| 393 | dyn_fifo_destroy( & socket->received ); |
438 | dyn_fifo_destroy( & socket->received ); |
| 394 | free( socket ); |
439 | free( socket ); |
| 395 | return ERROR_CODE; |
440 | return ERROR_CODE; |
| 396 | } |
441 | } |
| 397 | // request a new socket |
442 | // request a new socket |
| 398 | if( ERROR_OCCURRED(( int ) async_req_3_3( phone, NET_SOCKET, 0, 0, service, ( ipcarg_t * ) & socket_id, ( ipcarg_t * ) & socket->header_size, ( ipcarg_t * ) & socket->data_fragment_size ))){ |
443 | if( ERROR_OCCURRED(( int ) async_req_3_3( phone, NET_SOCKET, 0, 0, service, ( ipcarg_t * ) & socket_id, ( ipcarg_t * ) & socket->data_fragment_size, ( ipcarg_t * ) & socket->header_size ))){ |
| 399 | dyn_fifo_destroy( & socket->received ); |
444 | dyn_fifo_destroy( & socket->received ); |
| 400 | dyn_fifo_destroy( & socket->accepted ); |
445 | dyn_fifo_destroy( & socket->accepted ); |
| 401 | free( socket ); |
446 | free( socket ); |
| 402 | return ERROR_CODE; |
447 | return ERROR_CODE; |
| 403 | } |
448 | } |
| 404 | // finish the new socket initialization |
449 | // finish the new socket initialization |
| 405 | socket_initialize( socket, socket_id, phone, service ); |
450 | socket_initialize( socket, socket_id, phone, service ); |
| 406 | // store the new socket |
451 | // store the new socket |
| - | 452 | fibril_rwlock_write_lock( & socket_globals.lock ); |
|
| 407 | ERROR_CODE = sockets_add( socket_get_sockets(), socket_id, socket ); |
453 | ERROR_CODE = sockets_add( socket_get_sockets(), socket_id, socket ); |
| - | 454 | fibril_rwlock_write_unlock( & socket_globals.lock ); |
|
| 408 | if( ERROR_CODE < 0 ){ |
455 | if( ERROR_CODE < 0 ){ |
| 409 | dyn_fifo_destroy( & socket->received ); |
456 | dyn_fifo_destroy( & socket->received ); |
| 410 | dyn_fifo_destroy( & socket->accepted ); |
457 | dyn_fifo_destroy( & socket->accepted ); |
| 411 | free( socket ); |
458 | free( socket ); |
| 412 | async_msg_3( phone, NET_SOCKET_CLOSE, ( ipcarg_t ) socket_id, 0, service ); |
459 | async_msg_3( phone, NET_SOCKET_CLOSE, ( ipcarg_t ) socket_id, 0, service ); |
| Line 421... | Line 468... | ||
| 421 | aid_t message_id; |
468 | aid_t message_id; |
| 422 | ipcarg_t result; |
469 | ipcarg_t result; |
| 423 | 470 | ||
| 424 | if( ! data ) return EBADMEM; |
471 | if( ! data ) return EBADMEM; |
| 425 | if( ! datalength ) return NO_DATA; |
472 | if( ! datalength ) return NO_DATA; |
| - | 473 | ||
| - | 474 | fibril_rwlock_read_lock( & socket_globals.lock ); |
|
| 426 | // find the socket |
475 | // find the socket |
| 427 | socket = sockets_find( socket_get_sockets(), socket_id ); |
476 | socket = sockets_find( socket_get_sockets(), socket_id ); |
| - | 477 | if( ! socket ){ |
|
| - | 478 | fibril_rwlock_read_unlock( & socket_globals.lock ); |
|
| 428 | if( ! socket ) return ENOTSOCK; |
479 | return ENOTSOCK; |
| - | 480 | } |
|
| 429 | // request the message |
481 | // request the message |
| 430 | message_id = async_send_3( socket->phone, message, ( ipcarg_t ) socket->socket_id, arg2, socket->service, NULL ); |
482 | message_id = async_send_3( socket->phone, message, ( ipcarg_t ) socket->socket_id, arg2, socket->service, NULL ); |
| 431 | // send the address |
483 | // send the address |
| 432 | ipc_data_write_start( socket->phone, data, datalength ); |
484 | ipc_data_write_start( socket->phone, data, datalength ); |
| - | 485 | fibril_rwlock_read_unlock( & socket_globals.lock ); |
|
| 433 | async_wait_for( message_id, & result ); |
486 | async_wait_for( message_id, & result ); |
| 434 | return ( int ) result; |
487 | return ( int ) result; |
| 435 | } |
488 | } |
| 436 | 489 | ||
| 437 | int bind( int socket_id, const struct sockaddr * my_addr, socklen_t addrlen ){ |
490 | int bind( int socket_id, const struct sockaddr * my_addr, socklen_t addrlen ){ |
| Line 439... | Line 492... | ||
| 439 | // send the address |
492 | // send the address |
| 440 | return socket_send_data( socket_id, NET_SOCKET_BIND, 0, my_addr, ( size_t ) addrlen ); |
493 | return socket_send_data( socket_id, NET_SOCKET_BIND, 0, my_addr, ( size_t ) addrlen ); |
| 441 | } |
494 | } |
| 442 | 495 | ||
| 443 | int listen( int socket_id, int backlog ){ |
496 | int listen( int socket_id, int backlog ){ |
| 444 | socket_ref socket; |
497 | socket_ref socket; |
| - | 498 | int result; |
|
| 445 | 499 | ||
| 446 | if( backlog <= 0 ) return EINVAL; |
500 | if( backlog <= 0 ) return EINVAL; |
| - | 501 | fibril_rwlock_read_lock( & socket_globals.lock ); |
|
| 447 | // find the socket |
502 | // find the socket |
| 448 | socket = sockets_find( socket_get_sockets(), socket_id ); |
503 | socket = sockets_find( socket_get_sockets(), socket_id ); |
| - | 504 | if( ! socket ){ |
|
| - | 505 | fibril_rwlock_read_unlock( & socket_globals.lock ); |
|
| 449 | if( ! socket ) return ENOTSOCK; |
506 | return ENOTSOCK; |
| - | 507 | } |
|
| 450 | // request listen backlog change |
508 | // request listen backlog change |
| 451 | return ( int ) async_req_3_0( socket->phone, NET_SOCKET_LISTEN, ( ipcarg_t ) socket->socket_id, ( ipcarg_t ) backlog, socket->service ); |
509 | result = ( int ) async_req_3_0( socket->phone, NET_SOCKET_LISTEN, ( ipcarg_t ) socket->socket_id, ( ipcarg_t ) backlog, socket->service ); |
| - | 510 | fibril_rwlock_read_unlock( & socket_globals.lock ); |
|
| - | 511 | return result; |
|
| 452 | } |
512 | } |
| 453 | 513 | ||
| 454 | int accept( int socket_id, struct sockaddr * cliaddr, socklen_t * addrlen ){ |
514 | int accept( int socket_id, struct sockaddr * cliaddr, socklen_t * addrlen ){ |
| 455 | socket_ref socket; |
515 | socket_ref socket; |
| 456 | aid_t message_id; |
516 | aid_t message_id; |
| 457 | int result; |
517 | int result; |
| 458 | 518 | ||
| 459 | if(( ! cliaddr ) || ( ! addrlen )) return EBADMEM; |
519 | if(( ! cliaddr ) || ( ! addrlen )) return EBADMEM; |
| - | 520 | ||
| - | 521 | fibril_rwlock_read_lock( & socket_globals.lock ); |
|
| 460 | // find the socket |
522 | // find the socket |
| 461 | socket = sockets_find( socket_get_sockets(), socket_id ); |
523 | socket = sockets_find( socket_get_sockets(), socket_id ); |
| - | 524 | if( ! socket ){ |
|
| - | 525 | fibril_rwlock_read_unlock( & socket_globals.lock ); |
|
| 462 | if( ! socket ) return ENOTSOCK; |
526 | return ENOTSOCK; |
| - | 527 | } |
|
| 463 | fibril_mutex_lock( & socket->accept_lock ); |
528 | fibril_mutex_lock( & socket->accept_lock ); |
| 464 | // wait for an accepted socket |
529 | // wait for an accepted socket |
| - | 530 | ++ socket->blocked; |
|
| 465 | while( dyn_fifo_value( & socket->accepted ) <= 0 ){ |
531 | while( dyn_fifo_value( & socket->accepted ) <= 0 ){ |
| - | 532 | fibril_rwlock_read_unlock( & socket_globals.lock ); |
|
| 466 | fibril_condvar_wait( & socket->accept_signal, & socket->accept_lock ); |
533 | fibril_condvar_wait( & socket->accept_signal, & socket->accept_lock ); |
| - | 534 | fibril_rwlock_read_lock( & socket_globals.lock ); |
|
| 467 | } |
535 | } |
| - | 536 | -- socket->blocked; |
|
| 468 | // request accept |
537 | // request accept |
| 469 | message_id = async_send_3( socket->phone, NET_SOCKET_ACCEPT, ( ipcarg_t ) socket->socket_id, ( ipcarg_t ) dyn_fifo_value( & socket->accepted ), socket->service, NULL ); |
538 | message_id = async_send_3( socket->phone, NET_SOCKET_ACCEPT, ( ipcarg_t ) socket->socket_id, ( ipcarg_t ) dyn_fifo_value( & socket->accepted ), socket->service, NULL ); |
| 470 | // read address |
539 | // read address |
| 471 | ipc_data_read_start( socket->phone, cliaddr, * addrlen ); |
540 | ipc_data_read_start( socket->phone, cliaddr, * addrlen ); |
| - | 541 | fibril_rwlock_read_unlock( & socket_globals.lock ); |
|
| 472 | async_wait_for( message_id, ( ipcarg_t * ) & result ); |
542 | async_wait_for( message_id, ( ipcarg_t * ) & result ); |
| 473 | if( result > 0 ){ |
543 | if( result > 0 ){ |
| 474 | // dequeue the accepted apcket if successful |
544 | // dequeue the accepted apcket if successful |
| 475 | dyn_fifo_pop( & socket->accepted ); |
545 | dyn_fifo_pop( & socket->accepted ); |
| 476 | } |
546 | } |
| Line 486... | Line 556... | ||
| 486 | int closesocket( int socket_id ){ |
556 | int closesocket( int socket_id ){ |
| 487 | ERROR_DECLARE; |
557 | ERROR_DECLARE; |
| 488 | 558 | ||
| 489 | socket_ref socket; |
559 | socket_ref socket; |
| 490 | 560 | ||
| - | 561 | fibril_rwlock_write_unlock( & socket_globals.lock ); |
|
| 491 | socket = sockets_find( socket_get_sockets(), socket_id ); |
562 | socket = sockets_find( socket_get_sockets(), socket_id ); |
| - | 563 | if( ! socket ){ |
|
| - | 564 | fibril_rwlock_write_unlock( & socket_globals.lock ); |
|
| 492 | if( ! socket ) return ENOTSOCK; |
565 | return ENOTSOCK; |
| - | 566 | } |
|
| - | 567 | if( socket->blocked ){ |
|
| - | 568 | fibril_rwlock_write_unlock( & socket_globals.lock ); |
|
| - | 569 | return EINPROGRESS; |
|
| - | 570 | } |
|
| 493 | // request close |
571 | // request close |
| 494 | ERROR_PROPAGATE(( int ) async_req_3_0( socket->phone, NET_SOCKET_CLOSE, ( ipcarg_t ) socket->socket_id, 0, socket->service )); |
572 | ERROR_PROPAGATE(( int ) async_req_3_0( socket->phone, NET_SOCKET_CLOSE, ( ipcarg_t ) socket->socket_id, 0, socket->service )); |
| 495 | // free the socket structure |
573 | // free the socket structure |
| 496 | socket_destroy( socket ); |
574 | socket_destroy( socket ); |
| - | 575 | fibril_rwlock_write_unlock( & socket_globals.lock ); |
|
| 497 | return EOK; |
576 | return EOK; |
| 498 | } |
577 | } |
| 499 | 578 | ||
| 500 | void socket_destroy( socket_ref socket ){ |
579 | void socket_destroy( socket_ref socket ){ |
| 501 | int accepted_id; |
580 | int accepted_id; |
| Line 527... | Line 606... | ||
| 527 | ipcarg_t result; |
606 | ipcarg_t result; |
| 528 | size_t fragments; |
607 | size_t fragments; |
| 529 | 608 | ||
| 530 | if( ! data ) return EBADMEM; |
609 | if( ! data ) return EBADMEM; |
| 531 | if( ! datalength ) return NO_DATA; |
610 | if( ! datalength ) return NO_DATA; |
| - | 611 | fibril_rwlock_read_lock( & socket_globals.lock ); |
|
| 532 | // find socket |
612 | // find socket |
| 533 | socket = sockets_find( socket_get_sockets(), socket_id ); |
613 | socket = sockets_find( socket_get_sockets(), socket_id ); |
| - | 614 | if( ! socket ){ |
|
| - | 615 | fibril_rwlock_read_unlock( & socket_globals.lock ); |
|
| 534 | if( ! socket ) return ENOTSOCK; |
616 | return ENOTSOCK; |
| - | 617 | } |
|
| - | 618 | fibril_rwlock_read_lock( & socket->sending_lock ); |
|
| 535 | // compute data fragment count |
619 | // compute data fragment count |
| 536 | fragments = ( datalength + socket->header_size ) / socket->data_fragment_size; |
620 | fragments = ( datalength + socket->header_size ) / socket->data_fragment_size; |
| 537 | if(( datalength + socket->header_size ) % socket->data_fragment_size ) ++ fragments; |
621 | if(( datalength + socket->header_size ) % socket->data_fragment_size ) ++ fragments; |
| 538 | // request send |
622 | // request send |
| 539 | message_id = async_send_4( socket->phone, message, ( ipcarg_t ) socket->socket_id, fragments, socket->service, ( ipcarg_t ) flags, NULL ); |
623 | message_id = async_send_5( socket->phone, message, ( ipcarg_t ) socket->socket_id, socket->data_fragment_size, socket->service, ( ipcarg_t ) flags, fragments, NULL ); |
| 540 | // send the address if given |
624 | // send the address if given |
| 541 | if(( ! toaddr ) || ( ipc_data_write_start( socket->phone, toaddr, addrlen ) == EOK )){ |
625 | if(( ! toaddr ) || ( ipc_data_write_start( socket->phone, toaddr, addrlen ) == EOK )){ |
| 542 | if( fragments == 1 ){ |
626 | if( fragments == 1 ){ |
| 543 | // send all if only one fragment |
627 | // send all if only one fragment |
| 544 | ipc_data_write_start( socket->phone, data, datalength ); |
628 | ipc_data_write_start( socket->phone, data, datalength ); |
| Line 553... | Line 637... | ||
| 553 | } |
637 | } |
| 554 | // send the last fragment |
638 | // send the last fragment |
| 555 | ipc_data_write_start( socket->phone, data, ( datalength + socket->header_size ) % socket->data_fragment_size ); |
639 | ipc_data_write_start( socket->phone, data, ( datalength + socket->header_size ) % socket->data_fragment_size ); |
| 556 | } |
640 | } |
| 557 | } |
641 | } |
| - | 642 | fibril_rwlock_read_unlock( & socket->sending_lock ); |
|
| - | 643 | fibril_rwlock_read_unlock( & socket_globals.lock ); |
|
| 558 | async_wait_for( message_id, & result ); |
644 | async_wait_for( message_id, & result ); |
| 559 | return ( int ) result; |
645 | return ( int ) result; |
| 560 | } |
646 | } |
| 561 | 647 | ||
| 562 | int recv( int socket_id, void * data, size_t datalength, int flags ){ |
648 | int recv( int socket_id, void * data, size_t datalength, int flags ){ |
| Line 581... | Line 667... | ||
| 581 | ipc_call_t answer; |
667 | ipc_call_t answer; |
| 582 | 668 | ||
| 583 | if( ! data ) return EBADMEM; |
669 | if( ! data ) return EBADMEM; |
| 584 | if( ! datalength ) return NO_DATA; |
670 | if( ! datalength ) return NO_DATA; |
| 585 | if( fromaddr && ( ! addrlen )) return EINVAL; |
671 | if( fromaddr && ( ! addrlen )) return EINVAL; |
| - | 672 | fibril_rwlock_read_lock( & socket_globals.lock ); |
|
| 586 | // find the socket |
673 | // find the socket |
| 587 | socket = sockets_find( socket_get_sockets(), socket_id ); |
674 | socket = sockets_find( socket_get_sockets(), socket_id ); |
| - | 675 | if( ! socket ){ |
|
| - | 676 | fibril_rwlock_read_unlock( & socket_globals.lock ); |
|
| 588 | if( ! socket ) return ENOTSOCK; |
677 | return ENOTSOCK; |
| - | 678 | } |
|
| 589 | fibril_mutex_lock( & socket->receive_lock ); |
679 | fibril_mutex_lock( & socket->receive_lock ); |
| 590 | // wait for a received packet |
680 | // wait for a received packet |
| - | 681 | ++ socket->blocked; |
|
| 591 | while(( result = dyn_fifo_value( & socket->received )) <= 0 ){ |
682 | while(( result = dyn_fifo_value( & socket->received )) <= 0 ){ |
| - | 683 | fibril_rwlock_read_unlock( & socket_globals.lock ); |
|
| 592 | fibril_condvar_wait( & socket->receive_signal, & socket->receive_lock ); |
684 | fibril_condvar_wait( & socket->receive_signal, & socket->receive_lock ); |
| - | 685 | fibril_rwlock_read_lock( & socket_globals.lock ); |
|
| 593 | } |
686 | } |
| - | 687 | -- socket->blocked; |
|
| 594 | fragments = ( size_t ) result; |
688 | fragments = ( size_t ) result; |
| 595 | // prepare lengths if more fragments |
689 | // prepare lengths if more fragments |
| 596 | if( fragments > 1 ){ |
690 | if( fragments > 1 ){ |
| 597 | lengths = ( size_t * ) malloc( sizeof( size_t ) * fragments + sizeof( size_t )); |
691 | lengths = ( size_t * ) malloc( sizeof( size_t ) * fragments + sizeof( size_t )); |
| 598 | if( ! lengths ){ |
692 | if( ! lengths ){ |
| 599 | fibril_mutex_unlock( & socket->receive_lock ); |
693 | fibril_mutex_unlock( & socket->receive_lock ); |
| - | 694 | fibril_rwlock_read_unlock( & socket_globals.lock ); |
|
| 600 | return ENOMEM; |
695 | return ENOMEM; |
| 601 | } |
696 | } |
| 602 | // request packet data |
697 | // request packet data |
| 603 | message_id = async_send_4( socket->phone, message, ( ipcarg_t ) socket->socket_id, 0, socket->service, ( ipcarg_t ) flags, & answer ); |
698 | message_id = async_send_4( socket->phone, message, ( ipcarg_t ) socket->socket_id, 0, socket->service, ( ipcarg_t ) flags, & answer ); |
| 604 | // read the address if desired |
699 | // read the address if desired |
| Line 633... | Line 728... | ||
| 633 | result = SOCKET_GET_READ_DATA_LENGTH( answer ); |
728 | result = SOCKET_GET_READ_DATA_LENGTH( answer ); |
| 634 | // set address length |
729 | // set address length |
| 635 | if( fromaddr && addrlen ) * addrlen = SOCKET_GET_ADDRESS_LENGTH( answer ); |
730 | if( fromaddr && addrlen ) * addrlen = SOCKET_GET_ADDRESS_LENGTH( answer ); |
| 636 | } |
731 | } |
| 637 | fibril_mutex_unlock( & socket->receive_lock ); |
732 | fibril_mutex_unlock( & socket->receive_lock ); |
| - | 733 | fibril_rwlock_read_unlock( & socket_globals.lock ); |
|
| 638 | return result; |
734 | return result; |
| 639 | } |
735 | } |
| 640 | 736 | ||
| 641 | int getsockopt( int socket_id, int level, int optname, void * value, size_t * optlen ){ |
737 | int getsockopt( int socket_id, int level, int optname, void * value, size_t * optlen ){ |
| 642 | socket_ref socket; |
738 | socket_ref socket; |
| 643 | aid_t message_id; |
739 | aid_t message_id; |
| 644 | ipcarg_t result; |
740 | ipcarg_t result; |
| 645 | 741 | ||
| 646 | if( !( value && optlen )) return EBADMEM; |
742 | if( !( value && optlen )) return EBADMEM; |
| 647 | if( !( * optlen )) return NO_DATA; |
743 | if( !( * optlen )) return NO_DATA; |
| - | 744 | fibril_rwlock_read_lock( & socket_globals.lock ); |
|
| 648 | // find the socket |
745 | // find the socket |
| 649 | socket = sockets_find( socket_get_sockets(), socket_id ); |
746 | socket = sockets_find( socket_get_sockets(), socket_id ); |
| - | 747 | if( ! socket ){ |
|
| - | 748 | fibril_rwlock_read_unlock( & socket_globals.lock ); |
|
| 650 | if( ! socket ) return ENOTSOCK; |
749 | return ENOTSOCK; |
| - | 750 | } |
|
| 651 | // request option value |
751 | // request option value |
| 652 | message_id = async_send_3( socket->phone, NET_SOCKET_GETSOCKOPT, ( ipcarg_t ) socket->socket_id, ( ipcarg_t ) optname, socket->service, NULL ); |
752 | message_id = async_send_3( socket->phone, NET_SOCKET_GETSOCKOPT, ( ipcarg_t ) socket->socket_id, ( ipcarg_t ) optname, socket->service, NULL ); |
| 653 | // read the length |
753 | // read the length |
| 654 | if( ipc_data_read_start( socket->phone, optlen, sizeof( * optlen )) == EOK ){ |
754 | if( ipc_data_read_start( socket->phone, optlen, sizeof( * optlen )) == EOK ){ |
| 655 | // read the value |
755 | // read the value |
| 656 | ipc_data_read_start( socket->phone, value, * optlen ); |
756 | ipc_data_read_start( socket->phone, value, * optlen ); |
| 657 | } |
757 | } |
| - | 758 | fibril_rwlock_read_unlock( & socket_globals.lock ); |
|
| 658 | async_wait_for( message_id, & result ); |
759 | async_wait_for( message_id, & result ); |
| 659 | return ( int ) result; |
760 | return ( int ) result; |
| 660 | } |
761 | } |
| 661 | 762 | ||
| 662 | int setsockopt( int socket_id, int level, int optname, const void * value, size_t optlen ){ |
763 | int setsockopt( int socket_id, int level, int optname, const void * value, size_t optlen ){ |