Changeset eb522e8 in mainline for uspace/srv/net/tl/udp/udp.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/srv/net/tl/udp/udp.c
r9e2e715 reb522e8 36 36 */ 37 37 38 #include "udp.h"39 #include "udp_header.h"40 #include "udp_module.h"41 42 38 #include <async.h> 43 39 #include <fibril_synch.h> 44 40 #include <malloc.h> 45 41 #include <stdio.h> 46 #include <ipc/ipc.h>47 42 #include <ipc/services.h> 48 43 #include <ipc/net.h> … … 65 60 #include <ip_interface.h> 66 61 #include <icmp_client.h> 67 #include <icmp_ interface.h>62 #include <icmp_remote.h> 68 63 #include <net_interface.h> 69 64 #include <socket_core.h> 70 65 #include <tl_common.h> 71 #include <tl_local.h> 72 #include <tl_interface.h> 66 #include <tl_remote.h> 67 #include <tl_skel.h> 68 69 #include "udp.h" 70 #include "udp_header.h" 73 71 74 72 /** UDP module name. */ 75 #define NAME "UDP protocol"73 #define NAME "udp" 76 74 77 75 /** Default UDP checksum computing. */ … … 92 90 /** UDP global data. */ 93 91 udp_globals_t udp_globals; 94 95 /** Initializes the UDP module.96 *97 * @param[in] client_connection The client connection processing function. The98 * 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 22108 },109 {110 (char *) "UDP_AUTOBINDING",111 15112 }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 }185 92 186 93 /** Releases the packet and returns the result. … … 190 97 * @return The result parameter. 191 98 */ 192 static int udp_release_and_return(packet_t packet, int result)99 static int udp_release_and_return(packet_t *packet, int result) 193 100 { 194 101 pq_release_remote(udp_globals.net_phone, packet_get_id(packet)); … … 205 112 * @param[in] error The packet error reporting service. Prefixes the 206 113 * received packet. 207 * @return sEOK on success.208 * @return sEINVAL if the packet is not valid.209 * @return sEINVAL if the stored packet address is not the114 * @return EOK on success. 115 * @return EINVAL if the packet is not valid. 116 * @return EINVAL if the stored packet address is not the 210 117 * an_addr_t. 211 * @return sEINVAL if the packet does not contain any data.212 * @return sNO_DATA if the packet content is shorter than the user118 * @return EINVAL if the packet does not contain any data. 119 * @return NO_DATA if the packet content is shorter than the user 213 120 * datagram header. 214 * @return sENOMEM if there is not enough memory left.215 * @return sEADDRNOTAVAIL if the destination socket does not exist.216 * @return sOther error codes as defined for the121 * @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 the 217 124 * ip_client_process_packet() function. 218 125 */ 219 static int udp_process_packet(device_id_t device_id, packet_t packet,126 static int udp_process_packet(device_id_t device_id, packet_t *packet, 220 127 services_t error) 221 128 { … … 223 130 size_t offset; 224 131 int result; 225 udp_header_ refheader;226 socket_core_ refsocket;227 packet_t next_packet;132 udp_header_t *header; 133 socket_core_t *socket; 134 packet_t *next_packet; 228 135 size_t total_length; 229 136 uint32_t checksum; 230 137 int fragments; 231 packet_t tmp_packet;138 packet_t *tmp_packet; 232 139 icmp_type_t type; 233 140 icmp_code_t code; … … 235 142 struct sockaddr *src; 236 143 struct sockaddr *dest; 237 packet_dimension_ refpacket_dimension;144 packet_dimension_t *packet_dimension; 238 145 int rc; 239 146 … … 277 184 278 185 /* Get UDP header */ 279 header = (udp_header_ ref) packet_get_data(packet);186 header = (udp_header_t *) packet_get_data(packet); 280 187 if (!header) 281 188 return udp_release_and_return(packet, NO_DATA); … … 283 190 /* Find the destination socket */ 284 191 socket = socket_port_find(&udp_globals.sockets, 285 ntohs(header->destination_port),SOCKET_MAP_KEY_LISTENING, 0);192 ntohs(header->destination_port), (uint8_t *) SOCKET_MAP_KEY_LISTENING, 0); 286 193 if (!socket) { 287 194 if (tl_prepare_icmp_packet(udp_globals.net_phone, … … 393 300 fibril_rwlock_write_unlock(&udp_globals.lock); 394 301 async_msg_5(socket->phone, NET_SOCKET_RECEIVED, 395 ( ipcarg_t) socket->socket_id, packet_dimension->content, 0, 0,396 ( ipcarg_t) fragments);302 (sysarg_t) socket->socket_id, packet_dimension->content, 0, 0, 303 (sysarg_t) fragments); 397 304 398 305 return EOK; … … 409 316 * @param[in] error The packet error reporting service. Prefixes the 410 317 * received packet. 411 * @return sEOK on success.412 * @return sOther error codes as defined for the318 * @return EOK on success. 319 * @return Other error codes as defined for the 413 320 * udp_process_packet() function. 414 321 */ 415 static int udp_received_msg(device_id_t device_id, packet_t packet,322 static int udp_received_msg(device_id_t device_id, packet_t *packet, 416 323 services_t receiver, services_t error) 417 324 { … … 424 331 425 332 return result; 333 } 334 335 /** Process IPC messages from the IP module 336 * 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 22 379 }, 380 { 381 (uint8_t *) "UDP_AUTOBINDING", 382 15 383 } 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; 426 455 } 427 456 … … 439 468 * @param[out] data_fragment_size The data fragment size in bytes. 440 469 * @param[in] flags Various send flags. 441 * @return sEOK on success.442 * @return sEAFNOTSUPPORT if the address family is not supported.443 * @return sENOTSOCK if the socket is not found.444 * @return sEINVAL if the address is invalid.445 * @return sENOTCONN if the sending socket is not and cannot be470 * @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 be 446 475 * bound. 447 * @return sENOMEM if there is not enough memory left.448 * @return sOther error codes as defined for the476 * @return ENOMEM if there is not enough memory left. 477 * @return Other error codes as defined for the 449 478 * socket_read_packet_data() function. 450 * @return sOther error codes as defined for the479 * @return Other error codes as defined for the 451 480 * ip_client_prepare_packet() function. 452 * @return sOther error codes as defined for the ip_send_msg()481 * @return Other error codes as defined for the ip_send_msg() 453 482 * function. 454 483 */ 455 static int udp_sendto_message(socket_cores_ reflocal_sockets, int socket_id,484 static int udp_sendto_message(socket_cores_t *local_sockets, int socket_id, 456 485 const struct sockaddr *addr, socklen_t addrlen, int fragments, 457 486 size_t *data_fragment_size, int flags) 458 487 { 459 socket_core_ refsocket;460 packet_t packet;461 packet_t next_packet;462 udp_header_ refheader;488 socket_core_t *socket; 489 packet_t *packet; 490 packet_t *next_packet; 491 udp_header_t *header; 463 492 int index; 464 493 size_t total_length; … … 469 498 size_t headerlen; 470 499 device_id_t device_id; 471 packet_dimension_ref packet_dimension; 500 packet_dimension_t *packet_dimension; 501 size_t size; 472 502 int rc; 503 504 /* In case of error, do not update the data fragment size. */ 505 *data_fragment_size = 0; 473 506 474 507 rc = tl_get_address_port(addr, addrlen, &dest_port); … … 511 544 // } 512 545 546 /* 547 * Update the data fragment size based on what the lower layers can 548 * handle without fragmentation, but not more than the maximum allowed 549 * 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 513 556 /* Read the first packet fragment */ 514 557 result = tl_socket_read_packet_data(udp_globals.net_phone, &packet, … … 599 642 * @param[in] flags Various receive flags. 600 643 * @param[out] addrlen The source address length. 601 * @return sThe number of bytes received.602 * @return sENOTSOCK if the socket is not found.603 * @return sNO_DATA if there are no received packets or data.604 * @return sENOMEM if there is not enough memory left.605 * @return sEINVAL if the received address is not an IP address.606 * @return sOther error codes as defined for the packet_translate()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() 607 650 * function. 608 * @return sOther error codes as defined for the data_reply()651 * @return Other error codes as defined for the data_reply() 609 652 * function. 610 653 */ 611 static int udp_recvfrom_message(socket_cores_ reflocal_sockets, int socket_id,654 static int udp_recvfrom_message(socket_cores_t *local_sockets, int socket_id, 612 655 int flags, size_t *addrlen) 613 656 { 614 socket_core_ refsocket;657 socket_core_t *socket; 615 658 int packet_id; 616 packet_t packet;617 udp_header_ refheader;659 packet_t *packet; 660 udp_header_t *header; 618 661 struct sockaddr *addr; 619 662 size_t length; … … 644 687 return udp_release_and_return(packet, NO_DATA); 645 688 } 646 header = (udp_header_ ref) data;689 header = (udp_header_t *) data; 647 690 648 691 /* Set the source address port */ … … 698 741 * @param[in] callid The message identifier. 699 742 * @param[in] call The message parameters. 700 * @return sEOK on success.743 * @return EOK on success. 701 744 * 702 745 * @see socket.h … … 707 750 bool keep_on_going = true; 708 751 socket_cores_t local_sockets; 709 int app_phone = IPC_GET_PHONE( &call);752 int app_phone = IPC_GET_PHONE(call); 710 753 struct sockaddr *addr; 711 754 int socket_id; … … 713 756 size_t size; 714 757 ipc_call_t answer; 715 int answer_count;716 packet_dimension_ refpacket_dimension;758 size_t answer_count; 759 packet_dimension_t *packet_dimension; 717 760 718 761 /* … … 742 785 743 786 /* Process the call */ 744 switch (IPC_GET_ METHOD(call)) {787 switch (IPC_GET_IMETHOD(call)) { 745 788 case IPC_M_PHONE_HUNGUP: 746 789 keep_on_going = false; … … 757 800 break; 758 801 802 size = MAX_UDP_FRAGMENT_SIZE; 759 803 if (tl_get_ip_packet_dimension(udp_globals.ip_phone, 760 804 &udp_globals.dimensions, DEVICE_INVALID_ID, 761 805 &packet_dimension) == EOK) { 762 SOCKET_SET_DATA_FRAGMENT_SIZE(answer,763 packet_dimension->content);806 if (packet_dimension->content < size) 807 size = packet_dimension->content; 764 808 } 765 766 // SOCKET_SET_DATA_FRAGMENT_SIZE(answer, 767 // MAX_UDP_FRAGMENT_SIZE); 809 SOCKET_SET_DATA_FRAGMENT_SIZE(answer, size); 768 810 SOCKET_SET_HEADER_SIZE(answer, UDP_HEADER_SIZE); 769 811 answer_count = 3; … … 771 813 772 814 case NET_SOCKET_BIND: 773 res = data_receive((void **) &addr, &addrlen); 815 res = async_data_write_accept((void **) &addr, false, 816 0, 0, 0, &addrlen); 774 817 if (res != EOK) 775 818 break; … … 784 827 785 828 case NET_SOCKET_SENDTO: 786 res = data_receive((void **) &addr, &addrlen); 829 res = async_data_write_accept((void **) &addr, false, 830 0, 0, 0, &addrlen); 787 831 if (res != EOK) 788 832 break; … … 836 880 837 881 /* Release the application phone */ 838 ipc_hangup(app_phone);882 async_hangup(app_phone); 839 883 840 884 /* Release all local sockets */ … … 843 887 844 888 return res; 889 } 890 891 /** Per-connection initialization 892 * 893 */ 894 void tl_connection(void) 895 { 845 896 } 846 897 … … 852 903 * @param[out] answer_count The last parameter for the actual answer in the 853 904 * answer parameter. 854 * @return sEOK on success.855 * @return sENOTSUP if the message is not known.905 * @return EOK on success. 906 * @return ENOTSUP if the message is not known. 856 907 * 857 908 * @see udp_interface.h 858 909 * @see IS_NET_UDP_MESSAGE() 859 910 */ 860 int udp_message_standalone(ipc_callid_t callid, ipc_call_t *call, 861 ipc_call_t *answer, int *answer_count) 862 { 863 packet_t packet; 864 int rc; 865 911 int tl_message(ipc_callid_t callid, ipc_call_t *call, 912 ipc_call_t *answer, size_t *answer_count) 913 { 866 914 *answer_count = 0; 867 915 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)); 916 switch (IPC_GET_IMETHOD(*call)) { 876 917 case IPC_M_CONNECT_TO_ME: 877 return udp_process_client_messages(callid, * 918 return udp_process_client_messages(callid, *call); 878 919 } 879 920 … … 881 922 } 882 923 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 connection892 * - 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 processing913 * 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 module928 * start function.929 */930 924 int main(int argc, char *argv[]) 931 925 { 932 int rc;933 934 926 /* Start the module */ 935 rc = tl_module_start_standalone(tl_client_connection); 936 return rc; 927 return tl_module_start(SERVICE_UDP); 937 928 } 938 929
Note:
See TracChangeset
for help on using the changeset viewer.