Changeset b40bfac in mainline for uspace/srv/net/tl/udp/udp.c
- Timestamp:
- 2010-11-08T07:13:25Z (13 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade
- Children:
- 63a1e60
- Parents:
- d70a463 (diff), 3da12d74 (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
rd70a463 rb40bfac 28 28 29 29 /** @addtogroup udp 30 * 30 * @{ 31 31 */ 32 32 33 33 /** @file 34 * UDP module implementation. 35 * @see udp.h 36 */ 34 * UDP module implementation. 35 * @see udp.h 36 */ 37 38 #include "udp.h" 39 #include "udp_header.h" 40 #include "udp_module.h" 37 41 38 42 #include <async.h> … … 45 49 #include <ipc/tl.h> 46 50 #include <ipc/socket.h> 51 #include <adt/dynamic_fifo.h> 47 52 #include <errno.h> 48 #include <err.h>49 53 50 54 #include <net/socket_codes.h> … … 55 59 #include <net/modules.h> 56 60 57 #include <adt/dynamic_fifo.h>58 61 #include <packet_client.h> 59 62 #include <packet_remote.h> … … 69 72 #include <tl_interface.h> 70 73 71 #include "udp.h"72 #include "udp_header.h"73 #include "udp_module.h"74 75 74 /** UDP module name. */ 76 75 #define NAME "UDP protocol" … … 91 90 #define UDP_FREE_PORTS_END 65535 92 91 93 /** Processes the received UDP packet queue. 94 * 95 * Is used as an entry point from the underlying IP module. 96 * Locks the global lock and calls udp_process_packet() function. 97 * 98 * @param[in] device_id The receiving device identifier. 99 * @param[in,out] packet The received packet queue. 100 * @param receiver The target service. Ignored parameter. 101 * @param[in] error The packet error reporting service. Prefixes the 102 * received packet. 103 * @returns EOK on success. 104 * @returns Other error codes as defined for the 105 * udp_process_packet() function. 106 */ 107 int 108 udp_received_msg(device_id_t device_id, packet_t packet, services_t receiver, 109 services_t error); 110 111 /** Processes the received UDP packet queue. 112 * 113 * Notifies the destination socket application. 114 * Releases the packet on error or sends an ICMP error notification. 115 * 116 * @param[in] device_id The receiving device identifier. 117 * @param[in,out] packet The received packet queue. 118 * @param[in] error The packet error reporting service. Prefixes the 119 * received packet. 120 * @returns EOK on success. 121 * @returns EINVAL if the packet is not valid. 122 * @returns EINVAL if the stored packet address is not the 123 * an_addr_t. 124 * @returns EINVAL if the packet does not contain any data. 125 * @returns NO_DATA if the packet content is shorter than the user 126 * datagram header. 127 * @returns ENOMEM if there is not enough memory left. 128 * @returns EADDRNOTAVAIL if the destination socket does not exist. 129 * @returns Other error codes as defined for the 130 * ip_client_process_packet() function. 131 */ 132 int 133 udp_process_packet(device_id_t device_id, packet_t packet, services_t error); 134 135 /** Releases the packet and returns the result. 136 * 137 * @param[in] packet The packet queue to be released. 138 * @param[in] result The result to be returned. 139 * @return The result parameter. 140 */ 141 int udp_release_and_return(packet_t packet, int result); 142 143 /** @name Socket messages processing functions 144 */ 145 /*@{*/ 146 147 /** Processes the socket client messages. 148 * 149 * Runs until the client module disconnects. 150 * 151 * @param[in] callid The message identifier. 152 * @param[in] call The message parameters. 153 * @returns EOK on success. 154 * @see socket.h 155 */ 156 int udp_process_client_messages(ipc_callid_t callid, ipc_call_t call); 157 158 /** Sends data from the socket to the remote address. 159 * 160 * Binds the socket to a free port if not already connected/bound. 161 * Handles the NET_SOCKET_SENDTO message. 162 * Supports AF_INET and AF_INET6 address families. 163 * 164 * @param[in,out] local_sockets The application local sockets. 165 * @param[in] socket_id Socket identifier. 166 * @param[in] addr The destination address. 167 * @param[in] addrlen The address length. 168 * @param[in] fragments The number of data fragments. 169 * @param[out] data_fragment_size The data fragment size in bytes. 170 * @param[in] flags Various send flags. 171 * @returns EOK on success. 172 * @returns EAFNOTSUPPORT if the address family is not supported. 173 * @returns ENOTSOCK if the socket is not found. 174 * @returns EINVAL if the address is invalid. 175 * @returns ENOTCONN if the sending socket is not and cannot be 176 * bound. 177 * @returns ENOMEM if there is not enough memory left. 178 * @returns Other error codes as defined for the 179 * socket_read_packet_data() function. 180 * @returns Other error codes as defined for the 181 * ip_client_prepare_packet() function. 182 * @returns Other error codes as defined for the ip_send_msg() 183 * function. 184 */ 185 int 186 udp_sendto_message(socket_cores_ref local_sockets, int socket_id, 187 const struct sockaddr * addr, socklen_t addrlen, int fragments, 188 size_t * data_fragment_size, int flags); 189 190 /** Receives data to the socket. 191 * 192 * Handles the NET_SOCKET_RECVFROM message. 193 * Replies the source address as well. 194 * 195 * @param[in] local_sockets The application local sockets. 196 * @param[in] socket_id Socket identifier. 197 * @param[in] flags Various receive flags. 198 * @param[out] addrlen The source address length. 199 * @returns The number of bytes received. 200 * @returns ENOTSOCK if the socket is not found. 201 * @returns NO_DATA if there are no received packets or data. 202 * @returns ENOMEM if there is not enough memory left. 203 * @returns EINVAL if the received address is not an IP address. 204 * @returns Other error codes as defined for the packet_translate() 205 * function. 206 * @returns Other error codes as defined for the data_reply() 207 * function. 208 */ 209 int 210 udp_recvfrom_message(socket_cores_ref local_sockets, int socket_id, int flags, 211 size_t * addrlen); 212 213 /*@}*/ 214 215 /** UDP global data. 216 */ 92 /** UDP global data. */ 217 93 udp_globals_t udp_globals; 218 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 */ 219 102 int udp_initialize(async_client_conn_t client_connection) 220 103 { 221 ERROR_DECLARE;222 223 104 measured_string_t names[] = { 224 105 { 225 str_dup("UDP_CHECKSUM_COMPUTING"),106 (char *) "UDP_CHECKSUM_COMPUTING", 226 107 22 227 108 }, 228 109 { 229 str_dup("UDP_AUTOBINDING"),110 (char *) "UDP_AUTOBINDING", 230 111 15 231 112 } … … 233 114 measured_string_ref configuration; 234 115 size_t count = sizeof(names) / sizeof(measured_string_t); 235 char * data; 116 char *data; 117 int rc; 236 118 237 119 fibril_rwlock_initialize(&udp_globals.lock); … … 240 122 udp_globals.icmp_phone = icmp_connect_module(SERVICE_ICMP, 241 123 ICMP_CONNECT_TIMEOUT); 124 242 125 udp_globals.ip_phone = ip_bind_service(SERVICE_IP, IPPROTO_UDP, 243 126 SERVICE_UDP, client_connection); 244 if (udp_globals.ip_phone < 0) 127 if (udp_globals.ip_phone < 0) { 128 fibril_rwlock_write_unlock(&udp_globals.lock); 245 129 return udp_globals.ip_phone; 130 } 246 131 247 132 // read default packet dimensions 248 ERROR_PROPAGATE(ip_packet_size_req(udp_globals.ip_phone, -1, 249 &udp_globals.packet_dimension)); 250 ERROR_PROPAGATE(socket_ports_initialize(&udp_globals.sockets)); 251 if (ERROR_OCCURRED(packet_dimensions_initialize( 252 &udp_globals.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) { 253 148 socket_ports_destroy(&udp_globals.sockets); 254 return ERROR_CODE; 255 } 149 fibril_rwlock_write_unlock(&udp_globals.lock); 150 return rc; 151 } 152 256 153 udp_globals.packet_dimension.prefix += sizeof(udp_header_t); 257 154 udp_globals.packet_dimension.content -= sizeof(udp_header_t); 258 155 udp_globals.last_used_port = UDP_FREE_PORTS_START - 1; 259 156 260 // get configuration261 157 udp_globals.checksum_computing = NET_DEFAULT_UDP_CHECKSUM_COMPUTING; 262 158 udp_globals.autobinding = NET_DEFAULT_UDP_AUTOBINDING; 159 160 // get configuration 263 161 configuration = &names[0]; 264 ERROR_PROPAGATE(net_get_conf_req(udp_globals.net_phone, &configuration, 265 count, &data)); 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 266 170 if (configuration) { 267 171 if (configuration[0].value) … … 280 184 } 281 185 282 int 283 udp_received_msg(device_id_t device_id, packet_t packet, services_t receiver, 284 services_t error) 186 /** Releases the packet and returns the result. 187 * 188 * @param[in] packet The packet queue to be released. 189 * @param[in] result The result to be returned. 190 * @return The result parameter. 191 */ 192 static int udp_release_and_return(packet_t packet, int result) 285 193 { 286 int result; 287 288 fibril_rwlock_write_lock(&udp_globals.lock); 289 result = udp_process_packet(device_id, packet, error); 290 if (result != EOK) 291 fibril_rwlock_write_unlock(&udp_globals.lock); 292 194 pq_release_remote(udp_globals.net_phone, packet_get_id(packet)); 293 195 return result; 294 196 } 295 197 296 int udp_process_packet(device_id_t device_id, packet_t packet, services_t error) 198 /** Processes the received UDP packet queue. 199 * 200 * Notifies the destination socket application. 201 * Releases the packet on error or sends an ICMP error notification. 202 * 203 * @param[in] device_id The receiving device identifier. 204 * @param[in,out] packet The received packet queue. 205 * @param[in] error The packet error reporting service. Prefixes the 206 * received packet. 207 * @returns EOK on success. 208 * @returns EINVAL if the packet is not valid. 209 * @returns EINVAL if the stored packet address is not the 210 * an_addr_t. 211 * @returns EINVAL if the packet does not contain any data. 212 * @returns NO_DATA if the packet content is shorter than the user 213 * datagram header. 214 * @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 217 * ip_client_process_packet() function. 218 */ 219 static int 220 udp_process_packet(device_id_t device_id, packet_t packet, services_t error) 297 221 { 298 ERROR_DECLARE;299 300 222 size_t length; 301 223 size_t offset; … … 314 236 struct sockaddr *dest; 315 237 packet_dimension_ref packet_dimension; 316 317 if (error) { 318 switch (error) { 319 case SERVICE_ICMP: 320 // ignore error 321 // length = icmp_client_header_length(packet); 322 // process error 323 result = icmp_client_process_packet(packet, &type, 324 &code, NULL, NULL); 325 if (result < 0) 326 return udp_release_and_return(packet, result); 327 length = (size_t) result; 328 if (ERROR_OCCURRED(packet_trim(packet, length, 0))) 329 return udp_release_and_return(packet, 330 ERROR_CODE); 331 break; 332 default: 333 return udp_release_and_return(packet, ENOTSUP); 334 } 238 int rc; 239 240 switch (error) { 241 case SERVICE_NONE: 242 break; 243 case SERVICE_ICMP: 244 // ignore error 245 // length = icmp_client_header_length(packet); 246 // process error 247 result = icmp_client_process_packet(packet, &type, 248 &code, NULL, NULL); 249 if (result < 0) 250 return udp_release_and_return(packet, result); 251 length = (size_t) result; 252 rc = packet_trim(packet, length, 0); 253 if (rc != EOK) 254 return udp_release_and_return(packet, rc); 255 break; 256 default: 257 return udp_release_and_return(packet, ENOTSUP); 335 258 } 336 259 … … 348 271 349 272 // trim all but UDP header 350 if (ERROR_OCCURRED(packet_trim(packet, offset, 0))) 351 return udp_release_and_return(packet, ERROR_CODE); 273 rc = packet_trim(packet, offset, 0); 274 if (rc != EOK) 275 return udp_release_and_return(packet, rc); 352 276 353 277 // get udp header … … 374 298 375 299 // compute header checksum if set 376 if (header->checksum && (!error)) {300 if (header->checksum && !error) { 377 301 result = packet_get_addr(packet, (uint8_t **) &src, 378 302 (uint8_t **) &dest); 379 if (result <= 0)303 if (result <= 0) 380 304 return udp_release_and_return(packet, result); 381 382 if (ERROR_OCCURRED(ip_client_get_pseudo_header(IPPROTO_UDP,383 src, result, dest, result, total_length, &ip_header,384 &length))) {385 return udp_release_and_return(packet, ERROR_CODE);305 306 rc = ip_client_get_pseudo_header(IPPROTO_UDP, src, result, dest, 307 result, total_length, &ip_header, &length); 308 if (rc != EOK) { 309 return udp_release_and_return(packet, rc); 386 310 } else { 387 311 checksum = compute_checksum(0, ip_header, length); … … 396 320 397 321 do { 398 ++ fragments;322 fragments++; 399 323 length = packet_get_data_length(next_packet); 400 324 if (length <= 0) … … 402 326 403 327 if (total_length < length) { 404 if (ERROR_OCCURRED(packet_trim(next_packet, 0, 405 length - total_length))) { 406 return udp_release_and_return(packet, 407 ERROR_CODE); 408 } 328 rc = packet_trim(next_packet, 0, length - total_length); 329 if (rc != EOK) 330 return udp_release_and_return(packet, rc); 409 331 410 332 // add partial checksum if set … … 455 377 456 378 // queue the received packet 457 if (ERROR_OCCURRED(dyn_fifo_push(&socket->received, 458 packet_get_id(packet), SOCKET_MAX_RECEIVED_SIZE)) || 459 ERROR_OCCURRED(tl_get_ip_packet_dimension(udp_globals.ip_phone, 460 &udp_globals.dimensions, device_id, &packet_dimension))) { 461 return udp_release_and_return(packet, ERROR_CODE); 462 } 379 rc = dyn_fifo_push(&socket->received, packet_get_id(packet), 380 SOCKET_MAX_RECEIVED_SIZE); 381 if (rc != EOK) 382 return udp_release_and_return(packet, rc); 383 384 rc = tl_get_ip_packet_dimension(udp_globals.ip_phone, 385 &udp_globals.dimensions, device_id, &packet_dimension); 386 if (rc != EOK) 387 return udp_release_and_return(packet, rc); 463 388 464 389 // notify the destination socket … … 471 396 } 472 397 473 int 474 udp_message_standalone(ipc_callid_t callid, ipc_call_t * call, 475 ipc_call_t * answer, int * answer_count) 398 /** Processes the received UDP packet queue. 399 * 400 * Is used as an entry point from the underlying IP module. 401 * Locks the global lock and calls udp_process_packet() function. 402 * 403 * @param[in] device_id The receiving device identifier. 404 * @param[in,out] packet The received packet queue. 405 * @param receiver The target service. Ignored parameter. 406 * @param[in] error The packet error reporting service. Prefixes the 407 * received packet. 408 * @returns EOK on success. 409 * @returns Other error codes as defined for the 410 * udp_process_packet() function. 411 */ 412 static int 413 udp_received_msg(device_id_t device_id, packet_t packet, services_t receiver, 414 services_t error) 476 415 { 477 ERROR_DECLARE; 478 416 int result; 417 418 fibril_rwlock_write_lock(&udp_globals.lock); 419 result = udp_process_packet(device_id, packet, error); 420 if (result != EOK) 421 fibril_rwlock_write_unlock(&udp_globals.lock); 422 423 return result; 424 } 425 426 /** Sends data from the socket to the remote address. 427 * 428 * Binds the socket to a free port if not already connected/bound. 429 * Handles the NET_SOCKET_SENDTO message. 430 * Supports AF_INET and AF_INET6 address families. 431 * 432 * @param[in,out] local_sockets The application local sockets. 433 * @param[in] socket_id Socket identifier. 434 * @param[in] addr The destination address. 435 * @param[in] addrlen The address length. 436 * @param[in] fragments The number of data fragments. 437 * @param[out] data_fragment_size The data fragment size in bytes. 438 * @param[in] flags Various send flags. 439 * @returns EOK on success. 440 * @returns EAFNOTSUPPORT if the address family is not supported. 441 * @returns ENOTSOCK if the socket is not found. 442 * @returns EINVAL if the address is invalid. 443 * @returns ENOTCONN if the sending socket is not and cannot be 444 * bound. 445 * @returns ENOMEM if there is not enough memory left. 446 * @returns Other error codes as defined for the 447 * socket_read_packet_data() function. 448 * @returns Other error codes as defined for the 449 * ip_client_prepare_packet() function. 450 * @returns Other error codes as defined for the ip_send_msg() 451 * function. 452 */ 453 static int 454 udp_sendto_message(socket_cores_ref local_sockets, int socket_id, 455 const struct sockaddr *addr, socklen_t addrlen, int fragments, 456 size_t *data_fragment_size, int flags) 457 { 458 socket_core_ref socket; 479 459 packet_t packet; 480 481 *answer_count = 0; 482 483 switch (IPC_GET_METHOD(*call)) { 484 case NET_TL_RECEIVED: 485 if (!ERROR_OCCURRED(packet_translate_remote( 486 udp_globals.net_phone, &packet, IPC_GET_PACKET(call)))) { 487 ERROR_CODE = udp_received_msg(IPC_GET_DEVICE(call), 488 packet, SERVICE_UDP, IPC_GET_ERROR(call)); 460 packet_t next_packet; 461 udp_header_ref header; 462 int index; 463 size_t total_length; 464 int result; 465 uint16_t dest_port; 466 uint32_t checksum; 467 void *ip_header; 468 size_t headerlen; 469 device_id_t device_id; 470 packet_dimension_ref packet_dimension; 471 int rc; 472 473 rc = tl_get_address_port(addr, addrlen, &dest_port); 474 if (rc != EOK) 475 return rc; 476 477 socket = socket_cores_find(local_sockets, socket_id); 478 if (!socket) 479 return ENOTSOCK; 480 481 if ((socket->port <= 0) && udp_globals.autobinding) { 482 // bind the socket to a random free port if not bound 483 rc = socket_bind_free_port(&udp_globals.sockets, socket, 484 UDP_FREE_PORTS_START, UDP_FREE_PORTS_END, 485 udp_globals.last_used_port); 486 if (rc != EOK) 487 return rc; 488 // set the next port as the search starting port number 489 udp_globals.last_used_port = socket->port; 490 } 491 492 if (udp_globals.checksum_computing) { 493 rc = ip_get_route_req(udp_globals.ip_phone, IPPROTO_UDP, addr, 494 addrlen, &device_id, &ip_header, &headerlen); 495 if (rc != EOK) 496 return rc; 497 // get the device packet dimension 498 // rc = tl_get_ip_packet_dimension(udp_globals.ip_phone, 499 // &udp_globals.dimensions, device_id, &packet_dimension); 500 // if (rc != EOK) 501 // return rc; 502 } 503 // } else { 504 // do not ask all the time 505 rc = ip_packet_size_req(udp_globals.ip_phone, -1, 506 &udp_globals.packet_dimension); 507 if (rc != EOK) 508 return rc; 509 packet_dimension = &udp_globals.packet_dimension; 510 // } 511 512 // read the first packet fragment 513 result = tl_socket_read_packet_data(udp_globals.net_phone, &packet, 514 UDP_HEADER_SIZE, packet_dimension, addr, addrlen); 515 if (result < 0) 516 return result; 517 518 total_length = (size_t) result; 519 if (udp_globals.checksum_computing) 520 checksum = compute_checksum(0, packet_get_data(packet), 521 packet_get_data_length(packet)); 522 else 523 checksum = 0; 524 525 // prefix the udp header 526 header = PACKET_PREFIX(packet, udp_header_t); 527 if (!header) 528 return udp_release_and_return(packet, ENOMEM); 529 530 bzero(header, sizeof(*header)); 531 // read the rest of the packet fragments 532 for (index = 1; index < fragments; index++) { 533 result = tl_socket_read_packet_data(udp_globals.net_phone, 534 &next_packet, 0, packet_dimension, addr, addrlen); 535 if (result < 0) 536 return udp_release_and_return(packet, result); 537 538 rc = pq_add(&packet, next_packet, index, 0); 539 if (rc != EOK) 540 return udp_release_and_return(packet, rc); 541 542 total_length += (size_t) result; 543 if (udp_globals.checksum_computing) { 544 checksum = compute_checksum(checksum, 545 packet_get_data(next_packet), 546 packet_get_data_length(next_packet)); 489 547 } 490 return ERROR_CODE; 548 } 549 550 // set the udp header 551 header->source_port = htons((socket->port > 0) ? socket->port : 0); 552 header->destination_port = htons(dest_port); 553 header->total_length = htons(total_length + sizeof(*header)); 554 header->checksum = 0; 555 if (udp_globals.checksum_computing) { 556 // update the pseudo header 557 rc = ip_client_set_pseudo_header_data_length(ip_header, 558 headerlen, total_length + UDP_HEADER_SIZE); 559 if (rc != EOK) { 560 free(ip_header); 561 return udp_release_and_return(packet, rc); 562 } 563 564 // finish the checksum computation 565 checksum = compute_checksum(checksum, ip_header, headerlen); 566 checksum = compute_checksum(checksum, (uint8_t *) header, 567 sizeof(*header)); 568 header->checksum = 569 htons(flip_checksum(compact_checksum(checksum))); 570 free(ip_header); 571 } else { 572 device_id = DEVICE_INVALID_ID; 573 } 574 575 // prepare the first packet fragment 576 rc = ip_client_prepare_packet(packet, IPPROTO_UDP, 0, 0, 0, 0); 577 if (rc != EOK) 578 return udp_release_and_return(packet, rc); 579 580 /* Release the UDP global lock on success. */ 581 fibril_rwlock_write_unlock(&udp_globals.lock); 582 583 // send the packet 584 ip_send_msg(udp_globals.ip_phone, device_id, packet, SERVICE_UDP, 0); 585 586 return EOK; 587 } 588 589 /** Receives data to the socket. 590 * 591 * Handles the NET_SOCKET_RECVFROM message. 592 * Replies the source address as well. 593 * 594 * @param[in] local_sockets The application local sockets. 595 * @param[in] socket_id Socket identifier. 596 * @param[in] flags Various receive flags. 597 * @param[out] addrlen The source address length. 598 * @returns The number of bytes received. 599 * @returns ENOTSOCK if the socket is not found. 600 * @returns NO_DATA if there are no received packets or data. 601 * @returns ENOMEM if there is not enough memory left. 602 * @returns EINVAL if the received address is not an IP address. 603 * @returns Other error codes as defined for the packet_translate() 604 * function. 605 * @returns Other error codes as defined for the data_reply() 606 * function. 607 */ 608 static int 609 udp_recvfrom_message(socket_cores_ref local_sockets, int socket_id, int flags, 610 size_t *addrlen) 611 { 612 socket_core_ref socket; 613 int packet_id; 614 packet_t packet; 615 udp_header_ref header; 616 struct sockaddr *addr; 617 size_t length; 618 uint8_t *data; 619 int result; 620 int rc; 621 622 // find the socket 623 socket = socket_cores_find(local_sockets, socket_id); 624 if (!socket) 625 return ENOTSOCK; 626 627 // get the next received packet 628 packet_id = dyn_fifo_value(&socket->received); 629 if (packet_id < 0) 630 return NO_DATA; 491 631 492 case IPC_M_CONNECT_TO_ME: 493 return udp_process_client_messages(callid, * call); 494 } 495 496 return ENOTSUP; 632 rc = packet_translate_remote(udp_globals.net_phone, &packet, packet_id); 633 if (rc != EOK) { 634 (void) dyn_fifo_pop(&socket->received); 635 return rc; 636 } 637 638 // get udp header 639 data = packet_get_data(packet); 640 if (!data) { 641 (void) dyn_fifo_pop(&socket->received); 642 return udp_release_and_return(packet, NO_DATA); 643 } 644 header = (udp_header_ref) data; 645 646 // set the source address port 647 result = packet_get_addr(packet, (uint8_t **) &addr, NULL); 648 rc = tl_set_address_port(addr, result, ntohs(header->source_port)); 649 if (rc != EOK) { 650 (void) dyn_fifo_pop(&socket->received); 651 return udp_release_and_return(packet, rc); 652 } 653 *addrlen = (size_t) result; 654 655 // send the source address 656 rc = data_reply(addr, *addrlen); 657 switch (rc) { 658 case EOK: 659 break; 660 case EOVERFLOW: 661 return rc; 662 default: 663 (void) dyn_fifo_pop(&socket->received); 664 return udp_release_and_return(packet, rc); 665 } 666 667 // trim the header 668 rc = packet_trim(packet, UDP_HEADER_SIZE, 0); 669 if (rc != EOK) { 670 (void) dyn_fifo_pop(&socket->received); 671 return udp_release_and_return(packet, rc); 672 } 673 674 // reply the packets 675 rc = socket_reply_packets(packet, &length); 676 switch (rc) { 677 case EOK: 678 break; 679 case EOVERFLOW: 680 return rc; 681 default: 682 (void) dyn_fifo_pop(&socket->received); 683 return udp_release_and_return(packet, rc); 684 } 685 686 (void) dyn_fifo_pop(&socket->received); 687 688 // release the packet and return the total length 689 return udp_release_and_return(packet, (int) length); 497 690 } 498 691 499 int udp_process_client_messages(ipc_callid_t callid, ipc_call_t call) 692 /** Processes the socket client messages. 693 * 694 * Runs until the client module disconnects. 695 * 696 * @param[in] callid The message identifier. 697 * @param[in] call The message parameters. 698 * @returns EOK on success. 699 * 700 * @see socket.h 701 */ 702 static int udp_process_client_messages(ipc_callid_t callid, ipc_call_t call) 500 703 { 501 704 int res; … … 638 841 } 639 842 843 /** Processes the UDP message. 844 * 845 * @param[in] callid The message identifier. 846 * @param[in] call The message parameters. 847 * @param[out] answer The message answer parameters. 848 * @param[out] answer_count The last parameter for the actual answer in the 849 * answer parameter. 850 * @returns EOK on success. 851 * @returns ENOTSUP if the message is not known. 852 * 853 * @see udp_interface.h 854 * @see IS_NET_UDP_MESSAGE() 855 */ 640 856 int 641 udp_sendto_message(socket_cores_ref local_sockets, int socket_id, 642 const struct sockaddr *addr, socklen_t addrlen, int fragments, 643 size_t *data_fragment_size, int flags) 857 udp_message_standalone(ipc_callid_t callid, ipc_call_t *call, 858 ipc_call_t *answer, int *answer_count) 644 859 { 645 ERROR_DECLARE;646 647 socket_core_ref socket;648 860 packet_t packet; 649 packet_t next_packet; 650 udp_header_ref header; 651 int index; 652 size_t total_length; 653 int result; 654 uint16_t dest_port; 655 uint32_t checksum; 656 void *ip_header; 657 size_t headerlen; 658 device_id_t device_id; 659 packet_dimension_ref packet_dimension; 660 661 ERROR_PROPAGATE(tl_get_address_port(addr, addrlen, &dest_port)); 662 663 socket = socket_cores_find(local_sockets, socket_id); 664 if (!socket) 665 return ENOTSOCK; 666 667 if ((socket->port <= 0) && udp_globals.autobinding) { 668 // bind the socket to a random free port if not bound 669 // do { 670 // try to find a free port 671 // fibril_rwlock_read_unlock(&udp_globals.lock); 672 // fibril_rwlock_write_lock(&udp_globals.lock); 673 // might be changed in the meantime 674 // if (socket->port <= 0) { 675 if (ERROR_OCCURRED(socket_bind_free_port( 676 &udp_globals.sockets, socket, 677 UDP_FREE_PORTS_START, UDP_FREE_PORTS_END, 678 udp_globals.last_used_port))) { 679 // fibril_rwlock_write_unlock( 680 // &udp_globals.lock); 681 // fibril_rwlock_read_lock( 682 // &udp_globals.lock); 683 return ERROR_CODE; 684 } 685 // set the next port as the search starting port 686 // number 687 udp_globals.last_used_port = socket->port; 688 // } 689 // fibril_rwlock_write_unlock(&udp_globals.lock); 690 // fibril_rwlock_read_lock(&udp_globals.lock); 691 // might be changed in the meantime 692 // } while (socket->port <= 0); 693 } 694 695 if (udp_globals.checksum_computing) { 696 if (ERROR_OCCURRED(ip_get_route_req(udp_globals.ip_phone, 697 IPPROTO_UDP, addr, addrlen, &device_id, &ip_header, 698 &headerlen))) { 699 return udp_release_and_return(packet, ERROR_CODE); 700 } 701 // get the device packet dimension 702 // ERROR_PROPAGATE(tl_get_ip_packet_dimension(udp_globals.ip_phone, 703 // &udp_globals.dimensions, device_id, &packet_dimension)); 704 } 705 // } else { 706 // do not ask all the time 707 ERROR_PROPAGATE(ip_packet_size_req(udp_globals.ip_phone, -1, 708 &udp_globals.packet_dimension)); 709 packet_dimension = &udp_globals.packet_dimension; 710 // } 711 712 // read the first packet fragment 713 result = tl_socket_read_packet_data(udp_globals.net_phone, &packet, 714 UDP_HEADER_SIZE, packet_dimension, addr, addrlen); 715 if (result < 0) 716 return result; 717 718 total_length = (size_t) result; 719 if (udp_globals.checksum_computing) 720 checksum = compute_checksum(0, packet_get_data(packet), 721 packet_get_data_length(packet)); 722 else 723 checksum = 0; 724 725 // prefix the udp header 726 header = PACKET_PREFIX(packet, udp_header_t); 727 if(! header) 728 return udp_release_and_return(packet, ENOMEM); 729 730 bzero(header, sizeof(*header)); 731 // read the rest of the packet fragments 732 for (index = 1; index < fragments; ++ index) { 733 result = tl_socket_read_packet_data(udp_globals.net_phone, 734 &next_packet, 0, packet_dimension, addr, addrlen); 735 if (result < 0) 736 return udp_release_and_return(packet, result); 737 738 if (ERROR_OCCURRED(pq_add(&packet, next_packet, index, 0))) 739 return udp_release_and_return(packet, ERROR_CODE); 740 741 total_length += (size_t) result; 742 if (udp_globals.checksum_computing) { 743 checksum = compute_checksum(checksum, 744 packet_get_data(next_packet), 745 packet_get_data_length(next_packet)); 746 } 747 } 748 749 // set the udp header 750 header->source_port = htons((socket->port > 0) ? socket->port : 0); 751 header->destination_port = htons(dest_port); 752 header->total_length = htons(total_length + sizeof(*header)); 753 header->checksum = 0; 754 if (udp_globals.checksum_computing) { 755 // update the pseudo header 756 if (ERROR_OCCURRED(ip_client_set_pseudo_header_data_length( 757 ip_header, headerlen, total_length + UDP_HEADER_SIZE))) { 758 free(ip_header); 759 return udp_release_and_return(packet, ERROR_CODE); 760 } 761 762 // finish the checksum computation 763 checksum = compute_checksum(checksum, ip_header, headerlen); 764 checksum = compute_checksum(checksum, (uint8_t *) header, 765 sizeof(*header)); 766 header->checksum = 767 htons(flip_checksum(compact_checksum(checksum))); 768 free(ip_header); 769 } else { 770 device_id = DEVICE_INVALID_ID; 771 } 772 773 // prepare the first packet fragment 774 if (ERROR_OCCURRED(ip_client_prepare_packet(packet, IPPROTO_UDP, 0, 0, 775 0, 0))) { 776 return udp_release_and_return(packet, ERROR_CODE); 777 } 778 779 // send the packet 780 fibril_rwlock_write_unlock(&udp_globals.lock); 781 ip_send_msg(udp_globals.ip_phone, device_id, packet, SERVICE_UDP, 0); 782 783 return EOK; 861 int rc; 862 863 *answer_count = 0; 864 865 switch (IPC_GET_METHOD(*call)) { 866 case NET_TL_RECEIVED: 867 rc = packet_translate_remote(udp_globals.net_phone, &packet, 868 IPC_GET_PACKET(call)); 869 if (rc != EOK) 870 return rc; 871 return udp_received_msg(IPC_GET_DEVICE(call), packet, 872 SERVICE_UDP, IPC_GET_ERROR(call)); 873 case IPC_M_CONNECT_TO_ME: 874 return udp_process_client_messages(callid, * call); 875 } 876 877 return ENOTSUP; 784 878 } 785 879 786 int787 udp_recvfrom_message(socket_cores_ref local_sockets, int socket_id, int flags,788 size_t *addrlen)789 {790 ERROR_DECLARE;791 792 socket_core_ref socket;793 int packet_id;794 packet_t packet;795 udp_header_ref header;796 struct sockaddr *addr;797 size_t length;798 uint8_t *data;799 int result;800 801 // find the socket802 socket = socket_cores_find(local_sockets, socket_id);803 if (!socket)804 return ENOTSOCK;805 806 // get the next received packet807 packet_id = dyn_fifo_value(&socket->received);808 if (packet_id < 0)809 return NO_DATA;810 811 ERROR_PROPAGATE(packet_translate_remote(udp_globals.net_phone, &packet,812 packet_id));813 814 // get udp header815 data = packet_get_data(packet);816 if (!data) {817 pq_release_remote(udp_globals.net_phone, packet_id);818 return NO_DATA;819 }820 header = (udp_header_ref) data;821 822 // set the source address port823 result = packet_get_addr(packet, (uint8_t **) &addr, NULL);824 if (ERROR_OCCURRED(tl_set_address_port(addr, result,825 ntohs(header->source_port)))) {826 pq_release_remote(udp_globals.net_phone, packet_id);827 return ERROR_CODE;828 }829 *addrlen = (size_t) result;830 831 // send the source address832 ERROR_PROPAGATE(data_reply(addr, * addrlen));833 834 // trim the header835 ERROR_PROPAGATE(packet_trim(packet, UDP_HEADER_SIZE, 0));836 837 // reply the packets838 ERROR_PROPAGATE(socket_reply_packets(packet, &length));839 840 // release the packet841 dyn_fifo_pop(&socket->received);842 pq_release_remote(udp_globals.net_phone, packet_get_id(packet));843 844 // return the total length845 return (int) length;846 }847 848 int udp_release_and_return(packet_t packet, int result)849 {850 pq_release_remote(udp_globals.net_phone, packet_get_id(packet));851 return result;852 }853 854 880 /** Default thread for new connections. 855 881 * 856 * @param[in] iid The initial message identifier. 857 * @param[in] icall The initial message call structure. 858 * 882 * @param[in] iid The initial message identifier. 883 * @param[in] icall The initial message call structure. 859 884 */ 860 885 static void tl_client_connection(ipc_callid_t iid, ipc_call_t * icall) … … 882 907 883 908 /* 884 * End if said to either by the message or the processing result 909 * End if told to either by the message or the processing 910 * result. 885 911 */ 886 912 if ((IPC_GET_METHOD(call) == IPC_M_PHONE_HUNGUP) || … … 895 921 /** Starts the module. 896 922 * 897 * @param argc The count of the command line arguments. Ignored 898 * parameter. 899 * @param argv The command line parameters. Ignored parameter. 900 * 901 * @returns EOK on success. 902 * @returns Other error codes as defined for each specific module 923 * @returns EOK on success. 924 * @returns Other error codes as defined for each specific module 903 925 * start function. 904 926 */ 905 927 int main(int argc, char *argv[]) 906 928 { 907 ERROR_DECLARE;929 int rc; 908 930 909 931 /* Start the module */ 910 if (ERROR_OCCURRED(tl_module_start_standalone(tl_client_connection))) 911 return ERROR_CODE; 912 913 return EOK; 932 rc = tl_module_start_standalone(tl_client_connection); 933 return rc; 914 934 } 915 935
Note:
See TracChangeset
for help on using the changeset viewer.