Changeset eb522e8 in mainline for uspace/lib/c/generic/net/socket_client.c
- Timestamp:
- 2011-06-01T08:43:42Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 8d6c1f1
- Parents:
- 9e2e715 (diff), e51a514 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/generic/net/socket_client.c
r9e2e715 reb522e8 43 43 #include <stdlib.h> 44 44 #include <errno.h> 45 45 #include <task.h> 46 46 #include <ipc/services.h> 47 47 #include <ipc/socket.h> 48 49 48 #include <net/modules.h> 50 49 #include <net/in.h> … … 78 77 */ 79 78 typedef struct socket socket_t; 80 81 /** Type definition of the socket specific data pointer.82 * @see socket83 */84 typedef socket_t *socket_ref;85 79 86 80 /** Socket specific data. … … 162 156 163 157 /** Active sockets. */ 164 sockets_ refsockets;158 sockets_t *sockets; 165 159 166 160 /** Safety lock. … … 183 177 /** Returns the active sockets. 184 178 * 185 * @return sThe active sockets.186 */ 187 static sockets_ refsocket_get_sockets(void)179 * @return The active sockets. 180 */ 181 static sockets_t *socket_get_sockets(void) 188 182 { 189 183 if (!socket_globals.sockets) { 190 184 socket_globals.sockets = 191 (sockets_ ref) malloc(sizeof(sockets_t));185 (sockets_t *) malloc(sizeof(sockets_t)); 192 186 if (!socket_globals.sockets) 193 187 return NULL; … … 213 207 ipc_callid_t callid; 214 208 ipc_call_t call; 215 socket_ refsocket;209 socket_t *socket; 216 210 int rc; 217 211 … … 219 213 callid = async_get_call(&call); 220 214 221 switch (IPC_GET_ METHOD(call)) {215 switch (IPC_GET_IMETHOD(call)) { 222 216 case NET_SOCKET_RECEIVED: 223 217 case NET_SOCKET_ACCEPTED: … … 225 219 fibril_rwlock_read_lock(&socket_globals.lock); 226 220 227 / / find the socket221 /* Find the socket */ 228 222 socket = sockets_find(socket_get_sockets(), 229 223 SOCKET_GET_SOCKET_ID(call)); … … 234 228 } 235 229 236 switch (IPC_GET_ METHOD(call)) {230 switch (IPC_GET_IMETHOD(call)) { 237 231 case NET_SOCKET_RECEIVED: 238 232 fibril_mutex_lock(&socket->receive_lock); 239 / / push the number of received packet fragments233 /* Push the number of received packet fragments */ 240 234 rc = dyn_fifo_push(&socket->received, 241 235 SOCKET_GET_DATA_FRAGMENTS(call), 242 236 SOCKET_MAX_RECEIVED_SIZE); 243 237 if (rc == EOK) { 244 / / signal the received packet238 /* Signal the received packet */ 245 239 fibril_condvar_signal(&socket->receive_signal); 246 240 } … … 249 243 250 244 case NET_SOCKET_ACCEPTED: 251 / / push the new socket identifier245 /* Push the new socket identifier */ 252 246 fibril_mutex_lock(&socket->accept_lock); 253 247 rc = dyn_fifo_push(&socket->accepted, 1, 254 248 SOCKET_MAX_ACCEPTED_SIZE); 255 if (rc != EOK) {256 / / signal the accepted socket249 if (rc == EOK) { 250 /* Signal the accepted socket */ 257 251 fibril_condvar_signal(&socket->accept_signal); 258 252 } … … 269 263 fibril_rwlock_write_lock(&socket->sending_lock); 270 264 271 / / set the data fragment size265 /* Set the data fragment size */ 272 266 socket->data_fragment_size = 273 267 SOCKET_GET_DATA_FRAGMENT_SIZE(call); … … 283 277 } 284 278 285 ipc_answer_0(callid, (ipcarg_t) rc);279 async_answer_0(callid, (sysarg_t) rc); 286 280 goto loop; 287 281 } … … 291 285 * Connects to the TCP module if necessary. 292 286 * 293 * @return sThe TCP module phone.294 * @return sOther error codes as defined for the287 * @return The TCP module phone. 288 * @return Other error codes as defined for the 295 289 * bind_service_timeout() function. 296 290 */ … … 310 304 * Connects to the UDP module if necessary. 311 305 * 312 * @return sThe UDP module phone.313 * @return sOther error codes as defined for the306 * @return The UDP module phone. 307 * @return Other error codes as defined for the 314 308 * bind_service_timeout() function. 315 309 */ … … 327 321 /** Tries to find a new free socket identifier. 328 322 * 329 * @return sThe new socket identifier.330 * @return sELIMIT if there is no socket identifier available.323 * @return The new socket identifier. 324 * @return ELIMIT if there is no socket identifier available. 331 325 */ 332 326 static int socket_generate_new_id(void) 333 327 { 334 sockets_ refsockets;328 sockets_t *sockets; 335 329 int socket_id = 0; 336 330 int count; … … 347 341 socket_id = 1; 348 342 ++count; 349 / / only this branch for last_id343 /* Only this branch for last_id */ 350 344 } else { 351 345 if (socket_id < INT_MAX) { … … 372 366 */ 373 367 static void 374 socket_initialize(socket_ refsocket, int socket_id, int phone,368 socket_initialize(socket_t *socket, int socket_id, int phone, 375 369 services_t service) 376 370 { … … 392 386 * @param[in] type Socket type. 393 387 * @param[in] protocol Socket protocol. 394 * @return sThe socket identifier on success.395 * @return sEPFNOTSUPPORT if the protocol family is not supported.396 * @return sESOCKNOTSUPPORT if the socket type is not supported.397 * @return sEPROTONOSUPPORT if the protocol is not supported.398 * @return sENOMEM if there is not enough memory left.399 * @return sELIMIT if there was not a free socket identifier found388 * @return The socket identifier on success. 389 * @return EPFNOTSUPPORT if the protocol family is not supported. 390 * @return ESOCKNOTSUPPORT if the socket type is not supported. 391 * @return EPROTONOSUPPORT if the protocol is not supported. 392 * @return ENOMEM if there is not enough memory left. 393 * @return ELIMIT if there was not a free socket identifier found 400 394 * this time. 401 * @return sOther error codes as defined for the NET_SOCKET message.402 * @return sOther error codes as defined for the395 * @return Other error codes as defined for the NET_SOCKET message. 396 * @return Other error codes as defined for the 403 397 * bind_service_timeout() function. 404 398 */ 405 399 int socket(int domain, int type, int protocol) 406 400 { 407 socket_ refsocket;401 socket_t *socket; 408 402 int phone; 409 403 int socket_id; 410 404 services_t service; 411 ipcarg_t fragment_size;412 ipcarg_t header_size;405 sysarg_t fragment_size; 406 sysarg_t header_size; 413 407 int rc; 414 408 415 / / find the appropriate service409 /* Find the appropriate service */ 416 410 switch (domain) { 417 411 case PF_INET: … … 462 456 return phone; 463 457 464 / / create a new socket structure465 socket = (socket_ ref) malloc(sizeof(socket_t));458 /* Create a new socket structure */ 459 socket = (socket_t *) malloc(sizeof(socket_t)); 466 460 if (!socket) 467 461 return ENOMEM; … … 470 464 fibril_rwlock_write_lock(&socket_globals.lock); 471 465 472 / / request a new socket466 /* Request a new socket */ 473 467 socket_id = socket_generate_new_id(); 474 468 if (socket_id <= 0) { … … 489 483 socket->header_size = (size_t) header_size; 490 484 491 / / finish the new socket initialization485 /* Finish the new socket initialization */ 492 486 socket_initialize(socket, socket_id, phone, service); 493 / / store the new socket487 /* Store the new socket */ 494 488 rc = sockets_add(socket_get_sockets(), socket_id, socket); 495 489 … … 499 493 dyn_fifo_destroy(&socket->accepted); 500 494 free(socket); 501 async_msg_3(phone, NET_SOCKET_CLOSE, ( ipcarg_t) socket_id, 0,495 async_msg_3(phone, NET_SOCKET_CLOSE, (sysarg_t) socket_id, 0, 502 496 service); 503 497 return rc; … … 514 508 * @param[in] data The data to be sent. 515 509 * @param[in] datalength The data length. 516 * @return sEOK on success.517 * @return sENOTSOCK if the socket is not found.518 * @return sEBADMEM if the data parameter is NULL.519 * @return sNO_DATA if the datalength parameter is zero (0).520 * @return sOther error codes as defined for the spcific message.510 * @return EOK on success. 511 * @return ENOTSOCK if the socket is not found. 512 * @return EBADMEM if the data parameter is NULL. 513 * @return NO_DATA if the datalength parameter is zero (0). 514 * @return Other error codes as defined for the spcific message. 521 515 */ 522 516 static int 523 socket_send_data(int socket_id, ipcarg_t message, ipcarg_t arg2,517 socket_send_data(int socket_id, sysarg_t message, sysarg_t arg2, 524 518 const void *data, size_t datalength) 525 519 { 526 socket_ refsocket;520 socket_t *socket; 527 521 aid_t message_id; 528 ipcarg_t result;522 sysarg_t result; 529 523 530 524 if (!data) … … 536 530 fibril_rwlock_read_lock(&socket_globals.lock); 537 531 538 / / find the socket532 /* Find the socket */ 539 533 socket = sockets_find(socket_get_sockets(), socket_id); 540 534 if (!socket) { … … 543 537 } 544 538 545 / / request the message539 /* Request the message */ 546 540 message_id = async_send_3(socket->phone, message, 547 ( ipcarg_t) socket->socket_id, arg2, socket->service, NULL);548 / / send the address541 (sysarg_t) socket->socket_id, arg2, socket->service, NULL); 542 /* Send the address */ 549 543 async_data_write_start(socket->phone, data, datalength); 550 544 … … 559 553 * @param[in] my_addr The port address. 560 554 * @param[in] addrlen The address length. 561 * @return sEOK on success.562 * @return sENOTSOCK if the socket is not found.563 * @return sEBADMEM if the my_addr parameter is NULL.564 * @return sNO_DATA if the addlen parameter is zero.565 * @return sOther error codes as defined for the NET_SOCKET_BIND555 * @return EOK on success. 556 * @return ENOTSOCK if the socket is not found. 557 * @return EBADMEM if the my_addr parameter is NULL. 558 * @return NO_DATA if the addlen parameter is zero. 559 * @return Other error codes as defined for the NET_SOCKET_BIND 566 560 * message. 567 561 */ … … 571 565 return EINVAL; 572 566 573 / / send the address567 /* Send the address */ 574 568 return socket_send_data(socket_id, NET_SOCKET_BIND, 0, my_addr, 575 569 (size_t) addrlen); … … 580 574 * @param[in] socket_id Socket identifier. 581 575 * @param[in] backlog The maximum number of waiting sockets to be accepted. 582 * @return sEOK on success.583 * @return sEINVAL if the backlog parameter is not positive (<=0).584 * @return sENOTSOCK if the socket is not found.585 * @return sOther error codes as defined for the NET_SOCKET_LISTEN576 * @return EOK on success. 577 * @return EINVAL if the backlog parameter is not positive (<=0). 578 * @return ENOTSOCK if the socket is not found. 579 * @return Other error codes as defined for the NET_SOCKET_LISTEN 586 580 * message. 587 581 */ 588 582 int listen(int socket_id, int backlog) 589 583 { 590 socket_ refsocket;584 socket_t *socket; 591 585 int result; 592 586 … … 596 590 fibril_rwlock_read_lock(&socket_globals.lock); 597 591 598 / / find the socket592 /* Find the socket */ 599 593 socket = sockets_find(socket_get_sockets(), socket_id); 600 594 if (!socket) { … … 603 597 } 604 598 605 / / request listen backlog change599 /* Request listen backlog change */ 606 600 result = (int) async_req_3_0(socket->phone, NET_SOCKET_LISTEN, 607 ( ipcarg_t) socket->socket_id, (ipcarg_t) backlog, socket->service);601 (sysarg_t) socket->socket_id, (sysarg_t) backlog, socket->service); 608 602 609 603 fibril_rwlock_read_unlock(&socket_globals.lock); … … 618 612 * @param[out] cliaddr The remote client address. 619 613 * @param[in] addrlen The address length. 620 * @return sEOK on success.621 * @return sEBADMEM if the cliaddr or addrlen parameter is NULL.622 * @return sEINVAL if the backlog parameter is not positive (<=0).623 * @return sENOTSOCK if the socket is not found.624 * @return sOther error codes as defined for the NET_SOCKET_ACCEPT614 * @return EOK on success. 615 * @return EBADMEM if the cliaddr or addrlen parameter is NULL. 616 * @return EINVAL if the backlog parameter is not positive (<=0). 617 * @return ENOTSOCK if the socket is not found. 618 * @return Other error codes as defined for the NET_SOCKET_ACCEPT 625 619 * message. 626 620 */ 627 621 int accept(int socket_id, struct sockaddr * cliaddr, socklen_t * addrlen) 628 622 { 629 socket_ refsocket;630 socket_ refnew_socket;623 socket_t *socket; 624 socket_t *new_socket; 631 625 aid_t message_id; 632 ipcarg_t ipc_result;626 sysarg_t ipc_result; 633 627 int result; 634 628 ipc_call_t answer; … … 639 633 fibril_rwlock_write_lock(&socket_globals.lock); 640 634 641 / / find the socket635 /* Find the socket */ 642 636 socket = sockets_find(socket_get_sockets(), socket_id); 643 637 if (!socket) { … … 648 642 fibril_mutex_lock(&socket->accept_lock); 649 643 650 / / wait for an accepted socket644 /* Wait for an accepted socket */ 651 645 ++ socket->blocked; 652 646 while (dyn_fifo_value(&socket->accepted) <= 0) { 653 647 fibril_rwlock_write_unlock(&socket_globals.lock); 654 648 fibril_condvar_wait(&socket->accept_signal, &socket->accept_lock); 655 / / drop the accept lock to avoid deadlock649 /* Drop the accept lock to avoid deadlock */ 656 650 fibril_mutex_unlock(&socket->accept_lock); 657 651 fibril_rwlock_write_lock(&socket_globals.lock); … … 660 654 -- socket->blocked; 661 655 662 / / create a new scoket663 new_socket = (socket_ ref) malloc(sizeof(socket_t));656 /* Create a new socket */ 657 new_socket = (socket_t *) malloc(sizeof(socket_t)); 664 658 if (!new_socket) { 665 659 fibril_mutex_unlock(&socket->accept_lock); … … 686 680 } 687 681 688 / / request accept682 /* Request accept */ 689 683 message_id = async_send_5(socket->phone, NET_SOCKET_ACCEPT, 690 ( ipcarg_t) socket->socket_id, 0, socket->service, 0,684 (sysarg_t) socket->socket_id, 0, socket->service, 0, 691 685 new_socket->socket_id, &answer); 692 686 693 / / read address694 ipc_data_read_start(socket->phone, cliaddr, *addrlen);687 /* Read address */ 688 async_data_read_start(socket->phone, cliaddr, *addrlen); 695 689 fibril_rwlock_write_unlock(&socket_globals.lock); 696 690 async_wait_for(message_id, &ipc_result); … … 700 694 result = EINVAL; 701 695 702 / / dequeue the accepted socket if successful696 /* Dequeue the accepted socket if successful */ 703 697 dyn_fifo_pop(&socket->accepted); 704 / / set address length698 /* Set address length */ 705 699 *addrlen = SOCKET_GET_ADDRESS_LENGTH(answer); 706 700 new_socket->data_fragment_size = 707 701 SOCKET_GET_DATA_FRAGMENT_SIZE(answer); 708 702 } else if (result == ENOTSOCK) { 709 / / empty the queue if no accepted sockets703 /* Empty the queue if no accepted sockets */ 710 704 while (dyn_fifo_pop(&socket->accepted) > 0) 711 705 ; … … 721 715 * @param[in] serv_addr The remote server address. 722 716 * @param[in] addrlen The address length. 723 * @return sEOK on success.724 * @return sEBADMEM if the serv_addr parameter is NULL.725 * @return sNO_DATA if the addlen parameter is zero.726 * @return sENOTSOCK if the socket is not found.727 * @return sOther error codes as defined for the NET_SOCKET_CONNECT717 * @return EOK on success. 718 * @return EBADMEM if the serv_addr parameter is NULL. 719 * @return NO_DATA if the addlen parameter is zero. 720 * @return ENOTSOCK if the socket is not found. 721 * @return Other error codes as defined for the NET_SOCKET_CONNECT 728 722 * message. 729 723 */ … … 736 730 return EDESTADDRREQ; 737 731 738 / / send the address732 /* Send the address */ 739 733 return socket_send_data(socket_id, NET_SOCKET_CONNECT, 0, serv_addr, 740 734 addrlen); … … 745 739 * @param[in] socket The socket to be destroyed. 746 740 */ 747 static void socket_destroy(socket_ refsocket)741 static void socket_destroy(socket_t *socket) 748 742 { 749 743 int accepted_id; 750 744 751 / / destroy all accepted sockets745 /* Destroy all accepted sockets */ 752 746 while ((accepted_id = dyn_fifo_pop(&socket->accepted)) >= 0) 753 747 socket_destroy(sockets_find(socket_get_sockets(), accepted_id)); … … 755 749 dyn_fifo_destroy(&socket->received); 756 750 dyn_fifo_destroy(&socket->accepted); 757 sockets_exclude(socket_get_sockets(), socket->socket_id );751 sockets_exclude(socket_get_sockets(), socket->socket_id, free); 758 752 } 759 753 … … 761 755 * 762 756 * @param[in] socket_id Socket identifier. 763 * @return sEOK on success.764 * @return sENOTSOCK if the socket is not found.765 * @return sEINPROGRESS if there is another blocking function in757 * @return EOK on success. 758 * @return ENOTSOCK if the socket is not found. 759 * @return EINPROGRESS if there is another blocking function in 766 760 * progress. 767 * @return sOther error codes as defined for the NET_SOCKET_CLOSE761 * @return Other error codes as defined for the NET_SOCKET_CLOSE 768 762 * message. 769 763 */ 770 764 int closesocket(int socket_id) 771 765 { 772 socket_ refsocket;766 socket_t *socket; 773 767 int rc; 774 768 … … 785 779 } 786 780 787 / / request close781 /* Request close */ 788 782 rc = (int) async_req_3_0(socket->phone, NET_SOCKET_CLOSE, 789 ( ipcarg_t) socket->socket_id, 0, socket->service);783 (sysarg_t) socket->socket_id, 0, socket->service); 790 784 if (rc != EOK) { 791 785 fibril_rwlock_write_unlock(&socket_globals.lock); 792 786 return rc; 793 787 } 794 / / free the socket structure788 /* Free the socket structure */ 795 789 socket_destroy(socket); 796 790 … … 811 805 * sockets. 812 806 * @param[in] addrlen The address length. Used only if toaddr is not NULL. 813 * @return sEOK on success.814 * @return sENOTSOCK if the socket is not found.815 * @return sEBADMEM if the data or toaddr parameter is NULL.816 * @return sNO_DATA if the datalength or the addrlen parameter is807 * @return EOK on success. 808 * @return ENOTSOCK if the socket is not found. 809 * @return EBADMEM if the data or toaddr parameter is NULL. 810 * @return NO_DATA if the datalength or the addrlen parameter is 817 811 * zero (0). 818 * @return sOther error codes as defined for the NET_SOCKET_SENDTO812 * @return Other error codes as defined for the NET_SOCKET_SENDTO 819 813 * message. 820 814 */ 821 815 static int 822 sendto_core( ipcarg_t message, int socket_id, const void *data,816 sendto_core(sysarg_t message, int socket_id, const void *data, 823 817 size_t datalength, int flags, const struct sockaddr *toaddr, 824 818 socklen_t addrlen) 825 819 { 826 socket_ refsocket;820 socket_t *socket; 827 821 aid_t message_id; 828 ipcarg_t result;822 sysarg_t result; 829 823 size_t fragments; 830 824 ipc_call_t answer; … … 838 832 fibril_rwlock_read_lock(&socket_globals.lock); 839 833 840 / / find socket834 /* Find socket */ 841 835 socket = sockets_find(socket_get_sockets(), socket_id); 842 836 if (!socket) { … … 847 841 fibril_rwlock_read_lock(&socket->sending_lock); 848 842 849 / / compute data fragment count843 /* Compute data fragment count */ 850 844 if (socket->data_fragment_size > 0) { 851 845 fragments = (datalength + socket->header_size) / … … 858 852 } 859 853 860 / / request send854 /* Request send */ 861 855 message_id = async_send_5(socket->phone, message, 862 ( ipcarg_t) socket->socket_id,856 (sysarg_t) socket->socket_id, 863 857 (fragments == 1 ? datalength : socket->data_fragment_size), 864 socket->service, ( ipcarg_t) flags, fragments, &answer);865 866 / / send the address if given858 socket->service, (sysarg_t) flags, fragments, &answer); 859 860 /* Send the address if given */ 867 861 if (!toaddr || 868 862 (async_data_write_start(socket->phone, toaddr, addrlen) == EOK)) { 869 863 if (fragments == 1) { 870 / / send all if only one fragment864 /* Send all if only one fragment */ 871 865 async_data_write_start(socket->phone, data, datalength); 872 866 } else { 873 / / send the first fragment867 /* Send the first fragment */ 874 868 async_data_write_start(socket->phone, data, 875 869 socket->data_fragment_size - socket->header_size); … … 877 871 socket->data_fragment_size - socket->header_size; 878 872 879 / / send the middle fragments873 /* Send the middle fragments */ 880 874 while (--fragments > 1) { 881 875 async_data_write_start(socket->phone, data, … … 885 879 } 886 880 887 / / send the last fragment881 /* Send the last fragment */ 888 882 async_data_write_start(socket->phone, data, 889 883 (datalength + socket->header_size) % … … 897 891 (SOCKET_GET_DATA_FRAGMENT_SIZE(answer) != 898 892 socket->data_fragment_size)) { 899 / / set the data fragment size893 /* Set the data fragment size */ 900 894 socket->data_fragment_size = 901 895 SOCKET_GET_DATA_FRAGMENT_SIZE(answer); … … 913 907 * @param[in] datalength The data length. 914 908 * @param[in] flags Various send flags. 915 * @return sEOK on success.916 * @return sENOTSOCK if the socket is not found.917 * @return sEBADMEM if the data parameter is NULL.918 * @return sNO_DATA if the datalength parameter is zero.919 * @return sOther error codes as defined for the NET_SOCKET_SEND909 * @return EOK on success. 910 * @return ENOTSOCK if the socket is not found. 911 * @return EBADMEM if the data parameter is NULL. 912 * @return NO_DATA if the datalength parameter is zero. 913 * @return Other error codes as defined for the NET_SOCKET_SEND 920 914 * message. 921 915 */ 922 916 int send(int socket_id, void *data, size_t datalength, int flags) 923 917 { 924 / / without the address918 /* Without the address */ 925 919 return sendto_core(NET_SOCKET_SEND, socket_id, data, datalength, flags, 926 920 NULL, 0); … … 937 931 * @param[in] toaddr The destination address. 938 932 * @param[in] addrlen The address length. 939 * @return sEOK on success.940 * @return sENOTSOCK if the socket is not found.941 * @return sEBADMEM if the data or toaddr parameter is NULL.942 * @return sNO_DATA if the datalength or the addrlen parameter is933 * @return EOK on success. 934 * @return ENOTSOCK if the socket is not found. 935 * @return EBADMEM if the data or toaddr parameter is NULL. 936 * @return NO_DATA if the datalength or the addrlen parameter is 943 937 * zero. 944 * @return sOther error codes as defined for the NET_SOCKET_SENDTO938 * @return Other error codes as defined for the NET_SOCKET_SENDTO 945 939 * message. 946 940 */ … … 955 949 return EDESTADDRREQ; 956 950 957 / / with the address951 /* With the address */ 958 952 return sendto_core(NET_SOCKET_SENDTO, socket_id, data, datalength, 959 953 flags, toaddr, addrlen); … … 971 965 * read. The actual address length is set. Used only if 972 966 * fromaddr is not NULL. 973 * @returns EOK on success. 974 * @returns ENOTSOCK if the socket is not found. 975 * @returns EBADMEM if the data parameter is NULL. 976 * @returns NO_DATA if the datalength or addrlen parameter is zero. 977 * @returns Other error codes as defined for the spcific message. 978 */ 979 static int 980 recvfrom_core(ipcarg_t message, int socket_id, void *data, size_t datalength, 967 * @return Positive received message size in bytes on success. 968 * @return Zero if no more data (other side closed the connection). 969 * @return ENOTSOCK if the socket is not found. 970 * @return EBADMEM if the data parameter is NULL. 971 * @return NO_DATA if the datalength or addrlen parameter is zero. 972 * @return Other error codes as defined for the spcific message. 973 */ 974 static ssize_t 975 recvfrom_core(sysarg_t message, int socket_id, void *data, size_t datalength, 981 976 int flags, struct sockaddr *fromaddr, socklen_t *addrlen) 982 977 { 983 socket_ refsocket;978 socket_t *socket; 984 979 aid_t message_id; 985 ipcarg_t ipc_result;980 sysarg_t ipc_result; 986 981 int result; 987 982 size_t fragments; … … 989 984 size_t index; 990 985 ipc_call_t answer; 986 ssize_t retval; 991 987 992 988 if (!data) … … 1001 997 fibril_rwlock_read_lock(&socket_globals.lock); 1002 998 1003 / / find the socket999 /* Find the socket */ 1004 1000 socket = sockets_find(socket_get_sockets(), socket_id); 1005 1001 if (!socket) { … … 1009 1005 1010 1006 fibril_mutex_lock(&socket->receive_lock); 1011 / / wait for a received packet1007 /* Wait for a received packet */ 1012 1008 ++socket->blocked; 1013 while ((result = dyn_fifo_value(&socket->received)) < =0) {1009 while ((result = dyn_fifo_value(&socket->received)) < 0) { 1014 1010 fibril_rwlock_read_unlock(&socket_globals.lock); 1015 1011 fibril_condvar_wait(&socket->receive_signal, 1016 1012 &socket->receive_lock); 1017 1013 1018 / / drop the receive lock to avoid deadlock1014 /* Drop the receive lock to avoid deadlock */ 1019 1015 fibril_mutex_unlock(&socket->receive_lock); 1020 1016 fibril_rwlock_read_lock(&socket_globals.lock); … … 1024 1020 fragments = (size_t) result; 1025 1021 1026 // prepare lengths if more fragments 1022 if (fragments == 0) { 1023 /* No more data, other side has closed the connection. */ 1024 fibril_mutex_unlock(&socket->receive_lock); 1025 fibril_rwlock_read_unlock(&socket_globals.lock); 1026 return 0; 1027 } 1028 1029 /* Prepare lengths if more fragments */ 1027 1030 if (fragments > 1) { 1028 1031 lengths = (size_t *) malloc(sizeof(size_t) * fragments + … … 1034 1037 } 1035 1038 1036 / / request packet data1039 /* Request packet data */ 1037 1040 message_id = async_send_4(socket->phone, message, 1038 ( ipcarg_t) socket->socket_id, 0, socket->service,1039 ( ipcarg_t) flags, &answer);1040 1041 / / read the address if desired1041 (sysarg_t) socket->socket_id, 0, socket->service, 1042 (sysarg_t) flags, &answer); 1043 1044 /* Read the address if desired */ 1042 1045 if(!fromaddr || 1043 1046 (async_data_read_start(socket->phone, fromaddr, 1044 1047 *addrlen) == EOK)) { 1045 / / read the fragment lengths1048 /* Read the fragment lengths */ 1046 1049 if (async_data_read_start(socket->phone, lengths, 1047 1050 sizeof(int) * (fragments + 1)) == EOK) { 1048 1051 if (lengths[fragments] <= datalength) { 1049 1052 1050 / / read all fragments if long enough1053 /* Read all fragments if long enough */ 1051 1054 for (index = 0; index < fragments; 1052 1055 ++index) { … … 1062 1065 1063 1066 free(lengths); 1064 } else { 1065 / / request packet data1067 } else { /* fragments == 1 */ 1068 /* Request packet data */ 1066 1069 message_id = async_send_4(socket->phone, message, 1067 ( ipcarg_t) socket->socket_id, 0, socket->service,1068 ( ipcarg_t) flags, &answer);1069 1070 / / read the address if desired1070 (sysarg_t) socket->socket_id, 0, socket->service, 1071 (sysarg_t) flags, &answer); 1072 1073 /* Read the address if desired */ 1071 1074 if (!fromaddr || 1072 1075 (async_data_read_start(socket->phone, fromaddr, 1073 1076 *addrlen) == EOK)) { 1074 / / read all if only one fragment1077 /* Read all if only one fragment */ 1075 1078 async_data_read_start(socket->phone, data, datalength); 1076 1079 } … … 1080 1083 result = (int) ipc_result; 1081 1084 if (result == EOK) { 1082 / / dequeue the received packet1085 /* Dequeue the received packet */ 1083 1086 dyn_fifo_pop(&socket->received); 1084 / / return read data length1085 re sult= SOCKET_GET_READ_DATA_LENGTH(answer);1086 / / set address length1087 /* Return read data length */ 1088 retval = SOCKET_GET_READ_DATA_LENGTH(answer); 1089 /* Set address length */ 1087 1090 if (fromaddr && addrlen) 1088 1091 *addrlen = SOCKET_GET_ADDRESS_LENGTH(answer); 1092 } else { 1093 retval = (ssize_t) result; 1089 1094 } 1090 1095 1091 1096 fibril_mutex_unlock(&socket->receive_lock); 1092 1097 fibril_rwlock_read_unlock(&socket_globals.lock); 1093 return re sult;1098 return retval; 1094 1099 } 1095 1100 … … 1100 1105 * @param[in] datalength The data length. 1101 1106 * @param[in] flags Various receive flags. 1102 * @returns EOK on success. 1103 * @returns ENOTSOCK if the socket is not found. 1104 * @returns EBADMEM if the data parameter is NULL. 1105 * @returns NO_DATA if the datalength parameter is zero. 1106 * @returns Other error codes as defined for the NET_SOCKET_RECV 1107 * @return Positive received message size in bytes on success. 1108 * @return Zero if no more data (other side closed the connection). 1109 * @return ENOTSOCK if the socket is not found. 1110 * @return EBADMEM if the data parameter is NULL. 1111 * @return NO_DATA if the datalength parameter is zero. 1112 * @return Other error codes as defined for the NET_SOCKET_RECV 1107 1113 * message. 1108 1114 */ 1109 int recv(int socket_id, void *data, size_t datalength, int flags)1110 { 1111 / / without the address1115 ssize_t recv(int socket_id, void *data, size_t datalength, int flags) 1116 { 1117 /* Without the address */ 1112 1118 return recvfrom_core(NET_SOCKET_RECV, socket_id, data, datalength, 1113 1119 flags, NULL, NULL); … … 1123 1129 * @param[in,out] addrlen The address length. The maximum address length is 1124 1130 * read. The actual address length is set. 1125 * @returns EOK on success. 1126 * @returns ENOTSOCK if the socket is not found. 1127 * @returns EBADMEM if the data or fromaddr parameter is NULL. 1128 * @returns NO_DATA if the datalength or addrlen parameter is zero. 1129 * @returns Other error codes as defined for the NET_SOCKET_RECVFROM 1131 * @return Positive received message size in bytes on success. 1132 * @return Zero if no more data (other side closed the connection). 1133 * @return ENOTSOCK if the socket is not found. 1134 * @return EBADMEM if the data or fromaddr parameter is NULL. 1135 * @return NO_DATA if the datalength or addrlen parameter is zero. 1136 * @return Other error codes as defined for the NET_SOCKET_RECVFROM 1130 1137 * message. 1131 1138 */ 1132 int1139 ssize_t 1133 1140 recvfrom(int socket_id, void *data, size_t datalength, int flags, 1134 1141 struct sockaddr *fromaddr, socklen_t *addrlen) … … 1140 1147 return NO_DATA; 1141 1148 1142 / / with the address1149 /* With the address */ 1143 1150 return recvfrom_core(NET_SOCKET_RECVFROM, socket_id, data, datalength, 1144 1151 flags, fromaddr, addrlen); … … 1153 1160 * @param[in,out] optlen The value buffer length. The maximum length is read. 1154 1161 * The actual length is set. 1155 * @return sEOK on success.1156 * @return sENOTSOCK if the socket is not found.1157 * @return sEBADMEM if the value or optlen parameter is NULL.1158 * @return sNO_DATA if the optlen parameter is zero.1159 * @return sOther error codes as defined for the1162 * @return EOK on success. 1163 * @return ENOTSOCK if the socket is not found. 1164 * @return EBADMEM if the value or optlen parameter is NULL. 1165 * @return NO_DATA if the optlen parameter is zero. 1166 * @return Other error codes as defined for the 1160 1167 * NET_SOCKET_GETSOCKOPT message. 1161 1168 */ … … 1163 1170 getsockopt(int socket_id, int level, int optname, void *value, size_t *optlen) 1164 1171 { 1165 socket_ refsocket;1172 socket_t *socket; 1166 1173 aid_t message_id; 1167 ipcarg_t result;1174 sysarg_t result; 1168 1175 1169 1176 if (!value || !optlen) … … 1175 1182 fibril_rwlock_read_lock(&socket_globals.lock); 1176 1183 1177 / / find the socket1184 /* Find the socket */ 1178 1185 socket = sockets_find(socket_get_sockets(), socket_id); 1179 1186 if (!socket) { … … 1182 1189 } 1183 1190 1184 / / request option value1191 /* Request option value */ 1185 1192 message_id = async_send_3(socket->phone, NET_SOCKET_GETSOCKOPT, 1186 ( ipcarg_t) socket->socket_id, (ipcarg_t) optname, socket->service,1193 (sysarg_t) socket->socket_id, (sysarg_t) optname, socket->service, 1187 1194 NULL); 1188 1195 1189 / / read the length1196 /* Read the length */ 1190 1197 if (async_data_read_start(socket->phone, optlen, 1191 1198 sizeof(*optlen)) == EOK) { 1192 / / read the value1199 /* Read the value */ 1193 1200 async_data_read_start(socket->phone, value, *optlen); 1194 1201 } … … 1206 1213 * @param[in] value The value to be set. 1207 1214 * @param[in] optlen The value length. 1208 * @return sEOK on success.1209 * @return sENOTSOCK if the socket is not found.1210 * @return sEBADMEM if the value parameter is NULL.1211 * @return sNO_DATA if the optlen parameter is zero.1212 * @return sOther error codes as defined for the1215 * @return EOK on success. 1216 * @return ENOTSOCK if the socket is not found. 1217 * @return EBADMEM if the value parameter is NULL. 1218 * @return NO_DATA if the optlen parameter is zero. 1219 * @return Other error codes as defined for the 1213 1220 * NET_SOCKET_SETSOCKOPT message. 1214 1221 */ … … 1217 1224 size_t optlen) 1218 1225 { 1219 / / send the value1226 /* Send the value */ 1220 1227 return socket_send_data(socket_id, NET_SOCKET_SETSOCKOPT, 1221 ( ipcarg_t) optname, value, optlen);1228 (sysarg_t) optname, value, optlen); 1222 1229 } 1223 1230
Note:
See TracChangeset
for help on using the changeset viewer.