Changes in uspace/srv/net/tl/udp/udp.c [46d4d9f:8e3a65c] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/net/tl/udp/udp.c
r46d4d9f r8e3a65c 28 28 29 29 /** @addtogroup udp 30 * @{30 * @{ 31 31 */ 32 32 33 33 /** @file 34 * UDP module implementation. 35 * @see udp.h 36 */ 37 38 #include "udp.h" 39 #include "udp_header.h" 40 #include "udp_module.h" 34 * UDP module implementation. 35 * @see udp.h 36 */ 41 37 42 38 #include <async.h> … … 49 45 #include <ipc/tl.h> 50 46 #include <ipc/socket.h> 51 #include <adt/dynamic_fifo.h>52 47 #include <errno.h> 48 #include <err.h> 53 49 54 50 #include <net/socket_codes.h> … … 59 55 #include <net/modules.h> 60 56 57 #include <adt/dynamic_fifo.h> 61 58 #include <packet_client.h> 62 59 #include <packet_remote.h> … … 72 69 #include <tl_interface.h> 73 70 71 #include "udp.h" 72 #include "udp_header.h" 73 #include "udp_module.h" 74 74 75 /** UDP module name. */ 75 76 #define NAME "UDP protocol" … … 90 91 #define UDP_FREE_PORTS_END 65535 91 92 92 /** UDP global data. */ 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 */ 93 217 udp_globals_t udp_globals; 94 218 95 /** Initializes the UDP module.96 *97 * @param[in] client_connection The client connection processing function. The98 * module skeleton propagates its own one.99 * @return EOK on success.100 * @return ENOMEM if there is not enough memory left.101 */102 219 int udp_initialize(async_client_conn_t client_connection) 103 220 { 221 ERROR_DECLARE; 222 104 223 measured_string_t names[] = { 105 224 { 106 (char *) "UDP_CHECKSUM_COMPUTING",225 str_dup("UDP_CHECKSUM_COMPUTING"), 107 226 22 108 227 }, 109 228 { 110 (char *) "UDP_AUTOBINDING",229 str_dup("UDP_AUTOBINDING"), 111 230 15 112 231 } 113 232 }; 114 measured_string_ t *configuration;233 measured_string_ref configuration; 115 234 size_t count = sizeof(names) / sizeof(measured_string_t); 116 char *data; 117 int rc; 235 char * data; 118 236 119 237 fibril_rwlock_initialize(&udp_globals.lock); … … 122 240 udp_globals.icmp_phone = icmp_connect_module(SERVICE_ICMP, 123 241 ICMP_CONNECT_TIMEOUT); 124 125 242 udp_globals.ip_phone = ip_bind_service(SERVICE_IP, IPPROTO_UDP, 126 243 SERVICE_UDP, client_connection); 127 if (udp_globals.ip_phone < 0) { 128 fibril_rwlock_write_unlock(&udp_globals.lock); 244 if (udp_globals.ip_phone < 0) 129 245 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) { 246 247 // 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))) { 148 253 socket_ports_destroy(&udp_globals.sockets); 149 fibril_rwlock_write_unlock(&udp_globals.lock); 150 return rc; 151 } 152 254 return ERROR_CODE; 255 } 153 256 udp_globals.packet_dimension.prefix += sizeof(udp_header_t); 154 257 udp_globals.packet_dimension.content -= sizeof(udp_header_t); 155 258 udp_globals.last_used_port = UDP_FREE_PORTS_START - 1; 156 259 260 // get configuration 157 261 udp_globals.checksum_computing = NET_DEFAULT_UDP_CHECKSUM_COMPUTING; 158 262 udp_globals.autobinding = NET_DEFAULT_UDP_AUTOBINDING; 159 160 /* Get configuration */161 263 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 264 ERROR_PROPAGATE(net_get_conf_req(udp_globals.net_phone, &configuration, 265 count, &data)); 170 266 if (configuration) { 171 267 if (configuration[0].value) … … 184 280 } 185 281 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) 282 int 283 udp_received_msg(device_id_t device_id, packet_t packet, services_t receiver, 284 services_t error) 193 285 { 194 pq_release_remote(udp_globals.net_phone, packet_get_id(packet)); 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 195 293 return result; 196 294 } 197 295 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 * @return EOK on success. 208 * @return EINVAL if the packet is not valid. 209 * @return EINVAL if the stored packet address is not the 210 * an_addr_t. 211 * @return EINVAL if the packet does not contain any data. 212 * @return NO_DATA if the packet content is shorter than the user 213 * datagram header. 214 * @return ENOMEM if there is not enough memory left. 215 * @return EADDRNOTAVAIL if the destination socket does not exist. 216 * @return Other error codes as defined for the 217 * ip_client_process_packet() function. 218 */ 219 static int udp_process_packet(device_id_t device_id, packet_t *packet, 220 services_t error) 296 int udp_process_packet(device_id_t device_id, packet_t packet, services_t error) 221 297 { 298 ERROR_DECLARE; 299 222 300 size_t length; 223 301 size_t offset; 224 302 int result; 225 udp_header_ t *header;226 socket_core_ t *socket;227 packet_t *next_packet;303 udp_header_ref header; 304 socket_core_ref socket; 305 packet_t next_packet; 228 306 size_t total_length; 229 307 uint32_t checksum; 230 308 int fragments; 231 packet_t *tmp_packet;309 packet_t tmp_packet; 232 310 icmp_type_t type; 233 311 icmp_code_t code; … … 235 313 struct sockaddr *src; 236 314 struct sockaddr *dest; 237 packet_dimension_t *packet_dimension; 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 247 /* Process error */ 248 result = icmp_client_process_packet(packet, &type, 249 &code, NULL, NULL); 250 if (result < 0) 251 return udp_release_and_return(packet, result); 252 length = (size_t) result; 253 rc = packet_trim(packet, length, 0); 254 if (rc != EOK) 255 return udp_release_and_return(packet, rc); 256 break; 257 default: 258 return udp_release_and_return(packet, ENOTSUP); 259 } 260 261 /* TODO process received ipopts? */ 315 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 } 335 } 336 337 // TODO process received ipopts? 262 338 result = ip_client_process_packet(packet, NULL, NULL, NULL, NULL, NULL); 263 339 if (result < 0) … … 271 347 return udp_release_and_return(packet, NO_DATA); 272 348 273 /* Trim all but UDP header */ 274 rc = packet_trim(packet, offset, 0); 275 if (rc != EOK) 276 return udp_release_and_return(packet, rc); 277 278 /* Get UDP header */ 279 header = (udp_header_t *) packet_get_data(packet); 349 // trim all but UDP header 350 if (ERROR_OCCURRED(packet_trim(packet, offset, 0))) 351 return udp_release_and_return(packet, ERROR_CODE); 352 353 // get udp header 354 header = (udp_header_ref) packet_get_data(packet); 280 355 if (!header) 281 356 return udp_release_and_return(packet, NO_DATA); 282 357 283 / * Find the destination socket */358 // find the destination socket 284 359 socket = socket_port_find(&udp_globals.sockets, 285 360 ntohs(header->destination_port), SOCKET_MAP_KEY_LISTENING, 0); … … 293 368 } 294 369 295 / * Count the received packet fragments */370 // count the received packet fragments 296 371 next_packet = packet; 297 372 fragments = 0; 298 373 total_length = ntohs(header->total_length); 299 374 300 / * Compute header checksum if set */301 if (header->checksum && !error) {375 // compute header checksum if set 376 if (header->checksum && (!error)) { 302 377 result = packet_get_addr(packet, (uint8_t **) &src, 303 378 (uint8_t **) &dest); 304 if (result <= 0)379 if( result <= 0) 305 380 return udp_release_and_return(packet, result); 306 307 rc = ip_client_get_pseudo_header(IPPROTO_UDP, src, result, dest,308 result, total_length, &ip_header, &length);309 if (rc != EOK) {310 return udp_release_and_return(packet, rc);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); 311 386 } else { 312 387 checksum = compute_checksum(0, ip_header, length); 313 /* 314 * The udp header checksum will be added with the first 315 * fragment later. 316 */ 388 // the udp header checksum will be added with the first 389 // fragment later 317 390 free(ip_header); 318 391 } … … 323 396 324 397 do { 325 fragments++;398 ++ fragments; 326 399 length = packet_get_data_length(next_packet); 327 400 if (length <= 0) … … 329 402 330 403 if (total_length < length) { 331 rc = packet_trim(next_packet, 0, length - total_length); 332 if (rc != EOK) 333 return udp_release_and_return(packet, rc); 334 335 /* Add partial checksum if set */ 404 if (ERROR_OCCURRED(packet_trim(next_packet, 0, 405 length - total_length))) { 406 return udp_release_and_return(packet, 407 ERROR_CODE); 408 } 409 410 // add partial checksum if set 336 411 if (header->checksum) { 337 412 checksum = compute_checksum(checksum, … … 340 415 } 341 416 342 / * Relese the rest of the packet fragments */417 // relese the rest of the packet fragments 343 418 tmp_packet = pq_next(next_packet); 344 419 while (tmp_packet) { … … 349 424 } 350 425 351 / * Exit the loop */426 // exit the loop 352 427 break; 353 428 } 354 429 total_length -= length; 355 430 356 / * Add partial checksum if set */431 // add partial checksum if set 357 432 if (header->checksum) { 358 433 checksum = compute_checksum(checksum, … … 363 438 } while ((next_packet = pq_next(next_packet)) && (total_length > 0)); 364 439 365 / * Verify checksum */440 // check checksum 366 441 if (header->checksum) { 367 442 if (flip_checksum(compact_checksum(checksum)) != … … 369 444 if (tl_prepare_icmp_packet(udp_globals.net_phone, 370 445 udp_globals.icmp_phone, packet, error) == EOK) { 371 / * Checksum error ICMP */446 // checksum error ICMP 372 447 icmp_parameter_problem_msg( 373 448 udp_globals.icmp_phone, ICMP_PARAM_POINTER, … … 379 454 } 380 455 381 /* Queue the received packet */ 382 rc = dyn_fifo_push(&socket->received, packet_get_id(packet), 383 SOCKET_MAX_RECEIVED_SIZE); 384 if (rc != EOK) 385 return udp_release_and_return(packet, rc); 386 387 rc = tl_get_ip_packet_dimension(udp_globals.ip_phone, 388 &udp_globals.dimensions, device_id, &packet_dimension); 389 if (rc != EOK) 390 return udp_release_and_return(packet, rc); 391 392 /* Notify the destination socket */ 456 // 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 } 463 464 // notify the destination socket 393 465 fibril_rwlock_write_unlock(&udp_globals.lock); 394 466 async_msg_5(socket->phone, NET_SOCKET_RECEIVED, … … 399 471 } 400 472 401 /** Processes the received UDP packet queue. 402 * 403 * Is used as an entry point from the underlying IP module. 404 * Locks the global lock and calls udp_process_packet() function. 405 * 406 * @param[in] device_id The receiving device identifier. 407 * @param[in,out] packet The received packet queue. 408 * @param receiver The target service. Ignored parameter. 409 * @param[in] error The packet error reporting service. Prefixes the 410 * received packet. 411 * @return EOK on success. 412 * @return Other error codes as defined for the 413 * udp_process_packet() function. 414 */ 415 static int udp_received_msg(device_id_t device_id, packet_t *packet, 416 services_t receiver, services_t error) 473 int 474 udp_message_standalone(ipc_callid_t callid, ipc_call_t * call, 475 ipc_call_t * answer, int * answer_count) 417 476 { 418 int result; 419 420 fibril_rwlock_write_lock(&udp_globals.lock); 421 result = udp_process_packet(device_id, packet, error); 422 if (result != EOK) 423 fibril_rwlock_write_unlock(&udp_globals.lock); 424 425 return result; 477 ERROR_DECLARE; 478 479 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)); 489 } 490 return ERROR_CODE; 491 492 case IPC_M_CONNECT_TO_ME: 493 return udp_process_client_messages(callid, * call); 494 } 495 496 return ENOTSUP; 426 497 } 427 498 428 /** Sends data from the socket to the remote address. 429 * 430 * Binds the socket to a free port if not already connected/bound. 431 * Handles the NET_SOCKET_SENDTO message. 432 * Supports AF_INET and AF_INET6 address families. 433 * 434 * @param[in,out] local_sockets The application local sockets. 435 * @param[in] socket_id Socket identifier. 436 * @param[in] addr The destination address. 437 * @param[in] addrlen The address length. 438 * @param[in] fragments The number of data fragments. 439 * @param[out] data_fragment_size The data fragment size in bytes. 440 * @param[in] flags Various send flags. 441 * @return EOK on success. 442 * @return EAFNOTSUPPORT if the address family is not supported. 443 * @return ENOTSOCK if the socket is not found. 444 * @return EINVAL if the address is invalid. 445 * @return ENOTCONN if the sending socket is not and cannot be 446 * bound. 447 * @return ENOMEM if there is not enough memory left. 448 * @return Other error codes as defined for the 449 * socket_read_packet_data() function. 450 * @return Other error codes as defined for the 451 * ip_client_prepare_packet() function. 452 * @return Other error codes as defined for the ip_send_msg() 453 * function. 454 */ 455 static int udp_sendto_message(socket_cores_t *local_sockets, int socket_id, 456 const struct sockaddr *addr, socklen_t addrlen, int fragments, 457 size_t *data_fragment_size, int flags) 458 { 459 socket_core_t *socket; 460 packet_t *packet; 461 packet_t *next_packet; 462 udp_header_t *header; 463 int index; 464 size_t total_length; 465 int result; 466 uint16_t dest_port; 467 uint32_t checksum; 468 void *ip_header; 469 size_t headerlen; 470 device_id_t device_id; 471 packet_dimension_t *packet_dimension; 472 int rc; 473 474 rc = tl_get_address_port(addr, addrlen, &dest_port); 475 if (rc != EOK) 476 return rc; 477 478 socket = socket_cores_find(local_sockets, socket_id); 479 if (!socket) 480 return ENOTSOCK; 481 482 if ((socket->port <= 0) && udp_globals.autobinding) { 483 /* Bind the socket to a random free port if not bound */ 484 rc = socket_bind_free_port(&udp_globals.sockets, socket, 485 UDP_FREE_PORTS_START, UDP_FREE_PORTS_END, 486 udp_globals.last_used_port); 487 if (rc != EOK) 488 return rc; 489 /* Set the next port as the search starting port number */ 490 udp_globals.last_used_port = socket->port; 491 } 492 493 if (udp_globals.checksum_computing) { 494 rc = ip_get_route_req(udp_globals.ip_phone, IPPROTO_UDP, addr, 495 addrlen, &device_id, &ip_header, &headerlen); 496 if (rc != EOK) 497 return rc; 498 /* Get the device packet dimension */ 499 // rc = tl_get_ip_packet_dimension(udp_globals.ip_phone, 500 // &udp_globals.dimensions, device_id, &packet_dimension); 501 // if (rc != EOK) 502 // return rc; 503 } 504 // } else { 505 /* Do not ask all the time */ 506 rc = ip_packet_size_req(udp_globals.ip_phone, -1, 507 &udp_globals.packet_dimension); 508 if (rc != EOK) 509 return rc; 510 packet_dimension = &udp_globals.packet_dimension; 511 // } 512 513 /* Read the first packet fragment */ 514 result = tl_socket_read_packet_data(udp_globals.net_phone, &packet, 515 UDP_HEADER_SIZE, packet_dimension, addr, addrlen); 516 if (result < 0) 517 return result; 518 519 total_length = (size_t) result; 520 if (udp_globals.checksum_computing) 521 checksum = compute_checksum(0, packet_get_data(packet), 522 packet_get_data_length(packet)); 523 else 524 checksum = 0; 525 526 /* Prefix the UDP header */ 527 header = PACKET_PREFIX(packet, udp_header_t); 528 if (!header) 529 return udp_release_and_return(packet, ENOMEM); 530 531 bzero(header, sizeof(*header)); 532 533 /* Read the rest of the packet fragments */ 534 for (index = 1; index < fragments; index++) { 535 result = tl_socket_read_packet_data(udp_globals.net_phone, 536 &next_packet, 0, packet_dimension, addr, addrlen); 537 if (result < 0) 538 return udp_release_and_return(packet, result); 539 540 rc = pq_add(&packet, next_packet, index, 0); 541 if (rc != EOK) 542 return udp_release_and_return(packet, rc); 543 544 total_length += (size_t) result; 545 if (udp_globals.checksum_computing) { 546 checksum = compute_checksum(checksum, 547 packet_get_data(next_packet), 548 packet_get_data_length(next_packet)); 549 } 550 } 551 552 /* Set the UDP header */ 553 header->source_port = htons((socket->port > 0) ? socket->port : 0); 554 header->destination_port = htons(dest_port); 555 header->total_length = htons(total_length + sizeof(*header)); 556 header->checksum = 0; 557 558 if (udp_globals.checksum_computing) { 559 /* Update the pseudo header */ 560 rc = ip_client_set_pseudo_header_data_length(ip_header, 561 headerlen, total_length + UDP_HEADER_SIZE); 562 if (rc != EOK) { 563 free(ip_header); 564 return udp_release_and_return(packet, rc); 565 } 566 567 /* Finish the checksum computation */ 568 checksum = compute_checksum(checksum, ip_header, headerlen); 569 checksum = compute_checksum(checksum, (uint8_t *) header, 570 sizeof(*header)); 571 header->checksum = 572 htons(flip_checksum(compact_checksum(checksum))); 573 free(ip_header); 574 } else { 575 device_id = DEVICE_INVALID_ID; 576 } 577 578 /* Prepare the first packet fragment */ 579 rc = ip_client_prepare_packet(packet, IPPROTO_UDP, 0, 0, 0, 0); 580 if (rc != EOK) 581 return udp_release_and_return(packet, rc); 582 583 /* Release the UDP global lock on success. */ 584 fibril_rwlock_write_unlock(&udp_globals.lock); 585 586 /* Send the packet */ 587 ip_send_msg(udp_globals.ip_phone, device_id, packet, SERVICE_UDP, 0); 588 589 return EOK; 590 } 591 592 /** Receives data to the socket. 593 * 594 * Handles the NET_SOCKET_RECVFROM message. 595 * Replies the source address as well. 596 * 597 * @param[in] local_sockets The application local sockets. 598 * @param[in] socket_id Socket identifier. 599 * @param[in] flags Various receive flags. 600 * @param[out] addrlen The source address length. 601 * @return The number of bytes received. 602 * @return ENOTSOCK if the socket is not found. 603 * @return NO_DATA if there are no received packets or data. 604 * @return ENOMEM if there is not enough memory left. 605 * @return EINVAL if the received address is not an IP address. 606 * @return Other error codes as defined for the packet_translate() 607 * function. 608 * @return Other error codes as defined for the data_reply() 609 * function. 610 */ 611 static int udp_recvfrom_message(socket_cores_t *local_sockets, int socket_id, 612 int flags, size_t *addrlen) 613 { 614 socket_core_t *socket; 615 int packet_id; 616 packet_t *packet; 617 udp_header_t *header; 618 struct sockaddr *addr; 619 size_t length; 620 uint8_t *data; 621 int result; 622 int rc; 623 624 /* Find the socket */ 625 socket = socket_cores_find(local_sockets, socket_id); 626 if (!socket) 627 return ENOTSOCK; 628 629 /* Get the next received packet */ 630 packet_id = dyn_fifo_value(&socket->received); 631 if (packet_id < 0) 632 return NO_DATA; 633 634 rc = packet_translate_remote(udp_globals.net_phone, &packet, packet_id); 635 if (rc != EOK) { 636 (void) dyn_fifo_pop(&socket->received); 637 return rc; 638 } 639 640 /* Get UDP header */ 641 data = packet_get_data(packet); 642 if (!data) { 643 (void) dyn_fifo_pop(&socket->received); 644 return udp_release_and_return(packet, NO_DATA); 645 } 646 header = (udp_header_t *) data; 647 648 /* Set the source address port */ 649 result = packet_get_addr(packet, (uint8_t **) &addr, NULL); 650 rc = tl_set_address_port(addr, result, ntohs(header->source_port)); 651 if (rc != EOK) { 652 (void) dyn_fifo_pop(&socket->received); 653 return udp_release_and_return(packet, rc); 654 } 655 *addrlen = (size_t) result; 656 657 /* Send the source address */ 658 rc = data_reply(addr, *addrlen); 659 switch (rc) { 660 case EOK: 661 break; 662 case EOVERFLOW: 663 return rc; 664 default: 665 (void) dyn_fifo_pop(&socket->received); 666 return udp_release_and_return(packet, rc); 667 } 668 669 /* Trim the header */ 670 rc = packet_trim(packet, UDP_HEADER_SIZE, 0); 671 if (rc != EOK) { 672 (void) dyn_fifo_pop(&socket->received); 673 return udp_release_and_return(packet, rc); 674 } 675 676 /* Reply the packets */ 677 rc = socket_reply_packets(packet, &length); 678 switch (rc) { 679 case EOK: 680 break; 681 case EOVERFLOW: 682 return rc; 683 default: 684 (void) dyn_fifo_pop(&socket->received); 685 return udp_release_and_return(packet, rc); 686 } 687 688 (void) dyn_fifo_pop(&socket->received); 689 690 /* Release the packet and return the total length */ 691 return udp_release_and_return(packet, (int) length); 692 } 693 694 /** Processes the socket client messages. 695 * 696 * Runs until the client module disconnects. 697 * 698 * @param[in] callid The message identifier. 699 * @param[in] call The message parameters. 700 * @return EOK on success. 701 * 702 * @see socket.h 703 */ 704 static int udp_process_client_messages(ipc_callid_t callid, ipc_call_t call) 499 int udp_process_client_messages(ipc_callid_t callid, ipc_call_t call) 705 500 { 706 501 int res; … … 714 509 ipc_call_t answer; 715 510 int answer_count; 716 packet_dimension_ t *packet_dimension;511 packet_dimension_ref packet_dimension; 717 512 718 513 /* … … 723 518 answer_count = 0; 724 519 725 /* 726 * The client connection is only in one fibril and therefore no 727 * additional locks are needed. 728 */ 520 // The client connection is only in one fibril and therefore no 521 // additional locks are needed. 729 522 730 523 socket_cores_initialize(&local_sockets); … … 732 525 while (keep_on_going) { 733 526 734 / * Answer the call */527 // answer the call 735 528 answer_call(callid, res, &answer, answer_count); 736 529 737 / * Refresh data */530 // refresh data 738 531 refresh_answer(&answer, &answer_count); 739 532 740 / * Get the next call */533 // get the next call 741 534 callid = async_get_call(&call); 742 535 743 / * Process the call */536 // process the call 744 537 switch (IPC_GET_METHOD(call)) { 745 538 case IPC_M_PHONE_HUNGUP: … … 835 628 } 836 629 837 / * Release the application phone */630 // release the application phone 838 631 ipc_hangup(app_phone); 839 632 840 / * Release all local sockets */633 // release all local sockets 841 634 socket_cores_release(udp_globals.net_phone, &local_sockets, 842 635 &udp_globals.sockets, NULL); … … 845 638 } 846 639 847 /** Processes the UDP message. 848 * 849 * @param[in] callid The message identifier. 850 * @param[in] call The message parameters. 851 * @param[out] answer The message answer parameters. 852 * @param[out] answer_count The last parameter for the actual answer in the 853 * answer parameter. 854 * @return EOK on success. 855 * @return ENOTSUP if the message is not known. 856 * 857 * @see udp_interface.h 858 * @see IS_NET_UDP_MESSAGE() 859 */ 860 int udp_message_standalone(ipc_callid_t callid, ipc_call_t *call, 861 ipc_call_t *answer, int *answer_count) 640 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) 862 644 { 863 packet_t *packet; 864 int rc; 865 866 *answer_count = 0; 867 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)); 876 case IPC_M_CONNECT_TO_ME: 877 return udp_process_client_messages(callid, * call); 878 } 879 880 return ENOTSUP; 645 ERROR_DECLARE; 646 647 socket_core_ref socket; 648 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; 881 784 } 882 785 786 int 787 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 socket 802 socket = socket_cores_find(local_sockets, socket_id); 803 if (!socket) 804 return ENOTSOCK; 805 806 // get the next received packet 807 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 header 815 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 port 823 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 address 832 ERROR_PROPAGATE(data_reply(addr, * addrlen)); 833 834 // trim the header 835 ERROR_PROPAGATE(packet_trim(packet, UDP_HEADER_SIZE, 0)); 836 837 // reply the packets 838 ERROR_PROPAGATE(socket_reply_packets(packet, &length)); 839 840 // release the packet 841 dyn_fifo_pop(&socket->received); 842 pq_release_remote(udp_globals.net_phone, packet_get_id(packet)); 843 844 // return the total length 845 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 883 854 /** Default thread for new connections. 884 855 * 885 * @param[in] iid The initial message identifier. 886 * @param[in] icall The initial message call structure. 856 * @param[in] iid The initial message identifier. 857 * @param[in] icall The initial message call structure. 858 * 887 859 */ 888 860 static void tl_client_connection(ipc_callid_t iid, ipc_call_t * icall) … … 910 882 911 883 /* 912 * End if told to either by the message or the processing 913 * result. 884 * End if said to either by the message or the processing result 914 885 */ 915 886 if ((IPC_GET_METHOD(call) == IPC_M_PHONE_HUNGUP) || … … 924 895 /** Starts the module. 925 896 * 926 * @return EOK on success. 927 * @return Other error codes as defined for each specific module 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 928 903 * start function. 929 904 */ 930 905 int main(int argc, char *argv[]) 931 906 { 932 int rc;907 ERROR_DECLARE; 933 908 934 909 /* Start the module */ 935 rc = tl_module_start_standalone(tl_client_connection); 936 return rc; 910 if (ERROR_OCCURRED(tl_module_start_standalone(tl_client_connection))) 911 return ERROR_CODE; 912 913 return EOK; 937 914 } 938 915
Note:
See TracChangeset
for help on using the changeset viewer.