Changes in uspace/srv/net/tl/udp/udp.c [aadf01e:92307f1] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/net/tl/udp/udp.c
raadf01e r92307f1 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); 392 return EOK; 393 } 394 395 int udp_message(ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count){ 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 /* fibril_rwlock_write_unlock( & udp_globals.lock ); 393 async_msg_5( socket->phone, NET_SOCKET_RECEIVED, ( ipcarg_t ) socket->socket_id, 0, 0, 0, ( ipcarg_t ) fragments ); 394 */ return EOK; 395 } 396 397 int udp_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count ){ 396 398 ERROR_DECLARE; 397 399 398 packet_t 399 400 * answer_count = 0;401 switch( IPC_GET_METHOD(*call)){400 packet_t packet; 401 402 * answer_count = 0; 403 switch( IPC_GET_METHOD( * call )){ 402 404 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));405 if( ! ERROR_OCCURRED( packet_translate( 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 )); 405 407 } 406 408 return ERROR_CODE; 407 409 case IPC_M_CONNECT_TO_ME: 408 return udp_process_client_messages( callid, * call);410 return udp_process_client_messages( callid, * call ); 409 411 } 410 412 return ENOTSUP; 411 413 } 412 414 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; 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 size_t addrlen; 422 ipc_call_t answer; 423 int answer_count; 424 packet_dimension_ref packet_dimension; 424 425 425 426 /* … … 427 428 * - Answer the first IPC_M_CONNECT_TO_ME call. 428 429 */ 429 res = EOK; 430 answer_count = 0; 430 ipc_answer_0( callid, EOK ); 431 431 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){ 438 439 // answer the call 440 answer_call(callid, res, &answer, answer_count); 441 434 socket_cores_initialize( & local_sockets ); 435 436 while( keep_on_going ){ 442 437 // refresh data 443 refresh_answer(&answer, &answer_count); 444 445 // get the next call 446 callid = async_get_call(&call); 447 448 // process the call 449 switch(IPC_GET_METHOD(call)){ 438 refresh_answer( & answer, & answer_count ); 439 440 callid = async_get_call( & call ); 441 // printf( "message %d\n", IPC_GET_METHOD( * call )); 442 443 switch( IPC_GET_METHOD( call )){ 450 444 case IPC_M_PHONE_HUNGUP: 451 445 keep_on_going = false; 452 res = E HANGUP;446 res = EOK; 453 447 break; 454 448 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; 449 * SOCKET_SET_SOCKET_ID( answer ) = SOCKET_GET_SOCKET_ID( call ); 450 res = socket_create( & local_sockets, app_phone, NULL, SOCKET_SET_SOCKET_ID( answer )); 451 if( res == EOK ){ 452 if( tl_get_ip_packet_dimension( udp_globals.ip_phone, & udp_globals.dimensions, DEVICE_INVALID_ID, & packet_dimension ) == EOK ){ 453 * SOCKET_SET_DATA_FRAGMENT_SIZE( answer ) = packet_dimension->content; 462 454 } 463 // * SOCKET_SET_DATA_FRAGMENT_SIZE(answer) = MAX_UDP_FRAGMENT_SIZE;464 * SOCKET_SET_HEADER_SIZE(answer) = UDP_HEADER_SIZE;455 // * SOCKET_SET_DATA_FRAGMENT_SIZE( answer ) = MAX_UDP_FRAGMENT_SIZE; 456 * SOCKET_SET_HEADER_SIZE( answer ) = UDP_HEADER_SIZE; 465 457 answer_count = 3; 466 458 } 467 459 break; 468 460 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); 461 res = data_receive(( void ** ) & addr, & addrlen ); 462 if( res == EOK ){ 463 fibril_rwlock_write_lock( & udp_globals.lock ); 464 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 ); 465 fibril_rwlock_write_unlock( & udp_globals.lock ); 466 free( addr ); 477 467 } 478 468 break; 479 469 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); 470 res = data_receive(( void ** ) & addr, & addrlen ); 471 if( res == EOK ){ 472 fibril_rwlock_write_lock( & udp_globals.lock ); 473 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 )); 474 if( res != EOK ){ 475 fibril_rwlock_write_unlock( & udp_globals.lock ); 487 476 }else{ 488 477 answer_count = 2; 489 478 } 490 fibril_rwlock_read_unlock(&lock); 491 free(addr); 479 free( addr ); 492 480 } 493 481 break; 494 482 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; 483 fibril_rwlock_write_lock( & udp_globals.lock ); 484 res = udp_recvfrom_message( & local_sockets, SOCKET_GET_SOCKET_ID( call ), SOCKET_GET_FLAGS( call ), & addrlen ); 485 fibril_rwlock_write_unlock( & udp_globals.lock ); 486 if( res > 0 ){ 487 * SOCKET_SET_READ_DATA_LENGTH( answer ) = res; 488 * SOCKET_SET_ADDRESS_LENGTH( answer ) = addrlen; 503 489 answer_count = 3; 504 490 res = EOK; … … 506 492 break; 507 493 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); 494 fibril_rwlock_write_lock( & udp_globals.lock ); 495 res = socket_destroy( udp_globals.net_phone, SOCKET_GET_SOCKET_ID( call ), & local_sockets, & udp_globals.sockets, NULL ); 496 fibril_rwlock_write_unlock( & udp_globals.lock ); 513 497 break; 514 498 case NET_SOCKET_GETSOCKOPT: … … 518 502 break; 519 503 } 504 505 // printf( "res = %d\n", res ); 506 507 answer_call( callid, res, & answer, answer_count ); 520 508 } 521 509 522 510 // release all local sockets 523 socket_cores_release( udp_globals.net_phone, &local_sockets, &udp_globals.sockets, NULL);524 525 return res;526 } 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){511 socket_cores_release( udp_globals.net_phone, & local_sockets, & udp_globals.sockets, NULL ); 512 513 return EOK; 514 } 515 516 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 517 ERROR_DECLARE; 530 518 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){ 519 socket_core_ref socket; 520 packet_t packet; 521 packet_t next_packet; 522 udp_header_ref header; 523 int index; 524 size_t total_length; 525 int result; 526 uint16_t dest_port; 527 uint32_t checksum; 528 ip_pseudo_header_ref ip_header; 529 size_t headerlen; 530 device_id_t device_id; 531 packet_dimension_ref packet_dimension; 532 533 ERROR_PROPAGATE( tl_get_address_port( addr, addrlen, & dest_port )); 534 535 socket = socket_cores_find( local_sockets, socket_id ); 536 if( ! socket ) return ENOTSOCK; 537 538 if(( socket->port <= 0 ) && udp_globals.autobinding ){ 553 539 // bind the socket to a random free port if not bound 554 540 // do{ 555 541 // try to find a free port 556 // fibril_rwlock_read_unlock( &udp_globals.lock);557 // fibril_rwlock_write_lock( &udp_globals.lock);542 // fibril_rwlock_read_unlock( & udp_globals.lock ); 543 // fibril_rwlock_write_lock( & udp_globals.lock ); 558 544 // might be changed in the meantime 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);545 // if( socket->port <= 0 ){ 546 if( ERROR_OCCURRED( socket_bind_free_port( & udp_globals.sockets, socket, UDP_FREE_PORTS_START, UDP_FREE_PORTS_END, udp_globals.last_used_port ))){ 547 // fibril_rwlock_write_unlock( & udp_globals.lock ); 548 // fibril_rwlock_read_lock( & udp_globals.lock ); 563 549 return ERROR_CODE; 564 550 } … … 566 552 udp_globals.last_used_port = socket->port; 567 553 // } 568 // fibril_rwlock_write_unlock( &udp_globals.lock);569 // fibril_rwlock_read_lock( &udp_globals.lock);554 // fibril_rwlock_write_unlock( & udp_globals.lock ); 555 // fibril_rwlock_read_lock( & udp_globals.lock ); 570 556 // might be changed in the meantime 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);557 // }while( socket->port <= 0 ); 558 } 559 560 if( udp_globals.checksum_computing ){ 561 if( ERROR_OCCURRED( ip_get_route_req( udp_globals.ip_phone, IPPROTO_UDP, addr, addrlen, & device_id, & ip_header, & headerlen ))){ 562 return udp_release_and_return( packet, ERROR_CODE ); 577 563 } 578 564 // get the device packet dimension 579 // ERROR_PROPAGATE( tl_get_ip_packet_dimension(udp_globals.ip_phone, &udp_globals.dimensions, device_id, &packet_dimension));565 // ERROR_PROPAGATE( tl_get_ip_packet_dimension( udp_globals.ip_phone, & udp_globals.dimensions, device_id, & packet_dimension )); 580 566 } 581 567 // }else{ 582 568 // do not ask all the time 583 ERROR_PROPAGATE( ip_packet_size_req(udp_globals.ip_phone, -1, &udp_globals.packet_dimension));584 packet_dimension = & udp_globals.packet_dimension;569 ERROR_PROPAGATE( ip_packet_size_req( udp_globals.ip_phone, -1, & udp_globals.packet_dimension )); 570 packet_dimension = & udp_globals.packet_dimension; 585 571 // } 586 572 587 573 // read the first packet fragment 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)); 574 result = tl_socket_read_packet_data( udp_globals.net_phone, & packet, UDP_HEADER_SIZE, packet_dimension, addr, addrlen ); 575 if( result < 0 ) return result; 576 total_length = ( size_t ) result; 577 if( udp_globals.checksum_computing ){ 578 checksum = compute_checksum( 0, packet_get_data( packet ), packet_get_data_length( packet )); 595 579 }else{ 596 580 checksum = 0; 597 581 } 598 582 // prefix the udp 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));583 header = PACKET_PREFIX( packet, udp_header_t ); 584 if( ! header ){ 585 return udp_release_and_return( packet, ENOMEM ); 586 } 587 bzero( header, sizeof( * header )); 604 588 // read the rest of the packet fragments 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));589 for( index = 1; index < fragments; ++ index ){ 590 result = tl_socket_read_packet_data( udp_globals.net_phone, & next_packet, 0, packet_dimension, addr, addrlen ); 591 if( result < 0 ){ 592 return udp_release_and_return( packet, result ); 593 } 594 if( ERROR_OCCURRED( pq_add( & packet, next_packet, index, 0 ))){ 595 return udp_release_and_return( packet, ERROR_CODE ); 596 } 597 total_length += ( size_t ) result; 598 if( udp_globals.checksum_computing ){ 599 checksum = compute_checksum( checksum, packet_get_data( next_packet ), packet_get_data_length( next_packet )); 616 600 } 617 601 } 618 602 // set the udp 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));603 header->source_port = htons(( socket->port > 0 ) ? socket->port : 0 ); 604 header->destination_port = htons( dest_port ); 605 header->total_length = htons( total_length + sizeof( * header )); 622 606 header->checksum = 0; 623 if(udp_globals.checksum_computing){ 624 // update the pseudo header 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); 628 } 629 // finish the checksum computation 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); 607 if( udp_globals.checksum_computing ){ 608 // if( ERROR_OCCURRED( ip_get_route_req( udp_globals.ip_phone, IPPROTO_UDP, addr, addrlen, & device_id, & ip_header, & headerlen ))){ 609 // return udp_release_and_return( packet, ERROR_CODE ); 610 // } 611 if( ERROR_OCCURRED( ip_client_set_pseudo_header_data_length( ip_header, headerlen, total_length + UDP_HEADER_SIZE))){ 612 free( ip_header ); 613 return udp_release_and_return( packet, ERROR_CODE ); 614 } 615 checksum = compute_checksum( checksum, ip_header, headerlen ); 616 checksum = compute_checksum( checksum, ( uint8_t * ) header, sizeof( * header )); 617 header->checksum = htons( flip_checksum( compact_checksum( checksum ))); 618 free( ip_header ); 634 619 }else{ 635 620 device_id = DEVICE_INVALID_ID; 636 621 } 637 622 // prepare the first packet fragment 638 if( ERROR_OCCURRED(ip_client_prepare_packet(packet, IPPROTO_UDP, 0, 0, 0, 0))){639 return udp_release_and_return( packet, ERROR_CODE);623 if( ERROR_OCCURRED( ip_client_prepare_packet( packet, IPPROTO_UDP, 0, 0, 0, 0 ))){ 624 return udp_release_and_return( packet, ERROR_CODE ); 640 625 } 641 626 // send the packet 642 fibril_rwlock_write_unlock( &udp_globals.lock);643 ip_send_msg( udp_globals.ip_phone, device_id, packet, SERVICE_UDP, 0);627 fibril_rwlock_write_unlock( & udp_globals.lock ); 628 ip_send_msg( udp_globals.ip_phone, device_id, packet, SERVICE_UDP, 0 ); 644 629 return EOK; 645 630 } 646 631 647 int udp_recvfrom_message( socket_cores_ref local_sockets, int socket_id, int flags, size_t * addrlen){632 int udp_recvfrom_message( socket_cores_ref local_sockets, int socket_id, int flags, size_t * addrlen ){ 648 633 ERROR_DECLARE; 649 634 650 socket_core_ref 651 int 652 packet_t 653 udp_header_ref 654 struct sockaddr * 655 size_t 656 uint8_t * 657 int 635 socket_core_ref socket; 636 int packet_id; 637 packet_t packet; 638 udp_header_ref header; 639 struct sockaddr * addr; 640 size_t length; 641 uint8_t * data; 642 int result; 658 643 659 644 // find the socket 660 socket = socket_cores_find(local_sockets, socket_id); 661 if(! socket){ 662 return ENOTSOCK; 663 } 645 socket = socket_cores_find( local_sockets, socket_id ); 646 if( ! socket ) return ENOTSOCK; 664 647 // get the next received packet 665 packet_id = dyn_fifo_value(&socket->received); 666 if(packet_id < 0){ 648 packet_id = dyn_fifo_value( & socket->received ); 649 if( packet_id < 0 ) return NO_DATA; 650 ERROR_PROPAGATE( packet_translate( udp_globals.net_phone, & packet, packet_id )); 651 // get udp header 652 data = packet_get_data( packet ); 653 if( ! data ){ 654 pq_release( udp_globals.net_phone, packet_id ); 667 655 return NO_DATA; 668 656 } 669 ERROR_PROPAGATE(packet_translate(udp_globals.net_phone, &packet, packet_id)); 670 // get udp header 671 data = packet_get_data(packet); 672 if(! data){ 673 pq_release(udp_globals.net_phone, packet_id); 674 return NO_DATA; 675 } 676 header = (udp_header_ref) data; 657 header = ( udp_header_ref ) data; 677 658 678 659 // set the source address port 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);660 result = packet_get_addr( packet, ( uint8_t ** ) & addr, NULL ); 661 if( ERROR_OCCURRED( tl_set_address_port( addr, result, ntohs( header->source_port )))){ 662 pq_release( udp_globals.net_phone, packet_id ); 682 663 return ERROR_CODE; 683 664 } 684 * addrlen = (size_t) result;665 * addrlen = ( size_t ) result; 685 666 // send the source address 686 ERROR_PROPAGATE( data_reply(addr, * addrlen));667 ERROR_PROPAGATE( data_reply( addr, * addrlen )); 687 668 688 669 // trim the header 689 ERROR_PROPAGATE( packet_trim(packet, UDP_HEADER_SIZE, 0));670 ERROR_PROPAGATE( packet_trim( packet, UDP_HEADER_SIZE, 0 )); 690 671 691 672 // reply the packets 692 ERROR_PROPAGATE( socket_reply_packets(packet, &length));673 ERROR_PROPAGATE( socket_reply_packets( packet, & length )); 693 674 694 675 // release the packet 695 dyn_fifo_pop( &socket->received);696 pq_release( udp_globals.net_phone, packet_get_id(packet));676 dyn_fifo_pop( & socket->received ); 677 pq_release( udp_globals.net_phone, packet_get_id( packet )); 697 678 // return the total length 698 return ( int) length;699 } 700 701 int udp_release_and_return(packet_t packet, int result){702 pq_release( udp_globals.net_phone, packet_get_id(packet));679 return ( int ) length; 680 } 681 682 int udp_release_and_return( packet_t packet, int result ){ 683 pq_release( udp_globals.net_phone, packet_get_id( packet )); 703 684 return result; 704 685 }
Note:
See TracChangeset
for help on using the changeset viewer.