Changeset f14291b in mainline for uspace/srv/net/tl/udp/udp.c
- Timestamp:
- 2010-10-19T20:55:53Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- a93d79a
- Parents:
- 1882525 (diff), a7a85d16 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/net/tl/udp/udp.c
r1882525 rf14291b 42 42 #include <ipc/ipc.h> 43 43 #include <ipc/services.h> 44 45 #include <net_err.h> 46 #include <net_messages.h> 47 #include <net_modules.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 48 57 #include <adt/dynamic_fifo.h> 49 #include <packet /packet_client.h>58 #include <packet_client.h> 50 59 #include <packet_remote.h> 51 60 #include <net_checksum.h> 52 #include <in.h>53 #include <in6.h>54 #include <inet.h>55 61 #include <ip_client.h> 56 62 #include <ip_interface.h> 57 #include <ip_protocols.h>58 63 #include <icmp_client.h> 59 64 #include <icmp_interface.h> 60 65 #include <net_interface.h> 61 #include <socket_codes.h>62 #include <socket_errno.h>63 66 #include <socket_core.h> 64 #include <socket_messages.h>65 67 #include <tl_common.h> 66 68 #include <tl_local.h> 67 69 #include <tl_interface.h> 68 #include <tl_messages.h>69 70 70 71 #include "udp.h" … … 72 73 #include "udp_module.h" 73 74 74 /** UDP module name. 75 */ 75 /** UDP module name. */ 76 76 #define NAME "UDP protocol" 77 77 78 /** Default UDP checksum computing. 79 */ 78 /** Default UDP checksum computing. */ 80 79 #define NET_DEFAULT_UDP_CHECKSUM_COMPUTING true 81 80 82 /** Default UDP autobind when sending via unbound sockets. 83 */ 81 /** Default UDP autobind when sending via unbound sockets. */ 84 82 #define NET_DEFAULT_UDP_AUTOBINDING true 85 83 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 */ 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. */ 96 91 #define UDP_FREE_PORTS_END 65535 97 92 98 93 /** Processes the received UDP packet queue. 94 * 99 95 * Is used as an entry point from the underlying IP module. 100 96 * Locks the global lock and calls udp_process_packet() function. 97 * 101 98 * @param[in] device_id The receiving device identifier. 102 99 * @param[in,out] packet The received packet queue. 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); 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); 109 110 110 111 /** Processes the received UDP packet queue. 112 * 111 113 * Notifies the destination socket application. 112 * Releases the packet on error or sends an ICMP error notification.. 114 * Releases the packet on error or sends an ICMP error notification. 115 * 113 116 * @param[in] device_id The receiving device identifier. 114 117 * @param[in,out] packet The received packet queue. 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); 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); 126 134 127 135 /** Releases the packet and returns the result. 128 * @param[in] packet The packet queue to be released. 129 * @param[in] result The result to be returned. 130 * @return The result parameter. 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. 131 140 */ 132 141 int udp_release_and_return(packet_t packet, int result); … … 137 146 138 147 /** Processes the socket client messages. 148 * 139 149 * Runs until the client module disconnects. 140 * @param[in] callid The message identifier. 141 * @param[in] call The message parameters. 142 * @returns EOK on success. 143 * @see socket.h 150 * 151 * @param[in] callid The message identifier. 152 * @param[in] call The message parameters. 153 * @returns EOK on success. 154 * @see socket.h 144 155 */ 145 156 int udp_process_client_messages(ipc_callid_t callid, ipc_call_t call); 146 157 147 158 /** Sends data from the socket to the remote address. 159 * 148 160 * Binds the socket to a free port if not already connected/bound. 149 161 * Handles the NET_SOCKET_SENDTO message. 150 162 * Supports AF_INET and AF_INET6 address families. 163 * 151 164 * @param[in,out] local_sockets The application local sockets. 152 165 * @param[in] socket_id Socket identifier. 153 * @param[in] addr 154 * @param[in] addrlen 166 * @param[in] addr The destination address. 167 * @param[in] addrlen The address length. 155 168 * @param[in] fragments The number of data fragments. 156 169 * @param[out] data_fragment_size The data fragment size in bytes. 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); 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); 169 189 170 190 /** Receives data to the socket. 191 * 171 192 * Handles the NET_SOCKET_RECVFROM message. 172 193 * Replies the source address as well. 194 * 173 195 * @param[in] local_sockets The application local sockets. 174 196 * @param[in] socket_id Socket identifier. 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); 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); 186 212 187 213 /*@}*/ … … 189 215 /** UDP global data. 190 216 */ 191 udp_globals_t udp_globals; 192 193 int udp_initialize(async_client_conn_t client_connection){ 217 udp_globals_t udp_globals; 218 219 int udp_initialize(async_client_conn_t client_connection) 220 { 194 221 ERROR_DECLARE; 195 222 196 measured_string_t names[] = {{str_dup("UDP_CHECKSUM_COMPUTING"), 22}, {str_dup("UDP_AUTOBINDING"), 15}}; 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 }; 197 233 measured_string_ref configuration; 198 234 size_t count = sizeof(names) / sizeof(measured_string_t); … … 201 237 fibril_rwlock_initialize(&udp_globals.lock); 202 238 fibril_rwlock_write_lock(&udp_globals.lock); 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){ 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) 206 245 return udp_globals.ip_phone; 207 } 246 208 247 // read default packet dimensions 209 ERROR_PROPAGATE(ip_packet_size_req(udp_globals.ip_phone, -1, &udp_globals.packet_dimension)); 248 ERROR_PROPAGATE(ip_packet_size_req(udp_globals.ip_phone, -1, 249 &udp_globals.packet_dimension)); 210 250 ERROR_PROPAGATE(socket_ports_initialize(&udp_globals.sockets)); 211 if(ERROR_OCCURRED(packet_dimensions_initialize(&udp_globals.dimensions))){ 251 if (ERROR_OCCURRED(packet_dimensions_initialize( 252 &udp_globals.dimensions))) { 212 253 socket_ports_destroy(&udp_globals.sockets); 213 254 return ERROR_CODE; … … 216 257 udp_globals.packet_dimension.content -= sizeof(udp_header_t); 217 258 udp_globals.last_used_port = UDP_FREE_PORTS_START - 1; 259 218 260 // get configuration 219 261 udp_globals.checksum_computing = NET_DEFAULT_UDP_CHECKSUM_COMPUTING; 220 262 udp_globals.autobinding = NET_DEFAULT_UDP_AUTOBINDING; 221 263 configuration = &names[0]; 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 } 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 230 275 net_free_settings(configuration, data); 231 276 } 277 232 278 fibril_rwlock_write_unlock(&udp_globals.lock); 233 279 return EOK; 234 280 } 235 281 236 int udp_received_msg(device_id_t device_id, packet_t packet, services_t receiver, services_t error){ 282 int 283 udp_received_msg(device_id_t device_id, packet_t packet, services_t receiver, 284 services_t error) 285 { 237 286 int result; 238 287 239 288 fibril_rwlock_write_lock(&udp_globals.lock); 240 289 result = udp_process_packet(device_id, packet, error); 241 if (result != EOK){290 if (result != EOK) 242 291 fibril_rwlock_write_unlock(&udp_globals.lock); 243 }244 292 245 293 return result; 246 294 } 247 295 248 int udp_process_packet(device_id_t device_id, packet_t packet, services_t error){ 296 int udp_process_packet(device_id_t device_id, packet_t packet, services_t error) 297 { 249 298 ERROR_DECLARE; 250 299 … … 262 311 icmp_code_t code; 263 312 void *ip_header; 264 struct sockaddr * 265 struct sockaddr * 313 struct sockaddr *src; 314 struct sockaddr *dest; 266 315 packet_dimension_ref packet_dimension; 267 316 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 } 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 287 337 // TODO process received ipopts? 288 338 result = ip_client_process_packet(packet, NULL, NULL, NULL, NULL, NULL); 289 if (result < 0){339 if (result < 0) 290 340 return udp_release_and_return(packet, result); 291 }292 341 offset = (size_t) result; 293 342 294 343 length = packet_get_data_length(packet); 295 if (length <= 0){344 if (length <= 0) 296 345 return udp_release_and_return(packet, EINVAL); 297 } 298 if(length < UDP_HEADER_SIZE + offset){ 346 if (length < UDP_HEADER_SIZE + offset) 299 347 return udp_release_and_return(packet, NO_DATA); 300 }301 348 302 349 // trim all but UDP header 303 if (ERROR_OCCURRED(packet_trim(packet, offset, 0))){350 if (ERROR_OCCURRED(packet_trim(packet, offset, 0))) 304 351 return udp_release_and_return(packet, ERROR_CODE); 305 }306 352 307 353 // get udp header 308 354 header = (udp_header_ref) packet_get_data(packet); 309 if (! header){355 if (!header) 310 356 return udp_release_and_return(packet, NO_DATA); 311 } 357 312 358 // find the destination socket 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); 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); 317 366 } 318 367 return EADDRNOTAVAIL; … … 323 372 fragments = 0; 324 373 total_length = ntohs(header->total_length); 374 325 375 // compute header checksum if set 326 if(header->checksum && (! error)){ 327 result = packet_get_addr(packet, (uint8_t **) &src, (uint8_t **) &dest); 328 if(result <= 0){ 376 if (header->checksum && (!error)) { 377 result = packet_get_addr(packet, (uint8_t **) &src, 378 (uint8_t **) &dest); 379 if( result <= 0) 329 380 return udp_release_and_return(packet, result); 330 } 331 if(ERROR_OCCURRED(ip_client_get_pseudo_header(IPPROTO_UDP, src, result, dest, result, total_length, &ip_header, &length))){ 381 382 if (ERROR_OCCURRED(ip_client_get_pseudo_header(IPPROTO_UDP, 383 src, result, dest, result, total_length, &ip_header, 384 &length))) { 332 385 return udp_release_and_return(packet, ERROR_CODE); 333 } else{386 } else { 334 387 checksum = compute_checksum(0, ip_header, length); 335 // the udp header checksum will be added with the first fragment later 388 // the udp header checksum will be added with the first 389 // fragment later 336 390 free(ip_header); 337 391 } 338 } else{392 } else { 339 393 header->checksum = 0; 340 394 checksum = 0; 341 395 } 342 396 343 do {397 do { 344 398 ++ fragments; 345 399 length = packet_get_data_length(next_packet); 346 if (length <= 0){400 if (length <= 0) 347 401 return udp_release_and_return(packet, NO_DATA); 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); 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); 352 408 } 409 353 410 // add partial checksum if set 354 if(header->checksum){ 355 checksum = compute_checksum(checksum, packet_get_data(packet), packet_get_data_length(packet)); 411 if (header->checksum) { 412 checksum = compute_checksum(checksum, 413 packet_get_data(packet), 414 packet_get_data_length(packet)); 356 415 } 416 357 417 // relese the rest of the packet fragments 358 418 tmp_packet = pq_next(next_packet); 359 while (tmp_packet){419 while (tmp_packet) { 360 420 next_packet = pq_detach(tmp_packet); 361 pq_release_remote(udp_globals.net_phone, packet_get_id(tmp_packet)); 421 pq_release_remote(udp_globals.net_phone, 422 packet_get_id(tmp_packet)); 362 423 tmp_packet = next_packet; 363 424 } 425 364 426 // exit the loop 365 427 break; 366 428 } 367 429 total_length -= length; 430 368 431 // add partial checksum if set 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)); 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)); 373 439 374 440 // check checksum 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){ 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) { 378 446 // checksum error ICMP 379 icmp_parameter_problem_msg(udp_globals.icmp_phone, ICMP_PARAM_POINTER, ((size_t) ((void *) &header->checksum)) - ((size_t) ((void *) header)), packet); 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); 380 451 } 381 452 return EINVAL; … … 384 455 385 456 // queue the received packet 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))){ 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))) { 388 461 return udp_release_and_return(packet, ERROR_CODE); 389 462 } … … 391 464 // notify the destination socket 392 465 fibril_rwlock_write_unlock(&udp_globals.lock); 393 async_msg_5(socket->phone, NET_SOCKET_RECEIVED, (ipcarg_t) socket->socket_id, packet_dimension->content, 0, 0, (ipcarg_t) fragments); 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 394 470 return EOK; 395 471 } 396 472 397 int udp_message_standalone(ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count){ 473 int 474 udp_message_standalone(ipc_callid_t callid, ipc_call_t * call, 475 ipc_call_t * answer, int * answer_count) 476 { 398 477 ERROR_DECLARE; 399 478 … … 401 480 402 481 *answer_count = 0; 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 } 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 412 496 return ENOTSUP; 413 497 } 414 498 415 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) 500 { 416 501 int res; 417 502 bool keep_on_going = true; 418 503 socket_cores_t local_sockets; 419 504 int app_phone = IPC_GET_PHONE(&call); 420 struct sockaddr * 505 struct sockaddr *addr; 421 506 int socket_id; 422 507 size_t addrlen; … … 433 518 answer_count = 0; 434 519 435 // The client connection is only in one fibril and therefore no additional locks are needed. 520 // The client connection is only in one fibril and therefore no 521 // additional locks are needed. 436 522 437 523 socket_cores_initialize(&local_sockets); 438 524 439 while (keep_on_going){525 while (keep_on_going) { 440 526 441 527 // answer the call … … 449 535 450 536 // process the call 451 switch(IPC_GET_METHOD(call)){ 452 case IPC_M_PHONE_HUNGUP: 453 keep_on_going = false; 454 res = EHANGUP; 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) 455 550 break; 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 } 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) 469 568 break; 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 } 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) 478 581 break; 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 } 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) 591 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) 492 606 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); 496 fibril_rwlock_write_unlock(&udp_globals.lock); 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 } 503 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; 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; 514 627 } 515 628 } … … 519 632 520 633 // release all local sockets 521 socket_cores_release(udp_globals.net_phone, &local_sockets, &udp_globals.sockets, NULL); 634 socket_cores_release(udp_globals.net_phone, &local_sockets, 635 &udp_globals.sockets, NULL); 522 636 523 637 return res; 524 638 } 525 639 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){ 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 { 527 645 ERROR_DECLARE; 528 646 … … 544 662 545 663 socket = socket_cores_find(local_sockets, socket_id); 546 if (! socket){664 if (!socket) 547 665 return ENOTSOCK; 548 } 549 550 if((socket->port <= 0) && udp_globals.autobinding){ 666 667 if ((socket->port <= 0) && udp_globals.autobinding) { 551 668 // bind the socket to a random free port if not bound 552 // do {669 // do { 553 670 // try to find a free port 554 671 // fibril_rwlock_read_unlock(&udp_globals.lock); 555 672 // fibril_rwlock_write_lock(&udp_globals.lock); 556 673 // might be changed in the meantime 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); 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); 561 683 return ERROR_CODE; 562 684 } 563 // set the next port as the search starting port number 685 // set the next port as the search starting port 686 // number 564 687 udp_globals.last_used_port = socket->port; 565 688 // } … … 567 690 // fibril_rwlock_read_lock(&udp_globals.lock); 568 691 // might be changed in the meantime 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))){ 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))) { 574 699 return udp_release_and_return(packet, ERROR_CODE); 575 700 } 576 701 // get the device packet dimension 577 // ERROR_PROPAGATE(tl_get_ip_packet_dimension(udp_globals.ip_phone, &udp_globals.dimensions, device_id, &packet_dimension)); 578 } 579 // }else{ 702 // ERROR_PROPAGATE(tl_get_ip_packet_dimension(udp_globals.ip_phone, 703 // &udp_globals.dimensions, device_id, &packet_dimension)); 704 } 705 // } else { 580 706 // do not ask all the time 581 ERROR_PROPAGATE(ip_packet_size_req(udp_globals.ip_phone, -1, &udp_globals.packet_dimension)); 707 ERROR_PROPAGATE(ip_packet_size_req(udp_globals.ip_phone, -1, 708 &udp_globals.packet_dimension)); 582 709 packet_dimension = &udp_globals.packet_dimension; 583 710 // } 584 711 585 712 // read the first packet fragment 586 result = tl_socket_read_packet_data(udp_globals.net_phone, &packet, UDP_HEADER_SIZE, packet_dimension, addr, addrlen); 587 if(result < 0){ 713 result = tl_socket_read_packet_data(udp_globals.net_phone, &packet, 714 UDP_HEADER_SIZE, packet_dimension, addr, addrlen); 715 if (result < 0) 588 716 return result; 589 } 717 590 718 total_length = (size_t) result; 591 if(udp_globals.checksum_computing){ 592 checksum = compute_checksum(0, packet_get_data(packet), packet_get_data_length(packet)); 593 }else{ 719 if (udp_globals.checksum_computing) 720 checksum = compute_checksum(0, packet_get_data(packet), 721 packet_get_data_length(packet)); 722 else 594 723 checksum = 0; 595 } 724 596 725 // prefix the udp header 597 726 header = PACKET_PREFIX(packet, udp_header_t); 598 if(! header) {727 if(! header) 599 728 return udp_release_and_return(packet, ENOMEM); 600 } 729 601 730 bzero(header, sizeof(*header)); 602 731 // read the rest of the packet fragments 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){ 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) 606 736 return udp_release_and_return(packet, result); 607 } 608 if (ERROR_OCCURRED(pq_add(&packet, next_packet, index, 0))){737 738 if (ERROR_OCCURRED(pq_add(&packet, next_packet, index, 0))) 609 739 return udp_release_and_return(packet, ERROR_CODE); 610 } 740 611 741 total_length += (size_t) result; 612 if(udp_globals.checksum_computing){ 613 checksum = compute_checksum(checksum, packet_get_data(next_packet), packet_get_data_length(next_packet)); 614 } 615 } 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 616 749 // set the udp header 617 750 header->source_port = htons((socket->port > 0) ? socket->port : 0); … … 619 752 header->total_length = htons(total_length + sizeof(*header)); 620 753 header->checksum = 0; 621 if (udp_globals.checksum_computing){754 if (udp_globals.checksum_computing) { 622 755 // update the pseudo header 623 if(ERROR_OCCURRED(ip_client_set_pseudo_header_data_length(ip_header, headerlen, total_length + UDP_HEADER_SIZE))){ 756 if (ERROR_OCCURRED(ip_client_set_pseudo_header_data_length( 757 ip_header, headerlen, total_length + UDP_HEADER_SIZE))) { 624 758 free(ip_header); 625 759 return udp_release_and_return(packet, ERROR_CODE); 626 760 } 761 627 762 // finish the checksum computation 628 763 checksum = compute_checksum(checksum, ip_header, headerlen); 629 checksum = compute_checksum(checksum, (uint8_t *) header, sizeof(*header)); 630 header->checksum = htons(flip_checksum(compact_checksum(checksum))); 764 checksum = compute_checksum(checksum, (uint8_t *) header, 765 sizeof(*header)); 766 header->checksum = 767 htons(flip_checksum(compact_checksum(checksum))); 631 768 free(ip_header); 632 } else{769 } else { 633 770 device_id = DEVICE_INVALID_ID; 634 771 } 772 635 773 // prepare the first packet fragment 636 if(ERROR_OCCURRED(ip_client_prepare_packet(packet, IPPROTO_UDP, 0, 0, 0, 0))){ 774 if (ERROR_OCCURRED(ip_client_prepare_packet(packet, IPPROTO_UDP, 0, 0, 775 0, 0))) { 637 776 return udp_release_and_return(packet, ERROR_CODE); 638 777 } 778 639 779 // send the packet 640 780 fibril_rwlock_write_unlock(&udp_globals.lock); 641 781 ip_send_msg(udp_globals.ip_phone, device_id, packet, SERVICE_UDP, 0); 782 642 783 return EOK; 643 784 } 644 785 645 int udp_recvfrom_message(socket_cores_ref local_sockets, int socket_id, int flags, size_t * addrlen){ 786 int 787 udp_recvfrom_message(socket_cores_ref local_sockets, int socket_id, int flags, 788 size_t *addrlen) 789 { 646 790 ERROR_DECLARE; 647 791 … … 650 794 packet_t packet; 651 795 udp_header_ref header; 652 struct sockaddr * 796 struct sockaddr *addr; 653 797 size_t length; 654 uint8_t * 798 uint8_t *data; 655 799 int result; 656 800 657 801 // find the socket 658 802 socket = socket_cores_find(local_sockets, socket_id); 659 if (! socket){803 if (!socket) 660 804 return ENOTSOCK; 661 } 805 662 806 // get the next received packet 663 807 packet_id = dyn_fifo_value(&socket->received); 664 if (packet_id < 0){808 if (packet_id < 0) 665 809 return NO_DATA; 666 } 667 ERROR_PROPAGATE(packet_translate_remote(udp_globals.net_phone, &packet, packet_id)); 810 811 ERROR_PROPAGATE(packet_translate_remote(udp_globals.net_phone, &packet, 812 packet_id)); 813 668 814 // get udp header 669 815 data = packet_get_data(packet); 670 if (! data){816 if (!data) { 671 817 pq_release_remote(udp_globals.net_phone, packet_id); 672 818 return NO_DATA; … … 676 822 // set the source address port 677 823 result = packet_get_addr(packet, (uint8_t **) &addr, NULL); 678 if(ERROR_OCCURRED(tl_set_address_port(addr, result, ntohs(header->source_port)))){ 824 if (ERROR_OCCURRED(tl_set_address_port(addr, result, 825 ntohs(header->source_port)))) { 679 826 pq_release_remote(udp_globals.net_phone, packet_id); 680 827 return ERROR_CODE; 681 828 } 682 829 *addrlen = (size_t) result; 830 683 831 // send the source address 684 832 ERROR_PROPAGATE(data_reply(addr, * addrlen)); … … 693 841 dyn_fifo_pop(&socket->received); 694 842 pq_release_remote(udp_globals.net_phone, packet_get_id(packet)); 843 695 844 // return the total length 696 845 return (int) length; 697 846 } 698 847 699 int udp_release_and_return(packet_t packet, int result){ 848 int udp_release_and_return(packet_t packet, int result) 849 { 700 850 pq_release_remote(udp_globals.net_phone, packet_get_id(packet)); 701 851 return result; … … 704 854 /** Default thread for new connections. 705 855 * 706 * @param[in] iid 707 * @param[in] icall 856 * @param[in] iid The initial message identifier. 857 * @param[in] icall The initial message call structure. 708 858 * 709 859 */ … … 716 866 ipc_answer_0(iid, EOK); 717 867 718 while (true) {868 while (true) { 719 869 ipc_call_t answer; 720 870 int answer_count; … … 731 881 &answer_count); 732 882 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)) 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)) 735 888 return; 736 889 … … 742 895 /** Starts the module. 743 896 * 744 * @param argc The count of the command line arguments. Ignored parameter. 745 * @param argv The command line parameters. Ignored parameter. 746 * 747 * @returns EOK on success. 748 * @returns Other error codes as defined for each specific module start function. 749 * 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. 750 904 */ 751 905 int main(int argc, char *argv[])
Note:
See TracChangeset
for help on using the changeset viewer.