Changeset b5e68c8 in mainline for uspace/srv/net/tl/udp/udp.c
- Timestamp:
- 2011-05-12T16:49:44Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- f36787d7
- Parents:
- e80329d6 (diff), 750636a (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
-
TabularUnified uspace/srv/net/tl/udp/udp.c ¶
re80329d6 rb5e68c8 28 28 29 29 /** @addtogroup udp 30 * 30 * @{ 31 31 */ 32 32 33 33 /** @file 34 * 35 * 34 * UDP module implementation. 35 * @see udp.h 36 36 */ 37 37 … … 40 40 #include <malloc.h> 41 41 #include <stdio.h> 42 #include <ipc/ipc.h>43 42 #include <ipc/services.h> 44 43 #include <ipc/net.h> 45 44 #include <ipc/tl.h> 46 45 #include <ipc/socket.h> 46 #include <adt/dynamic_fifo.h> 47 47 #include <errno.h> 48 #include <err.h>49 48 50 49 #include <net/socket_codes.h> … … 55 54 #include <net/modules.h> 56 55 57 #include <adt/dynamic_fifo.h>58 56 #include <packet_client.h> 59 57 #include <packet_remote.h> … … 62 60 #include <ip_interface.h> 63 61 #include <icmp_client.h> 64 #include <icmp_ interface.h>62 #include <icmp_remote.h> 65 63 #include <net_interface.h> 66 64 #include <socket_core.h> 67 65 #include <tl_common.h> 68 #include <tl_ local.h>69 #include <tl_ interface.h>66 #include <tl_remote.h> 67 #include <tl_skel.h> 70 68 71 69 #include "udp.h" 72 70 #include "udp_header.h" 73 #include "udp_module.h"74 71 75 72 /** UDP module name. */ 76 #define NAME "UDP protocol"73 #define NAME "udp" 77 74 78 75 /** Default UDP checksum computing. */ … … 91 88 #define UDP_FREE_PORTS_END 65535 92 89 90 /** UDP global data. */ 91 udp_globals_t udp_globals; 92 93 /** Releases the packet and returns the result. 94 * 95 * @param[in] packet The packet queue to be released. 96 * @param[in] result The result to be returned. 97 * @return The result parameter. 98 */ 99 static int udp_release_and_return(packet_t *packet, int result) 100 { 101 pq_release_remote(udp_globals.net_phone, packet_get_id(packet)); 102 return result; 103 } 104 93 105 /** Processes the received UDP packet queue. 94 106 * 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 107 * Notifies the destination socket application. 108 * Releases the packet on error or sends an ICMP error notification. 109 * 110 * @param[in] device_id The receiving device identifier. 111 * @param[in,out] packet The received packet queue. 112 * @param[in] error The packet error reporting service. Prefixes the 102 113 * received packet. 103 * @returns EOK on success. 104 * @returns Other error codes as defined for the 114 * @return EOK on success. 115 * @return EINVAL if the packet is not valid. 116 * @return EINVAL if the stored packet address is not the 117 * an_addr_t. 118 * @return EINVAL if the packet does not contain any data. 119 * @return NO_DATA if the packet content is shorter than the user 120 * datagram header. 121 * @return ENOMEM if there is not enough memory left. 122 * @return EADDRNOTAVAIL if the destination socket does not exist. 123 * @return Other error codes as defined for the 124 * ip_client_process_packet() function. 125 */ 126 static int udp_process_packet(device_id_t device_id, packet_t *packet, 127 services_t error) 128 { 129 size_t length; 130 size_t offset; 131 int result; 132 udp_header_t *header; 133 socket_core_t *socket; 134 packet_t *next_packet; 135 size_t total_length; 136 uint32_t checksum; 137 int fragments; 138 packet_t *tmp_packet; 139 icmp_type_t type; 140 icmp_code_t code; 141 void *ip_header; 142 struct sockaddr *src; 143 struct sockaddr *dest; 144 packet_dimension_t *packet_dimension; 145 int rc; 146 147 switch (error) { 148 case SERVICE_NONE: 149 break; 150 case SERVICE_ICMP: 151 /* Ignore error */ 152 // length = icmp_client_header_length(packet); 153 154 /* Process error */ 155 result = icmp_client_process_packet(packet, &type, 156 &code, NULL, NULL); 157 if (result < 0) 158 return udp_release_and_return(packet, result); 159 length = (size_t) result; 160 rc = packet_trim(packet, length, 0); 161 if (rc != EOK) 162 return udp_release_and_return(packet, rc); 163 break; 164 default: 165 return udp_release_and_return(packet, ENOTSUP); 166 } 167 168 /* TODO process received ipopts? */ 169 result = ip_client_process_packet(packet, NULL, NULL, NULL, NULL, NULL); 170 if (result < 0) 171 return udp_release_and_return(packet, result); 172 offset = (size_t) result; 173 174 length = packet_get_data_length(packet); 175 if (length <= 0) 176 return udp_release_and_return(packet, EINVAL); 177 if (length < UDP_HEADER_SIZE + offset) 178 return udp_release_and_return(packet, NO_DATA); 179 180 /* Trim all but UDP header */ 181 rc = packet_trim(packet, offset, 0); 182 if (rc != EOK) 183 return udp_release_and_return(packet, rc); 184 185 /* Get UDP header */ 186 header = (udp_header_t *) packet_get_data(packet); 187 if (!header) 188 return udp_release_and_return(packet, NO_DATA); 189 190 /* Find the destination socket */ 191 socket = socket_port_find(&udp_globals.sockets, 192 ntohs(header->destination_port), (uint8_t *) SOCKET_MAP_KEY_LISTENING, 0); 193 if (!socket) { 194 if (tl_prepare_icmp_packet(udp_globals.net_phone, 195 udp_globals.icmp_phone, packet, error) == EOK) { 196 icmp_destination_unreachable_msg(udp_globals.icmp_phone, 197 ICMP_PORT_UNREACH, 0, packet); 198 } 199 return EADDRNOTAVAIL; 200 } 201 202 /* Count the received packet fragments */ 203 next_packet = packet; 204 fragments = 0; 205 total_length = ntohs(header->total_length); 206 207 /* Compute header checksum if set */ 208 if (header->checksum && !error) { 209 result = packet_get_addr(packet, (uint8_t **) &src, 210 (uint8_t **) &dest); 211 if (result <= 0) 212 return udp_release_and_return(packet, result); 213 214 rc = ip_client_get_pseudo_header(IPPROTO_UDP, src, result, dest, 215 result, total_length, &ip_header, &length); 216 if (rc != EOK) { 217 return udp_release_and_return(packet, rc); 218 } else { 219 checksum = compute_checksum(0, ip_header, length); 220 /* 221 * The udp header checksum will be added with the first 222 * fragment later. 223 */ 224 free(ip_header); 225 } 226 } else { 227 header->checksum = 0; 228 checksum = 0; 229 } 230 231 do { 232 fragments++; 233 length = packet_get_data_length(next_packet); 234 if (length <= 0) 235 return udp_release_and_return(packet, NO_DATA); 236 237 if (total_length < length) { 238 rc = packet_trim(next_packet, 0, length - total_length); 239 if (rc != EOK) 240 return udp_release_and_return(packet, rc); 241 242 /* Add partial checksum if set */ 243 if (header->checksum) { 244 checksum = compute_checksum(checksum, 245 packet_get_data(packet), 246 packet_get_data_length(packet)); 247 } 248 249 /* Relese the rest of the packet fragments */ 250 tmp_packet = pq_next(next_packet); 251 while (tmp_packet) { 252 next_packet = pq_detach(tmp_packet); 253 pq_release_remote(udp_globals.net_phone, 254 packet_get_id(tmp_packet)); 255 tmp_packet = next_packet; 256 } 257 258 /* Exit the loop */ 259 break; 260 } 261 total_length -= length; 262 263 /* Add partial checksum if set */ 264 if (header->checksum) { 265 checksum = compute_checksum(checksum, 266 packet_get_data(packet), 267 packet_get_data_length(packet)); 268 } 269 270 } while ((next_packet = pq_next(next_packet)) && (total_length > 0)); 271 272 /* Verify checksum */ 273 if (header->checksum) { 274 if (flip_checksum(compact_checksum(checksum)) != 275 IP_CHECKSUM_ZERO) { 276 if (tl_prepare_icmp_packet(udp_globals.net_phone, 277 udp_globals.icmp_phone, packet, error) == EOK) { 278 /* Checksum error ICMP */ 279 icmp_parameter_problem_msg( 280 udp_globals.icmp_phone, ICMP_PARAM_POINTER, 281 ((size_t) ((void *) &header->checksum)) - 282 ((size_t) ((void *) header)), packet); 283 } 284 return EINVAL; 285 } 286 } 287 288 /* Queue the received packet */ 289 rc = dyn_fifo_push(&socket->received, packet_get_id(packet), 290 SOCKET_MAX_RECEIVED_SIZE); 291 if (rc != EOK) 292 return udp_release_and_return(packet, rc); 293 294 rc = tl_get_ip_packet_dimension(udp_globals.ip_phone, 295 &udp_globals.dimensions, device_id, &packet_dimension); 296 if (rc != EOK) 297 return udp_release_and_return(packet, rc); 298 299 /* Notify the destination socket */ 300 fibril_rwlock_write_unlock(&udp_globals.lock); 301 async_msg_5(socket->phone, NET_SOCKET_RECEIVED, 302 (sysarg_t) socket->socket_id, packet_dimension->content, 0, 0, 303 (sysarg_t) fragments); 304 305 return EOK; 306 } 307 308 /** Processes the received UDP packet queue. 309 * 310 * Is used as an entry point from the underlying IP module. 311 * Locks the global lock and calls udp_process_packet() function. 312 * 313 * @param[in] device_id The receiving device identifier. 314 * @param[in,out] packet The received packet queue. 315 * @param receiver The target service. Ignored parameter. 316 * @param[in] error The packet error reporting service. Prefixes the 317 * received packet. 318 * @return EOK on success. 319 * @return Other error codes as defined for the 105 320 * udp_process_packet() function. 106 321 */ 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 */ 217 udp_globals_t udp_globals; 218 219 int udp_initialize(async_client_conn_t client_connection) 220 { 221 ERROR_DECLARE; 222 322 static int udp_received_msg(device_id_t device_id, packet_t *packet, 323 services_t receiver, services_t error) 324 { 325 int result; 326 327 fibril_rwlock_write_lock(&udp_globals.lock); 328 result = udp_process_packet(device_id, packet, error); 329 if (result != EOK) 330 fibril_rwlock_write_unlock(&udp_globals.lock); 331 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 { 223 375 measured_string_t names[] = { 224 376 { 225 str_dup("UDP_CHECKSUM_COMPUTING"),377 (uint8_t *) "UDP_CHECKSUM_COMPUTING", 226 378 22 227 379 }, 228 380 { 229 str_dup("UDP_AUTOBINDING"),381 (uint8_t *) "UDP_AUTOBINDING", 230 382 15 231 383 } 232 384 }; 233 measured_string_ refconfiguration;385 measured_string_t *configuration; 234 386 size_t count = sizeof(names) / sizeof(measured_string_t); 235 char *data;236 387 uint8_t *data; 388 237 389 fibril_rwlock_initialize(&udp_globals.lock); 238 390 fibril_rwlock_write_lock(&udp_globals.lock); 239 240 udp_globals.icmp_phone = icmp_connect_module(SERVICE_ICMP, 241 ICMP_CONNECT_TIMEOUT); 391 392 udp_globals.net_phone = net_phone; 393 394 udp_globals.icmp_phone = icmp_connect_module(ICMP_CONNECT_TIMEOUT); 395 242 396 udp_globals.ip_phone = ip_bind_service(SERVICE_IP, IPPROTO_UDP, 243 SERVICE_UDP, client_connection); 244 if (udp_globals.ip_phone < 0) 397 SERVICE_UDP, udp_receiver); 398 if (udp_globals.ip_phone < 0) { 399 fibril_rwlock_write_unlock(&udp_globals.lock); 245 400 return udp_globals.ip_phone; 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))) { 253 socket_ports_destroy(&udp_globals.sockets); 254 return ERROR_CODE; 255 } 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 256 424 udp_globals.packet_dimension.prefix += sizeof(udp_header_t); 257 425 udp_globals.packet_dimension.content -= sizeof(udp_header_t); 258 426 udp_globals.last_used_port = UDP_FREE_PORTS_START - 1; 259 427 260 // get configuration261 428 udp_globals.checksum_computing = NET_DEFAULT_UDP_CHECKSUM_COMPUTING; 262 429 udp_globals.autobinding = NET_DEFAULT_UDP_AUTOBINDING; 430 431 /* Get configuration */ 263 432 configuration = &names[0]; 264 ERROR_PROPAGATE(net_get_conf_req(udp_globals.net_phone, &configuration, 265 count, &data)); 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 266 441 if (configuration) { 267 442 if (configuration[0].value) … … 280 455 } 281 456 282 int 283 udp_received_msg(device_id_t device_id, packet_t packet, services_t receiver, 284 services_t error) 285 { 457 /** Sends data from the socket to the remote address. 458 * 459 * Binds the socket to a free port if not already connected/bound. 460 * Handles the NET_SOCKET_SENDTO message. 461 * Supports AF_INET and AF_INET6 address families. 462 * 463 * @param[in,out] local_sockets The application local sockets. 464 * @param[in] socket_id Socket identifier. 465 * @param[in] addr The destination address. 466 * @param[in] addrlen The address length. 467 * @param[in] fragments The number of data fragments. 468 * @param[out] data_fragment_size The data fragment size in bytes. 469 * @param[in] flags Various send flags. 470 * @return EOK on success. 471 * @return EAFNOTSUPPORT if the address family is not supported. 472 * @return ENOTSOCK if the socket is not found. 473 * @return EINVAL if the address is invalid. 474 * @return ENOTCONN if the sending socket is not and cannot be 475 * bound. 476 * @return ENOMEM if there is not enough memory left. 477 * @return Other error codes as defined for the 478 * socket_read_packet_data() function. 479 * @return Other error codes as defined for the 480 * ip_client_prepare_packet() function. 481 * @return Other error codes as defined for the ip_send_msg() 482 * function. 483 */ 484 static int udp_sendto_message(socket_cores_t *local_sockets, int socket_id, 485 const struct sockaddr *addr, socklen_t addrlen, int fragments, 486 size_t *data_fragment_size, int flags) 487 { 488 socket_core_t *socket; 489 packet_t *packet; 490 packet_t *next_packet; 491 udp_header_t *header; 492 int index; 493 size_t total_length; 286 494 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 293 return result; 294 } 295 296 int udp_process_packet(device_id_t device_id, packet_t packet, services_t error) 297 { 298 ERROR_DECLARE; 299 495 uint16_t dest_port; 496 uint32_t checksum; 497 void *ip_header; 498 size_t headerlen; 499 device_id_t device_id; 500 packet_dimension_t *packet_dimension; 501 size_t size; 502 int rc; 503 504 /* In case of error, do not update the data fragment size. */ 505 *data_fragment_size = 0; 506 507 rc = tl_get_address_port(addr, addrlen, &dest_port); 508 if (rc != EOK) 509 return rc; 510 511 socket = socket_cores_find(local_sockets, socket_id); 512 if (!socket) 513 return ENOTSOCK; 514 515 if ((socket->port <= 0) && udp_globals.autobinding) { 516 /* Bind the socket to a random free port if not bound */ 517 rc = socket_bind_free_port(&udp_globals.sockets, socket, 518 UDP_FREE_PORTS_START, UDP_FREE_PORTS_END, 519 udp_globals.last_used_port); 520 if (rc != EOK) 521 return rc; 522 /* Set the next port as the search starting port number */ 523 udp_globals.last_used_port = socket->port; 524 } 525 526 if (udp_globals.checksum_computing) { 527 rc = ip_get_route_req(udp_globals.ip_phone, IPPROTO_UDP, addr, 528 addrlen, &device_id, &ip_header, &headerlen); 529 if (rc != EOK) 530 return rc; 531 /* Get the device packet dimension */ 532 // rc = tl_get_ip_packet_dimension(udp_globals.ip_phone, 533 // &udp_globals.dimensions, device_id, &packet_dimension); 534 // if (rc != EOK) 535 // return rc; 536 } 537 // } else { 538 /* Do not ask all the time */ 539 rc = ip_packet_size_req(udp_globals.ip_phone, -1, 540 &udp_globals.packet_dimension); 541 if (rc != EOK) 542 return rc; 543 packet_dimension = &udp_globals.packet_dimension; 544 // } 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 556 /* Read the first packet fragment */ 557 result = tl_socket_read_packet_data(udp_globals.net_phone, &packet, 558 UDP_HEADER_SIZE, packet_dimension, addr, addrlen); 559 if (result < 0) 560 return result; 561 562 total_length = (size_t) result; 563 if (udp_globals.checksum_computing) 564 checksum = compute_checksum(0, packet_get_data(packet), 565 packet_get_data_length(packet)); 566 else 567 checksum = 0; 568 569 /* Prefix the UDP header */ 570 header = PACKET_PREFIX(packet, udp_header_t); 571 if (!header) 572 return udp_release_and_return(packet, ENOMEM); 573 574 bzero(header, sizeof(*header)); 575 576 /* Read the rest of the packet fragments */ 577 for (index = 1; index < fragments; index++) { 578 result = tl_socket_read_packet_data(udp_globals.net_phone, 579 &next_packet, 0, packet_dimension, addr, addrlen); 580 if (result < 0) 581 return udp_release_and_return(packet, result); 582 583 rc = pq_add(&packet, next_packet, index, 0); 584 if (rc != EOK) 585 return udp_release_and_return(packet, rc); 586 587 total_length += (size_t) result; 588 if (udp_globals.checksum_computing) { 589 checksum = compute_checksum(checksum, 590 packet_get_data(next_packet), 591 packet_get_data_length(next_packet)); 592 } 593 } 594 595 /* Set the UDP header */ 596 header->source_port = htons((socket->port > 0) ? socket->port : 0); 597 header->destination_port = htons(dest_port); 598 header->total_length = htons(total_length + sizeof(*header)); 599 header->checksum = 0; 600 601 if (udp_globals.checksum_computing) { 602 /* Update the pseudo header */ 603 rc = ip_client_set_pseudo_header_data_length(ip_header, 604 headerlen, total_length + UDP_HEADER_SIZE); 605 if (rc != EOK) { 606 free(ip_header); 607 return udp_release_and_return(packet, rc); 608 } 609 610 /* Finish the checksum computation */ 611 checksum = compute_checksum(checksum, ip_header, headerlen); 612 checksum = compute_checksum(checksum, (uint8_t *) header, 613 sizeof(*header)); 614 header->checksum = 615 htons(flip_checksum(compact_checksum(checksum))); 616 free(ip_header); 617 } else { 618 device_id = DEVICE_INVALID_ID; 619 } 620 621 /* Prepare the first packet fragment */ 622 rc = ip_client_prepare_packet(packet, IPPROTO_UDP, 0, 0, 0, 0); 623 if (rc != EOK) 624 return udp_release_and_return(packet, rc); 625 626 /* Release the UDP global lock on success. */ 627 fibril_rwlock_write_unlock(&udp_globals.lock); 628 629 /* Send the packet */ 630 ip_send_msg(udp_globals.ip_phone, device_id, packet, SERVICE_UDP, 0); 631 632 return EOK; 633 } 634 635 /** Receives data to the socket. 636 * 637 * Handles the NET_SOCKET_RECVFROM message. 638 * Replies the source address as well. 639 * 640 * @param[in] local_sockets The application local sockets. 641 * @param[in] socket_id Socket identifier. 642 * @param[in] flags Various receive flags. 643 * @param[out] addrlen The source address length. 644 * @return The number of bytes received. 645 * @return ENOTSOCK if the socket is not found. 646 * @return NO_DATA if there are no received packets or data. 647 * @return ENOMEM if there is not enough memory left. 648 * @return EINVAL if the received address is not an IP address. 649 * @return Other error codes as defined for the packet_translate() 650 * function. 651 * @return Other error codes as defined for the data_reply() 652 * function. 653 */ 654 static int udp_recvfrom_message(socket_cores_t *local_sockets, int socket_id, 655 int flags, size_t *addrlen) 656 { 657 socket_core_t *socket; 658 int packet_id; 659 packet_t *packet; 660 udp_header_t *header; 661 struct sockaddr *addr; 300 662 size_t length; 301 size_t offset;663 uint8_t *data; 302 664 int result; 303 udp_header_ref header; 304 socket_core_ref socket; 305 packet_t next_packet; 306 size_t total_length; 307 uint32_t checksum; 308 int fragments; 309 packet_t tmp_packet; 310 icmp_type_t type; 311 icmp_code_t code; 312 void *ip_header; 313 struct sockaddr *src; 314 struct sockaddr *dest; 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? 338 result = ip_client_process_packet(packet, NULL, NULL, NULL, NULL, NULL); 339 if (result < 0) 340 return udp_release_and_return(packet, result); 341 offset = (size_t) result; 342 343 length = packet_get_data_length(packet); 344 if (length <= 0) 345 return udp_release_and_return(packet, EINVAL); 346 if (length < UDP_HEADER_SIZE + offset) 665 int rc; 666 667 /* Find the socket */ 668 socket = socket_cores_find(local_sockets, socket_id); 669 if (!socket) 670 return ENOTSOCK; 671 672 /* Get the next received packet */ 673 packet_id = dyn_fifo_value(&socket->received); 674 if (packet_id < 0) 675 return NO_DATA; 676 677 rc = packet_translate_remote(udp_globals.net_phone, &packet, packet_id); 678 if (rc != EOK) { 679 (void) dyn_fifo_pop(&socket->received); 680 return rc; 681 } 682 683 /* Get UDP header */ 684 data = packet_get_data(packet); 685 if (!data) { 686 (void) dyn_fifo_pop(&socket->received); 347 687 return udp_release_and_return(packet, NO_DATA); 348 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); 355 if (!header) 356 return udp_release_and_return(packet, NO_DATA); 357 358 // find the destination socket 359 socket = socket_port_find(&udp_globals.sockets, 360 ntohs(header->destination_port), SOCKET_MAP_KEY_LISTENING, 0); 361 if (!socket) { 362 if (tl_prepare_icmp_packet(udp_globals.net_phone, 363 udp_globals.icmp_phone, packet, error) == EOK) { 364 icmp_destination_unreachable_msg(udp_globals.icmp_phone, 365 ICMP_PORT_UNREACH, 0, packet); 366 } 367 return EADDRNOTAVAIL; 368 } 369 370 // count the received packet fragments 371 next_packet = packet; 372 fragments = 0; 373 total_length = ntohs(header->total_length); 374 375 // compute header checksum if set 376 if (header->checksum && (!error)) { 377 result = packet_get_addr(packet, (uint8_t **) &src, 378 (uint8_t **) &dest); 379 if( result <= 0) 380 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); 386 } else { 387 checksum = compute_checksum(0, ip_header, length); 388 // the udp header checksum will be added with the first 389 // fragment later 390 free(ip_header); 391 } 392 } else { 393 header->checksum = 0; 394 checksum = 0; 395 } 396 397 do { 398 ++ fragments; 399 length = packet_get_data_length(next_packet); 400 if (length <= 0) 401 return udp_release_and_return(packet, NO_DATA); 402 403 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 } 409 410 // add partial checksum if set 411 if (header->checksum) { 412 checksum = compute_checksum(checksum, 413 packet_get_data(packet), 414 packet_get_data_length(packet)); 415 } 416 417 // relese the rest of the packet fragments 418 tmp_packet = pq_next(next_packet); 419 while (tmp_packet) { 420 next_packet = pq_detach(tmp_packet); 421 pq_release_remote(udp_globals.net_phone, 422 packet_get_id(tmp_packet)); 423 tmp_packet = next_packet; 424 } 425 426 // exit the loop 427 break; 428 } 429 total_length -= length; 430 431 // add partial checksum if set 432 if (header->checksum) { 433 checksum = compute_checksum(checksum, 434 packet_get_data(packet), 435 packet_get_data_length(packet)); 436 } 437 438 } while ((next_packet = pq_next(next_packet)) && (total_length > 0)); 439 440 // check checksum 441 if (header->checksum) { 442 if (flip_checksum(compact_checksum(checksum)) != 443 IP_CHECKSUM_ZERO) { 444 if (tl_prepare_icmp_packet(udp_globals.net_phone, 445 udp_globals.icmp_phone, packet, error) == EOK) { 446 // checksum error ICMP 447 icmp_parameter_problem_msg( 448 udp_globals.icmp_phone, ICMP_PARAM_POINTER, 449 ((size_t) ((void *) &header->checksum)) - 450 ((size_t) ((void *) header)), packet); 451 } 452 return EINVAL; 453 } 454 } 455 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 465 fibril_rwlock_write_unlock(&udp_globals.lock); 466 async_msg_5(socket->phone, NET_SOCKET_RECEIVED, 467 (ipcarg_t) socket->socket_id, packet_dimension->content, 0, 0, 468 (ipcarg_t) fragments); 469 470 return EOK; 471 } 472 473 int 474 udp_message_standalone(ipc_callid_t callid, ipc_call_t * call, 475 ipc_call_t * answer, int * answer_count) 476 { 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; 497 } 498 499 int udp_process_client_messages(ipc_callid_t callid, ipc_call_t call) 688 } 689 header = (udp_header_t *) data; 690 691 /* Set the source address port */ 692 result = packet_get_addr(packet, (uint8_t **) &addr, NULL); 693 rc = tl_set_address_port(addr, result, ntohs(header->source_port)); 694 if (rc != EOK) { 695 (void) dyn_fifo_pop(&socket->received); 696 return udp_release_and_return(packet, rc); 697 } 698 *addrlen = (size_t) result; 699 700 /* Send the source address */ 701 rc = data_reply(addr, *addrlen); 702 switch (rc) { 703 case EOK: 704 break; 705 case EOVERFLOW: 706 return rc; 707 default: 708 (void) dyn_fifo_pop(&socket->received); 709 return udp_release_and_return(packet, rc); 710 } 711 712 /* Trim the header */ 713 rc = packet_trim(packet, UDP_HEADER_SIZE, 0); 714 if (rc != EOK) { 715 (void) dyn_fifo_pop(&socket->received); 716 return udp_release_and_return(packet, rc); 717 } 718 719 /* Reply the packets */ 720 rc = socket_reply_packets(packet, &length); 721 switch (rc) { 722 case EOK: 723 break; 724 case EOVERFLOW: 725 return rc; 726 default: 727 (void) dyn_fifo_pop(&socket->received); 728 return udp_release_and_return(packet, rc); 729 } 730 731 (void) dyn_fifo_pop(&socket->received); 732 733 /* Release the packet and return the total length */ 734 return udp_release_and_return(packet, (int) length); 735 } 736 737 /** Processes the socket client messages. 738 * 739 * Runs until the client module disconnects. 740 * 741 * @param[in] callid The message identifier. 742 * @param[in] call The message parameters. 743 * @return EOK on success. 744 * 745 * @see socket.h 746 */ 747 static int udp_process_client_messages(ipc_callid_t callid, ipc_call_t call) 500 748 { 501 749 int res; 502 750 bool keep_on_going = true; 503 751 socket_cores_t local_sockets; 504 int app_phone = IPC_GET_PHONE( &call);752 int app_phone = IPC_GET_PHONE(call); 505 753 struct sockaddr *addr; 506 754 int socket_id; … … 508 756 size_t size; 509 757 ipc_call_t answer; 510 int answer_count;511 packet_dimension_ refpacket_dimension;758 size_t answer_count; 759 packet_dimension_t *packet_dimension; 512 760 513 761 /* … … 518 766 answer_count = 0; 519 767 520 // The client connection is only in one fibril and therefore no 521 // additional locks are needed. 768 /* 769 * The client connection is only in one fibril and therefore no 770 * additional locks are needed. 771 */ 522 772 523 773 socket_cores_initialize(&local_sockets); … … 525 775 while (keep_on_going) { 526 776 527 / / answer the call777 /* Answer the call */ 528 778 answer_call(callid, res, &answer, answer_count); 529 779 530 / / refresh data780 /* Refresh data */ 531 781 refresh_answer(&answer, &answer_count); 532 782 533 / / get the next call783 /* Get the next call */ 534 784 callid = async_get_call(&call); 535 785 536 / / process the call537 switch (IPC_GET_ METHOD(call)) {786 /* Process the call */ 787 switch (IPC_GET_IMETHOD(call)) { 538 788 case IPC_M_PHONE_HUNGUP: 539 789 keep_on_going = false; … … 550 800 break; 551 801 802 size = MAX_UDP_FRAGMENT_SIZE; 552 803 if (tl_get_ip_packet_dimension(udp_globals.ip_phone, 553 804 &udp_globals.dimensions, DEVICE_INVALID_ID, 554 805 &packet_dimension) == EOK) { 555 SOCKET_SET_DATA_FRAGMENT_SIZE(answer,556 packet_dimension->content);806 if (packet_dimension->content < size) 807 size = packet_dimension->content; 557 808 } 558 559 // SOCKET_SET_DATA_FRAGMENT_SIZE(answer, 560 // MAX_UDP_FRAGMENT_SIZE); 809 SOCKET_SET_DATA_FRAGMENT_SIZE(answer, size); 561 810 SOCKET_SET_HEADER_SIZE(answer, UDP_HEADER_SIZE); 562 811 answer_count = 3; … … 564 813 565 814 case NET_SOCKET_BIND: 566 res = data_receive((void **) &addr, &addrlen); 815 res = async_data_write_accept((void **) &addr, false, 816 0, 0, 0, &addrlen); 567 817 if (res != EOK) 568 818 break; … … 577 827 578 828 case NET_SOCKET_SENDTO: 579 res = data_receive((void **) &addr, &addrlen); 829 res = async_data_write_accept((void **) &addr, false, 830 0, 0, 0, &addrlen); 580 831 if (res != EOK) 581 832 break; … … 628 879 } 629 880 630 / / release the application phone631 ipc_hangup(app_phone);632 633 / / release all local sockets881 /* Release the application phone */ 882 async_hangup(app_phone); 883 884 /* Release all local sockets */ 634 885 socket_cores_release(udp_globals.net_phone, &local_sockets, 635 886 &udp_globals.sockets, NULL); … … 638 889 } 639 890 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) 644 { 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; 784 } 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 854 /** Default thread for new connections. 855 * 856 * @param[in] iid The initial message identifier. 857 * @param[in] icall The initial message call structure. 858 * 859 */ 860 static void tl_client_connection(ipc_callid_t iid, ipc_call_t * icall) 861 { 862 /* 863 * Accept the connection 864 * - Answer the first IPC_M_CONNECT_ME_TO call. 865 */ 866 ipc_answer_0(iid, EOK); 867 868 while (true) { 869 ipc_call_t answer; 870 int answer_count; 871 872 /* Clear the answer structure */ 873 refresh_answer(&answer, &answer_count); 874 875 /* Fetch the next message */ 876 ipc_call_t call; 877 ipc_callid_t callid = async_get_call(&call); 878 879 /* Process the message */ 880 int res = tl_module_message_standalone(callid, &call, &answer, 881 &answer_count); 882 883 /* 884 * End if said to either by the message or the processing result 885 */ 886 if ((IPC_GET_METHOD(call) == IPC_M_PHONE_HUNGUP) || 887 (res == EHANGUP)) 888 return; 889 890 /* Answer the message */ 891 answer_call(callid, res, &answer, answer_count); 892 } 893 } 894 895 /** Starts the module. 896 * 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 903 * start function. 904 */ 891 /** Per-connection initialization 892 * 893 */ 894 void tl_connection(void) 895 { 896 } 897 898 /** Processes the UDP message. 899 * 900 * @param[in] callid The message identifier. 901 * @param[in] call The message parameters. 902 * @param[out] answer The message answer parameters. 903 * @param[out] answer_count The last parameter for the actual answer in the 904 * answer parameter. 905 * @return EOK on success. 906 * @return ENOTSUP if the message is not known. 907 * 908 * @see udp_interface.h 909 * @see IS_NET_UDP_MESSAGE() 910 */ 911 int tl_message(ipc_callid_t callid, ipc_call_t *call, 912 ipc_call_t *answer, size_t *answer_count) 913 { 914 *answer_count = 0; 915 916 switch (IPC_GET_IMETHOD(*call)) { 917 case IPC_M_CONNECT_TO_ME: 918 return udp_process_client_messages(callid, *call); 919 } 920 921 return ENOTSUP; 922 } 923 905 924 int main(int argc, char *argv[]) 906 925 { 907 ERROR_DECLARE;908 909 926 /* Start the module */ 910 if (ERROR_OCCURRED(tl_module_start_standalone(tl_client_connection))) 911 return ERROR_CODE; 912 913 return EOK; 927 return tl_module_start(SERVICE_UDP); 914 928 } 915 929
Note:
See TracChangeset
for help on using the changeset viewer.