Changes in uspace/srv/net/tl/udp/udp.c [8e3a65c:14f1db0] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/net/tl/udp/udp.c
r8e3a65c r14f1db0 42 42 #include <ipc/ipc.h> 43 43 #include <ipc/services.h> 44 #include <ipc/net.h> 45 #include <ipc/tl.h> 46 #include <ipc/socket.h> 47 #include <errno.h> 48 #include <err.h> 49 50 #include <net/socket_codes.h> 51 #include <net/ip_protocols.h> 52 #include <net/in.h> 53 #include <net/in6.h> 54 #include <net/inet.h> 55 #include <net/modules.h> 56 44 45 #include <net_err.h> 46 #include <net_messages.h> 47 #include <net_modules.h> 57 48 #include <adt/dynamic_fifo.h> 58 #include <packet _client.h>49 #include <packet/packet_client.h> 59 50 #include <packet_remote.h> 60 51 #include <net_checksum.h> 52 #include <in.h> 53 #include <in6.h> 54 #include <inet.h> 61 55 #include <ip_client.h> 62 56 #include <ip_interface.h> 57 #include <ip_protocols.h> 63 58 #include <icmp_client.h> 64 59 #include <icmp_interface.h> 65 60 #include <net_interface.h> 61 #include <socket_codes.h> 62 #include <socket_errno.h> 66 63 #include <socket_core.h> 64 #include <socket_messages.h> 67 65 #include <tl_common.h> 68 66 #include <tl_local.h> 69 67 #include <tl_interface.h> 68 #include <tl_messages.h> 70 69 71 70 #include "udp.h" … … 73 72 #include "udp_module.h" 74 73 75 /** UDP module name. */ 74 /** UDP module name. 75 */ 76 76 #define NAME "UDP protocol" 77 77 78 /** Default UDP checksum computing. */ 78 /** Default UDP checksum computing. 79 */ 79 80 #define NET_DEFAULT_UDP_CHECKSUM_COMPUTING true 80 81 81 /** Default UDP autobind when sending via unbound sockets. */ 82 /** Default UDP autobind when sending via unbound sockets. 83 */ 82 84 #define NET_DEFAULT_UDP_AUTOBINDING true 83 85 84 /** Maximum UDP fragment size. */ 85 #define MAX_UDP_FRAGMENT_SIZE 65535 86 87 /** Free ports pool start. */ 88 #define UDP_FREE_PORTS_START 1025 89 90 /** Free ports pool end. */ 86 /** Maximum UDP fragment size. 87 */ 88 #define MAX_UDP_FRAGMENT_SIZE 65535 89 90 /** Free ports pool start. 91 */ 92 #define UDP_FREE_PORTS_START 1025 93 94 /** Free ports pool end. 95 */ 91 96 #define UDP_FREE_PORTS_END 65535 92 97 93 98 /** Processes the received UDP packet queue. 94 *95 99 * Is used as an entry point from the underlying IP module. 96 100 * Locks the global lock and calls udp_process_packet() function. 97 *98 101 * @param[in] device_id The receiving device identifier. 99 102 * @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); 103 * @param receiver The target service. Ignored parameter. 104 * @param[in] error The packet error reporting service. Prefixes the received packet. 105 * @returns EOK on success. 106 * @returns Other error codes as defined for the udp_process_packet() function. 107 */ 108 int udp_received_msg(device_id_t device_id, packet_t packet, services_t receiver, services_t error); 110 109 111 110 /** Processes the received UDP packet queue. 112 *113 111 * Notifies the destination socket application. 114 * Releases the packet on error or sends an ICMP error notification. 115 * 112 * Releases the packet on error or sends an ICMP error notification.. 116 113 * @param[in] device_id The receiving device identifier. 117 114 * @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); 115 * @param[in] error The packet error reporting service. Prefixes the received packet. 116 * @returns EOK on success. 117 * @returns EINVAL if the packet is not valid. 118 * @returns EINVAL if the stored packet address is not the an_addr_t. 119 * @returns EINVAL if the packet does not contain any data. 120 * @returns NO_DATA if the packet content is shorter than the user datagram header. 121 * @returns ENOMEM if there is not enough memory left. 122 * @returns EADDRNOTAVAIL if the destination socket does not exist. 123 * @returns Other error codes as defined for the ip_client_process_packet() function. 124 */ 125 int udp_process_packet(device_id_t device_id, packet_t packet, services_t error); 134 126 135 127 /** 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. 128 * @param[in] packet The packet queue to be released. 129 * @param[in] result The result to be returned. 130 * @return The result parameter. 140 131 */ 141 132 int udp_release_and_return(packet_t packet, int result); … … 146 137 147 138 /** Processes the socket client messages. 148 *149 139 * 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 140 * @param[in] callid The message identifier. 141 * @param[in] call The message parameters. 142 * @returns EOK on success. 143 * @see socket.h 155 144 */ 156 145 int udp_process_client_messages(ipc_callid_t callid, ipc_call_t call); 157 146 158 147 /** Sends data from the socket to the remote address. 159 *160 148 * Binds the socket to a free port if not already connected/bound. 161 149 * Handles the NET_SOCKET_SENDTO message. 162 150 * Supports AF_INET and AF_INET6 address families. 163 *164 151 * @param[in,out] local_sockets The application local sockets. 165 152 * @param[in] socket_id Socket identifier. 166 * @param[in] addr 167 * @param[in] addrlen 153 * @param[in] addr The destination address. 154 * @param[in] addrlen The address length. 168 155 * @param[in] fragments The number of data fragments. 169 156 * @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); 157 * @param[in] flags Various send flags. 158 * @returns EOK on success. 159 * @returns EAFNOTSUPPORT if the address family is not supported. 160 * @returns ENOTSOCK if the socket is not found. 161 * @returns EINVAL if the address is invalid. 162 * @returns ENOTCONN if the sending socket is not and cannot be bound. 163 * @returns ENOMEM if there is not enough memory left. 164 * @returns Other error codes as defined for the socket_read_packet_data() function. 165 * @returns Other error codes as defined for the ip_client_prepare_packet() function. 166 * @returns Other error codes as defined for the ip_send_msg() function. 167 */ 168 int udp_sendto_message(socket_cores_ref local_sockets, int socket_id, const struct sockaddr * addr, socklen_t addrlen, int fragments, size_t * data_fragment_size, int flags); 189 169 190 170 /** Receives data to the socket. 191 *192 171 * Handles the NET_SOCKET_RECVFROM message. 193 172 * Replies the source address as well. 194 *195 173 * @param[in] local_sockets The application local sockets. 196 174 * @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); 175 * @param[in] flags Various receive flags. 176 * @param[out] addrlen The source address length. 177 * @returns The number of bytes received. 178 * @returns ENOTSOCK if the socket is not found. 179 * @returns NO_DATA if there are no received packets or data. 180 * @returns ENOMEM if there is not enough memory left. 181 * @returns EINVAL if the received address is not an IP address. 182 * @returns Other error codes as defined for the packet_translate() function. 183 * @returns Other error codes as defined for the data_reply() function. 184 */ 185 int udp_recvfrom_message(socket_cores_ref local_sockets, int socket_id, int flags, size_t * addrlen); 212 186 213 187 /*@}*/ … … 215 189 /** UDP global data. 216 190 */ 217 udp_globals_t udp_globals; 218 219 int udp_initialize(async_client_conn_t client_connection) 220 { 191 udp_globals_t udp_globals; 192 193 int udp_initialize(async_client_conn_t client_connection){ 221 194 ERROR_DECLARE; 222 195 223 measured_string_t names[] = { 224 { 225 str_dup("UDP_CHECKSUM_COMPUTING"), 226 22 227 }, 228 { 229 str_dup("UDP_AUTOBINDING"), 230 15 231 } 232 }; 196 measured_string_t names[] = {{str_dup("UDP_CHECKSUM_COMPUTING"), 22}, {str_dup("UDP_AUTOBINDING"), 15}}; 233 197 measured_string_ref configuration; 234 198 size_t count = sizeof(names) / sizeof(measured_string_t); … … 237 201 fibril_rwlock_initialize(&udp_globals.lock); 238 202 fibril_rwlock_write_lock(&udp_globals.lock); 239 240 udp_globals.icmp_phone = icmp_connect_module(SERVICE_ICMP, 241 ICMP_CONNECT_TIMEOUT); 242 udp_globals.ip_phone = ip_bind_service(SERVICE_IP, IPPROTO_UDP, 243 SERVICE_UDP, client_connection); 244 if (udp_globals.ip_phone < 0) 203 udp_globals.icmp_phone = icmp_connect_module(SERVICE_ICMP, ICMP_CONNECT_TIMEOUT); 204 udp_globals.ip_phone = ip_bind_service(SERVICE_IP, IPPROTO_UDP, SERVICE_UDP, client_connection, udp_received_msg); 205 if(udp_globals.ip_phone < 0){ 245 206 return udp_globals.ip_phone; 246 207 } 247 208 // read default packet dimensions 248 ERROR_PROPAGATE(ip_packet_size_req(udp_globals.ip_phone, -1, 249 &udp_globals.packet_dimension)); 209 ERROR_PROPAGATE(ip_packet_size_req(udp_globals.ip_phone, -1, &udp_globals.packet_dimension)); 250 210 ERROR_PROPAGATE(socket_ports_initialize(&udp_globals.sockets)); 251 if (ERROR_OCCURRED(packet_dimensions_initialize( 252 &udp_globals.dimensions))) { 211 if(ERROR_OCCURRED(packet_dimensions_initialize(&udp_globals.dimensions))){ 253 212 socket_ports_destroy(&udp_globals.sockets); 254 213 return ERROR_CODE; … … 257 216 udp_globals.packet_dimension.content -= sizeof(udp_header_t); 258 217 udp_globals.last_used_port = UDP_FREE_PORTS_START - 1; 259 260 218 // get configuration 261 219 udp_globals.checksum_computing = NET_DEFAULT_UDP_CHECKSUM_COMPUTING; 262 220 udp_globals.autobinding = NET_DEFAULT_UDP_AUTOBINDING; 263 221 configuration = &names[0]; 264 ERROR_PROPAGATE(net_get_conf_req(udp_globals.net_phone, &configuration, 265 count, &data)); 266 if (configuration) { 267 if (configuration[0].value) 268 udp_globals.checksum_computing = 269 (configuration[0].value[0] == 'y'); 270 271 if (configuration[1].value) 272 udp_globals.autobinding = 273 (configuration[1].value[0] == 'y'); 274 222 ERROR_PROPAGATE(net_get_conf_req(udp_globals.net_phone, &configuration, count, &data)); 223 if(configuration){ 224 if(configuration[0].value){ 225 udp_globals.checksum_computing = (configuration[0].value[0] == 'y'); 226 } 227 if(configuration[1].value){ 228 udp_globals.autobinding = (configuration[1].value[0] == 'y'); 229 } 275 230 net_free_settings(configuration, data); 276 231 } 277 278 232 fibril_rwlock_write_unlock(&udp_globals.lock); 279 233 return EOK; 280 234 } 281 235 282 int 283 udp_received_msg(device_id_t device_id, packet_t packet, services_t receiver, 284 services_t error) 285 { 236 int udp_received_msg(device_id_t device_id, packet_t packet, services_t receiver, services_t error){ 286 237 int result; 287 238 288 239 fibril_rwlock_write_lock(&udp_globals.lock); 289 240 result = udp_process_packet(device_id, packet, error); 290 if (result != EOK)241 if(result != EOK){ 291 242 fibril_rwlock_write_unlock(&udp_globals.lock); 243 } 292 244 293 245 return result; 294 246 } 295 247 296 int udp_process_packet(device_id_t device_id, packet_t packet, services_t error) 297 { 248 int udp_process_packet(device_id_t device_id, packet_t packet, services_t error){ 298 249 ERROR_DECLARE; 299 250 … … 311 262 icmp_code_t code; 312 263 void *ip_header; 313 struct sockaddr * src;314 struct sockaddr * dest;264 struct sockaddr * src; 265 struct sockaddr * dest; 315 266 packet_dimension_ref packet_dimension; 316 267 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 268 if(error){ 269 switch(error){ 270 case SERVICE_ICMP: 271 // ignore error 272 // length = icmp_client_header_length(packet); 273 // process error 274 result = icmp_client_process_packet(packet, &type, &code, NULL, NULL); 275 if(result < 0){ 276 return udp_release_and_return(packet, result); 277 } 278 length = (size_t) result; 279 if(ERROR_OCCURRED(packet_trim(packet, length, 0))){ 280 return udp_release_and_return(packet, ERROR_CODE); 281 } 282 break; 283 default: 284 return udp_release_and_return(packet, ENOTSUP); 285 } 286 } 337 287 // TODO process received ipopts? 338 288 result = ip_client_process_packet(packet, NULL, NULL, NULL, NULL, NULL); 339 if (result < 0)289 if(result < 0){ 340 290 return udp_release_and_return(packet, result); 291 } 341 292 offset = (size_t) result; 342 293 343 294 length = packet_get_data_length(packet); 344 if (length <= 0)295 if(length <= 0){ 345 296 return udp_release_and_return(packet, EINVAL); 346 if (length < UDP_HEADER_SIZE + offset) 297 } 298 if(length < UDP_HEADER_SIZE + offset){ 347 299 return udp_release_and_return(packet, NO_DATA); 300 } 348 301 349 302 // trim all but UDP header 350 if (ERROR_OCCURRED(packet_trim(packet, offset, 0)))303 if(ERROR_OCCURRED(packet_trim(packet, offset, 0))){ 351 304 return udp_release_and_return(packet, ERROR_CODE); 305 } 352 306 353 307 // get udp header 354 308 header = (udp_header_ref) packet_get_data(packet); 355 if (!header)309 if(! header){ 356 310 return udp_release_and_return(packet, NO_DATA); 357 311 } 358 312 // 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); 313 socket = socket_port_find(&udp_globals.sockets, ntohs(header->destination_port), SOCKET_MAP_KEY_LISTENING, 0); 314 if(! socket){ 315 if(tl_prepare_icmp_packet(udp_globals.net_phone, udp_globals.icmp_phone, packet, error) == EOK){ 316 icmp_destination_unreachable_msg(udp_globals.icmp_phone, ICMP_PORT_UNREACH, 0, packet); 366 317 } 367 318 return EADDRNOTAVAIL; … … 372 323 fragments = 0; 373 324 total_length = ntohs(header->total_length); 374 375 325 // 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) 326 if(header->checksum && (! error)){ 327 result = packet_get_addr(packet, (uint8_t **) &src, (uint8_t **) &dest); 328 if(result <= 0){ 380 329 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))) { 330 } 331 if(ERROR_OCCURRED(ip_client_get_pseudo_header(IPPROTO_UDP, src, result, dest, result, total_length, &ip_header, &length))){ 385 332 return udp_release_and_return(packet, ERROR_CODE); 386 } else{333 }else{ 387 334 checksum = compute_checksum(0, ip_header, length); 388 // the udp header checksum will be added with the first 389 // fragment later 335 // the udp header checksum will be added with the first fragment later 390 336 free(ip_header); 391 337 } 392 } else{338 }else{ 393 339 header->checksum = 0; 394 340 checksum = 0; 395 341 } 396 342 397 do 343 do{ 398 344 ++ fragments; 399 345 length = packet_get_data_length(next_packet); 400 if (length <= 0)346 if(length <= 0){ 401 347 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); 348 } 349 if(total_length < length){ 350 if(ERROR_OCCURRED(packet_trim(next_packet, 0, length - total_length))){ 351 return udp_release_and_return(packet, ERROR_CODE); 408 352 } 409 410 353 // 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)); 354 if(header->checksum){ 355 checksum = compute_checksum(checksum, packet_get_data(packet), packet_get_data_length(packet)); 415 356 } 416 417 357 // relese the rest of the packet fragments 418 358 tmp_packet = pq_next(next_packet); 419 while (tmp_packet){359 while(tmp_packet){ 420 360 next_packet = pq_detach(tmp_packet); 421 pq_release_remote(udp_globals.net_phone, 422 packet_get_id(tmp_packet)); 361 pq_release_remote(udp_globals.net_phone, packet_get_id(tmp_packet)); 423 362 tmp_packet = next_packet; 424 363 } 425 426 364 // exit the loop 427 365 break; 428 366 } 429 367 total_length -= length; 430 431 368 // 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)); 369 if(header->checksum){ 370 checksum = compute_checksum(checksum, packet_get_data(packet), packet_get_data_length(packet)); 371 } 372 }while((next_packet = pq_next(next_packet)) && (total_length > 0)); 439 373 440 374 // 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) { 375 if(header->checksum){ 376 if(flip_checksum(compact_checksum(checksum)) != IP_CHECKSUM_ZERO){ 377 if(tl_prepare_icmp_packet(udp_globals.net_phone, udp_globals.icmp_phone, packet, error) == EOK){ 446 378 // 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); 379 icmp_parameter_problem_msg(udp_globals.icmp_phone, ICMP_PARAM_POINTER, ((size_t) ((void *) &header->checksum)) - ((size_t) ((void *) header)), packet); 451 380 } 452 381 return EINVAL; … … 455 384 456 385 // 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))) { 386 if(ERROR_OCCURRED(dyn_fifo_push(&socket->received, packet_get_id(packet), SOCKET_MAX_RECEIVED_SIZE)) 387 || ERROR_OCCURRED(tl_get_ip_packet_dimension(udp_globals.ip_phone, &udp_globals.dimensions, device_id, &packet_dimension))){ 461 388 return udp_release_and_return(packet, ERROR_CODE); 462 389 } … … 464 391 // notify the destination socket 465 392 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 393 async_msg_5(socket->phone, NET_SOCKET_RECEIVED, (ipcarg_t) socket->socket_id, packet_dimension->content, 0, 0, (ipcarg_t) fragments); 470 394 return EOK; 471 395 } 472 396 473 int 474 udp_message_standalone(ipc_callid_t callid, ipc_call_t * call, 475 ipc_call_t * answer, int * answer_count) 476 { 397 int udp_message_standalone(ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count){ 477 398 ERROR_DECLARE; 478 399 … … 480 401 481 402 *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 403 switch(IPC_GET_METHOD(*call)){ 404 case NET_TL_RECEIVED: 405 if(! ERROR_OCCURRED(packet_translate_remote(udp_globals.net_phone, &packet, IPC_GET_PACKET(call)))){ 406 ERROR_CODE = udp_received_msg(IPC_GET_DEVICE(call), packet, SERVICE_UDP, IPC_GET_ERROR(call)); 407 } 408 return ERROR_CODE; 409 case IPC_M_CONNECT_TO_ME: 410 return udp_process_client_messages(callid, * call); 411 } 496 412 return ENOTSUP; 497 413 } 498 414 499 int udp_process_client_messages(ipc_callid_t callid, ipc_call_t call) 500 { 415 int udp_process_client_messages(ipc_callid_t callid, ipc_call_t call){ 501 416 int res; 502 417 bool keep_on_going = true; 503 418 socket_cores_t local_sockets; 504 419 int app_phone = IPC_GET_PHONE(&call); 505 struct sockaddr * addr;420 struct sockaddr * addr; 506 421 int socket_id; 507 422 size_t addrlen; … … 518 433 answer_count = 0; 519 434 520 // The client connection is only in one fibril and therefore no 521 // additional locks are needed. 435 // The client connection is only in one fibril and therefore no additional locks are needed. 522 436 523 437 socket_cores_initialize(&local_sockets); 524 438 525 while (keep_on_going){439 while(keep_on_going){ 526 440 527 441 // answer the call … … 535 449 536 450 // process the call 537 switch (IPC_GET_METHOD(call)) { 538 case IPC_M_PHONE_HUNGUP: 539 keep_on_going = false; 540 res = EHANGUP; 541 break; 542 543 case NET_SOCKET: 544 socket_id = SOCKET_GET_SOCKET_ID(call); 545 res = socket_create(&local_sockets, app_phone, NULL, 546 &socket_id); 547 SOCKET_SET_SOCKET_ID(answer, socket_id); 548 549 if (res != EOK) 451 switch(IPC_GET_METHOD(call)){ 452 case IPC_M_PHONE_HUNGUP: 453 keep_on_going = false; 454 res = EHANGUP; 550 455 break; 551 552 if (tl_get_ip_packet_dimension(udp_globals.ip_phone, 553 &udp_globals.dimensions, DEVICE_INVALID_ID, 554 &packet_dimension) == EOK) { 555 SOCKET_SET_DATA_FRAGMENT_SIZE(answer, 556 packet_dimension->content); 557 } 558 559 // SOCKET_SET_DATA_FRAGMENT_SIZE(answer, 560 // MAX_UDP_FRAGMENT_SIZE); 561 SOCKET_SET_HEADER_SIZE(answer, UDP_HEADER_SIZE); 562 answer_count = 3; 563 break; 564 565 case NET_SOCKET_BIND: 566 res = data_receive((void **) &addr, &addrlen); 567 if (res != EOK) 456 case NET_SOCKET: 457 socket_id = SOCKET_GET_SOCKET_ID(call); 458 res = socket_create(&local_sockets, app_phone, NULL, &socket_id); 459 SOCKET_SET_SOCKET_ID(answer, socket_id); 460 461 if(res == EOK){ 462 if (tl_get_ip_packet_dimension(udp_globals.ip_phone, &udp_globals.dimensions, DEVICE_INVALID_ID, &packet_dimension) == EOK){ 463 SOCKET_SET_DATA_FRAGMENT_SIZE(answer, packet_dimension->content); 464 } 465 // SOCKET_SET_DATA_FRAGMENT_SIZE(answer, MAX_UDP_FRAGMENT_SIZE); 466 SOCKET_SET_HEADER_SIZE(answer, UDP_HEADER_SIZE); 467 answer_count = 3; 468 } 568 469 break; 569 fibril_rwlock_write_lock(&udp_globals.lock); 570 res = socket_bind(&local_sockets, &udp_globals.sockets, 571 SOCKET_GET_SOCKET_ID(call), addr, addrlen, 572 UDP_FREE_PORTS_START, UDP_FREE_PORTS_END, 573 udp_globals.last_used_port); 574 fibril_rwlock_write_unlock(&udp_globals.lock); 575 free(addr); 576 break; 577 578 case NET_SOCKET_SENDTO: 579 res = data_receive((void **) &addr, &addrlen); 580 if (res != EOK) 470 case NET_SOCKET_BIND: 471 res = data_receive((void **) &addr, &addrlen); 472 if(res == EOK){ 473 fibril_rwlock_write_lock(&udp_globals.lock); 474 res = socket_bind(&local_sockets, &udp_globals.sockets, SOCKET_GET_SOCKET_ID(call), addr, addrlen, UDP_FREE_PORTS_START, UDP_FREE_PORTS_END, udp_globals.last_used_port); 475 fibril_rwlock_write_unlock(&udp_globals.lock); 476 free(addr); 477 } 581 478 break; 582 583 fibril_rwlock_write_lock(&udp_globals.lock); 584 res = udp_sendto_message(&local_sockets, 585 SOCKET_GET_SOCKET_ID(call), addr, addrlen, 586 SOCKET_GET_DATA_FRAGMENTS(call), &size, 587 SOCKET_GET_FLAGS(call)); 588 SOCKET_SET_DATA_FRAGMENT_SIZE(answer, size); 589 590 if (res != EOK) 479 case NET_SOCKET_SENDTO: 480 res = data_receive((void **) &addr, &addrlen); 481 if(res == EOK){ 482 fibril_rwlock_write_lock(&udp_globals.lock); 483 res = udp_sendto_message(&local_sockets, SOCKET_GET_SOCKET_ID(call), addr, addrlen, SOCKET_GET_DATA_FRAGMENTS(call), &size, SOCKET_GET_FLAGS(call)); 484 SOCKET_SET_DATA_FRAGMENT_SIZE(answer, size); 485 if(res != EOK){ 486 fibril_rwlock_write_unlock(&udp_globals.lock); 487 }else{ 488 answer_count = 2; 489 } 490 free(addr); 491 } 492 break; 493 case NET_SOCKET_RECVFROM: 494 fibril_rwlock_write_lock(&udp_globals.lock); 495 res = udp_recvfrom_message(&local_sockets, SOCKET_GET_SOCKET_ID(call), SOCKET_GET_FLAGS(call), &addrlen); 591 496 fibril_rwlock_write_unlock(&udp_globals.lock); 592 else 593 answer_count = 2; 594 595 free(addr); 596 break; 597 598 case NET_SOCKET_RECVFROM: 599 fibril_rwlock_write_lock(&udp_globals.lock); 600 res = udp_recvfrom_message(&local_sockets, 601 SOCKET_GET_SOCKET_ID(call), SOCKET_GET_FLAGS(call), 602 &addrlen); 603 fibril_rwlock_write_unlock(&udp_globals.lock); 604 605 if (res <= 0) 497 if(res > 0){ 498 SOCKET_SET_READ_DATA_LENGTH(answer, res); 499 SOCKET_SET_ADDRESS_LENGTH(answer, addrlen); 500 answer_count = 3; 501 res = EOK; 502 } 606 503 break; 607 608 SOCKET_SET_READ_DATA_LENGTH(answer, res); 609 SOCKET_SET_ADDRESS_LENGTH(answer, addrlen); 610 answer_count = 3; 611 res = EOK; 612 break; 613 614 case NET_SOCKET_CLOSE: 615 fibril_rwlock_write_lock(&udp_globals.lock); 616 res = socket_destroy(udp_globals.net_phone, 617 SOCKET_GET_SOCKET_ID(call), &local_sockets, 618 &udp_globals.sockets, NULL); 619 fibril_rwlock_write_unlock(&udp_globals.lock); 620 break; 621 622 case NET_SOCKET_GETSOCKOPT: 623 case NET_SOCKET_SETSOCKOPT: 624 default: 625 res = ENOTSUP; 626 break; 504 case NET_SOCKET_CLOSE: 505 fibril_rwlock_write_lock(&udp_globals.lock); 506 res = socket_destroy(udp_globals.net_phone, SOCKET_GET_SOCKET_ID(call), &local_sockets, &udp_globals.sockets, NULL); 507 fibril_rwlock_write_unlock(&udp_globals.lock); 508 break; 509 case NET_SOCKET_GETSOCKOPT: 510 case NET_SOCKET_SETSOCKOPT: 511 default: 512 res = ENOTSUP; 513 break; 627 514 } 628 515 } … … 632 519 633 520 // release all local sockets 634 socket_cores_release(udp_globals.net_phone, &local_sockets, 635 &udp_globals.sockets, NULL); 521 socket_cores_release(udp_globals.net_phone, &local_sockets, &udp_globals.sockets, NULL); 636 522 637 523 return res; 638 524 } 639 525 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 { 526 int udp_sendto_message(socket_cores_ref local_sockets, int socket_id, const struct sockaddr * addr, socklen_t addrlen, int fragments, size_t * data_fragment_size, int flags){ 645 527 ERROR_DECLARE; 646 528 … … 662 544 663 545 socket = socket_cores_find(local_sockets, socket_id); 664 if (!socket)546 if(! socket){ 665 547 return ENOTSOCK; 666 667 if ((socket->port <= 0) && udp_globals.autobinding) { 548 } 549 550 if((socket->port <= 0) && udp_globals.autobinding){ 668 551 // bind the socket to a random free port if not bound 669 // do 552 // do{ 670 553 // try to find a free port 671 554 // fibril_rwlock_read_unlock(&udp_globals.lock); 672 555 // fibril_rwlock_write_lock(&udp_globals.lock); 673 556 // 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); 557 // if(socket->port <= 0){ 558 if(ERROR_OCCURRED(socket_bind_free_port(&udp_globals.sockets, socket, UDP_FREE_PORTS_START, UDP_FREE_PORTS_END, udp_globals.last_used_port))){ 559 // fibril_rwlock_write_unlock(&udp_globals.lock); 560 // fibril_rwlock_read_lock(&udp_globals.lock); 683 561 return ERROR_CODE; 684 562 } 685 // set the next port as the search starting port 686 // number 563 // set the next port as the search starting port number 687 564 udp_globals.last_used_port = socket->port; 688 565 // } … … 690 567 // fibril_rwlock_read_lock(&udp_globals.lock); 691 568 // 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))) { 569 // }while(socket->port <= 0); 570 } 571 572 if(udp_globals.checksum_computing){ 573 if(ERROR_OCCURRED(ip_get_route_req(udp_globals.ip_phone, IPPROTO_UDP, addr, addrlen, &device_id, &ip_header, &headerlen))){ 699 574 return udp_release_and_return(packet, ERROR_CODE); 700 575 } 701 576 // 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 { 577 // ERROR_PROPAGATE(tl_get_ip_packet_dimension(udp_globals.ip_phone, &udp_globals.dimensions, device_id, &packet_dimension)); 578 } 579 // }else{ 706 580 // do not ask all the time 707 ERROR_PROPAGATE(ip_packet_size_req(udp_globals.ip_phone, -1, 708 &udp_globals.packet_dimension)); 581 ERROR_PROPAGATE(ip_packet_size_req(udp_globals.ip_phone, -1, &udp_globals.packet_dimension)); 709 582 packet_dimension = &udp_globals.packet_dimension; 710 583 // } 711 584 712 585 // 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) 586 result = tl_socket_read_packet_data(udp_globals.net_phone, &packet, UDP_HEADER_SIZE, packet_dimension, addr, addrlen); 587 if(result < 0){ 716 588 return result; 717 589 } 718 590 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 591 if(udp_globals.checksum_computing){ 592 checksum = compute_checksum(0, packet_get_data(packet), packet_get_data_length(packet)); 593 }else{ 723 594 checksum = 0; 724 595 } 725 596 // prefix the udp header 726 597 header = PACKET_PREFIX(packet, udp_header_t); 727 if(! header) 598 if(! header){ 728 599 return udp_release_and_return(packet, ENOMEM); 729 600 } 730 601 bzero(header, sizeof(*header)); 731 602 // 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) 603 for(index = 1; index < fragments; ++ index){ 604 result = tl_socket_read_packet_data(udp_globals.net_phone, &next_packet, 0, packet_dimension, addr, addrlen); 605 if(result < 0){ 736 606 return udp_release_and_return(packet, result); 737 738 if (ERROR_OCCURRED(pq_add(&packet, next_packet, index, 0)))607 } 608 if(ERROR_OCCURRED(pq_add(&packet, next_packet, index, 0))){ 739 609 return udp_release_and_return(packet, ERROR_CODE); 740 610 } 741 611 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 612 if(udp_globals.checksum_computing){ 613 checksum = compute_checksum(checksum, packet_get_data(next_packet), packet_get_data_length(next_packet)); 614 } 615 } 749 616 // set the udp header 750 617 header->source_port = htons((socket->port > 0) ? socket->port : 0); … … 752 619 header->total_length = htons(total_length + sizeof(*header)); 753 620 header->checksum = 0; 754 if (udp_globals.checksum_computing){621 if(udp_globals.checksum_computing){ 755 622 // update the pseudo header 756 if (ERROR_OCCURRED(ip_client_set_pseudo_header_data_length( 757 ip_header, headerlen, total_length + UDP_HEADER_SIZE))) { 623 if(ERROR_OCCURRED(ip_client_set_pseudo_header_data_length(ip_header, headerlen, total_length + UDP_HEADER_SIZE))){ 758 624 free(ip_header); 759 625 return udp_release_and_return(packet, ERROR_CODE); 760 626 } 761 762 627 // finish the checksum computation 763 628 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))); 629 checksum = compute_checksum(checksum, (uint8_t *) header, sizeof(*header)); 630 header->checksum = htons(flip_checksum(compact_checksum(checksum))); 768 631 free(ip_header); 769 } else{632 }else{ 770 633 device_id = DEVICE_INVALID_ID; 771 634 } 772 773 635 // prepare the first packet fragment 774 if (ERROR_OCCURRED(ip_client_prepare_packet(packet, IPPROTO_UDP, 0, 0, 775 0, 0))) { 636 if(ERROR_OCCURRED(ip_client_prepare_packet(packet, IPPROTO_UDP, 0, 0, 0, 0))){ 776 637 return udp_release_and_return(packet, ERROR_CODE); 777 638 } 778 779 639 // send the packet 780 640 fibril_rwlock_write_unlock(&udp_globals.lock); 781 641 ip_send_msg(udp_globals.ip_phone, device_id, packet, SERVICE_UDP, 0); 782 783 642 return EOK; 784 643 } 785 644 786 int 787 udp_recvfrom_message(socket_cores_ref local_sockets, int socket_id, int flags, 788 size_t *addrlen) 789 { 645 int udp_recvfrom_message(socket_cores_ref local_sockets, int socket_id, int flags, size_t * addrlen){ 790 646 ERROR_DECLARE; 791 647 … … 794 650 packet_t packet; 795 651 udp_header_ref header; 796 struct sockaddr * addr;652 struct sockaddr * addr; 797 653 size_t length; 798 uint8_t * data;654 uint8_t * data; 799 655 int result; 800 656 801 657 // find the socket 802 658 socket = socket_cores_find(local_sockets, socket_id); 803 if (!socket)659 if(! socket){ 804 660 return ENOTSOCK; 805 661 } 806 662 // get the next received packet 807 663 packet_id = dyn_fifo_value(&socket->received); 808 if (packet_id < 0)664 if(packet_id < 0){ 809 665 return NO_DATA; 810 811 ERROR_PROPAGATE(packet_translate_remote(udp_globals.net_phone, &packet, 812 packet_id)); 813 666 } 667 ERROR_PROPAGATE(packet_translate_remote(udp_globals.net_phone, &packet, packet_id)); 814 668 // get udp header 815 669 data = packet_get_data(packet); 816 if (!data){670 if(! data){ 817 671 pq_release_remote(udp_globals.net_phone, packet_id); 818 672 return NO_DATA; … … 822 676 // set the source address port 823 677 result = packet_get_addr(packet, (uint8_t **) &addr, NULL); 824 if (ERROR_OCCURRED(tl_set_address_port(addr, result, 825 ntohs(header->source_port)))) { 678 if(ERROR_OCCURRED(tl_set_address_port(addr, result, ntohs(header->source_port)))){ 826 679 pq_release_remote(udp_globals.net_phone, packet_id); 827 680 return ERROR_CODE; 828 681 } 829 682 *addrlen = (size_t) result; 830 831 683 // send the source address 832 684 ERROR_PROPAGATE(data_reply(addr, * addrlen)); … … 841 693 dyn_fifo_pop(&socket->received); 842 694 pq_release_remote(udp_globals.net_phone, packet_get_id(packet)); 843 844 695 // return the total length 845 696 return (int) length; 846 697 } 847 698 848 int udp_release_and_return(packet_t packet, int result) 849 { 699 int udp_release_and_return(packet_t packet, int result){ 850 700 pq_release_remote(udp_globals.net_phone, packet_get_id(packet)); 851 701 return result; … … 854 704 /** Default thread for new connections. 855 705 * 856 * @param[in] iid 857 * @param[in] icall 706 * @param[in] iid The initial message identifier. 707 * @param[in] icall The initial message call structure. 858 708 * 859 709 */ … … 866 716 ipc_answer_0(iid, EOK); 867 717 868 while 718 while(true) { 869 719 ipc_call_t answer; 870 720 int answer_count; … … 881 731 &answer_count); 882 732 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)) 733 /* End if said to either by the message or the processing result */ 734 if ((IPC_GET_METHOD(call) == IPC_M_PHONE_HUNGUP) || (res == EHANGUP)) 888 735 return; 889 736 … … 895 742 /** Starts the module. 896 743 * 897 * @param argc The count of the command line arguments. Ignored 898 * parameter. 899 * @param argv The command line parameters. Ignored parameter. 744 * @param argc The count of the command line arguments. Ignored parameter. 745 * @param argv The command line parameters. Ignored parameter. 900 746 * 901 * @returns 902 * @returns Other error codes as defined for each specific module903 * start function.747 * @returns EOK on success. 748 * @returns Other error codes as defined for each specific module start function. 749 * 904 750 */ 905 751 int main(int argc, char *argv[])
Note:
See TracChangeset
for help on using the changeset viewer.