Changeset 71b00dcc in mainline for uspace/srv/net/tl/udp/udp.c
- Timestamp:
- 2010-03-07T22:51:38Z (15 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 60ab6c3
- Parents:
- b5cbff4 (diff), 31c80a5 (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
rb5cbff4 r71b00dcc 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 /* 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 417 bool 418 socket_cores_t 419 int app_phone = IPC_GET_PHONE( & call);420 struct sockaddr * 421 size_t 422 ipc_call_t 423 int 424 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 ipc_call_t answer; 421 int answer_count; 422 packet_dimension_ref packet_dimension; 425 423 426 424 /* … … 428 426 * - Answer the first IPC_M_CONNECT_TO_ME call. 429 427 */ 430 ipc_answer_0( callid, EOK ); 428 res = EOK; 429 answer_count = 0; 431 430 432 431 // The client connection is only in one fibril and therefore no additional locks are needed. 433 432 434 socket_cores_initialize( & local_sockets ); 435 436 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 437 440 // refresh data 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 )){ 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)){ 444 448 case IPC_M_PHONE_HUNGUP: 445 449 keep_on_going = false; 446 res = E OK;450 res = EHANGUP; 447 451 break; 448 452 case NET_SOCKET: 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;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; 454 458 } 455 // * SOCKET_SET_DATA_FRAGMENT_SIZE( answer) = MAX_UDP_FRAGMENT_SIZE;456 * 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; 457 461 answer_count = 3; 458 462 } 459 463 break; 460 464 case NET_SOCKET_BIND: 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);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); 467 471 } 468 472 break; 469 473 case NET_SOCKET_SENDTO: 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);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); 476 480 }else{ 477 481 answer_count = 2; 478 482 } 479 free( addr);483 free(addr); 480 484 } 481 485 break; 482 486 case NET_SOCKET_RECVFROM: 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;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; 489 493 answer_count = 3; 490 494 res = EOK; … … 492 496 break; 493 497 case NET_SOCKET_CLOSE: 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);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); 497 501 break; 498 502 case NET_SOCKET_GETSOCKOPT: … … 502 506 break; 503 507 } 504 505 // printf( "res = %d\n", res );506 507 answer_call( callid, res, & answer, answer_count );508 508 } 509 509 510 510 // release all local sockets 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){511 socket_cores_release(udp_globals.net_phone, &local_sockets, &udp_globals.sockets, NULL); 512 513 return res; 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){ 517 517 ERROR_DECLARE; 518 518 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 ){ 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){ 537 return ENOTSOCK; 538 } 539 540 if((socket->port <= 0) && udp_globals.autobinding){ 539 541 // bind the socket to a random free port if not bound 540 542 // do{ 541 543 // try to find a free port 542 // fibril_rwlock_read_unlock( & udp_globals.lock);543 // fibril_rwlock_write_lock( & udp_globals.lock);544 // fibril_rwlock_read_unlock(&udp_globals.lock); 545 // fibril_rwlock_write_lock(&udp_globals.lock); 544 546 // might be changed in the meantime 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);547 // if(socket->port <= 0){ 548 if(ERROR_OCCURRED(socket_bind_free_port(&udp_globals.sockets, socket, UDP_FREE_PORTS_START, UDP_FREE_PORTS_END, udp_globals.last_used_port))){ 549 // fibril_rwlock_write_unlock(&udp_globals.lock); 550 // fibril_rwlock_read_lock(&udp_globals.lock); 549 551 return ERROR_CODE; 550 552 } … … 552 554 udp_globals.last_used_port = socket->port; 553 555 // } 554 // fibril_rwlock_write_unlock( & udp_globals.lock);555 // fibril_rwlock_read_lock( & udp_globals.lock);556 // fibril_rwlock_write_unlock(&udp_globals.lock); 557 // fibril_rwlock_read_lock(&udp_globals.lock); 556 558 // might be changed in the meantime 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);559 // }while(socket->port <= 0); 560 } 561 562 if(udp_globals.checksum_computing){ 563 if(ERROR_OCCURRED(ip_get_route_req(udp_globals.ip_phone, IPPROTO_UDP, addr, addrlen, &device_id, &ip_header, &headerlen))){ 564 return udp_release_and_return(packet, ERROR_CODE); 563 565 } 564 566 // get the device packet dimension 565 // ERROR_PROPAGATE( tl_get_ip_packet_dimension( udp_globals.ip_phone, & udp_globals.dimensions, device_id, & packet_dimension));567 // ERROR_PROPAGATE(tl_get_ip_packet_dimension(udp_globals.ip_phone, &udp_globals.dimensions, device_id, &packet_dimension)); 566 568 } 567 569 // }else{ 568 570 // do not ask all the time 569 ERROR_PROPAGATE( ip_packet_size_req( udp_globals.ip_phone, -1, & udp_globals.packet_dimension));570 packet_dimension = & 571 ERROR_PROPAGATE(ip_packet_size_req(udp_globals.ip_phone, -1, &udp_globals.packet_dimension)); 572 packet_dimension = &udp_globals.packet_dimension; 571 573 // } 572 574 573 575 // read the first packet fragment 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 )); 576 result = tl_socket_read_packet_data(udp_globals.net_phone, &packet, UDP_HEADER_SIZE, packet_dimension, addr, addrlen); 577 if(result < 0){ 578 return result; 579 } 580 total_length = (size_t) result; 581 if(udp_globals.checksum_computing){ 582 checksum = compute_checksum(0, packet_get_data(packet), packet_get_data_length(packet)); 579 583 }else{ 580 584 checksum = 0; 581 585 } 582 586 // prefix the udp 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));587 header = PACKET_PREFIX(packet, udp_header_t); 588 if(! header){ 589 return udp_release_and_return(packet, ENOMEM); 590 } 591 bzero(header, sizeof(*header)); 588 592 // read the rest of the packet fragments 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));593 for(index = 1; index < fragments; ++ index){ 594 result = tl_socket_read_packet_data(udp_globals.net_phone, &next_packet, 0, packet_dimension, addr, addrlen); 595 if(result < 0){ 596 return udp_release_and_return(packet, result); 597 } 598 if(ERROR_OCCURRED(pq_add(&packet, next_packet, index, 0))){ 599 return udp_release_and_return(packet, ERROR_CODE); 600 } 601 total_length += (size_t) result; 602 if(udp_globals.checksum_computing){ 603 checksum = compute_checksum(checksum, packet_get_data(next_packet), packet_get_data_length(next_packet)); 600 604 } 601 605 } 602 606 // set the udp 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));607 header->source_port = htons((socket->port > 0) ? socket->port : 0); 608 header->destination_port = htons(dest_port); 609 header->total_length = htons(total_length + sizeof(*header)); 606 610 header->checksum = 0; 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 ); 611 if(udp_globals.checksum_computing){ 612 // update the pseudo header 613 if(ERROR_OCCURRED(ip_client_set_pseudo_header_data_length(ip_header, headerlen, total_length + UDP_HEADER_SIZE))){ 614 free(ip_header); 615 return udp_release_and_return(packet, ERROR_CODE); 616 } 617 // finish the checksum computation 618 checksum = compute_checksum(checksum, ip_header, headerlen); 619 checksum = compute_checksum(checksum, (uint8_t *) header, sizeof(*header)); 620 header->checksum = htons(flip_checksum(compact_checksum(checksum))); 621 free(ip_header); 619 622 }else{ 620 623 device_id = DEVICE_INVALID_ID; 621 624 } 622 625 // prepare the first packet fragment 623 if( ERROR_OCCURRED( ip_client_prepare_packet( packet, IPPROTO_UDP, 0, 0, 0, 0))){624 return udp_release_and_return( packet, ERROR_CODE);626 if(ERROR_OCCURRED(ip_client_prepare_packet(packet, IPPROTO_UDP, 0, 0, 0, 0))){ 627 return udp_release_and_return(packet, ERROR_CODE); 625 628 } 626 629 // send the packet 627 fibril_rwlock_write_unlock( & udp_globals.lock);628 ip_send_msg( udp_globals.ip_phone, device_id, packet, SERVICE_UDP, 0);630 fibril_rwlock_write_unlock(&udp_globals.lock); 631 ip_send_msg(udp_globals.ip_phone, device_id, packet, SERVICE_UDP, 0); 629 632 return EOK; 630 633 } 631 634 632 int udp_recvfrom_message( socket_cores_ref local_sockets, int socket_id, int flags, size_t * addrlen){635 int udp_recvfrom_message(socket_cores_ref local_sockets, int socket_id, int flags, size_t * addrlen){ 633 636 ERROR_DECLARE; 634 637 635 socket_core_ref 636 int 637 packet_t 638 udp_header_ref 639 struct sockaddr * 640 size_t 641 uint8_t * 642 int 638 socket_core_ref socket; 639 int packet_id; 640 packet_t packet; 641 udp_header_ref header; 642 struct sockaddr * addr; 643 size_t length; 644 uint8_t * data; 645 int result; 643 646 644 647 // find the socket 645 socket = socket_cores_find( local_sockets, socket_id ); 646 if( ! socket ) return ENOTSOCK; 648 socket = socket_cores_find(local_sockets, socket_id); 649 if(! socket){ 650 return ENOTSOCK; 651 } 647 652 // get the next received packet 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 )); 653 packet_id = dyn_fifo_value(&socket->received); 654 if(packet_id < 0){ 655 return NO_DATA; 656 } 657 ERROR_PROPAGATE(packet_translate(udp_globals.net_phone, &packet, packet_id)); 651 658 // get udp header 652 data = packet_get_data( packet);653 if( ! data){654 pq_release( udp_globals.net_phone, packet_id);659 data = packet_get_data(packet); 660 if(! data){ 661 pq_release(udp_globals.net_phone, packet_id); 655 662 return NO_DATA; 656 663 } 657 header = ( udp_header_ref) data;664 header = (udp_header_ref) data; 658 665 659 666 // set the source address port 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);667 result = packet_get_addr(packet, (uint8_t **) &addr, NULL); 668 if(ERROR_OCCURRED(tl_set_address_port(addr, result, ntohs(header->source_port)))){ 669 pq_release(udp_globals.net_phone, packet_id); 663 670 return ERROR_CODE; 664 671 } 665 * addrlen = ( size_t) result;672 *addrlen = (size_t) result; 666 673 // send the source address 667 ERROR_PROPAGATE( data_reply( addr, * addrlen));674 ERROR_PROPAGATE(data_reply(addr, * addrlen)); 668 675 669 676 // trim the header 670 ERROR_PROPAGATE( packet_trim( packet, UDP_HEADER_SIZE, 0));677 ERROR_PROPAGATE(packet_trim(packet, UDP_HEADER_SIZE, 0)); 671 678 672 679 // reply the packets 673 ERROR_PROPAGATE( socket_reply_packets( packet, & length));680 ERROR_PROPAGATE(socket_reply_packets(packet, &length)); 674 681 675 682 // release the packet 676 dyn_fifo_pop( & socket->received);677 pq_release( udp_globals.net_phone, packet_get_id( packet));683 dyn_fifo_pop(&socket->received); 684 pq_release(udp_globals.net_phone, packet_get_id(packet)); 678 685 // return the total length 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));686 return (int) length; 687 } 688 689 int udp_release_and_return(packet_t packet, int result){ 690 pq_release(udp_globals.net_phone, packet_get_id(packet)); 684 691 return result; 685 692 }
Note:
See TracChangeset
for help on using the changeset viewer.