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