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