Rev 4701 | Rev 4726 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
| Rev 4701 | Rev 4708 | ||
|---|---|---|---|
| Line 93... | Line 93... | ||
| 93 | */ |
93 | */ |
| 94 | services_t service; |
94 | services_t service; |
| 95 | /** Underlying protocol header size. |
95 | /** Underlying protocol header size. |
| 96 | * Sending and receiving optimalization. |
96 | * Sending and receiving optimalization. |
| 97 | */ |
97 | */ |
| 98 | int header_size; |
98 | size_t header_size; |
| 99 | /** Packet data fragment size. |
99 | /** Packet data fragment size. |
| 100 | * Sending and receiving optimalization. |
100 | * Sending and receiving optimalization. |
| 101 | */ |
101 | */ |
| 102 | int data_fragment_size; |
102 | size_t data_fragment_size; |
| 103 | /** Received packets queue. |
103 | /** Received packets queue. |
| 104 | */ |
104 | */ |
| 105 | dyn_fifo_t received; |
105 | dyn_fifo_t received; |
| 106 | /** Received packets safety lock. |
106 | /** Received packets safety lock. |
| 107 | */ |
107 | */ |
| Line 144... | Line 144... | ||
| 144 | 144 | ||
| 145 | /** Returns the TCP module phone. |
145 | /** Returns the TCP module phone. |
| 146 | * Connects to the TCP module if necessary. |
146 | * Connects to the TCP module if necessary. |
| 147 | * @returns The TCP module phone. |
147 | * @returns The TCP module phone. |
| 148 | */ |
148 | */ |
| 149 | static int socket_get_tcp_phone(); |
149 | static int socket_get_tcp_phone( void ); |
| 150 | 150 | ||
| 151 | /** Returns the UDP module phone. |
151 | /** Returns the UDP module phone. |
| 152 | * Connects to the UDP module if necessary. |
152 | * Connects to the UDP module if necessary. |
| 153 | * @returns The UDP module phone. |
153 | * @returns The UDP module phone. |
| 154 | */ |
154 | */ |
| 155 | static int socket_get_tcp_phone(); |
155 | static int socket_get_udp_phone( void ); |
| 156 | 156 | ||
| 157 | /** Returns the active sockets. |
157 | /** Returns the active sockets. |
| 158 | * @returns The active sockets. |
158 | * @returns The active sockets. |
| 159 | */ |
159 | */ |
| 160 | static sockets_ref socket_get_sockets(); |
160 | static sockets_ref socket_get_sockets( void ); |
| 161 | 161 | ||
| 162 | /** Default thread for new connections. |
162 | /** Default thread for new connections. |
| 163 | * @param iid The initial message identifier. Input parameter. |
163 | * @param iid The initial message identifier. Input parameter. |
| 164 | * @param icall The initial message call structure. Input parameter. |
164 | * @param icall The initial message call structure. Input parameter. |
| 165 | */ |
165 | */ |
| Line 175... | Line 175... | ||
| 175 | * @returns ENOTSOCK if the socket is not found. |
175 | * @returns ENOTSOCK if the socket is not found. |
| 176 | * @returns EBADMEM if the data parameter is NULL. |
176 | * @returns EBADMEM if the data parameter is NULL. |
| 177 | * @returns NO_DATA if the datalength parameter is zero (0). |
177 | * @returns NO_DATA if the datalength parameter is zero (0). |
| 178 | * @returns Other error codes as defined for the spcific message. |
178 | * @returns Other error codes as defined for the spcific message. |
| 179 | */ |
179 | */ |
| 180 | int socket_send_data( int socket_id, int message, ipcarg_t arg2, const void * data, size_t datalength ); |
180 | int socket_send_data( int socket_id, ipcarg_t message, ipcarg_t arg2, const void * data, size_t datalength ); |
| 181 | 181 | ||
| 182 | /** Initializes a new socket specific data. |
182 | /** Initializes a new socket specific data. |
| 183 | * @param socket The socket to be initialized. Input/output parameter. |
183 | * @param socket The socket to be initialized. Input/output parameter. |
| 184 | * @param socket_id The new socket identifier. Input parameter. |
184 | * @param socket_id The new socket identifier. Input parameter. |
| 185 | * @param phone The parent module phone. Input parameter. |
185 | * @param phone The parent module phone. Input parameter. |
| Line 204... | Line 204... | ||
| 204 | * @returns ENOTSOCK if the socket is not found. |
204 | * @returns ENOTSOCK if the socket is not found. |
| 205 | * @returns EBADMEM if the data parameter is NULL. |
205 | * @returns EBADMEM if the data parameter is NULL. |
| 206 | * @returns NO_DATA if the datalength or addrlen parameter is zero (0). |
206 | * @returns NO_DATA if the datalength or addrlen parameter is zero (0). |
| 207 | * @returns Other error codes as defined for the spcific message. |
207 | * @returns Other error codes as defined for the spcific message. |
| 208 | */ |
208 | */ |
| 209 | int recvfrom_core( int message, int socket_id, void * data, size_t datalength, int flags, struct sockaddr * fromaddr, socklen_t * addrlen ); |
209 | int recvfrom_core( ipcarg_t message, int socket_id, void * data, size_t datalength, int flags, struct sockaddr * fromaddr, socklen_t * addrlen ); |
| 210 | 210 | ||
| 211 | /** Sends data via the socket to the remote address. |
211 | /** Sends data via the socket to the remote address. |
| 212 | * Binds the socket to a free port if not already connected/bound. |
212 | * Binds the socket to a free port if not already connected/bound. |
| 213 | * @param message The action message. Input parameter. |
213 | * @param message The action message. Input parameter. |
| 214 | * @param socket_id Socket identifier. Input parameter. |
214 | * @param socket_id Socket identifier. Input parameter. |
| Line 221... | Line 221... | ||
| 221 | * @returns ENOTSOCK if the socket is not found. |
221 | * @returns ENOTSOCK if the socket is not found. |
| 222 | * @returns EBADMEM if the data or toaddr parameter is NULL. |
222 | * @returns EBADMEM if the data or toaddr parameter is NULL. |
| 223 | * @returns NO_DATA if the datalength or the addrlen parameter is zero (0). |
223 | * @returns NO_DATA if the datalength or the addrlen parameter is zero (0). |
| 224 | * @returns Other error codes as defined for the NET_SOCKET_SENDTO message. |
224 | * @returns Other error codes as defined for the NET_SOCKET_SENDTO message. |
| 225 | */ |
225 | */ |
| 226 | int sendto_core( int message, int socket_id, const void * data, size_t datalength, int flags, const struct sockaddr * toaddr, socklen_t addrlen ); |
226 | int sendto_core( ipcarg_t message, int socket_id, const void * data, size_t datalength, int flags, const struct sockaddr * toaddr, socklen_t addrlen ); |
| 227 | 227 | ||
| 228 | static int socket_get_tcp_phone(){ |
228 | static int socket_get_tcp_phone( void ){ |
| 229 | if( socket_globals.tcp_phone < 0 ){ |
229 | if( socket_globals.tcp_phone < 0 ){ |
| 230 | socket_globals.tcp_phone = bind_service( SERVICE_TCP, 0, 0, SERVICE_TCP, socket_connection ); |
230 | socket_globals.tcp_phone = bind_service( SERVICE_TCP, 0, 0, SERVICE_TCP, socket_connection ); |
| 231 | } |
231 | } |
| 232 | return socket_globals.tcp_phone; |
232 | return socket_globals.tcp_phone; |
| 233 | } |
233 | } |
| 234 | 234 | ||
| 235 | static int socket_get_udp_phone(){ |
235 | static int socket_get_udp_phone( void ){ |
| 236 | if( socket_globals.udp_phone < 0 ){ |
236 | if( socket_globals.udp_phone < 0 ){ |
| 237 | socket_globals.udp_phone = bind_service( SERVICE_UDP, 0, 0, SERVICE_UDP, socket_connection ); |
237 | socket_globals.udp_phone = bind_service( SERVICE_UDP, 0, 0, SERVICE_UDP, socket_connection ); |
| 238 | } |
238 | } |
| 239 | return socket_globals.udp_phone; |
239 | return socket_globals.udp_phone; |
| 240 | } |
240 | } |
| 241 | 241 | ||
| 242 | static sockets_ref socket_get_sockets(){ |
242 | static sockets_ref socket_get_sockets( void ){ |
| 243 | if( ! socket_globals.sockets ){ |
243 | if( ! socket_globals.sockets ){ |
| 244 | socket_globals.sockets = ( sockets_ref ) malloc( sizeof( sockets_t )); |
244 | socket_globals.sockets = ( sockets_ref ) malloc( sizeof( sockets_t )); |
| 245 | if( ! socket_globals.sockets ) return NULL; |
245 | if( ! socket_globals.sockets ) return NULL; |
| 246 | if( sockets_initialize( socket_globals.sockets ) != EOK ){ |
246 | if( sockets_initialize( socket_globals.sockets ) != EOK ){ |
| 247 | free( socket_globals.sockets ); |
247 | free( socket_globals.sockets ); |
| Line 333... | Line 333... | ||
| 333 | ERROR_CODE = EOK; |
333 | ERROR_CODE = EOK; |
| 334 | break; |
334 | break; |
| 335 | default: |
335 | default: |
| 336 | ERROR_CODE = ENOTSUP; |
336 | ERROR_CODE = ENOTSUP; |
| 337 | } |
337 | } |
| 338 | ipc_answer_0( callid, ERROR_CODE ); |
338 | ipc_answer_0( callid, ( ipcarg_t ) ERROR_CODE ); |
| 339 | } |
339 | } |
| 340 | } |
340 | } |
| 341 | 341 | ||
| 342 | int socket( int domain, int type, int protocol ){ |
342 | int socket( int domain, int type, int protocol ){ |
| 343 | ERROR_DECLARE; |
343 | ERROR_DECLARE; |
| Line 393... | Line 393... | ||
| 393 | dyn_fifo_destroy( & socket->received ); |
393 | dyn_fifo_destroy( & socket->received ); |
| 394 | free( socket ); |
394 | free( socket ); |
| 395 | return ERROR_CODE; |
395 | return ERROR_CODE; |
| 396 | } |
396 | } |
| 397 | // request a new socket |
397 | // request a new socket |
| 398 | if( ERROR_OCCURRED( 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 ))){ |
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 ))){ |
| 399 | dyn_fifo_destroy( & socket->received ); |
399 | dyn_fifo_destroy( & socket->received ); |
| 400 | dyn_fifo_destroy( & socket->accepted ); |
400 | dyn_fifo_destroy( & socket->accepted ); |
| 401 | free( socket ); |
401 | free( socket ); |
| 402 | return ERROR_CODE; |
402 | return ERROR_CODE; |
| 403 | } |
403 | } |
| Line 407... | Line 407... | ||
| 407 | ERROR_CODE = sockets_add( socket_get_sockets(), socket_id, socket ); |
407 | ERROR_CODE = sockets_add( socket_get_sockets(), socket_id, socket ); |
| 408 | if( ERROR_CODE < 0 ){ |
408 | if( ERROR_CODE < 0 ){ |
| 409 | dyn_fifo_destroy( & socket->received ); |
409 | dyn_fifo_destroy( & socket->received ); |
| 410 | dyn_fifo_destroy( & socket->accepted ); |
410 | dyn_fifo_destroy( & socket->accepted ); |
| 411 | free( socket ); |
411 | free( socket ); |
| 412 | async_msg_3( phone, NET_SOCKET_CLOSE, socket_id, 0, service ); |
412 | async_msg_3( phone, NET_SOCKET_CLOSE, ( ipcarg_t ) socket_id, 0, service ); |
| 413 | return ERROR_CODE; |
413 | return ERROR_CODE; |
| 414 | } |
414 | } |
| 415 | 415 | ||
| 416 | return socket_id; |
416 | return socket_id; |
| 417 | } |
417 | } |
| 418 | 418 | ||
| 419 | int socket_send_data( int socket_id, int message, ipcarg_t arg2, const void * data, size_t datalength ){ |
419 | int socket_send_data( int socket_id, ipcarg_t message, ipcarg_t arg2, const void * data, size_t datalength ){ |
| 420 | socket_ref socket; |
420 | socket_ref socket; |
| 421 | aid_t message_id; |
421 | aid_t message_id; |
| 422 | ipcarg_t result; |
422 | ipcarg_t result; |
| 423 | 423 | ||
| 424 | if( ! data ) return EBADMEM; |
424 | if( ! data ) return EBADMEM; |
| 425 | if( ! datalength ) return NO_DATA; |
425 | if( ! datalength ) return NO_DATA; |
| 426 | // find the socket |
426 | // find the socket |
| 427 | socket = sockets_find( socket_get_sockets(), socket_id ); |
427 | socket = sockets_find( socket_get_sockets(), socket_id ); |
| 428 | if( ! socket ) return ENOTSOCK; |
428 | if( ! socket ) return ENOTSOCK; |
| 429 | // request the message |
429 | // request the message |
| 430 | message_id = async_send_3( socket->phone, message, socket->socket_id, arg2, socket->service, NULL ); |
430 | message_id = async_send_3( socket->phone, message, ( ipcarg_t ) socket->socket_id, arg2, socket->service, NULL ); |
| 431 | // send the address |
431 | // send the address |
| 432 | ipc_data_write_start( socket->phone, data, datalength ); |
432 | ipc_data_write_start( socket->phone, data, datalength ); |
| 433 | async_wait_for( message_id, & result ); |
433 | async_wait_for( message_id, & result ); |
| 434 | return ( int ) result; |
434 | return ( int ) result; |
| 435 | } |
435 | } |
| 436 | 436 | ||
| 437 | int bind( int socket_id, const struct sockaddr * my_addr, socklen_t addrlen ){ |
437 | int bind( int socket_id, const struct sockaddr * my_addr, socklen_t addrlen ){ |
| - | 438 | if( addrlen <= 0 ) return EINVAL; |
|
| 438 | // send the address |
439 | // send the address |
| 439 | return socket_send_data( socket_id, NET_SOCKET_BIND, 0, my_addr, addrlen ); |
440 | return socket_send_data( socket_id, NET_SOCKET_BIND, 0, my_addr, ( size_t ) addrlen ); |
| 440 | } |
441 | } |
| 441 | 442 | ||
| 442 | int listen( int socket_id, int backlog ){ |
443 | int listen( int socket_id, int backlog ){ |
| 443 | socket_ref socket; |
444 | socket_ref socket; |
| 444 | 445 | ||
| 445 | if( backlog <= 0 ) return EINVAL; |
446 | if( backlog <= 0 ) return EINVAL; |
| 446 | // find the socket |
447 | // find the socket |
| 447 | socket = sockets_find( socket_get_sockets(), socket_id ); |
448 | socket = sockets_find( socket_get_sockets(), socket_id ); |
| 448 | if( ! socket ) return ENOTSOCK; |
449 | if( ! socket ) return ENOTSOCK; |
| 449 | // request listen backlog change |
450 | // request listen backlog change |
| 450 | return async_req_3_0( socket->phone, NET_SOCKET_LISTEN, socket->socket_id, backlog, socket->service ); |
451 | return ( int ) async_req_3_0( socket->phone, NET_SOCKET_LISTEN, ( ipcarg_t ) socket->socket_id, ( ipcarg_t ) backlog, socket->service ); |
| 451 | } |
452 | } |
| 452 | 453 | ||
| 453 | int accept( int socket_id, struct sockaddr * cliaddr, socklen_t * addrlen ){ |
454 | int accept( int socket_id, struct sockaddr * cliaddr, socklen_t * addrlen ){ |
| 454 | socket_ref socket; |
455 | socket_ref socket; |
| 455 | aid_t message_id; |
456 | aid_t message_id; |
| Line 463... | Line 464... | ||
| 463 | // wait for an accepted socket |
464 | // wait for an accepted socket |
| 464 | while( dyn_fifo_value( & socket->accepted ) <= 0 ){ |
465 | while( dyn_fifo_value( & socket->accepted ) <= 0 ){ |
| 465 | fibril_condvar_wait( & socket->accept_signal, & socket->accept_lock ); |
466 | fibril_condvar_wait( & socket->accept_signal, & socket->accept_lock ); |
| 466 | } |
467 | } |
| 467 | // request accept |
468 | // request accept |
| 468 | message_id = async_send_3( socket->phone, NET_SOCKET_ACCEPT, socket->socket_id, dyn_fifo_value( & socket->accepted ), socket->service, NULL ); |
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 ); |
| 469 | // read address |
470 | // read address |
| 470 | ipc_data_read_start( socket->phone, cliaddr, * addrlen ); |
471 | ipc_data_read_start( socket->phone, cliaddr, * addrlen ); |
| 471 | async_wait_for( message_id, ( ipcarg_t * ) & result ); |
472 | async_wait_for( message_id, ( ipcarg_t * ) & result ); |
| 472 | if( result > 0 ){ |
473 | if( result > 0 ){ |
| 473 | // dequeue the accepted apcket if successful |
474 | // dequeue the accepted apcket if successful |
| Line 488... | Line 489... | ||
| 488 | socket_ref socket; |
489 | socket_ref socket; |
| 489 | 490 | ||
| 490 | socket = sockets_find( socket_get_sockets(), socket_id ); |
491 | socket = sockets_find( socket_get_sockets(), socket_id ); |
| 491 | if( ! socket ) return ENOTSOCK; |
492 | if( ! socket ) return ENOTSOCK; |
| 492 | // request close |
493 | // request close |
| 493 | ERROR_PROPAGATE( async_req_3_0( socket->phone, NET_SOCKET_CLOSE, socket->socket_id, 0, socket->service )); |
494 | ERROR_PROPAGATE(( int ) async_req_3_0( socket->phone, NET_SOCKET_CLOSE, ( ipcarg_t ) socket->socket_id, 0, socket->service )); |
| 494 | // free the socket structure |
495 | // free the socket structure |
| 495 | socket_destroy( socket ); |
496 | socket_destroy( socket ); |
| 496 | return EOK; |
497 | return EOK; |
| 497 | } |
498 | } |
| 498 | 499 | ||
| Line 518... | Line 519... | ||
| 518 | if( ! addrlen ) return NO_DATA; |
519 | if( ! addrlen ) return NO_DATA; |
| 519 | // with the address |
520 | // with the address |
| 520 | return sendto_core( NET_SOCKET_SENDTO, socket_id, data, datalength, flags, toaddr, addrlen ); |
521 | return sendto_core( NET_SOCKET_SENDTO, socket_id, data, datalength, flags, toaddr, addrlen ); |
| 521 | } |
522 | } |
| 522 | 523 | ||
| 523 | int sendto_core( int message, int socket_id, const void * data, size_t datalength, int flags, const struct sockaddr * toaddr, socklen_t addrlen ){ |
524 | int sendto_core( ipcarg_t message, int socket_id, const void * data, size_t datalength, int flags, const struct sockaddr * toaddr, socklen_t addrlen ){ |
| 524 | socket_ref socket; |
525 | socket_ref socket; |
| 525 | aid_t message_id; |
526 | aid_t message_id; |
| 526 | ipcarg_t result; |
527 | ipcarg_t result; |
| 527 | int fragments; |
528 | size_t fragments; |
| 528 | 529 | ||
| 529 | if( ! data ) return EBADMEM; |
530 | if( ! data ) return EBADMEM; |
| 530 | if( ! datalength ) return NO_DATA; |
531 | if( ! datalength ) return NO_DATA; |
| 531 | // find socket |
532 | // find socket |
| 532 | socket = sockets_find( socket_get_sockets(), socket_id ); |
533 | socket = sockets_find( socket_get_sockets(), socket_id ); |
| 533 | if( ! socket ) return ENOTSOCK; |
534 | if( ! socket ) return ENOTSOCK; |
| 534 | // compute data fragment count |
535 | // compute data fragment count |
| 535 | fragments = ( datalength + socket->header_size ) / socket->data_fragment_size; |
536 | fragments = ( datalength + socket->header_size ) / socket->data_fragment_size; |
| 536 | if(( datalength + socket->header_size ) % socket->data_fragment_size ) ++ fragments; |
537 | if(( datalength + socket->header_size ) % socket->data_fragment_size ) ++ fragments; |
| 537 | // request send |
538 | // request send |
| 538 | message_id = async_send_4( socket->phone, message, socket->socket_id, fragments, socket->service, flags, NULL ); |
539 | message_id = async_send_4( socket->phone, message, ( ipcarg_t ) socket->socket_id, fragments, socket->service, ( ipcarg_t ) flags, NULL ); |
| 539 | // send the address if given |
540 | // send the address if given |
| 540 | if(( ! toaddr ) || ( ipc_data_write_start( socket->phone, toaddr, addrlen ) == EOK )){ |
541 | if(( ! toaddr ) || ( ipc_data_write_start( socket->phone, toaddr, addrlen ) == EOK )){ |
| 541 | if( fragments == 1 ){ |
542 | if( fragments == 1 ){ |
| 542 | // send all if only one fragment |
543 | // send all if only one fragment |
| 543 | ipc_data_write_start( socket->phone, data, datalength ); |
544 | ipc_data_write_start( socket->phone, data, datalength ); |
| 544 | }else{ |
545 | }else{ |
| 545 | // send the first fragment |
546 | // send the first fragment |
| 546 | ipc_data_write_start( socket->phone, data, socket->data_fragment_size - socket->header_size ); |
547 | ipc_data_write_start( socket->phone, data, socket->data_fragment_size - socket->header_size ); |
| 547 | data += socket->data_fragment_size - socket->header_size; |
548 | data = (( const uint8_t * ) data ) + socket->data_fragment_size - socket->header_size; |
| 548 | // send the middle fragments |
549 | // send the middle fragments |
| 549 | while(( -- fragments ) > 1 ){ |
550 | while(( -- fragments ) > 1 ){ |
| 550 | ipc_data_write_start( socket->phone, data, socket->data_fragment_size ); |
551 | ipc_data_write_start( socket->phone, data, socket->data_fragment_size ); |
| 551 | data += socket->data_fragment_size; |
552 | data = (( const uint8_t * ) data ) + socket->data_fragment_size; |
| 552 | } |
553 | } |
| 553 | // send the last fragment |
554 | // send the last fragment |
| 554 | ipc_data_write_start( socket->phone, data, ( datalength + socket->header_size ) % socket->data_fragment_size ); |
555 | ipc_data_write_start( socket->phone, data, ( datalength + socket->header_size ) % socket->data_fragment_size ); |
| 555 | } |
556 | } |
| 556 | } |
557 | } |
| Line 568... | Line 569... | ||
| 568 | if( ! addrlen ) return NO_DATA; |
569 | if( ! addrlen ) return NO_DATA; |
| 569 | // with the address |
570 | // with the address |
| 570 | return recvfrom_core( NET_SOCKET_RECVFROM, socket_id, data, datalength, flags, fromaddr, addrlen ); |
571 | return recvfrom_core( NET_SOCKET_RECVFROM, socket_id, data, datalength, flags, fromaddr, addrlen ); |
| 571 | } |
572 | } |
| 572 | 573 | ||
| 573 | int recvfrom_core( int message, int socket_id, void * data, size_t datalength, int flags, struct sockaddr * fromaddr, socklen_t * addrlen ){ |
574 | int recvfrom_core( ipcarg_t message, int socket_id, void * data, size_t datalength, int flags, struct sockaddr * fromaddr, socklen_t * addrlen ){ |
| 574 | socket_ref socket; |
575 | socket_ref socket; |
| 575 | aid_t message_id; |
576 | aid_t message_id; |
| 576 | int result; |
577 | int result; |
| 577 | int fragments; |
578 | size_t fragments; |
| 578 | int * lengths; |
579 | size_t * lengths; |
| 579 | int index; |
580 | size_t index; |
| 580 | ipc_call_t answer; |
581 | ipc_call_t answer; |
| 581 | 582 | ||
| 582 | if( ! data ) return EBADMEM; |
583 | if( ! data ) return EBADMEM; |
| 583 | if( ! datalength ) return NO_DATA; |
584 | if( ! datalength ) return NO_DATA; |
| 584 | if( fromaddr && ( ! addrlen )) return EINVAL; |
585 | if( fromaddr && ( ! addrlen )) return EINVAL; |
| 585 | // find the socket |
586 | // find the socket |
| 586 | socket = sockets_find( socket_get_sockets(), socket_id ); |
587 | socket = sockets_find( socket_get_sockets(), socket_id ); |
| 587 | if( ! socket ) return ENOTSOCK; |
588 | if( ! socket ) return ENOTSOCK; |
| 588 | fibril_mutex_lock( & socket->receive_lock ); |
589 | fibril_mutex_lock( & socket->receive_lock ); |
| 589 | // wait for a received packet |
590 | // wait for a received packet |
| 590 | while(( fragments = dyn_fifo_value( & socket->received )) <= 0 ){ |
591 | while(( result = dyn_fifo_value( & socket->received )) <= 0 ){ |
| 591 | fibril_condvar_wait( & socket->receive_signal, & socket->receive_lock ); |
592 | fibril_condvar_wait( & socket->receive_signal, & socket->receive_lock ); |
| 592 | } |
593 | } |
| - | 594 | fragments = ( size_t ) result; |
|
| 593 | // prepare lengths if more fragments |
595 | // prepare lengths if more fragments |
| 594 | if( fragments > 1 ){ |
596 | if( fragments > 1 ){ |
| 595 | lengths = ( int * ) malloc( sizeof( int ) * ( fragments + 1 )); |
597 | lengths = ( size_t * ) malloc( sizeof( size_t ) * fragments + sizeof( size_t )); |
| 596 | if( ! lengths ){ |
598 | if( ! lengths ){ |
| 597 | fibril_mutex_unlock( & socket->receive_lock ); |
599 | fibril_mutex_unlock( & socket->receive_lock ); |
| 598 | return ENOMEM; |
600 | return ENOMEM; |
| 599 | } |
601 | } |
| 600 | } |
- | |
| 601 | // request packet data |
602 | // request packet data |
| 602 | message_id = async_send_4( socket->phone, message, socket->socket_id, 0, socket->service, flags, & answer ); |
603 | message_id = async_send_4( socket->phone, message, ( ipcarg_t ) socket->socket_id, 0, socket->service, ( ipcarg_t ) flags, & answer ); |
| 603 | // read the address if desired |
604 | // read the address if desired |
| 604 | if(( ! fromaddr ) || ( ipc_data_read_start( socket->phone, fromaddr, * addrlen ) == EOK )){ |
605 | if(( ! fromaddr ) || ( ipc_data_read_start( socket->phone, fromaddr, * addrlen ) == EOK )){ |
| 605 | if( fragments == 1 ){ |
- | |
| 606 | // read all if only one fragment |
- | |
| 607 | ipc_data_read_start( socket->phone, data, datalength ); |
- | |
| 608 | }else{ |
- | |
| 609 | // read the fragment lengths |
606 | // read the fragment lengths |
| 610 | if( ipc_data_read_start( socket->phone, lengths, sizeof( int ) * ( fragments + 1 )) == EOK ){ |
607 | if( ipc_data_read_start( socket->phone, lengths, sizeof( int ) * ( fragments + 1 )) == EOK ){ |
| 611 | if( lengths[ fragments ] <= datalength ){ |
608 | if( lengths[ fragments ] <= datalength ){ |
| 612 | // read all fragments if long enough |
609 | // read all fragments if long enough |
| 613 | for( index = 0; index < fragments; ++ index ){ |
610 | for( index = 0; index < fragments; ++ index ){ |
| 614 | ipc_data_read_start( socket->phone, data, lengths[ index ] ); |
611 | ipc_data_read_start( socket->phone, data, lengths[ index ] ); |
| 615 | data += lengths[ index ]; |
612 | data = (( uint8_t * ) data ) + lengths[ index ]; |
| 616 | } |
613 | } |
| 617 | } |
614 | } |
| 618 | } |
615 | } |
| 619 | free( lengths ); |
- | |
| 620 | } |
616 | } |
| 621 | }else if( fragments > 1 ){ |
- | |
| 622 | free( lengths ); |
617 | free( lengths ); |
| - | 618 | }else{ |
|
| - | 619 | // request packet data |
|
| - | 620 | message_id = async_send_4( socket->phone, message, ( ipcarg_t ) socket->socket_id, 0, socket->service, ( ipcarg_t ) flags, & answer ); |
|
| - | 621 | // read the address if desired |
|
| - | 622 | if(( ! fromaddr ) || ( ipc_data_read_start( socket->phone, fromaddr, * addrlen ) == EOK )){ |
|
| - | 623 | // read all if only one fragment |
|
| - | 624 | ipc_data_read_start( socket->phone, data, datalength ); |
|
| - | 625 | } |
|
| 623 | } |
626 | } |
| 624 | async_wait_for( message_id, ( ipcarg_t * ) & result ); |
627 | async_wait_for( message_id, ( ipcarg_t * ) & result ); |
| 625 | // if successful |
628 | // if successful |
| 626 | if( result == EOK ){ |
629 | if( result == EOK ){ |
| 627 | // dequeue the received packet |
630 | // dequeue the received packet |
| Line 644... | Line 647... | ||
| 644 | if( !( * optlen )) return NO_DATA; |
647 | if( !( * optlen )) return NO_DATA; |
| 645 | // find the socket |
648 | // find the socket |
| 646 | socket = sockets_find( socket_get_sockets(), socket_id ); |
649 | socket = sockets_find( socket_get_sockets(), socket_id ); |
| 647 | if( ! socket ) return ENOTSOCK; |
650 | if( ! socket ) return ENOTSOCK; |
| 648 | // request option value |
651 | // request option value |
| 649 | message_id = async_send_3( socket->phone, NET_SOCKET_GETSOCKOPT, socket->socket_id, optname, socket->service, NULL ); |
652 | message_id = async_send_3( socket->phone, NET_SOCKET_GETSOCKOPT, ( ipcarg_t ) socket->socket_id, ( ipcarg_t ) optname, socket->service, NULL ); |
| 650 | // read the length |
653 | // read the length |
| 651 | if( ipc_data_read_start( socket->phone, optlen, sizeof( * optlen )) == EOK ){ |
654 | if( ipc_data_read_start( socket->phone, optlen, sizeof( * optlen )) == EOK ){ |
| 652 | // read the value |
655 | // read the value |
| 653 | ipc_data_read_start( socket->phone, value, * optlen ); |
656 | ipc_data_read_start( socket->phone, value, * optlen ); |
| 654 | } |
657 | } |
| Line 656... | Line 659... | ||
| 656 | return ( int ) result; |
659 | return ( int ) result; |
| 657 | } |
660 | } |
| 658 | 661 | ||
| 659 | int setsockopt( int socket_id, int level, int optname, const void * value, size_t optlen ){ |
662 | int setsockopt( int socket_id, int level, int optname, const void * value, size_t optlen ){ |
| 660 | // send the value |
663 | // send the value |
| 661 | return socket_send_data( socket_id, NET_SOCKET_SETSOCKOPT, optname, value, optlen ); |
664 | return socket_send_data( socket_id, NET_SOCKET_SETSOCKOPT, ( ipcarg_t ) optname, value, optlen ); |
| 662 | 665 | ||
| 663 | } |
666 | } |
| 664 | 667 | ||
| 665 | /** @} |
668 | /** @} |
| 666 | */ |
669 | */ |