Changeset aadf01e in mainline for uspace/srv/net/tl/udp/udp.c
- Timestamp:
- 2010-03-07T15:13:28Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 936835e
- Parents:
- aa85487
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/net/tl/udp/udp.c
raa85487 raadf01e 104 104 * @returns Other error codes as defined for the udp_process_packet() function. 105 105 */ 106 int udp_received_msg( device_id_t device_id, packet_t packet, services_t receiver, services_t error);106 int udp_received_msg(device_id_t device_id, packet_t packet, services_t receiver, services_t error); 107 107 108 108 /** Processes the received UDP packet queue. … … 121 121 * @returns Other error codes as defined for the ip_client_process_packet() function. 122 122 */ 123 int udp_process_packet( device_id_t device_id, packet_t packet, services_t error);123 int udp_process_packet(device_id_t device_id, packet_t packet, services_t error); 124 124 125 125 /** Releases the packet and returns the result. … … 128 128 * @return The result parameter. 129 129 */ 130 int udp_release_and_return( packet_t packet, int result);130 int udp_release_and_return(packet_t packet, int result); 131 131 132 132 /** @name Socket messages processing functions … … 141 141 * @see socket.h 142 142 */ 143 int udp_process_client_messages( ipc_callid_t callid, ipc_call_t call);143 int udp_process_client_messages(ipc_callid_t callid, ipc_call_t call); 144 144 145 145 /** Sends data from the socket to the remote address. … … 164 164 * @returns Other error codes as defined for the ip_send_msg() function. 165 165 */ 166 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);166 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); 167 167 168 168 /** Receives data to the socket. … … 181 181 * @returns Other error codes as defined for the data_reply() function. 182 182 */ 183 int udp_recvfrom_message( socket_cores_ref local_sockets, int socket_id, int flags, size_t * addrlen);183 int udp_recvfrom_message(socket_cores_ref local_sockets, int socket_id, int flags, size_t * addrlen); 184 184 185 185 /*@}*/ … … 189 189 udp_globals_t udp_globals; 190 190 191 int udp_initialize( async_client_conn_t client_connection){191 int udp_initialize(async_client_conn_t client_connection){ 192 192 ERROR_DECLARE; 193 193 194 measured_string_t names[] = {{ str_dup("UDP_CHECKSUM_COMPUTING"), 22 }, { str_dup("UDP_AUTOBINDING"), 15}};195 measured_string_ref 196 size_t count = sizeof( names ) / sizeof( measured_string_t);197 char * 198 199 fibril_rwlock_initialize( & udp_globals.lock);200 fibril_rwlock_write_lock( & udp_globals.lock);201 udp_globals.icmp_phone = icmp_connect_module( SERVICE_ICMP, ICMP_CONNECT_TIMEOUT);202 udp_globals.ip_phone = ip_bind_service( SERVICE_IP, IPPROTO_UDP, SERVICE_UDP, client_connection, udp_received_msg);203 if( udp_globals.ip_phone < 0){194 measured_string_t names[] = {{str_dup("UDP_CHECKSUM_COMPUTING"), 22}, {str_dup("UDP_AUTOBINDING"), 15}}; 195 measured_string_ref configuration; 196 size_t count = sizeof(names) / sizeof(measured_string_t); 197 char * data; 198 199 fibril_rwlock_initialize(&udp_globals.lock); 200 fibril_rwlock_write_lock(&udp_globals.lock); 201 udp_globals.icmp_phone = icmp_connect_module(SERVICE_ICMP, ICMP_CONNECT_TIMEOUT); 202 udp_globals.ip_phone = ip_bind_service(SERVICE_IP, IPPROTO_UDP, SERVICE_UDP, client_connection, udp_received_msg); 203 if(udp_globals.ip_phone < 0){ 204 204 return udp_globals.ip_phone; 205 205 } 206 206 // read default packet dimensions 207 ERROR_PROPAGATE( ip_packet_size_req( udp_globals.ip_phone, -1, & udp_globals.packet_dimension));208 ERROR_PROPAGATE( socket_ports_initialize( & udp_globals.sockets));209 if( ERROR_OCCURRED( packet_dimensions_initialize( & udp_globals.dimensions))){210 socket_ports_destroy( & udp_globals.sockets);207 ERROR_PROPAGATE(ip_packet_size_req(udp_globals.ip_phone, -1, &udp_globals.packet_dimension)); 208 ERROR_PROPAGATE(socket_ports_initialize(&udp_globals.sockets)); 209 if(ERROR_OCCURRED(packet_dimensions_initialize(&udp_globals.dimensions))){ 210 socket_ports_destroy(&udp_globals.sockets); 211 211 return ERROR_CODE; 212 212 } 213 udp_globals.packet_dimension.prefix += sizeof( udp_header_t);214 udp_globals.packet_dimension.content -= sizeof( udp_header_t);213 udp_globals.packet_dimension.prefix += sizeof(udp_header_t); 214 udp_globals.packet_dimension.content -= sizeof(udp_header_t); 215 215 udp_globals.last_used_port = UDP_FREE_PORTS_START - 1; 216 216 // get configuration 217 217 udp_globals.checksum_computing = NET_DEFAULT_UDP_CHECKSUM_COMPUTING; 218 218 udp_globals.autobinding = NET_DEFAULT_UDP_AUTOBINDING; 219 configuration = & names[ 0];220 ERROR_PROPAGATE( net_get_conf_req( udp_globals.net_phone, & configuration, count, & data));221 if( configuration){222 if( configuration[ 0 ].value){223 udp_globals.checksum_computing = ( configuration[ 0 ].value[ 0 ] == 'y');224 } 225 if( configuration[ 1 ].value){226 udp_globals.autobinding = ( configuration[ 1 ].value[ 0 ] == 'y');227 } 228 net_free_settings( configuration, data);229 } 230 fibril_rwlock_write_unlock( & udp_globals.lock);219 configuration = &names[0]; 220 ERROR_PROPAGATE(net_get_conf_req(udp_globals.net_phone, &configuration, count, &data)); 221 if(configuration){ 222 if(configuration[0].value){ 223 udp_globals.checksum_computing = (configuration[0].value[0] == 'y'); 224 } 225 if(configuration[1].value){ 226 udp_globals.autobinding = (configuration[1].value[0] == 'y'); 227 } 228 net_free_settings(configuration, data); 229 } 230 fibril_rwlock_write_unlock(&udp_globals.lock); 231 231 return EOK; 232 232 } 233 233 234 int udp_received_msg( device_id_t device_id, packet_t packet, services_t receiver, services_t error){235 int 236 237 fibril_rwlock_write_lock( & udp_globals.lock);238 result = udp_process_packet( device_id, packet, error);239 if( result != EOK){240 fibril_rwlock_write_unlock( & udp_globals.lock);234 int udp_received_msg(device_id_t device_id, packet_t packet, services_t receiver, services_t error){ 235 int result; 236 237 fibril_rwlock_write_lock(&udp_globals.lock); 238 result = udp_process_packet(device_id, packet, error); 239 if(result != EOK){ 240 fibril_rwlock_write_unlock(&udp_globals.lock); 241 241 } 242 242 … … 244 244 } 245 245 246 int udp_process_packet( device_id_t device_id, packet_t packet, services_t error){246 int udp_process_packet(device_id_t device_id, packet_t packet, services_t error){ 247 247 ERROR_DECLARE; 248 248 249 size_t 250 size_t 251 int 252 udp_header_ref 253 socket_core_ref 254 packet_t 255 size_t 256 uint32_t 257 int 258 packet_t 259 icmp_type_t 260 icmp_code_t 261 ip_pseudo_header_ref 262 struct sockaddr * 263 struct sockaddr * 264 packet_dimension_ref 265 266 if( error){267 switch( error){249 size_t length; 250 size_t offset; 251 int result; 252 udp_header_ref header; 253 socket_core_ref socket; 254 packet_t next_packet; 255 size_t total_length; 256 uint32_t checksum; 257 int fragments; 258 packet_t tmp_packet; 259 icmp_type_t type; 260 icmp_code_t code; 261 ip_pseudo_header_ref ip_header; 262 struct sockaddr * src; 263 struct sockaddr * dest; 264 packet_dimension_ref packet_dimension; 265 266 if(error){ 267 switch(error){ 268 268 case SERVICE_ICMP: 269 269 // ignore error 270 // length = icmp_client_header_length( packet);270 // length = icmp_client_header_length(packet); 271 271 // process error 272 result = icmp_client_process_packet( packet, & type, & code, NULL, NULL);273 if( result < 0){274 return udp_release_and_return( packet, result);272 result = icmp_client_process_packet(packet, &type, &code, NULL, NULL); 273 if(result < 0){ 274 return udp_release_and_return(packet, result); 275 275 } 276 length = ( size_t) result;277 if( ERROR_OCCURRED( packet_trim( packet, length, 0))){278 return udp_release_and_return( packet, ERROR_CODE);276 length = (size_t) result; 277 if(ERROR_OCCURRED(packet_trim(packet, length, 0))){ 278 return udp_release_and_return(packet, ERROR_CODE); 279 279 } 280 280 break; 281 281 default: 282 return udp_release_and_return( packet, ENOTSUP);282 return udp_release_and_return(packet, ENOTSUP); 283 283 } 284 284 } 285 285 // TODO process received ipopts? 286 result = ip_client_process_packet( packet, NULL, NULL, NULL, NULL, NULL);287 if( result < 0){288 return udp_release_and_return( packet, result);289 } 290 offset = ( size_t) result;291 292 length = packet_get_data_length( packet);293 if( length <= 0){294 return udp_release_and_return( packet, EINVAL);295 } 296 if( length < UDP_HEADER_SIZE + offset){297 return udp_release_and_return( packet, NO_DATA);286 result = ip_client_process_packet(packet, NULL, NULL, NULL, NULL, NULL); 287 if(result < 0){ 288 return udp_release_and_return(packet, result); 289 } 290 offset = (size_t) result; 291 292 length = packet_get_data_length(packet); 293 if(length <= 0){ 294 return udp_release_and_return(packet, EINVAL); 295 } 296 if(length < UDP_HEADER_SIZE + offset){ 297 return udp_release_and_return(packet, NO_DATA); 298 298 } 299 299 300 300 // trim all but UDP header 301 if( ERROR_OCCURRED( packet_trim( packet, offset, 0))){302 return udp_release_and_return( packet, ERROR_CODE);301 if(ERROR_OCCURRED(packet_trim(packet, offset, 0))){ 302 return udp_release_and_return(packet, ERROR_CODE); 303 303 } 304 304 305 305 // get udp header 306 header = ( udp_header_ref ) packet_get_data( packet);307 if( ! header){308 return udp_release_and_return( packet, NO_DATA);306 header = (udp_header_ref) packet_get_data(packet); 307 if(! header){ 308 return udp_release_and_return(packet, NO_DATA); 309 309 } 310 310 // find the destination socket 311 socket = socket_port_find( & udp_globals.sockets, ntohs( header->destination_port ), SOCKET_MAP_KEY_LISTENING, 0);312 if( ! socket){313 if( tl_prepare_icmp_packet( udp_globals.net_phone, udp_globals.icmp_phone, packet, error ) == EOK){314 icmp_destination_unreachable_msg( udp_globals.icmp_phone, ICMP_PORT_UNREACH, 0, packet);311 socket = socket_port_find(&udp_globals.sockets, ntohs(header->destination_port), SOCKET_MAP_KEY_LISTENING, 0); 312 if(! socket){ 313 if(tl_prepare_icmp_packet(udp_globals.net_phone, udp_globals.icmp_phone, packet, error) == EOK){ 314 icmp_destination_unreachable_msg(udp_globals.icmp_phone, ICMP_PORT_UNREACH, 0, packet); 315 315 } 316 316 return EADDRNOTAVAIL; … … 320 320 next_packet = packet; 321 321 fragments = 0; 322 total_length = ntohs( header->total_length);322 total_length = ntohs(header->total_length); 323 323 // compute header checksum if set 324 if( header->checksum && ( ! error)){325 result = packet_get_addr( packet, ( uint8_t ** ) & src, ( uint8_t ** ) & dest);326 if( result <= 0){327 return udp_release_and_return( packet, result);328 } 329 if( ERROR_OCCURRED( ip_client_get_pseudo_header( IPPROTO_UDP, src, result, dest, result, total_length, & ip_header, & length))){330 return udp_release_and_return( packet, ERROR_CODE);324 if(header->checksum && (! error)){ 325 result = packet_get_addr(packet, (uint8_t **) &src, (uint8_t **) &dest); 326 if(result <= 0){ 327 return udp_release_and_return(packet, result); 328 } 329 if(ERROR_OCCURRED(ip_client_get_pseudo_header(IPPROTO_UDP, src, result, dest, result, total_length, &ip_header, &length))){ 330 return udp_release_and_return(packet, ERROR_CODE); 331 331 }else{ 332 checksum = compute_checksum( 0, ip_header, length);332 checksum = compute_checksum(0, ip_header, length); 333 333 // the udp header checksum will be added with the first fragment later 334 free( ip_header);334 free(ip_header); 335 335 } 336 336 }else{ … … 341 341 do{ 342 342 ++ fragments; 343 length = packet_get_data_length( next_packet);344 if( length <= 0){345 return udp_release_and_return( packet, NO_DATA);346 } 347 if( total_length < length){348 if( ERROR_OCCURRED( packet_trim( next_packet, 0, length - total_length))){349 return udp_release_and_return( packet, ERROR_CODE);343 length = packet_get_data_length(next_packet); 344 if(length <= 0){ 345 return udp_release_and_return(packet, NO_DATA); 346 } 347 if(total_length < length){ 348 if(ERROR_OCCURRED(packet_trim(next_packet, 0, length - total_length))){ 349 return udp_release_and_return(packet, ERROR_CODE); 350 350 } 351 351 // add partial checksum if set 352 if( header->checksum){353 checksum = compute_checksum( checksum, packet_get_data( packet ), packet_get_data_length( packet));352 if(header->checksum){ 353 checksum = compute_checksum(checksum, packet_get_data(packet), packet_get_data_length(packet)); 354 354 } 355 355 // relese the rest of the packet fragments 356 tmp_packet = pq_next( next_packet);357 while( tmp_packet){358 next_packet = pq_detach( tmp_packet);359 pq_release( udp_globals.net_phone, packet_get_id( tmp_packet));356 tmp_packet = pq_next(next_packet); 357 while(tmp_packet){ 358 next_packet = pq_detach(tmp_packet); 359 pq_release(udp_globals.net_phone, packet_get_id(tmp_packet)); 360 360 tmp_packet = next_packet; 361 361 } … … 365 365 total_length -= length; 366 366 // add partial checksum if set 367 if( header->checksum){368 checksum = compute_checksum( checksum, packet_get_data( packet ), packet_get_data_length( packet));369 } 370 }while(( next_packet = pq_next( next_packet )) && ( total_length > 0));367 if(header->checksum){ 368 checksum = compute_checksum(checksum, packet_get_data(packet), packet_get_data_length(packet)); 369 } 370 }while((next_packet = pq_next(next_packet)) && (total_length > 0)); 371 371 372 372 // check checksum 373 if( header->checksum){374 if( flip_checksum( compact_checksum( checksum )) != IP_CHECKSUM_ZERO){375 if( tl_prepare_icmp_packet( udp_globals.net_phone, udp_globals.icmp_phone, packet, error ) == EOK){373 if(header->checksum){ 374 if(flip_checksum(compact_checksum(checksum)) != IP_CHECKSUM_ZERO){ 375 if(tl_prepare_icmp_packet(udp_globals.net_phone, udp_globals.icmp_phone, packet, error) == EOK){ 376 376 // checksum error ICMP 377 icmp_parameter_problem_msg( udp_globals.icmp_phone, ICMP_PARAM_POINTER, (( size_t ) (( void * ) & header->checksum )) - (( size_t ) (( void * ) header )), packet);377 icmp_parameter_problem_msg(udp_globals.icmp_phone, ICMP_PARAM_POINTER, ((size_t) ((void *) &header->checksum)) - ((size_t) ((void *) header)), packet); 378 378 } 379 379 return EINVAL; … … 382 382 383 383 // queue the received packet 384 if( ERROR_OCCURRED( dyn_fifo_push( & socket->received, packet_get_id( packet ), SOCKET_MAX_RECEIVED_SIZE))385 || ERROR_OCCURRED( tl_get_ip_packet_dimension( udp_globals.ip_phone, & udp_globals.dimensions, device_id, & packet_dimension))){386 return udp_release_and_return( packet, ERROR_CODE);384 if(ERROR_OCCURRED(dyn_fifo_push(&socket->received, packet_get_id(packet), SOCKET_MAX_RECEIVED_SIZE)) 385 || ERROR_OCCURRED(tl_get_ip_packet_dimension(udp_globals.ip_phone, &udp_globals.dimensions, device_id, &packet_dimension))){ 386 return udp_release_and_return(packet, ERROR_CODE); 387 387 } 388 388 389 389 // notify the destination socket 390 fibril_rwlock_write_unlock( & udp_globals.lock);391 async_msg_5( socket->phone, NET_SOCKET_RECEIVED, ( ipcarg_t ) socket->socket_id, packet_dimension->content, 0, 0, ( ipcarg_t ) fragments);390 fibril_rwlock_write_unlock(&udp_globals.lock); 391 async_msg_5(socket->phone, NET_SOCKET_RECEIVED, (ipcarg_t) socket->socket_id, packet_dimension->content, 0, 0, (ipcarg_t) fragments); 392 392 return EOK; 393 393 } 394 394 395 int udp_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count){395 int udp_message(ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count){ 396 396 ERROR_DECLARE; 397 397 398 packet_t 399 400 * 401 switch( IPC_GET_METHOD( * call)){398 packet_t packet; 399 400 *answer_count = 0; 401 switch(IPC_GET_METHOD(*call)){ 402 402 case NET_TL_RECEIVED: 403 if( ! ERROR_OCCURRED( packet_translate( udp_globals.net_phone, & packet, IPC_GET_PACKET( call)))){404 ERROR_CODE = udp_received_msg( IPC_GET_DEVICE( call ), packet, SERVICE_UDP, IPC_GET_ERROR( call));403 if(! ERROR_OCCURRED(packet_translate(udp_globals.net_phone, &packet, IPC_GET_PACKET(call)))){ 404 ERROR_CODE = udp_received_msg(IPC_GET_DEVICE(call), packet, SERVICE_UDP, IPC_GET_ERROR(call)); 405 405 } 406 406 return ERROR_CODE; 407 407 case IPC_M_CONNECT_TO_ME: 408 return udp_process_client_messages( callid, * call);408 return udp_process_client_messages(callid, * call); 409 409 } 410 410 return ENOTSUP; 411 411 } 412 412 413 int udp_process_client_messages( ipc_callid_t callid, ipc_call_t call){414 int 415 bool 416 socket_cores_t 417 int app_phone = IPC_GET_PHONE( & call);418 struct sockaddr * 419 size_t 420 fibril_rwlock_t 421 ipc_call_t 422 int 423 packet_dimension_ref 413 int udp_process_client_messages(ipc_callid_t callid, ipc_call_t call){ 414 int res; 415 bool keep_on_going = true; 416 socket_cores_t local_sockets; 417 int app_phone = IPC_GET_PHONE(&call); 418 struct sockaddr * addr; 419 size_t addrlen; 420 fibril_rwlock_t lock; 421 ipc_call_t answer; 422 int answer_count; 423 packet_dimension_ref packet_dimension; 424 424 425 425 /* … … 432 432 // The client connection is only in one fibril and therefore no additional locks are needed. 433 433 434 socket_cores_initialize( & local_sockets);435 fibril_rwlock_initialize( & lock);436 437 while( keep_on_going){434 socket_cores_initialize(&local_sockets); 435 fibril_rwlock_initialize(&lock); 436 437 while(keep_on_going){ 438 438 439 439 // answer the call 440 answer_call( callid, res, & answer, answer_count);440 answer_call(callid, res, &answer, answer_count); 441 441 442 442 // refresh data 443 refresh_answer( & answer, & answer_count);443 refresh_answer(&answer, &answer_count); 444 444 445 445 // get the next call 446 callid = async_get_call( & call);446 callid = async_get_call(&call); 447 447 448 448 // process the call 449 switch( IPC_GET_METHOD( call)){449 switch(IPC_GET_METHOD(call)){ 450 450 case IPC_M_PHONE_HUNGUP: 451 451 keep_on_going = false; … … 453 453 break; 454 454 case NET_SOCKET: 455 fibril_rwlock_write_lock( & lock);456 * SOCKET_SET_SOCKET_ID( answer ) = SOCKET_GET_SOCKET_ID( call);457 res = socket_create( & local_sockets, app_phone, NULL, SOCKET_SET_SOCKET_ID( answer));458 fibril_rwlock_write_unlock( & lock);459 if( res == EOK){460 if( tl_get_ip_packet_dimension( udp_globals.ip_phone, & udp_globals.dimensions, DEVICE_INVALID_ID, & packet_dimension ) == EOK){461 * SOCKET_SET_DATA_FRAGMENT_SIZE( answer) = packet_dimension->content;455 fibril_rwlock_write_lock(&lock); 456 *SOCKET_SET_SOCKET_ID(answer) = SOCKET_GET_SOCKET_ID(call); 457 res = socket_create(&local_sockets, app_phone, NULL, SOCKET_SET_SOCKET_ID(answer)); 458 fibril_rwlock_write_unlock(&lock); 459 if(res == EOK){ 460 if(tl_get_ip_packet_dimension(udp_globals.ip_phone, &udp_globals.dimensions, DEVICE_INVALID_ID, &packet_dimension) == EOK){ 461 *SOCKET_SET_DATA_FRAGMENT_SIZE(answer) = packet_dimension->content; 462 462 } 463 // * SOCKET_SET_DATA_FRAGMENT_SIZE( answer) = MAX_UDP_FRAGMENT_SIZE;464 * SOCKET_SET_HEADER_SIZE( answer) = UDP_HEADER_SIZE;463 // *SOCKET_SET_DATA_FRAGMENT_SIZE(answer) = MAX_UDP_FRAGMENT_SIZE; 464 *SOCKET_SET_HEADER_SIZE(answer) = UDP_HEADER_SIZE; 465 465 answer_count = 3; 466 466 } 467 467 break; 468 468 case NET_SOCKET_BIND: 469 res = data_receive(( void ** ) & addr, & addrlen);470 if( res == EOK){471 fibril_rwlock_read_lock( & lock);472 fibril_rwlock_write_lock( & udp_globals.lock);473 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);474 fibril_rwlock_write_unlock( & udp_globals.lock);475 fibril_rwlock_read_unlock( & lock);476 free( addr);469 res = data_receive((void **) &addr, &addrlen); 470 if(res == EOK){ 471 fibril_rwlock_read_lock(&lock); 472 fibril_rwlock_write_lock(&udp_globals.lock); 473 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); 474 fibril_rwlock_write_unlock(&udp_globals.lock); 475 fibril_rwlock_read_unlock(&lock); 476 free(addr); 477 477 } 478 478 break; 479 479 case NET_SOCKET_SENDTO: 480 res = data_receive(( void ** ) & addr, & addrlen);481 if( res == EOK){482 fibril_rwlock_read_lock( & lock);483 fibril_rwlock_write_lock( & udp_globals.lock);484 res = udp_sendto_message( & local_sockets, SOCKET_GET_SOCKET_ID( call ), addr, addrlen, SOCKET_GET_DATA_FRAGMENTS( call ), SOCKET_SET_DATA_FRAGMENT_SIZE( answer ), SOCKET_GET_FLAGS( call));485 if( res != EOK){486 fibril_rwlock_write_unlock( & udp_globals.lock);480 res = data_receive((void **) &addr, &addrlen); 481 if(res == EOK){ 482 fibril_rwlock_read_lock(&lock); 483 fibril_rwlock_write_lock(&udp_globals.lock); 484 res = udp_sendto_message(&local_sockets, SOCKET_GET_SOCKET_ID(call), addr, addrlen, SOCKET_GET_DATA_FRAGMENTS(call), SOCKET_SET_DATA_FRAGMENT_SIZE(answer), SOCKET_GET_FLAGS(call)); 485 if(res != EOK){ 486 fibril_rwlock_write_unlock(&udp_globals.lock); 487 487 }else{ 488 488 answer_count = 2; 489 489 } 490 fibril_rwlock_read_unlock( & lock);491 free( addr);490 fibril_rwlock_read_unlock(&lock); 491 free(addr); 492 492 } 493 493 break; 494 494 case NET_SOCKET_RECVFROM: 495 fibril_rwlock_read_lock( & lock);496 fibril_rwlock_write_lock( & udp_globals.lock);497 res = udp_recvfrom_message( & local_sockets, SOCKET_GET_SOCKET_ID( call ), SOCKET_GET_FLAGS( call ), & addrlen);498 fibril_rwlock_write_unlock( & udp_globals.lock);499 fibril_rwlock_read_unlock( & lock);500 if( res > 0){501 * SOCKET_SET_READ_DATA_LENGTH( answer) = res;502 * SOCKET_SET_ADDRESS_LENGTH( answer) = addrlen;495 fibril_rwlock_read_lock(&lock); 496 fibril_rwlock_write_lock(&udp_globals.lock); 497 res = udp_recvfrom_message(&local_sockets, SOCKET_GET_SOCKET_ID(call), SOCKET_GET_FLAGS(call), &addrlen); 498 fibril_rwlock_write_unlock(&udp_globals.lock); 499 fibril_rwlock_read_unlock(&lock); 500 if(res > 0){ 501 *SOCKET_SET_READ_DATA_LENGTH(answer) = res; 502 *SOCKET_SET_ADDRESS_LENGTH(answer) = addrlen; 503 503 answer_count = 3; 504 504 res = EOK; … … 506 506 break; 507 507 case NET_SOCKET_CLOSE: 508 fibril_rwlock_write_lock( & lock);509 fibril_rwlock_write_lock( & udp_globals.lock);510 res = socket_destroy( udp_globals.net_phone, SOCKET_GET_SOCKET_ID( call ), & local_sockets, & udp_globals.sockets, NULL);511 fibril_rwlock_write_unlock( & udp_globals.lock);512 fibril_rwlock_write_unlock( & lock);508 fibril_rwlock_write_lock(&lock); 509 fibril_rwlock_write_lock(&udp_globals.lock); 510 res = socket_destroy(udp_globals.net_phone, SOCKET_GET_SOCKET_ID(call), &local_sockets, &udp_globals.sockets, NULL); 511 fibril_rwlock_write_unlock(&udp_globals.lock); 512 fibril_rwlock_write_unlock(&lock); 513 513 break; 514 514 case NET_SOCKET_GETSOCKOPT: … … 521 521 522 522 // release all local sockets 523 socket_cores_release( udp_globals.net_phone, & local_sockets, & udp_globals.sockets, NULL);523 socket_cores_release(udp_globals.net_phone, &local_sockets, &udp_globals.sockets, NULL); 524 524 525 525 return res; 526 526 } 527 527 528 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){528 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){ 529 529 ERROR_DECLARE; 530 530 531 socket_core_ref socket; 532 packet_t packet; 533 packet_t next_packet; 534 udp_header_ref header; 535 int index; 536 size_t total_length; 537 int result; 538 uint16_t dest_port; 539 uint32_t checksum; 540 ip_pseudo_header_ref ip_header; 541 size_t headerlen; 542 device_id_t device_id; 543 packet_dimension_ref packet_dimension; 544 545 ERROR_PROPAGATE( tl_get_address_port( addr, addrlen, & dest_port )); 546 547 socket = socket_cores_find( local_sockets, socket_id ); 548 if( ! socket ) return ENOTSOCK; 549 550 if(( socket->port <= 0 ) && udp_globals.autobinding ){ 531 socket_core_ref socket; 532 packet_t packet; 533 packet_t next_packet; 534 udp_header_ref header; 535 int index; 536 size_t total_length; 537 int result; 538 uint16_t dest_port; 539 uint32_t checksum; 540 ip_pseudo_header_ref ip_header; 541 size_t headerlen; 542 device_id_t device_id; 543 packet_dimension_ref packet_dimension; 544 545 ERROR_PROPAGATE(tl_get_address_port(addr, addrlen, &dest_port)); 546 547 socket = socket_cores_find(local_sockets, socket_id); 548 if(! socket){ 549 return ENOTSOCK; 550 } 551 552 if((socket->port <= 0) && udp_globals.autobinding){ 551 553 // bind the socket to a random free port if not bound 552 554 // do{ 553 555 // try to find a free port 554 // fibril_rwlock_read_unlock( & udp_globals.lock);555 // fibril_rwlock_write_lock( & udp_globals.lock);556 // fibril_rwlock_read_unlock(&udp_globals.lock); 557 // fibril_rwlock_write_lock(&udp_globals.lock); 556 558 // 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);559 // if(socket->port <= 0){ 560 if(ERROR_OCCURRED(socket_bind_free_port(&udp_globals.sockets, socket, UDP_FREE_PORTS_START, UDP_FREE_PORTS_END, udp_globals.last_used_port))){ 561 // fibril_rwlock_write_unlock(&udp_globals.lock); 562 // fibril_rwlock_read_lock(&udp_globals.lock); 561 563 return ERROR_CODE; 562 564 } … … 564 566 udp_globals.last_used_port = socket->port; 565 567 // } 566 // fibril_rwlock_write_unlock( & udp_globals.lock);567 // fibril_rwlock_read_lock( & udp_globals.lock);568 // fibril_rwlock_write_unlock(&udp_globals.lock); 569 // fibril_rwlock_read_lock(&udp_globals.lock); 568 570 // 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);571 // }while(socket->port <= 0); 572 } 573 574 if(udp_globals.checksum_computing){ 575 if(ERROR_OCCURRED(ip_get_route_req(udp_globals.ip_phone, IPPROTO_UDP, addr, addrlen, &device_id, &ip_header, &headerlen))){ 576 return udp_release_and_return(packet, ERROR_CODE); 575 577 } 576 578 // get the device packet dimension 577 // ERROR_PROPAGATE( tl_get_ip_packet_dimension( udp_globals.ip_phone, & udp_globals.dimensions, device_id, & packet_dimension));579 // ERROR_PROPAGATE(tl_get_ip_packet_dimension(udp_globals.ip_phone, &udp_globals.dimensions, device_id, &packet_dimension)); 578 580 } 579 581 // }else{ 580 582 // do not ask all the time 581 ERROR_PROPAGATE( ip_packet_size_req( udp_globals.ip_phone, -1, & udp_globals.packet_dimension));582 packet_dimension = & 583 ERROR_PROPAGATE(ip_packet_size_req(udp_globals.ip_phone, -1, &udp_globals.packet_dimension)); 584 packet_dimension = &udp_globals.packet_dimension; 583 585 // } 584 586 585 587 // 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 ) return result; 588 total_length = ( size_t ) result; 589 if( udp_globals.checksum_computing ){ 590 checksum = compute_checksum( 0, packet_get_data( packet ), packet_get_data_length( packet )); 588 result = tl_socket_read_packet_data(udp_globals.net_phone, &packet, UDP_HEADER_SIZE, packet_dimension, addr, addrlen); 589 if(result < 0){ 590 return result; 591 } 592 total_length = (size_t) result; 593 if(udp_globals.checksum_computing){ 594 checksum = compute_checksum(0, packet_get_data(packet), packet_get_data_length(packet)); 591 595 }else{ 592 596 checksum = 0; 593 597 } 594 598 // prefix the udp header 595 header = PACKET_PREFIX( packet, udp_header_t);596 if( ! header){597 return udp_release_and_return( packet, ENOMEM);598 } 599 bzero( header, sizeof( * header));599 header = PACKET_PREFIX(packet, udp_header_t); 600 if(! header){ 601 return udp_release_and_return(packet, ENOMEM); 602 } 603 bzero(header, sizeof(*header)); 600 604 // read the rest of the packet fragments 601 for( index = 1; index < fragments; ++ index){602 result = tl_socket_read_packet_data( udp_globals.net_phone, & next_packet, 0, packet_dimension, addr, addrlen);603 if( result < 0){604 return udp_release_and_return( packet, result);605 } 606 if( ERROR_OCCURRED( pq_add( & packet, next_packet, index, 0))){607 return udp_release_and_return( packet, ERROR_CODE);608 } 609 total_length += ( size_t) result;610 if( udp_globals.checksum_computing){611 checksum = compute_checksum( checksum, packet_get_data( next_packet ), packet_get_data_length( next_packet));605 for(index = 1; index < fragments; ++ index){ 606 result = tl_socket_read_packet_data(udp_globals.net_phone, &next_packet, 0, packet_dimension, addr, addrlen); 607 if(result < 0){ 608 return udp_release_and_return(packet, result); 609 } 610 if(ERROR_OCCURRED(pq_add(&packet, next_packet, index, 0))){ 611 return udp_release_and_return(packet, ERROR_CODE); 612 } 613 total_length += (size_t) result; 614 if(udp_globals.checksum_computing){ 615 checksum = compute_checksum(checksum, packet_get_data(next_packet), packet_get_data_length(next_packet)); 612 616 } 613 617 } 614 618 // set the udp header 615 header->source_port = htons(( socket->port > 0 ) ? socket->port : 0);616 header->destination_port = htons( dest_port);617 header->total_length = htons( total_length + sizeof( * header));619 header->source_port = htons((socket->port > 0) ? socket->port : 0); 620 header->destination_port = htons(dest_port); 621 header->total_length = htons(total_length + sizeof(*header)); 618 622 header->checksum = 0; 619 if( udp_globals.checksum_computing){623 if(udp_globals.checksum_computing){ 620 624 // update the pseudo header 621 if( ERROR_OCCURRED( ip_client_set_pseudo_header_data_length( ip_header, headerlen, total_length + UDP_HEADER_SIZE))){622 free( ip_header);623 return udp_release_and_return( packet, ERROR_CODE);625 if(ERROR_OCCURRED(ip_client_set_pseudo_header_data_length(ip_header, headerlen, total_length + UDP_HEADER_SIZE))){ 626 free(ip_header); 627 return udp_release_and_return(packet, ERROR_CODE); 624 628 } 625 629 // finish the checksum computation 626 checksum = compute_checksum( checksum, ip_header, headerlen);627 checksum = compute_checksum( checksum, ( uint8_t * ) header, sizeof( * header));628 header->checksum = htons( flip_checksum( compact_checksum( checksum)));629 free( ip_header);630 checksum = compute_checksum(checksum, ip_header, headerlen); 631 checksum = compute_checksum(checksum, (uint8_t *) header, sizeof(*header)); 632 header->checksum = htons(flip_checksum(compact_checksum(checksum))); 633 free(ip_header); 630 634 }else{ 631 635 device_id = DEVICE_INVALID_ID; 632 636 } 633 637 // prepare the first packet fragment 634 if( ERROR_OCCURRED( ip_client_prepare_packet( packet, IPPROTO_UDP, 0, 0, 0, 0))){635 return udp_release_and_return( packet, ERROR_CODE);638 if(ERROR_OCCURRED(ip_client_prepare_packet(packet, IPPROTO_UDP, 0, 0, 0, 0))){ 639 return udp_release_and_return(packet, ERROR_CODE); 636 640 } 637 641 // send the packet 638 fibril_rwlock_write_unlock( & udp_globals.lock);639 ip_send_msg( udp_globals.ip_phone, device_id, packet, SERVICE_UDP, 0);642 fibril_rwlock_write_unlock(&udp_globals.lock); 643 ip_send_msg(udp_globals.ip_phone, device_id, packet, SERVICE_UDP, 0); 640 644 return EOK; 641 645 } 642 646 643 int udp_recvfrom_message( socket_cores_ref local_sockets, int socket_id, int flags, size_t * addrlen){647 int udp_recvfrom_message(socket_cores_ref local_sockets, int socket_id, int flags, size_t * addrlen){ 644 648 ERROR_DECLARE; 645 649 646 socket_core_ref 647 int 648 packet_t 649 udp_header_ref 650 struct sockaddr * 651 size_t 652 uint8_t * 653 int 650 socket_core_ref socket; 651 int packet_id; 652 packet_t packet; 653 udp_header_ref header; 654 struct sockaddr * addr; 655 size_t length; 656 uint8_t * data; 657 int result; 654 658 655 659 // find the socket 656 socket = socket_cores_find( local_sockets, socket_id ); 657 if( ! socket ) return ENOTSOCK; 660 socket = socket_cores_find(local_sockets, socket_id); 661 if(! socket){ 662 return ENOTSOCK; 663 } 658 664 // get the next received packet 659 packet_id = dyn_fifo_value( & socket->received ); 660 if( packet_id < 0 ) return NO_DATA; 661 ERROR_PROPAGATE( packet_translate( udp_globals.net_phone, & packet, packet_id )); 665 packet_id = dyn_fifo_value(&socket->received); 666 if(packet_id < 0){ 667 return NO_DATA; 668 } 669 ERROR_PROPAGATE(packet_translate(udp_globals.net_phone, &packet, packet_id)); 662 670 // get udp header 663 data = packet_get_data( packet);664 if( ! data){665 pq_release( udp_globals.net_phone, packet_id);671 data = packet_get_data(packet); 672 if(! data){ 673 pq_release(udp_globals.net_phone, packet_id); 666 674 return NO_DATA; 667 675 } 668 header = ( udp_header_ref) data;676 header = (udp_header_ref) data; 669 677 670 678 // set the source address port 671 result = packet_get_addr( packet, ( uint8_t ** ) & addr, NULL);672 if( ERROR_OCCURRED( tl_set_address_port( addr, result, ntohs( header->source_port)))){673 pq_release( udp_globals.net_phone, packet_id);679 result = packet_get_addr(packet, (uint8_t **) &addr, NULL); 680 if(ERROR_OCCURRED(tl_set_address_port(addr, result, ntohs(header->source_port)))){ 681 pq_release(udp_globals.net_phone, packet_id); 674 682 return ERROR_CODE; 675 683 } 676 * addrlen = ( size_t) result;684 *addrlen = (size_t) result; 677 685 // send the source address 678 ERROR_PROPAGATE( data_reply( addr, * addrlen));686 ERROR_PROPAGATE(data_reply(addr, * addrlen)); 679 687 680 688 // trim the header 681 ERROR_PROPAGATE( packet_trim( packet, UDP_HEADER_SIZE, 0));689 ERROR_PROPAGATE(packet_trim(packet, UDP_HEADER_SIZE, 0)); 682 690 683 691 // reply the packets 684 ERROR_PROPAGATE( socket_reply_packets( packet, & length));692 ERROR_PROPAGATE(socket_reply_packets(packet, &length)); 685 693 686 694 // release the packet 687 dyn_fifo_pop( & socket->received);688 pq_release( udp_globals.net_phone, packet_get_id( packet));695 dyn_fifo_pop(&socket->received); 696 pq_release(udp_globals.net_phone, packet_get_id(packet)); 689 697 // return the total length 690 return ( int) length;698 return (int) length; 691 699 } 692 700 693 int udp_release_and_return( packet_t packet, int result){694 pq_release( udp_globals.net_phone, packet_get_id( packet));701 int udp_release_and_return(packet_t packet, int result){ 702 pq_release(udp_globals.net_phone, packet_get_id(packet)); 695 703 return result; 696 704 }
Note:
See TracChangeset
for help on using the changeset viewer.