Changes in uspace/srv/net/tl/udp/udp.c [348c589:fb04cba8] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/net/tl/udp/udp.c
r348c589 rfb04cba8 36 36 */ 37 37 38 #include "udp.h" 39 #include "udp_header.h" 40 #include "udp_module.h" 41 38 42 #include <async.h> 39 43 #include <fibril_synch.h> 40 44 #include <malloc.h> 41 45 #include <stdio.h> 46 #include <ipc/ipc.h> 42 47 #include <ipc/services.h> 43 48 #include <ipc/net.h> … … 60 65 #include <ip_interface.h> 61 66 #include <icmp_client.h> 62 #include <icmp_ remote.h>67 #include <icmp_interface.h> 63 68 #include <net_interface.h> 64 69 #include <socket_core.h> 65 70 #include <tl_common.h> 66 #include <tl_remote.h> 67 #include <tl_skel.h> 68 69 #include "udp.h" 70 #include "udp_header.h" 71 #include <tl_local.h> 72 #include <tl_interface.h> 71 73 72 74 /** UDP module name. */ 73 #define NAME "udp"75 #define NAME "UDP protocol" 74 76 75 77 /** Default UDP checksum computing. */ … … 90 92 /** UDP global data. */ 91 93 udp_globals_t udp_globals; 94 95 /** Initializes the UDP module. 96 * 97 * @param[in] client_connection The client connection processing function. The 98 * module skeleton propagates its own one. 99 * @returns EOK on success. 100 * @returns ENOMEM if there is not enough memory left. 101 */ 102 int udp_initialize(async_client_conn_t client_connection) 103 { 104 measured_string_t names[] = { 105 { 106 (char *) "UDP_CHECKSUM_COMPUTING", 107 22 108 }, 109 { 110 (char *) "UDP_AUTOBINDING", 111 15 112 } 113 }; 114 measured_string_ref configuration; 115 size_t count = sizeof(names) / sizeof(measured_string_t); 116 char *data; 117 int rc; 118 119 fibril_rwlock_initialize(&udp_globals.lock); 120 fibril_rwlock_write_lock(&udp_globals.lock); 121 122 udp_globals.icmp_phone = icmp_connect_module(SERVICE_ICMP, 123 ICMP_CONNECT_TIMEOUT); 124 125 udp_globals.ip_phone = ip_bind_service(SERVICE_IP, IPPROTO_UDP, 126 SERVICE_UDP, client_connection); 127 if (udp_globals.ip_phone < 0) { 128 fibril_rwlock_write_unlock(&udp_globals.lock); 129 return udp_globals.ip_phone; 130 } 131 132 /* Read default packet dimensions */ 133 rc = ip_packet_size_req(udp_globals.ip_phone, -1, 134 &udp_globals.packet_dimension); 135 if (rc != EOK) { 136 fibril_rwlock_write_unlock(&udp_globals.lock); 137 return rc; 138 } 139 140 rc = socket_ports_initialize(&udp_globals.sockets); 141 if (rc != EOK) { 142 fibril_rwlock_write_unlock(&udp_globals.lock); 143 return rc; 144 } 145 146 rc = packet_dimensions_initialize(&udp_globals.dimensions); 147 if (rc != EOK) { 148 socket_ports_destroy(&udp_globals.sockets); 149 fibril_rwlock_write_unlock(&udp_globals.lock); 150 return rc; 151 } 152 153 udp_globals.packet_dimension.prefix += sizeof(udp_header_t); 154 udp_globals.packet_dimension.content -= sizeof(udp_header_t); 155 udp_globals.last_used_port = UDP_FREE_PORTS_START - 1; 156 157 udp_globals.checksum_computing = NET_DEFAULT_UDP_CHECKSUM_COMPUTING; 158 udp_globals.autobinding = NET_DEFAULT_UDP_AUTOBINDING; 159 160 /* Get configuration */ 161 configuration = &names[0]; 162 rc = net_get_conf_req(udp_globals.net_phone, &configuration, count, 163 &data); 164 if (rc != EOK) { 165 socket_ports_destroy(&udp_globals.sockets); 166 fibril_rwlock_write_unlock(&udp_globals.lock); 167 return rc; 168 } 169 170 if (configuration) { 171 if (configuration[0].value) 172 udp_globals.checksum_computing = 173 (configuration[0].value[0] == 'y'); 174 175 if (configuration[1].value) 176 udp_globals.autobinding = 177 (configuration[1].value[0] == 'y'); 178 179 net_free_settings(configuration, data); 180 } 181 182 fibril_rwlock_write_unlock(&udp_globals.lock); 183 return EOK; 184 } 92 185 93 186 /** Releases the packet and returns the result. … … 97 190 * @return The result parameter. 98 191 */ 99 static int udp_release_and_return(packet_t *packet, int result)192 static int udp_release_and_return(packet_t packet, int result) 100 193 { 101 194 pq_release_remote(udp_globals.net_phone, packet_get_id(packet)); … … 112 205 * @param[in] error The packet error reporting service. Prefixes the 113 206 * received packet. 114 * @return EOK on success.115 * @return EINVAL if the packet is not valid.116 * @return EINVAL if the stored packet address is not the207 * @returns EOK on success. 208 * @returns EINVAL if the packet is not valid. 209 * @returns EINVAL if the stored packet address is not the 117 210 * an_addr_t. 118 * @return EINVAL if the packet does not contain any data.119 * @return NO_DATA if the packet content is shorter than the user211 * @returns EINVAL if the packet does not contain any data. 212 * @returns NO_DATA if the packet content is shorter than the user 120 213 * datagram header. 121 * @return ENOMEM if there is not enough memory left.122 * @return EADDRNOTAVAIL if the destination socket does not exist.123 * @return Other error codes as defined for the214 * @returns ENOMEM if there is not enough memory left. 215 * @returns EADDRNOTAVAIL if the destination socket does not exist. 216 * @returns Other error codes as defined for the 124 217 * ip_client_process_packet() function. 125 218 */ 126 static int udp_process_packet(device_id_t device_id, packet_t *packet,219 static int udp_process_packet(device_id_t device_id, packet_t packet, 127 220 services_t error) 128 221 { … … 130 223 size_t offset; 131 224 int result; 132 udp_header_ t *header;133 socket_core_ t *socket;134 packet_t *next_packet;225 udp_header_ref header; 226 socket_core_ref socket; 227 packet_t next_packet; 135 228 size_t total_length; 136 229 uint32_t checksum; 137 230 int fragments; 138 packet_t *tmp_packet;231 packet_t tmp_packet; 139 232 icmp_type_t type; 140 233 icmp_code_t code; … … 142 235 struct sockaddr *src; 143 236 struct sockaddr *dest; 144 packet_dimension_ t *packet_dimension;237 packet_dimension_ref packet_dimension; 145 238 int rc; 146 239 … … 184 277 185 278 /* Get UDP header */ 186 header = (udp_header_ t *) packet_get_data(packet);279 header = (udp_header_ref) packet_get_data(packet); 187 280 if (!header) 188 281 return udp_release_and_return(packet, NO_DATA); … … 190 283 /* Find the destination socket */ 191 284 socket = socket_port_find(&udp_globals.sockets, 192 ntohs(header->destination_port), (uint8_t *)SOCKET_MAP_KEY_LISTENING, 0);285 ntohs(header->destination_port), SOCKET_MAP_KEY_LISTENING, 0); 193 286 if (!socket) { 194 287 if (tl_prepare_icmp_packet(udp_globals.net_phone, … … 300 393 fibril_rwlock_write_unlock(&udp_globals.lock); 301 394 async_msg_5(socket->phone, NET_SOCKET_RECEIVED, 302 ( sysarg_t) socket->socket_id, packet_dimension->content, 0, 0,303 ( sysarg_t) fragments);395 (ipcarg_t) socket->socket_id, packet_dimension->content, 0, 0, 396 (ipcarg_t) fragments); 304 397 305 398 return EOK; … … 316 409 * @param[in] error The packet error reporting service. Prefixes the 317 410 * received packet. 318 * @return EOK on success.319 * @return Other error codes as defined for the411 * @returns EOK on success. 412 * @returns Other error codes as defined for the 320 413 * udp_process_packet() function. 321 414 */ 322 static int udp_received_msg(device_id_t device_id, packet_t *packet,415 static int udp_received_msg(device_id_t device_id, packet_t packet, 323 416 services_t receiver, services_t error) 324 417 { … … 331 424 332 425 return result; 333 }334 335 /** Process IPC messages from the IP module336 *337 * @param[in] iid Message identifier.338 * @param[in,out] icall Message parameters.339 *340 */341 static void udp_receiver(ipc_callid_t iid, ipc_call_t *icall)342 {343 packet_t *packet;344 int rc;345 346 while (true) {347 switch (IPC_GET_IMETHOD(*icall)) {348 case NET_TL_RECEIVED:349 rc = packet_translate_remote(udp_globals.net_phone, &packet,350 IPC_GET_PACKET(*icall));351 if (rc == EOK)352 rc = udp_received_msg(IPC_GET_DEVICE(*icall), packet,353 SERVICE_UDP, IPC_GET_ERROR(*icall));354 355 async_answer_0(iid, (sysarg_t) rc);356 break;357 default:358 async_answer_0(iid, (sysarg_t) ENOTSUP);359 }360 361 iid = async_get_call(icall);362 }363 }364 365 /** Initialize the UDP module.366 *367 * @param[in] net_phone Network module phone.368 *369 * @return EOK on success.370 * @return ENOMEM if there is not enough memory left.371 *372 */373 int tl_initialize(int net_phone)374 {375 measured_string_t names[] = {376 {377 (uint8_t *) "UDP_CHECKSUM_COMPUTING",378 22379 },380 {381 (uint8_t *) "UDP_AUTOBINDING",382 15383 }384 };385 measured_string_t *configuration;386 size_t count = sizeof(names) / sizeof(measured_string_t);387 uint8_t *data;388 389 fibril_rwlock_initialize(&udp_globals.lock);390 fibril_rwlock_write_lock(&udp_globals.lock);391 392 udp_globals.net_phone = net_phone;393 394 udp_globals.icmp_phone = icmp_connect_module(ICMP_CONNECT_TIMEOUT);395 396 udp_globals.ip_phone = ip_bind_service(SERVICE_IP, IPPROTO_UDP,397 SERVICE_UDP, udp_receiver);398 if (udp_globals.ip_phone < 0) {399 fibril_rwlock_write_unlock(&udp_globals.lock);400 return udp_globals.ip_phone;401 }402 403 /* Read default packet dimensions */404 int rc = ip_packet_size_req(udp_globals.ip_phone, -1,405 &udp_globals.packet_dimension);406 if (rc != EOK) {407 fibril_rwlock_write_unlock(&udp_globals.lock);408 return rc;409 }410 411 rc = socket_ports_initialize(&udp_globals.sockets);412 if (rc != EOK) {413 fibril_rwlock_write_unlock(&udp_globals.lock);414 return rc;415 }416 417 rc = packet_dimensions_initialize(&udp_globals.dimensions);418 if (rc != EOK) {419 socket_ports_destroy(&udp_globals.sockets, free);420 fibril_rwlock_write_unlock(&udp_globals.lock);421 return rc;422 }423 424 udp_globals.packet_dimension.prefix += sizeof(udp_header_t);425 udp_globals.packet_dimension.content -= sizeof(udp_header_t);426 udp_globals.last_used_port = UDP_FREE_PORTS_START - 1;427 428 udp_globals.checksum_computing = NET_DEFAULT_UDP_CHECKSUM_COMPUTING;429 udp_globals.autobinding = NET_DEFAULT_UDP_AUTOBINDING;430 431 /* Get configuration */432 configuration = &names[0];433 rc = net_get_conf_req(udp_globals.net_phone, &configuration, count,434 &data);435 if (rc != EOK) {436 socket_ports_destroy(&udp_globals.sockets, free);437 fibril_rwlock_write_unlock(&udp_globals.lock);438 return rc;439 }440 441 if (configuration) {442 if (configuration[0].value)443 udp_globals.checksum_computing =444 (configuration[0].value[0] == 'y');445 446 if (configuration[1].value)447 udp_globals.autobinding =448 (configuration[1].value[0] == 'y');449 450 net_free_settings(configuration, data);451 }452 453 fibril_rwlock_write_unlock(&udp_globals.lock);454 return EOK;455 426 } 456 427 … … 468 439 * @param[out] data_fragment_size The data fragment size in bytes. 469 440 * @param[in] flags Various send flags. 470 * @return EOK on success.471 * @return EAFNOTSUPPORT if the address family is not supported.472 * @return ENOTSOCK if the socket is not found.473 * @return EINVAL if the address is invalid.474 * @return ENOTCONN if the sending socket is not and cannot be441 * @returns EOK on success. 442 * @returns EAFNOTSUPPORT if the address family is not supported. 443 * @returns ENOTSOCK if the socket is not found. 444 * @returns EINVAL if the address is invalid. 445 * @returns ENOTCONN if the sending socket is not and cannot be 475 446 * bound. 476 * @return ENOMEM if there is not enough memory left.477 * @return Other error codes as defined for the447 * @returns ENOMEM if there is not enough memory left. 448 * @returns Other error codes as defined for the 478 449 * socket_read_packet_data() function. 479 * @return Other error codes as defined for the450 * @returns Other error codes as defined for the 480 451 * ip_client_prepare_packet() function. 481 * @return Other error codes as defined for the ip_send_msg()452 * @returns Other error codes as defined for the ip_send_msg() 482 453 * function. 483 454 */ 484 static int udp_sendto_message(socket_cores_ t *local_sockets, int socket_id,455 static int udp_sendto_message(socket_cores_ref local_sockets, int socket_id, 485 456 const struct sockaddr *addr, socklen_t addrlen, int fragments, 486 457 size_t *data_fragment_size, int flags) 487 458 { 488 socket_core_ t *socket;489 packet_t *packet;490 packet_t *next_packet;491 udp_header_ t *header;459 socket_core_ref socket; 460 packet_t packet; 461 packet_t next_packet; 462 udp_header_ref header; 492 463 int index; 493 464 size_t total_length; … … 498 469 size_t headerlen; 499 470 device_id_t device_id; 500 packet_dimension_t *packet_dimension; 501 size_t size; 471 packet_dimension_ref packet_dimension; 502 472 int rc; 503 504 /* In case of error, do not update the data fragment size. */505 *data_fragment_size = 0;506 473 507 474 rc = tl_get_address_port(addr, addrlen, &dest_port); … … 544 511 // } 545 512 546 /*547 * Update the data fragment size based on what the lower layers can548 * handle without fragmentation, but not more than the maximum allowed549 * for UDP.550 */551 size = MAX_UDP_FRAGMENT_SIZE;552 if (packet_dimension->content < size)553 size = packet_dimension->content;554 *data_fragment_size = size;555 556 513 /* Read the first packet fragment */ 557 514 result = tl_socket_read_packet_data(udp_globals.net_phone, &packet, … … 642 599 * @param[in] flags Various receive flags. 643 600 * @param[out] addrlen The source address length. 644 * @return The number of bytes received.645 * @return ENOTSOCK if the socket is not found.646 * @return NO_DATA if there are no received packets or data.647 * @return ENOMEM if there is not enough memory left.648 * @return EINVAL if the received address is not an IP address.649 * @return Other error codes as defined for the packet_translate()601 * @returns The number of bytes received. 602 * @returns ENOTSOCK if the socket is not found. 603 * @returns NO_DATA if there are no received packets or data. 604 * @returns ENOMEM if there is not enough memory left. 605 * @returns EINVAL if the received address is not an IP address. 606 * @returns Other error codes as defined for the packet_translate() 650 607 * function. 651 * @return Other error codes as defined for the data_reply()608 * @returns Other error codes as defined for the data_reply() 652 609 * function. 653 610 */ 654 static int udp_recvfrom_message(socket_cores_ t *local_sockets, int socket_id,611 static int udp_recvfrom_message(socket_cores_ref local_sockets, int socket_id, 655 612 int flags, size_t *addrlen) 656 613 { 657 socket_core_ t *socket;614 socket_core_ref socket; 658 615 int packet_id; 659 packet_t *packet;660 udp_header_ t *header;616 packet_t packet; 617 udp_header_ref header; 661 618 struct sockaddr *addr; 662 619 size_t length; … … 687 644 return udp_release_and_return(packet, NO_DATA); 688 645 } 689 header = (udp_header_ t *) data;646 header = (udp_header_ref) data; 690 647 691 648 /* Set the source address port */ … … 741 698 * @param[in] callid The message identifier. 742 699 * @param[in] call The message parameters. 743 * @return EOK on success.700 * @returns EOK on success. 744 701 * 745 702 * @see socket.h … … 750 707 bool keep_on_going = true; 751 708 socket_cores_t local_sockets; 752 int app_phone = IPC_GET_PHONE( call);709 int app_phone = IPC_GET_PHONE(&call); 753 710 struct sockaddr *addr; 754 711 int socket_id; … … 756 713 size_t size; 757 714 ipc_call_t answer; 758 size_t answer_count;759 packet_dimension_ t *packet_dimension;715 int answer_count; 716 packet_dimension_ref packet_dimension; 760 717 761 718 /* … … 785 742 786 743 /* Process the call */ 787 switch (IPC_GET_ IMETHOD(call)) {744 switch (IPC_GET_METHOD(call)) { 788 745 case IPC_M_PHONE_HUNGUP: 789 746 keep_on_going = false; … … 800 757 break; 801 758 802 size = MAX_UDP_FRAGMENT_SIZE;803 759 if (tl_get_ip_packet_dimension(udp_globals.ip_phone, 804 760 &udp_globals.dimensions, DEVICE_INVALID_ID, 805 761 &packet_dimension) == EOK) { 806 if (packet_dimension->content < size)807 size = packet_dimension->content;762 SOCKET_SET_DATA_FRAGMENT_SIZE(answer, 763 packet_dimension->content); 808 764 } 809 SOCKET_SET_DATA_FRAGMENT_SIZE(answer, size); 765 766 // SOCKET_SET_DATA_FRAGMENT_SIZE(answer, 767 // MAX_UDP_FRAGMENT_SIZE); 810 768 SOCKET_SET_HEADER_SIZE(answer, UDP_HEADER_SIZE); 811 769 answer_count = 3; … … 813 771 814 772 case NET_SOCKET_BIND: 815 res = async_data_write_accept((void **) &addr, false, 816 0, 0, 0, &addrlen); 773 res = data_receive((void **) &addr, &addrlen); 817 774 if (res != EOK) 818 775 break; … … 827 784 828 785 case NET_SOCKET_SENDTO: 829 res = async_data_write_accept((void **) &addr, false, 830 0, 0, 0, &addrlen); 786 res = data_receive((void **) &addr, &addrlen); 831 787 if (res != EOK) 832 788 break; … … 880 836 881 837 /* Release the application phone */ 882 async_hangup(app_phone);838 ipc_hangup(app_phone); 883 839 884 840 /* Release all local sockets */ … … 887 843 888 844 return res; 889 }890 891 /** Per-connection initialization892 *893 */894 void tl_connection(void)895 {896 845 } 897 846 … … 903 852 * @param[out] answer_count The last parameter for the actual answer in the 904 853 * answer parameter. 905 * @return EOK on success.906 * @return ENOTSUP if the message is not known.854 * @returns EOK on success. 855 * @returns ENOTSUP if the message is not known. 907 856 * 908 857 * @see udp_interface.h 909 858 * @see IS_NET_UDP_MESSAGE() 910 859 */ 911 int tl_message(ipc_callid_t callid, ipc_call_t *call,912 ipc_call_t *answer, size_t *answer_count)860 int udp_message_standalone(ipc_callid_t callid, ipc_call_t *call, 861 ipc_call_t *answer, int *answer_count) 913 862 { 863 packet_t packet; 864 int rc; 865 914 866 *answer_count = 0; 915 867 916 switch (IPC_GET_IMETHOD(*call)) { 868 switch (IPC_GET_METHOD(*call)) { 869 case NET_TL_RECEIVED: 870 rc = packet_translate_remote(udp_globals.net_phone, &packet, 871 IPC_GET_PACKET(call)); 872 if (rc != EOK) 873 return rc; 874 return udp_received_msg(IPC_GET_DEVICE(call), packet, 875 SERVICE_UDP, IPC_GET_ERROR(call)); 917 876 case IPC_M_CONNECT_TO_ME: 918 return udp_process_client_messages(callid, * call);877 return udp_process_client_messages(callid, * call); 919 878 } 920 879 … … 922 881 } 923 882 883 /** Default thread for new connections. 884 * 885 * @param[in] iid The initial message identifier. 886 * @param[in] icall The initial message call structure. 887 */ 888 static void tl_client_connection(ipc_callid_t iid, ipc_call_t * icall) 889 { 890 /* 891 * Accept the connection 892 * - Answer the first IPC_M_CONNECT_ME_TO call. 893 */ 894 ipc_answer_0(iid, EOK); 895 896 while (true) { 897 ipc_call_t answer; 898 int answer_count; 899 900 /* Clear the answer structure */ 901 refresh_answer(&answer, &answer_count); 902 903 /* Fetch the next message */ 904 ipc_call_t call; 905 ipc_callid_t callid = async_get_call(&call); 906 907 /* Process the message */ 908 int res = tl_module_message_standalone(callid, &call, &answer, 909 &answer_count); 910 911 /* 912 * End if told to either by the message or the processing 913 * result. 914 */ 915 if ((IPC_GET_METHOD(call) == IPC_M_PHONE_HUNGUP) || 916 (res == EHANGUP)) 917 return; 918 919 /* Answer the message */ 920 answer_call(callid, res, &answer, answer_count); 921 } 922 } 923 924 /** Starts the module. 925 * 926 * @returns EOK on success. 927 * @returns Other error codes as defined for each specific module 928 * start function. 929 */ 924 930 int main(int argc, char *argv[]) 925 931 { 932 int rc; 933 926 934 /* Start the module */ 927 return tl_module_start(SERVICE_UDP); 935 rc = tl_module_start_standalone(tl_client_connection); 936 return rc; 928 937 } 929 938
Note:
See TracChangeset
for help on using the changeset viewer.