Ejemplo n.º 1
0
/*  ----------------------------
 *          MONITOR CODE
 *  ---------------------------- */
void run_dtnperf_monitor(monitor_parameters_t * parameters)
{
	/* ------------------------
	 * variables
	 * ------------------------ */
	dtnperf_options_t * perf_opt = parameters->perf_g_opt->perf_opt;

	bp_error_t error;
	bp_endpoint_id_t local_eid;
	bp_reg_info_t reginfo;
	bp_reg_id_t regid;
	bp_bundle_object_t bundle_object;
	bp_bundle_status_report_t * status_report;
	bp_endpoint_id_t bundle_source_addr;
	bp_timestamp_t bundle_creation_timestamp;
	bp_timeval_t bundle_expiration;
	bp_endpoint_id_t relative_source_addr;
	bp_timestamp_t relative_creation_timestamp;
	HEADER_TYPE bundle_header;

	session_t * session;
	bundle_type_t bundle_type;
	struct timeval current, start;
	char * command;
	char temp[256];
	char * filename;
	int filename_len;
	char * full_filename;
	FILE * file;


	/* ------------------------
	 * initialize variables
	 * ------------------------ */
	boolean_t debug = perf_opt->debug;
	int debug_level = perf_opt->debug_level;

	dedicated_monitor = parameters->dedicated_monitor;
	bp_handle_open = FALSE;

	perf_opt->logs_dir = correct_dirname(perf_opt->logs_dir);

	status_report = NULL;
	session_list = session_list_create();

	// set out buffer size if daemon
	if (perf_opt->daemon)
	{
		setlinebuf(stdout);
		setlinebuf(stderr);
	}

	// create dir where dtnperf monitor will save logs
	// command should be: mkdir -p "logs_dir"
	if(debug && debug_level > 0)
		printf("[debug] initializing shell command...");
	command = malloc(sizeof(char) * (10 + strlen(perf_opt->logs_dir)));
	sprintf(command, "mkdir -p %s", perf_opt->logs_dir);
	if(debug && debug_level > 0)
		printf("done. Shell command = %s\n", command);

	// execute shell command
	if(debug && debug_level > 0)
		printf("[debug] executing shell command...");
	if (system(command) < 0)
	{
		perror("Error opening monitor logs dir");
		monitor_clean_exit(-1);
	}
	free(command);
	if(debug && debug_level > 0)
		printf("done\n");

	// signal handlers
	signal(SIGINT, monitor_handler);
	signal(SIGUSR1, monitor_handler);
	signal(SIGUSR2, monitor_handler);

	//open the connection to the bundle protocol router
	if(debug && debug_level > 0)
		printf("[debug] opening connection to bundle protocol router...");
	if (perf_opt->use_ip)
		error = bp_open_with_ip(perf_opt->ip_addr, perf_opt->ip_port, &handle);
	else
		error = bp_open(&handle);
	if (error != BP_SUCCESS)
	{
		fflush(stdout);
		fprintf(stderr, "fatal error opening bp handle: %s\n", bp_strerror(error));
		monitor_clean_exit(1);
	}
	else
	{
		bp_handle_open = TRUE;
	}
	if(debug && debug_level > 0)
		printf("done\n");

	//build a local eid
	if(debug && debug_level > 0)
		printf("[debug] building a local eid...");
	if (parameters->dedicated_monitor)
		sprintf(temp, "%s_%d", MON_EP_STRING, parameters->client_id);
	else
		sprintf(temp, "%s", MON_EP_STRING);
	bp_build_local_eid(handle, &local_eid, temp);
	if(debug && debug_level > 0)
		printf("done\n");
	if (debug)
		printf("local_eid = %s\n", local_eid.uri);

	// checking if there is already a registration
	if(debug && debug_level > 0)
		printf("[debug] checking for existing registration...");
	error = bp_find_registration(handle, &local_eid, &regid);
	if (error == BP_SUCCESS)
	{
		fflush(stdout);
		fprintf(stderr, "error: there is a registration with the same eid.\n");
		fprintf(stderr, "regid 0x%x\n", (unsigned int) regid);
		monitor_clean_exit(1);
	}
	if ((debug) && (debug_level > 0))
		printf(" done\n");

	//create a new registration to the local router based on this eid
	if(debug && debug_level > 0)
		printf("[debug] registering to local daemon...");
	memset(&reginfo, 0, sizeof(reginfo));
	bp_copy_eid(&reginfo.endpoint, &local_eid);
	reginfo.flags = BP_REG_DEFER;
	reginfo.regid = BP_REGID_NONE;
	reginfo.expiration = 0;
	if ((error = bp_register(handle, &reginfo, &regid)) != 0)
	{
		fflush(stdout);
		fprintf(stderr, "error creating registration: %d (%s)\n",
				error, bp_strerror(bp_errno(handle)));
		monitor_clean_exit(1);
	}
	if ((debug) && (debug_level > 0))
		printf(" done\n");
	if (debug)
		printf("regid 0x%x\n", (unsigned int) regid);

	// start expiration timer thread
	pthread_mutex_init (&mutexdata, NULL);
	pthread_create(&session_exp_timer, NULL, session_expiration_timer, (void *) parameters);

	if (!dedicated_monitor)
		printf("DTNperf Monitor started\n Waiting for bundles...\n");


	// start infinite loop
	while(1)
	{
		// reset variables
		bundle_type = NONE;

		// create a bundle object
		if ((debug) && (debug_level > 0))
			printf("[debug] initiating memory for bundles...\n");
		error = bp_bundle_create(&bundle_object);
		if (error != BP_SUCCESS)
		{
			fflush(stdout);
			fprintf(stderr, "fatal error initiating memory for bundles: %s\n", bp_strerror(error));
			monitor_clean_exit(1);
		}
		if(debug && debug_level > 0)
			printf("done\n");


		// wait until receive a bundle
		if ((debug) && (debug_level > 0))
			printf("[debug] waiting for bundles...\n");
		error = bp_bundle_receive(handle, bundle_object, BP_PAYLOAD_MEM, -1);
		if (error != BP_SUCCESS)
		{
			fflush(stdout);
			fprintf(stderr, "error getting recv reply: %d (%s)\n",
					error, bp_strerror(bp_errno(handle)));
			monitor_clean_exit(1);
		}
		if ((debug) && (debug_level > 0))
			printf(" bundle received\n");

		// mark current time
		if ((debug) && (debug_level > 0))
			printf("[debug] marking time...");
		gettimeofday(&current, NULL);
		if ((debug) && (debug_level > 0))
			printf(" done\n");

		// get SOURCE eid
		if ((debug) && (debug_level > 0))
			printf("[debug]\tgetting source eid...");
		error = bp_bundle_get_source(bundle_object, &bundle_source_addr);
		if (error != BP_SUCCESS)
		{
			fflush(stdout);
			fprintf(stderr, "error getting bundle source eid: %s\n",
					bp_strerror(error));
			monitor_clean_exit(1);
		}
		if ((debug) && (debug_level > 0))
		{
			printf(" done:\n");
			printf("\tbundle_source_addr = %s\n", bundle_source_addr.uri);
			printf("\n");
		}

		// get bundle CREATION TIMESTAMP
		if ((debug) && (debug_level > 0))
			printf("[debug]\tgetting bundle creation timestamp...");
		error = bp_bundle_get_creation_timestamp(bundle_object, &bundle_creation_timestamp);
		if (error != BP_SUCCESS)
		{
			fflush(stdout);
			fprintf(stderr, "error getting bundle creation timestamp: %s\n",
					bp_strerror(error));
			monitor_clean_exit(1);
		}
		if ((debug) && (debug_level > 0))
		{
			printf(" done:\n");
			printf("\tbundle creation timestamp:\n"
					"\tsecs = %d\n\tseqno= %d\n",
					(int)bundle_creation_timestamp.secs, (int)bundle_creation_timestamp.seqno);
			printf("\n");
		}

		// get bundle EXPIRATION TIME
		if ((debug) && (debug_level > 0))
			printf("[debug]\tgetting bundle expiration time...");
		error = bp_bundle_get_expiration(bundle_object, &bundle_expiration);
		if (error != BP_SUCCESS)
		{
			fflush(stdout);
			fprintf(stderr, "error getting bundle expiration time: %s\n",
					bp_strerror(error));
			monitor_clean_exit(1);
		}
		if ((debug) && (debug_level > 0))
		{
			printf(" done:\n");
			printf("\tbundle expiration: %lu\n", bundle_expiration);
			printf("\n");
		}

		// check if bundle is a status report
		if ((debug) && (debug_level > 0))
			printf("[debug] check if bundle is a status report...\n");
		error = bp_bundle_get_status_report(bundle_object, &status_report);
		if (error != BP_SUCCESS)
		{
			fflush(stdout);
			fprintf(stderr, "error checking if bundle is a status report: %d (%s)\n",
					error, bp_strerror(bp_errno(handle)));
			continue;
		}
		if ((debug) && (debug_level > 0))
			printf(" %s\n", status_report == NULL ? "no" : "yes");

		// check for other bundle types
		if (status_report != NULL)
			bundle_type = STATUS_REPORT;
		else
		{
			get_bundle_header_and_options(&bundle_object, & bundle_header, NULL);

			if (bundle_header == FORCE_STOP_HEADER)
				bundle_type = CLIENT_FORCE_STOP;
			else if (bundle_header == STOP_HEADER)
				bundle_type = CLIENT_STOP;
			else if (bundle_header == DSA_HEADER)
				bundle_type = SERVER_ACK;
			else // unknown bundle type
			{
				fprintf(stderr, "error: unknown bundle type\n");
				continue;
			}
		}

		// retrieve or open log file
		pthread_mutex_lock(&mutexdata);

		session = NULL;

		switch (bundle_type)
		{
		case STATUS_REPORT:
			bp_copy_eid(&relative_source_addr, &(status_report->bundle_id.source));
			relative_creation_timestamp = status_report->bundle_id.creation_ts;
			break;

		case SERVER_ACK:
			get_info_from_ack(&bundle_object, &relative_source_addr, &relative_creation_timestamp);
			break;

		case CLIENT_STOP:
		case CLIENT_FORCE_STOP:
			bp_copy_eid(&relative_source_addr, &bundle_source_addr);
			relative_creation_timestamp = bundle_creation_timestamp;
			break;

		default:
			break;
		}

		session = session_get(session_list, relative_source_addr);

		if (session == NULL) // start a new session
		{
			// mark start time
			start = current;
			char * ptr;
			filename_len = strlen(relative_source_addr.uri) - strlen("dtn://") + 15;
			filename = (char *) malloc(filename_len);
			memset(filename, 0, filename_len);
			strncpy(temp, relative_source_addr.uri, strlen(relative_source_addr.uri) + 1);
			strtok(temp, "/");
			sprintf(filename, "%lu_", relative_creation_timestamp.secs);
			strcat(filename, strtok(NULL, "/"));

			// remove .dtn suffix from the filename
			ptr = strstr(filename, ".dtn");
			if (ptr != NULL)
				ptr[0] = '\0';

			// add .csv extension
			strcat(filename, ".csv");
			full_filename = (char *) malloc(strlen(perf_opt->logs_dir) + strlen(filename) + 2);
			sprintf(full_filename, "%s/%s", perf_opt->logs_dir, filename);
			file = fopen(full_filename, "w");
			session = session_create(relative_source_addr, full_filename, file, start,
					relative_creation_timestamp.secs, bundle_expiration);
			session_put(session_list, session);
			// write header in csv log file
			fprintf(file,"Mon_RX_TIME;BSR_OR_ACK_SOURCE;BSR_OR_ACK_TIMESTAMP;BSR_OR_ACK_SEQNO;"
					"TYPE;BUNDLE_X_SOURCE;BUNDLE_X_TIMESTAMP;BUNDLE_X_SEQNO;"
					"FRAG_OFFSET;FRAG_LENGTH;");
			csv_print_status_report_timestamps_header(file);
			csv_end_line(file);
		}

		// update session infos
		session->last_bundle_time = bundle_creation_timestamp.secs;
		session->expiration = bundle_expiration;
		file = session->file;
		memcpy(&start, session->start, sizeof(struct timeval));

		if (bundle_type == STATUS_REPORT && (status_report->flags & BP_STATUS_DELIVERED))
		{
			session->delivered_count++;
		}

		pthread_mutex_unlock(&mutexdata);

		// print rx time in csv log
		csv_print_rx_time(file, current, start);

		// print bundle source in csv log
		csv_print_eid(file, bundle_source_addr);

		//print bundle creation timestamp in csv log
		csv_print_timestamp(file, bundle_creation_timestamp);

		// print bundle type in csv log
		switch (bundle_type)
		{
		case CLIENT_STOP:
			csv_print(file, "CLIENT_STOP");
			break;
		case CLIENT_FORCE_STOP:
			csv_print(file, "CLIENT_FORCE_STOP");
			break;
		case SERVER_ACK:
			csv_print(file, "SERVER_ACK");
			break;
		case STATUS_REPORT:
			csv_print(file, "STATUS_REPORT");
			break;
		default:
			csv_print(file, "UNKNOWN");
			break;
		}

		// print relative source and timestamp
		if (bundle_type == SERVER_ACK || bundle_type == STATUS_REPORT)
		{
			csv_print_eid(file, relative_source_addr);
			csv_print_timestamp(file, relative_creation_timestamp);
		}

		// print status report infos in csv log
		if (bundle_type == STATUS_REPORT)
		{
			csv_print_ulong(file, status_report->bundle_id.frag_offset);
			csv_print_ulong(file, status_report->bundle_id.orig_length);
			csv_print_status_report_timestamps(file, * status_report);
		}

		// end line in csv log
		csv_end_line(file);

		// close file
		if (bundle_type == CLIENT_STOP)
		{
			int total_to_receive;
			get_info_from_stop(&bundle_object, &total_to_receive);
			pthread_mutex_lock(&mutexdata);
			session->total_to_receive = total_to_receive;
			session->wait_after_stop = bundle_expiration;
			gettimeofday(session->stop_arrival_time, NULL);
			pthread_mutex_unlock(&mutexdata);
		}
		else if (bundle_type == CLIENT_FORCE_STOP)
		{
			printf("DTNperf monitor: received forced end session bundle\n");
			session_close(session_list, session);
		}


	} // end loop

	session_list_destroy(session_list);
	bp_close(handle);
	bp_handle_open = FALSE;
}
/*  ----------------------------
 *          SERVER CODE
 *  ---------------------------- */
void run_dtnperf_server(dtnperf_global_options_t * perf_g_opt)
{
	/* ------------------------
	 * variables
	 * ------------------------ */

	dtnperf_options_t * perf_opt = perf_g_opt->perf_opt;
	dtnperf_connection_options_t * conn_opt = perf_g_opt->conn_opt;

	al_bp_reg_info_t reginfo;
	al_bp_bundle_payload_location_t pl_location;
	al_bp_endpoint_id_t bundle_source_addr;
	al_bp_endpoint_id_t bundle_dest_addr;
	al_bp_endpoint_id_t bundle_replyto_addr;
	al_bp_error_t error;
	al_bp_bundle_object_t bundle_object;
	al_bp_bundle_object_t bundle_ack_object;
	al_bp_bundle_delivery_opts_t bundle_ack_dopts;
	al_bp_timestamp_t bundle_creation_timestamp;
	al_bp_timeval_t bundle_expiration;
	size_t bundle_payload_len;
	dtnperf_server_ack_payload_t server_ack_payload;
	HEADER_TYPE bundle_header;
	dtnperf_bundle_ack_options_t bundle_ack_options;
	time_t current;
	char* command = NULL;
	char* pl_filename = NULL;
	size_t pl_filename_len = 0;
	char* pl_buffer = NULL;
	size_t pl_buffer_size = 0;
	boolean_t is_file_transfer_bundle;
	int indicator; // for file transfer functions purposes


	/* ------------------------
	 * initialize variables
	 * ------------------------ */
	boolean_t debug = perf_g_opt->perf_opt->debug;
	int debug_level =  perf_g_opt->perf_opt->debug_level;

	perf_opt->dest_dir = correct_dirname(perf_opt->dest_dir);
	perf_opt->file_dir = correct_dirname(perf_opt->file_dir);

	bp_handle_open = FALSE;

	// initialize structures for file transfers
	file_transfer_info_list = file_transfer_info_list_create();

	// set out buffer size if daemon
	if (perf_opt->daemon)
	{
		setlinebuf(stdout);
		setlinebuf(stderr);
	}

	// show requested options (debug)
	if (debug)
	{
		printf("\nOptions;\n");
		printf("\tendpoint:\t%s\n", al_bp_get_implementation() == BP_ION ? SERV_EP_NUM_SERVICE : SERV_EP_STRING);
		printf("\tsave bundles to:\t%s\n", perf_opt->use_file ? "file":"memory");
		if(perf_opt->use_file)
			printf("\tdestination dir:\t%s\n", perf_opt->dest_dir);
		printf("\tsend acks:\t%s\n", perf_opt->no_acks ? "no":"yes");
		if (!perf_opt->no_acks)
		{
			//printf("\tsend acks to monitor: %s\n", perf_opt->acks_to_mon ? "yes":"no");
			printf("\tacks expiration time: %d\n", (int) conn_opt->expiration);
			char * prior;
			switch(conn_opt->priority.priority)
			{
			case BP_PRIORITY_BULK:
				prior = "bulk";
				break;
			case BP_PRIORITY_NORMAL:
				prior = "normal";
				break;
			case BP_PRIORITY_EXPEDITED:
				prior = "expedited";
				break;
			case BP_PRIORITY_RESERVED:
				prior = "reserved";
				break;
			default:
				prior = "unknown";
				break;
			}
			printf("\tacks priority       : %s\n", prior);
		}
		printf("\n");

	}

	//Ctrl+C handler
	signal(SIGINT, server_handler);

	// create dir where dtnperf server will save incoming bundles
	// command should be: mkdir -p "dest_dir"
	if(debug && debug_level > 0)
		printf("[debug] initializing shell command...");
	command = malloc(sizeof(char) * (10 + strlen(perf_opt->dest_dir)));
	sprintf(command, "mkdir -p %s", perf_opt->dest_dir);
	if(debug && debug_level > 0)
		printf("done. Shell command = %s\n", command);

	// execute shell command
	if(debug && debug_level > 0)
		printf("[debug] executing shell command...");
	if (system(command) < 0)
	{
		perror("Error opening bundle destination dir");
		exit(-1);
	}
	free(command);
	if(debug && debug_level > 0)
		printf("done\n");

	// create dir where dtnperf server will save incoming files
	// command should be: mkdir -p "file_dir"
	if(debug && debug_level > 0)
		printf("[debug] initializing shell command...");
	command = malloc(sizeof(char) * (10 + strlen(perf_opt->file_dir)));
	sprintf(command, "mkdir -p %s", perf_opt->file_dir);
	if(debug && debug_level > 0)
		printf("done. Shell command = %s\n", command);

	// execute shell command
	if(debug && debug_level > 0)
		printf("[debug] executing shell command...");
	if (system(command) < 0)
	{
		perror("Error opening transfered files destination dir");
		exit(-1);
	}
	free(command);
	if(debug && debug_level > 0)
		printf("done\n");

	//open the connection to the bundle protocol router
	if(debug && debug_level > 0)
		printf("[debug] opening connection to bundle protocol router...");
	if (perf_opt->use_ip)
		error = al_bp_open_with_ip(perf_opt->ip_addr, perf_opt->ip_port, &handle);
	else
		error = al_bp_open(&handle);
	if (error != BP_SUCCESS)
	{
		fflush(stdout);
		fprintf(stderr, "fatal error opening bp handle: %s\n", al_bp_strerror(error));
		exit(1);
	}
	else
	{
		bp_handle_open = TRUE;
	}
	if(debug && debug_level > 0)
		printf("done\n");

	//build a local eid
	if(debug && debug_level > 0)
		printf("[debug] building a local eid...");

	if(al_bp_get_implementation() == BP_ION)
		al_bp_build_local_eid(handle, &local_eid, SERV_EP_NUM_SERVICE,"Server-CBHE",NULL);
	else if(al_bp_get_implementation() == BP_DTN)
		al_bp_build_local_eid(handle, &local_eid, SERV_EP_STRING,"Server-DTN",NULL);

	if(debug && debug_level > 0)
		printf("done\n");
	if (debug)
		printf("local_eid = %s\n", local_eid.uri);

	// checking if there is already a registration
	if(debug && debug_level > 0)
		printf("[debug] checking for existing registration...");
	error = al_bp_find_registration(handle, &local_eid, &regid);
	if (error == BP_SUCCESS)
	{
		fflush(stdout);
		fprintf(stderr, "error: there is a registration with the same eid.\n");
		fprintf(stderr, "regid 0x%x\n", (unsigned int) regid);
		al_bp_close(handle);
		exit(1);
	}
	if ((debug) && (debug_level > 0))
		printf(" done\n");

	//create a new registration to the local router based on this eid
	if(debug && debug_level > 0)
		printf("[debug] registering to local daemon...");
	memset(&reginfo, 0, sizeof(reginfo));
	al_bp_copy_eid(&reginfo.endpoint, &local_eid);
	reginfo.flags = BP_REG_DEFER;
	reginfo.regid = BP_REGID_NONE;
	reginfo.expiration = 0;
	if ((error = al_bp_register(&handle, &reginfo, &regid)) != 0)
	{
		fflush(stdout);
		fprintf(stderr, "error creating registration: %d (%s)\n",
				error, al_bp_strerror(al_bp_errno(handle)));
		exit(1);
	}
	if ((debug) && (debug_level > 0))
		printf(" done\n");
	if (debug)
		printf("regid 0x%x\n", (unsigned int) regid);

	// set bundle destination type
	if ((debug) && (debug_level > 0))
		printf("[debug] choosing bundle destination type...");
	if (perf_opt->use_file)
		pl_location = BP_PAYLOAD_FILE;
	else
		pl_location = BP_PAYLOAD_MEM;
	if ((debug) && (debug_level > 0))
		printf(" done. Bundles will be saved into %s\n", perf_opt->use_file ? "file" : "memory");

	// start thread
	pthread_mutex_init (&mutexdata, NULL);
	pthread_create(&file_exp_timer, NULL, file_expiration_timer, NULL);



	if ((debug) && (debug_level > 0))
		printf("[debug] entering infinite loop...\n");

	// start infinite loop
	while(1)
	{

		// create a bundle object
		if ((debug) && (debug_level > 0))
			printf("[debug] initiating memory for bundles...\n");

		error = al_bp_bundle_create(&bundle_object);
		if (error != BP_SUCCESS)
		{
			fflush(stdout);
			fprintf(stderr, "fatal error initiating memory for bundles: %s\n", al_bp_strerror(error));
			exit(1);
		}
		if(debug && debug_level > 0)
			printf("done\n");

		// reset file transfer indicators
		is_file_transfer_bundle = FALSE;

		// wait until receive a bundle
		if ((debug) && (debug_level > 0))
			printf("[debug] waiting for bundles...\n");

		error = al_bp_bundle_receive(handle, bundle_object, pl_location, -1);
		if (error != BP_SUCCESS)
		{
			fflush(stdout);
			fprintf(stderr, "error getting recv reply: %d (%s)\n",
					error, al_bp_strerror(al_bp_errno(handle)));
			exit(1);
		}
		if ((debug) && (debug_level > 0))
			printf(" bundle received\n");

		// find payload size
		if ((debug) && (debug_level > 0))
			printf("[debug] calculating bundle payload size...");
		error = al_bp_bundle_get_payload_size(bundle_object, (u32_t *) &bundle_payload_len);
		if (error != BP_SUCCESS)
		{
			fflush(stdout);
			fprintf(stderr, "error getting bundle payload size: %s\n",
					al_bp_strerror(error));
			exit(1);
		}
		if(debug && debug_level > 0)
			printf("done\n");

		// mark current time

		if ((debug) && (debug_level > 0))
			printf("[debug] marking time...");
		current = time(NULL);
		if ((debug) && (debug_level > 0))
			printf(" done\n");

		// print bundle arrival
		printf("%s : %zu bytes from %s\n",
				ctime(&current),
				bundle_payload_len,
				bundle_object.spec->source.uri);


		// get SOURCE eid
		if ((debug) && (debug_level > 0))
			printf("[debug]\tgetting source eid...");
		error = al_bp_bundle_get_source(bundle_object, &bundle_source_addr);
		if (error != BP_SUCCESS)
		{
			fflush(stdout);
			fprintf(stderr, "error getting bundle source eid: %s\n",
					al_bp_strerror(error));
			exit(1);
		}
		if ((debug) && (debug_level > 0))
		{
			printf(" done:\n");
			printf("\tbundle_source_addr = %s\n", bundle_source_addr.uri);
			printf("\n");
		}

		// get DEST eid
		if ((debug) && (debug_level > 0))
			printf("[debug]\tgetting destination eid...");
		error = al_bp_bundle_get_dest(bundle_object, &bundle_dest_addr);
		if (error != BP_SUCCESS)
		{
			fflush(stdout);
			fprintf(stderr, "error getting bundle destination eid: %s\n",
					al_bp_strerror(error));
			exit(1);
		}
		if ((debug) && (debug_level > 0))
		{
			printf(" done:\n");
			printf("\tbundle_dest_eid = %s\n", bundle_dest_addr.uri);
			printf("\n");
		}

		// get REPLY TO eid
		if ((debug) && (debug_level > 0))
			printf("[debug]\tgetting reply to eid...");
		error = al_bp_bundle_get_replyto(bundle_object, &bundle_replyto_addr);
		if (error != BP_SUCCESS)
		{
			fflush(stdout);
			fprintf(stderr, "error getting bundle reply to eid: %s\n",
					al_bp_strerror(error));
			exit(1);
		}
		if ((debug) && (debug_level > 0))
		{
			printf(" done:\n");
			printf("\tbundle_replyto_eid = %s\n", bundle_replyto_addr.uri);
			printf("\n");
		}

		// get bundle CREATION TIMESTAMP
		if ((debug) && (debug_level > 0))
			printf("[debug]\tgetting bundle creation timestamp...");
		error = al_bp_bundle_get_creation_timestamp(bundle_object, &bundle_creation_timestamp);
		if (error != BP_SUCCESS)
		{
			fflush(stdout);
			fprintf(stderr, "error getting bundle creation timestamp: %s\n",
					al_bp_strerror(error));
			exit(1);
		}
		if ((debug) && (debug_level > 0))
		{
			printf(" done:\n");
			printf("\tbundle creation timestamp:\n"
					"\tsecs = %d\n\tseqno= %d\n",
					(int)bundle_creation_timestamp.secs, (int)bundle_creation_timestamp.seqno);
			printf("\n");
		}


		// get bundle payload filename
		if(perf_opt->use_file)
		{
			if ((debug) && (debug_level > 0))
				printf("[debug]\tgetting bundle payload filename...");
			error = al_bp_bundle_get_payload_file(bundle_object, &pl_filename, (u32_t *) &pl_filename_len);
			if (error != BP_SUCCESS)
			{
				fflush(stdout);
				fprintf(stderr, "error getting bundle payload filename: %s\n",
						al_bp_strerror(error));
				exit(1);
			}
			if ((debug) && (debug_level > 0))
			{
				printf(" done:\n");
			}
		}

		if ((debug))
		{
			printf ("======================================\n");
			printf (" Bundle received at %s\n", ctime(&current));
			printf ("  source: %s\n", bundle_source_addr.uri);
			if (perf_opt->use_file)
			{
				printf ("  saved into    : %s\n", pl_filename);
			}

			printf ("--------------------------------------\n");
		};
		// get bundle header and options
		if ((debug) && (debug_level > 0))
			printf("[debug]\tgetting bundle header and options...");
		if (get_bundle_header_and_options(&bundle_object, &bundle_header, &bundle_ack_options) < 0)
		{
			printf("Error in getting bundle header and options\n");
			continue;
		}
		if ((debug) && (debug_level > 0))
		{
			printf(" done.\n");
		}

		// check if is file transfer bundle
		if ((debug) && (debug_level > 0))
			printf("[debug]\tchecking if this is a file transfer bundle...");
		if (bundle_header == FILE_HEADER)
		{
			is_file_transfer_bundle = TRUE;
		}
		if ((debug) && (debug_level > 0))
		{
			printf(" done.\n");
			printf("\tbundle is%sa file transfer bundle\n",
					is_file_transfer_bundle ? " " : " not ");
			printf("\n");
		}

		// process file transfer bundle
		if(is_file_transfer_bundle)
		{
			if ((debug) && (debug_level > 0))
				printf("[debug]\tprocessing file transfer bundle...");

			pthread_mutex_lock(&mutexdata);

			indicator = process_incoming_file_transfer_bundle(&file_transfer_info_list,
					&bundle_object, perf_opt->file_dir);

			pthread_mutex_unlock(&mutexdata);
			sched_yield();

			if (indicator < 0) // error in processing bundle
			{
				fprintf(stderr, "Error in processing file transfer bundle: %s\n", strerror(errno));
			}
			if ((debug) && (debug_level > 0))
			{
				printf("done.");
				if (indicator == 1)
					printf("Transfer Completed\n");
			}
		}
		// get bundle expiration time and priority
		if (bundle_ack_options.set_ack_expiration)
		{
			al_bp_bundle_get_expiration(bundle_object, &bundle_expiration);
		}

		// send acks to the client only if requested by client
		// send acks to the monitor if:
		// ack requested by client AND ack-to-monitor option set AND bundle_ack_options.ack_to_mon == ATM_NORMAL
		// OR client forced server to send ack to monitor

		boolean_t send_ack_to_client = bundle_ack_options.ack_to_client;
		boolean_t send_ack_to_monitor = FALSE;
		send_ack_to_monitor = (bundle_ack_options.ack_to_client && (bundle_ack_options.ack_to_mon == ATM_NORMAL) && bundle_ack_options.ack_to_client && perf_opt->acks_to_mon)
				|| (bundle_ack_options.ack_to_mon == ATM_FORCE_YES);
		if (send_ack_to_client || send_ack_to_monitor)
		{

			// create bundle ack to send
			if ((debug) && (debug_level > 0))
				printf("[debug] initiating memory for bundle ack...");
			error = al_bp_bundle_create(&bundle_ack_object);
			if (error != BP_SUCCESS)
			{
				fflush(stdout);
				fprintf(stderr, "fatal error initiating memory for bundle ack: %s\n", al_bp_strerror(error));
				exit(1);
			}
			if(debug && debug_level > 0)
				printf("done\n");


			// initiate server ack payload
			// set server ack payload source
			server_ack_payload.bundle_source = bundle_source_addr;
			// set server ack payload timestamp
			server_ack_payload.bundle_creation_ts = bundle_creation_timestamp;
			// preparing the bundle ack payload
			if ((debug) && (debug_level > 0))
				printf("[debug] preparing the payload of the bundle ack...");
			error = prepare_server_ack_payload(server_ack_payload, &pl_buffer, &pl_buffer_size);

			if (error != BP_SUCCESS)
			{
				fflush(stdout);
				fprintf(stderr, "fatal error preparing the payload of the bundle ack: %s\n", al_bp_strerror(error));
				exit(1);
			}
			if(debug && debug_level > 0)
				printf("done\n");

			// setting the bundle ack payload
			if ((debug) && (debug_level > 0))
				printf("[debug] setting the payload of the bundle ack...");
			error = al_bp_bundle_set_payload_mem(&bundle_ack_object, pl_buffer, pl_buffer_size);
			if (error != BP_SUCCESS)
			{
				fflush(stdout);
				fprintf(stderr, "fatal error setting the payload of the bundle ack: %s\n", al_bp_strerror(error));
				exit(1);
			}
			if(debug && debug_level > 0)
				printf("done\n");

			// setting the bundle ack options
			if (debug && debug_level > 0)
			{
				printf("[debug] setting source of the bundle ack: %s ...", bundle_source_addr.uri);
			}
			error = al_bp_bundle_set_source(& bundle_ack_object, local_eid);
			if (error != BP_SUCCESS)
			{
				fflush(stdout);
				fprintf(stderr, "fatal error setting the source of the bundle ack: %s\n", al_bp_strerror(error));
				exit(1);
			}
			if(debug && debug_level > 0)
				printf("done\n");

			if (debug && debug_level > 0)
			{
				printf("[debug] setting destination of the bundle ack: %s ...", bundle_source_addr.uri);
			}
			error = al_bp_bundle_set_dest(& bundle_ack_object, bundle_source_addr);
			if (error != BP_SUCCESS)
			{
				fflush(stdout);
				fprintf(stderr, "fatal error setting the destination of the bundle ack: %s\n", al_bp_strerror(error));
				exit(1);
			}
			if(debug && debug_level > 0)
				printf("done\n");

			if (debug && debug_level > 0)
			{
				printf("[debug] setting replyto eid of the bundle ack: %s ...", bundle_replyto_addr.uri);
			}
			al_bp_bundle_set_replyto(& bundle_ack_object, bundle_replyto_addr);
			if (error != BP_SUCCESS)
			{
				fflush(stdout);
				fprintf(stderr, "fatal error setting the reply to eid of the bundle ack: %s\n", al_bp_strerror(error));
				exit(1);
			}
			if(debug && debug_level > 0)
				printf("done\n");

			if (debug && debug_level > 0)
			{
				printf("[debug] setting priority of the bundle ack...");
			}
			if (bundle_ack_options.set_ack_priority == TRUE)
			{
				al_bp_bundle_set_priority(& bundle_ack_object, bundle_ack_options.priority);
			}
			else
			{
				al_bp_bundle_set_priority(& bundle_ack_object, conn_opt->priority);
			}
			if (error != BP_SUCCESS)
			{
				fflush(stdout);
				fprintf(stderr, "fatal error setting priority of the bundle ack: %s\n", al_bp_strerror(error));
				exit(1);
			}
			if(debug && debug_level > 0)
				printf("done\n");

			if (debug && debug_level > 0)
			{
				printf("[debug] setting expiration time of the bundle ack...");
			}
			if (bundle_ack_options.set_ack_expiration)
				al_bp_bundle_set_expiration(& bundle_ack_object, bundle_expiration);
			else
				al_bp_bundle_set_expiration(& bundle_ack_object, conn_opt->expiration);
			if (error != BP_SUCCESS)
			{
				fflush(stdout);
				fprintf(stderr, "fatal error setting expiration time of the bundle ack: %s\n", al_bp_strerror(error));
				exit(1);
			}
			if(debug && debug_level > 0)
				printf("done\n");

			if (debug && debug_level > 0)
			{
				printf("[debug] setting delivery options of the bundle ack...");
			}
			bundle_ack_dopts = BP_DOPTS_CUSTODY;
			al_bp_bundle_set_delivery_opts(& bundle_ack_object, bundle_ack_dopts);
			if (error != BP_SUCCESS)
			{
				fflush(stdout);
				fprintf(stderr, "fatal error setting delivery options of the bundle ack: %s\n", al_bp_strerror(error));
				exit(1);
			}
			if(debug && debug_level > 0)
				printf("done\n");

			// send the bundle ack to the client
			if (send_ack_to_client)
			{
				if ((debug) && (debug_level > 0))
					printf("[debug] sending bundle ack to client...");
				error = al_bp_bundle_send(handle, regid, & bundle_ack_object);
				if (error != BP_SUCCESS)
				{
					fflush(stdout);
					fprintf(stderr, "error sending bundle ack to client: %d (%s)\n",
							error, al_bp_strerror(al_bp_errno(handle)));
					exit(1);
				}
				if ((debug) && (debug_level > 0))
					printf(" bundle ack sent to client\n");
			}
			printf("Send bundle to client ok\n");

			// send the bundle ack to the monitor
			if (send_ack_to_monitor)
			{
				al_bp_bundle_set_dest(& bundle_ack_object, bundle_replyto_addr);
				if ((debug) && (debug_level > 0))
					printf("[debug] sending bundle ack to monitor...");
				error = al_bp_bundle_send(handle, regid, & bundle_ack_object);
				if (error != BP_SUCCESS)
				{
					fflush(stdout);
					fprintf(stderr, "error sending bundle ack to monitor: %d (%s)\n",
							error, al_bp_strerror(al_bp_errno(handle)));
					exit(1);
				}
				if ((debug) && (debug_level > 0))
					printf(" bundle ack sent to monitor\n");
			}

			//free memory for bundle ack
			al_bp_bundle_free(&bundle_ack_object);
			free(pl_buffer);
			pl_buffer_size = 0;

		}

		// free memory for bundle
		al_bp_bundle_free(&bundle_object);

		free(pl_filename);
		pl_filename_len = 0;

	}// while(1)

	al_bp_close(handle);
	al_bp_unregister(handle,regid,local_eid);
	bp_handle_open = FALSE;


}
Ejemplo n.º 3
0
/*  ----------------------------
 *          CLIENT CODE
 *  ---------------------------- */
void run_dtnperf_client(dtnperf_global_options_t * perf_g_opt)
{
	/* ------------------------
	 * variables
	 * ------------------------ */
	char * client_demux_string;
	int pthread_status;

	char temp1[256]; // buffer for different purpose
	char temp2[256];
	FILE * stream; // stream for preparing payolad
	bp_bundle_object_t bundle_stop;
	monitor_parameters_t mon_params;


	/* ------------------------
	 * initialize variables
	 * ------------------------ */
	perf_opt = perf_g_opt->perf_opt;
	conn_opt = perf_g_opt->conn_opt;
	boolean_t debug = perf_opt->debug;
	int debug_level =  perf_opt->debug_level;
	boolean_t verbose = perf_opt->verbose;
	boolean_t create_log = perf_opt->create_log;
	log_open = FALSE;
	bp_handle_open = FALSE;
	source_file_created = FALSE;
	stream = NULL;
	tot_bundles = 0;
	process_interrupted = FALSE;
	perf_opt->log_filename = correct_dirname(perf_opt->log_filename);
	source_file = (char*) malloc(strlen(SOURCE_FILE) + 7);
	sprintf(source_file, "%s_%d", SOURCE_FILE, getpid());

	// Create a new log file
	if (create_log)
	{
		if ((log_file = fopen(perf_opt->log_filename, "w")) == NULL)
		{
			fprintf(stderr, "fatal error opening log file\n");
			client_clean_exit(1);
		}
		log_open = TRUE;
	}

	// Connect to BP Daemon
	if ((debug) && (debug_level > 0))
		printf("[debug] opening connection to local BP daemon...");

	if (perf_opt->use_ip)
		error = bp_open_with_ip(perf_opt->ip_addr,perf_opt->ip_port,&handle);
	else
		error = bp_open(&handle);

	if (error != BP_SUCCESS)
	{
		fprintf(stderr, "fatal error opening bp handle: %s\n", bp_strerror(error));
		if (create_log)
			fprintf(log_file, "fatal error opening bp handle: %s\n", bp_strerror(error));
		client_clean_exit(1);
	}
	else
	{
		bp_handle_open = TRUE;
	}

	if ((debug) && (debug_level > 0))
		printf("done\n");

	// Ctrl+C handler
	signal(SIGINT, &client_handler);

	/* -----------------------------------------------------
	 *   initialize and parse bundle src/dest/replyto EIDs
	 * ----------------------------------------------------- */

	// append process id to the client demux string
	client_demux_string = malloc (strlen(CLI_EP_STRING) + 10);
	sprintf(client_demux_string, "%s_%d", CLI_EP_STRING, getpid());

	//build a local eid
	if(debug && debug_level > 0)
		printf("[debug] building a local eid...");
	bp_build_local_eid(handle, &local_eid, client_demux_string);
	if(debug && debug_level > 0)
		printf("done\n");
	if (debug)
		printf("Source     : %s\n", local_eid.uri);
	if (create_log)
		fprintf(log_file, "\nSource     : %s\n", local_eid.uri);

	// parse SERVER EID
	// append server demux string to destination eid
	strcat(perf_opt->dest_eid, SERV_EP_STRING);

	if (verbose)
		fprintf(stdout, "%s (local)\n", perf_opt->dest_eid);
	// parse
	error = bp_parse_eid_string(&dest_eid, perf_opt->dest_eid);

	if (error != BP_SUCCESS)
	{
		fprintf(stderr, "fatal error parsing bp EID: invalid eid string '%s'\n", perf_opt->dest_eid);
		if (create_log)
			fprintf(log_file, "\nfatal error parsing bp EID: invalid eid string '%s'", perf_opt->dest_eid);
		client_clean_exit(1);
	}

	if (debug)
		printf("Destination: %s\n", dest_eid.uri);

	if (create_log)
		fprintf(log_file, "Destination: %s\n", dest_eid.uri);


	// parse REPLY-TO (if none specified, same as the source)
	if (strlen(perf_opt->mon_eid) == 0)
	{
		char * ptr;
		ptr = strstr(local_eid.uri, CLI_EP_STRING);
		// copy from local eid only the uri (not the demux string)
		strncpy(perf_opt->mon_eid, local_eid.uri, ptr - local_eid.uri);

	}
	// append monitor demux string to replyto eid
	strcat(perf_opt->mon_eid, MON_EP_STRING);
	// parse
	error = bp_parse_eid_string(&mon_eid, perf_opt->mon_eid);
	if (error != BP_SUCCESS)
	{
		fprintf(stderr, "fatal error parsing bp EID: invalid eid string '%s'\n", perf_opt->dest_eid);
		if (create_log)
			fprintf(log_file, "\nfatal error parsing bp EID: invalid eid string '%s'", perf_opt->dest_eid);
		client_clean_exit(1);
	}
	if (debug)
		printf("Reply-to   : %s\n\n", mon_eid.uri);

	if (create_log)
		fprintf(log_file, "Reply-to   : %s\n\n", mon_eid.uri);

	if(create_log)
		fflush(log_file);

	// checking if there is a running monitor on this endpoint
	if(perf_g_opt->mode == DTNPERF_CLIENT_MONITOR)
	{
		if(debug && debug_level > 0)
			printf("[debug] checking for existing monitor on this endpoint...\n");
		error = bp_find_registration(handle, &mon_eid, &regid);
		if (error == BP_SUCCESS)
		{
			dedicated_monitor = FALSE;
			printf("there is already a monitor on this endpoint.\n");
			printf("regid 0x%x\n", (unsigned int) regid);
		}
		else
		{
			dedicated_monitor = TRUE;
			mon_params.client_id = getpid();
			mon_params.perf_g_opt = perf_g_opt;
			printf("there is not a monitor on this endpoint.\n");
			sprintf(temp1, "%s_%d", mon_eid.uri, mon_params.client_id);
			bp_parse_eid_string(&mon_eid, temp1);

			// start dedicated monitor
			if ((monitor_pid = fork()) == 0)
			{
				start_dedicated_monitor((void *) &mon_params);
				exit(0);
			}
			printf("started a new dedicated monitor\n");

		}
		if ((debug) && (debug_level > 0))
			printf(" done\n");
	}

	//create a new registration to the local router based on this eid
	if(debug && debug_level > 0)
		printf("[debug] registering to local daemon...");
	memset(&reginfo, 0, sizeof(reginfo));
	bp_copy_eid(&reginfo.endpoint, &local_eid);
	reginfo.flags = BP_REG_DEFER;
	reginfo.regid = BP_REGID_NONE;
	reginfo.expiration = 0;
	if ((error = bp_register(handle, &reginfo, &regid)) != 0)
	{
		fflush(stdout);
		fprintf(stderr, "error creating registration: %d (%s)\n",
				error, bp_strerror(bp_errno(handle)));
		if (create_log)
			fprintf(log_file, "error creating registration: %d (%s)\n",
					error, bp_strerror(bp_errno(handle)));
		client_clean_exit(1);
	}
	if ((debug) && (debug_level > 0))
		printf(" done\n");
	if (debug)
		printf("regid 0x%x\n", (unsigned int) regid);
	if (create_log)
		fprintf(log_file, "regid 0x%x\n", (unsigned int) regid);

	// if bundle payload > MAX_MEM_PAYLOAD, then transfer a file
	if (!perf_opt->use_file && perf_opt->bundle_payload > MAX_MEM_PAYLOAD)
	{
		perf_opt->use_file = 1;
		perf_opt->bundle_payload = BP_PAYLOAD_FILE;
		if (verbose)
			printf("Payload %ld > %d: Using file instead of memory\n", perf_opt->bundle_payload, MAX_MEM_PAYLOAD);
		if (create_log)
			fprintf(log_file, "Payload %ld > %d: Using file instead of memory\n", perf_opt->bundle_payload, MAX_MEM_PAYLOAD);
	}

	/* ------------------------------------------------------------------------------
	 * select the operative-mode (between Time_Mode, Data_Mode and File_Mode)
	 * ------------------------------------------------------------------------------ */

	if (perf_opt->op_mode == 'T')	// Time mode
	{

		if (verbose)
			printf("Working in Time_Mode\n");

		if (create_log)
			fprintf(log_file, "Working in Time_Mode\n");

		if (verbose)
			printf("requested %d second(s) of transmission\n", perf_opt->transmission_time);

		if (create_log)
			fprintf(log_file, "requested %d second(s) of transmission\n", perf_opt->transmission_time);
	}
	else if (perf_opt->op_mode == 'D') // Data mode
	{
		if (verbose)
			printf("Working in Data_Mode\n");
		if (create_log)
			fprintf(log_file, "Working in Data_Mode\n");
		if (verbose)
			printf("requested transmission of %ld bytes of data\n", perf_opt->data_qty);
		if (create_log)
			fprintf(log_file, "requested transmission of %ld bytes of data\n", perf_opt->data_qty);
	}
	else if (perf_opt->op_mode == 'F') // File mode
	{
		if (verbose)
			printf("Working in File_Mode\n");
		if (create_log)
			fprintf(log_file, "Working in File_Mode\n");
		if (verbose)
			printf("requested transmission of file %s\n", perf_opt->F_arg);
		if (create_log)
			fprintf(log_file, "requested transmission of file %s\n", perf_opt->F_arg);

	}

	if (verbose)
		printf(" transmitting data %s\n", perf_opt->use_file ? "using a file" : "using memory");
	if (create_log)
		fprintf(log_file, " transmitting data %s\n", perf_opt->use_file ? "using a file" : "using memory");

	if (verbose)
		printf("%s based congestion control:\n", perf_opt->congestion_ctrl == 'w' ? "sliding window" : "rate");
	if (create_log)
		fprintf(log_file, "%s based congestion control:\n", perf_opt->congestion_ctrl == 'w' ? "sliding window" : "rate");
	if(perf_opt->congestion_ctrl == 'w')
	{
		if (verbose)
			printf("\twindow is %d bundles\n", perf_opt->window);
		if (create_log)
			fprintf(log_file, "\twindow is %d bundles\n", perf_opt->window);
	}
	else
	{
		if (verbose)
			printf("\trate is %ld %c\n", perf_opt->rate, perf_opt->rate_unit);
		if (create_log)
			fprintf(log_file, "\trate is %ld %c\n", perf_opt->rate, perf_opt->rate_unit);
	}
	if (verbose)
		printf("payload is %ld bytes\n", perf_opt->bundle_payload);
	if (create_log)
		fprintf(log_file, "payload is %ld bytes\n", perf_opt->bundle_payload);


	sent_bundles = 0;

	if (perf_opt->op_mode == 'D' || perf_opt->op_mode == 'F') // Data or File mode
	{
		if ((debug) && (debug_level > 0))
			printf("[debug] calculating how many bundles are needed...");

		if (perf_opt->op_mode == 'F') // File mode
		{
			struct stat file;
			if (stat(perf_opt->F_arg, &file) < 0)
			{
				fprintf(stderr, "couldn't stat file %s : %s", perf_opt->F_arg, strerror(errno));
				if (create_log)
					fprintf(log_file, "couldn't stat file %s : %s", perf_opt->F_arg, strerror(errno));
				client_clean_exit(1);
			}

			// get transfer file basename
			strcpy(temp1, perf_opt->F_arg);
			strcpy(temp2, basename(temp1));
			transfer_filename = malloc(strlen(temp2) + 1);
			strcpy(transfer_filename, temp2);

			transfer_filedim = file.st_size;
			tot_bundles += bundles_needed(transfer_filedim, get_file_fragment_size(perf_opt->bundle_payload, strlen(transfer_filename)));
		}
		else // Data mode
			tot_bundles += bundles_needed(perf_opt->data_qty, perf_opt->bundle_payload);

		if ((debug) && (debug_level > 0))
			printf(" n_bundles = %ld\n", tot_bundles);

	}


	// Create the file
	if (perf_opt->use_file)
	{
		// create the file
		if ((debug) && (debug_level > 0))
			printf("[debug] creating file %s...", source_file);

		stream = fopen(source_file,	"wb");

		if (stream == NULL)
		{
			fprintf(stderr, "ERROR: couldn't create file %s.\n \b Maybe you don't have permissions\n", source_file);

			if (create_log)
				fprintf(log_file, "ERROR: couldn't create file %s.\n \b Maybe you don't have permissions\n", source_file);

			client_clean_exit(2);
		}

		source_file_created = TRUE;

		fclose(stream);

		if ((debug) && (debug_level > 0))
			printf(" done\n");

		// set the absolute path of the source file
		char buf[256];
		getcwd(buf, 256);
		strcat(buf, "/");
		strcat(buf, source_file);
		source_file_abs = malloc(strlen(buf) + 1);
		strncpy(source_file_abs, buf, strlen(buf) + 1);
	}

	// Create the bundle object
	if ((debug) && (debug_level > 0))
		printf("[debug] creating the bundle object...");
	error = bp_bundle_create(& bundle);
	if (error != BP_SUCCESS)
	{
		fprintf(stderr, "ERROR: couldn't create bundle object\n");

		if (create_log)
			fprintf(log_file, "ERROR: couldn't create bundle object\n");
		client_clean_exit(1);
	}
	if ((debug) && (debug_level > 0))
		printf(" done\n");

	// Fill the payload
	if ((debug) && (debug_level > 0))
		printf("[debug] filling payload...");

	if (perf_opt->use_file)
		error = bp_bundle_set_payload_file(&bundle, source_file_abs, strlen(source_file_abs));
	else
		error = bp_bundle_set_payload_mem(&bundle, buffer, bufferLen);
	if (error != BP_SUCCESS)
	{
		fprintf(stderr, "ERROR: couldn't set bundle payload\n");

		if (create_log)
			fprintf(log_file, "ERROR: couldn't set bundle payload\n");
		client_clean_exit(1);
	}
	if ((debug) && (debug_level > 0))
		printf(" done\n");


	// open payload stream in write mode
	if (open_payload_stream_write(bundle, &stream) < 0)
	{
		fprintf(stderr, "ERROR: couldn't open payload stream in write mode");

		if (create_log)
			fprintf(log_file, "ERROR: couldn't open payload stream in write mode");

		client_clean_exit(2);
	}

	// prepare the payload
	if(perf_opt->op_mode == 'F') // File mode
	{
		// payload will be prepared into send_bundles() cycle

		// open file to transfer in read mode
		if ((transfer_fd = open(perf_opt->F_arg, O_RDONLY)) < 0)
		{
			fprintf(stderr, "couldn't stat file %s : %s", perf_opt->F_arg, strerror(errno));
			if (create_log)
				fprintf(log_file, "couldn't stat file %s : %s", perf_opt->F_arg, strerror(errno));
			client_clean_exit(2);
		}
	}
	else // Time and Data mode
	{
		error = prepare_generic_payload(perf_opt, stream, perf_opt->bundle_payload);
		if (error != BP_SUCCESS)
		{
			fprintf(stderr, "error preparing payload: %s\n", bp_strerror(error));
			if (create_log)
				fprintf(log_file, "error preparing payload: %s\n", bp_strerror(error));
			client_clean_exit(1);
		}
	}

	// close the stream
	close_payload_stream_write(&bundle, stream);

	if(debug)
		printf("[debug] payload prepared");

	// Create the array for the bundle send info (only for sliding window congestion control)
	if (perf_opt->congestion_ctrl == 'w') {
		if ((debug) && (debug_level > 0))
			printf("[debug] creating structure for sending information...");

		send_info = (send_information_t*) malloc(perf_opt->window * sizeof(send_information_t));
		init_info(send_info, perf_opt->window);

		if ((debug) && (debug_level > 0))
			printf(" done\n");
	}


	// Setting the bundle options
	bp_bundle_set_source(&bundle, local_eid);
	bp_bundle_set_dest(&bundle, dest_eid);
	bp_bundle_set_replyto(&bundle, mon_eid);
	set_bp_options(&bundle, conn_opt);

	// intialize stop bundle;
	bp_bundle_create(&bundle_stop);

	if ((debug) && (debug_level > 0))
		printf("[debug] entering in loop\n");

	// Run threads
	if (perf_opt->congestion_ctrl == 'w') // sliding window congestion control
		sem_init(&window, 0, perf_opt->window);
	else								// rate based congestion control
		sem_init(&window, 0, 0);


	sigset_t sigset;

	// blocking signals for the threads
	sigemptyset(&sigset);
	sigaddset(&sigset, SIGINT);
	sigaddset(&sigset, SIGUSR1);
	sigaddset(&sigset, SIGUSR2);
	pthread_sigmask(SIG_BLOCK, &sigset, NULL);


	pthread_cond_init(&cond_ackreceiver, NULL);
	pthread_mutex_init (&mutexdata, NULL);


	pthread_create(&sender, NULL, send_bundles, (void*)perf_g_opt);
	pthread_create(&cong_ctrl, NULL, congestion_control, (void*)perf_g_opt);
	pthread_create(&wait_for_signal, NULL, wait_for_sigint, (void*) client_demux_string);

	pthread_join(cong_ctrl, (void**)&pthread_status);
	pthread_join(sender, (void**)&pthread_status);

	pthread_mutex_destroy(&mutexdata);
	sem_destroy(&window);
	pthread_cond_destroy(&cond_ackreceiver);

	// if user sent Ctrl+C to the client,
	// let the wait_for_signal thread to terminate the execution
	if (process_interrupted)
		pause();

	if ((debug) && (debug_level > 0))
		printf("[debug] out from loop\n");

	// Get the TOTAL end time
	if ((debug) && (debug_level > 0))
		printf("[debug] getting total end-time...");

	gettimeofday(&end, NULL);

	if ((debug) && (debug_level > 0))
		printf(" end.tv_sec = %u sec\n", (u_int)end.tv_sec);

	// Print final report
	print_final_report(NULL);
	if(perf_opt->create_log)
		print_final_report(log_file);

	// fill the stop bundle
	prepare_stop_bundle(&bundle_stop, mon_eid, conn_opt->expiration, conn_opt->priority, sent_bundles);
	bp_bundle_set_source(&bundle_stop, local_eid);

	// send stop bundle to monitor
	if (debug)
		printf("sending the stop bundle to the monitor...");
	if ((error = bp_bundle_send(handle, regid, &bundle_stop)) != 0)
	{
		fprintf(stderr, "error sending the stop bundle: %d (%s)\n", error, bp_strerror(error));
		if (create_log)
			fprintf(log_file, "error sending the stop bundle: %d (%s)\n", error, bp_strerror(error));
		client_clean_exit(1);
	}
	if (debug)
		printf("done.\n");

	// waiting monitor stops
	if (dedicated_monitor)
	{
		printf("\nWaiting for dedicated monitor to stop...\n");
		wait(&monitor_status);
	}


	// Close the BP handle --
	if ((debug) && (debug_level > 0))
		printf("[debug] closing DTN handle...");

	if (bp_close(handle) != BP_SUCCESS)
	{
		fprintf(stderr, "fatal error closing bp handle: %s\n", strerror(errno));
		if (create_log)
			fprintf(log_file, "fatal error closing bp handle: %s\n", strerror(errno));
		client_clean_exit(1);
	}
	else
	{
		bp_handle_open = FALSE;
	}

	if ((debug) && (debug_level > 0))
		printf(" done\n");

	if (create_log)
	{
		fclose(log_file);
		log_open = FALSE;
	}

	// deallocate memory
	if (perf_opt->op_mode == 'F')
	{
		close(transfer_fd);
	}
	if (perf_opt->use_file)
	{
		remove(source_file);
		source_file_created = FALSE;

		if (debug && debug > 1)
		{
			printf("[debug] removed file %s\n", source_file);
		}
	}
	free((void*)buffer);
	free(client_demux_string);
	free(source_file_abs);
	free(source_file);
	free(transfer_filename);
	free(send_info);
	bp_bundle_free(&bundle);
	bp_bundle_free(&bundle_stop);


	if (perf_opt->create_log)
		printf("\nClient log saved: %s\n", perf_opt->log_filename);

	printf("\n");

	exit(0);
}
Ejemplo n.º 4
0
/*  ----------------------------
 *          SERVER CODE
 *  ---------------------------- */
void run_dtnperf_server(dtnperf_global_options_t * perf_g_opt)
{
	/* ------------------------
	 * variables
	 * ------------------------ */

	dtnperf_options_t * perf_opt = perf_g_opt->perf_opt;
	dtnperf_connection_options_t * conn_opt = perf_g_opt->conn_opt;

	al_bp_reg_info_t reginfo;
	al_bp_bundle_payload_location_t pl_location;
	al_bp_endpoint_id_t bundle_source_addr;
	al_bp_endpoint_id_t bundle_dest_addr;
	al_bp_endpoint_id_t bundle_replyto_addr;
	al_bp_error_t error;
	al_bp_bundle_object_t bundle_object;
	al_bp_bundle_object_t bundle_ack_object;
	al_bp_bundle_delivery_opts_t bundle_ack_dopts;
	al_bp_timestamp_t bundle_creation_timestamp;
	al_bp_timeval_t bundle_expiration;
	al_bp_bundle_priority_t bundle_priority;
	size_t bundle_payload_len;
	dtnperf_server_ack_payload_t server_ack_payload;
	HEADER_TYPE bundle_header;
	dtnperf_bundle_ack_options_t bundle_ack_options;
	time_t current;
	char* command = NULL;
	char* pl_filename = NULL;
	size_t pl_filename_len = 0;
	char* pl_buffer = NULL;
	char temp[256];
	size_t pl_buffer_size = 0;
	boolean_t is_file_transfer_bundle;
	int indicator; // for file transfer functions purposes
	int num_ack; // for name file bundle ack

	/* ------------------------
	 * initialize variables
	 * ------------------------ */
	boolean_t debug = perf_g_opt->perf_opt->debug;
	int debug_level =  perf_g_opt->perf_opt->debug_level;

	perf_opt->dest_dir = correct_dirname(perf_opt->dest_dir);
	perf_opt->file_dir = correct_dirname(perf_opt->file_dir);

	bp_handle_open = FALSE;

	num_ack=0;

	// initialize structures for file transfers
	file_transfer_info_list = file_transfer_info_list_create();

	// set out buffer size if daemon
	if (perf_opt->daemon)
	{
		setlinebuf(stdout);
		setlinebuf(stderr);
	}

	// show requested options (debug)
	if (debug)
	{
		printf("\nOptions;\n");
		printf("\tendpoint:\t%s\n", perf_opt->bp_implementation == BP_ION ? SERV_EP_NUM_SERVICE : SERV_EP_STRING);
		printf("\tsave bundles to:\t%s\n", perf_opt->use_file ? "file":"memory");
		if(perf_opt->use_file)
			printf("\tdestination dir:\t%s\n", perf_opt->dest_dir);
		printf("\tsend acks:\t%s\n", perf_opt->no_acks ? "no":"yes");
		if (!perf_opt->no_acks)
		{
			//printf("\tsend acks to monitor: %s\n", perf_opt->acks_to_mon ? "yes":"no");
			printf("\tacks expiration time: %d\n", (int) conn_opt->expiration);
			char * prior;
			switch(conn_opt->priority.priority)
			{
			case BP_PRIORITY_BULK:
				prior = "bulk";
				break;
			case BP_PRIORITY_NORMAL:
				prior = "normal";
				break;
			case BP_PRIORITY_EXPEDITED:
				prior = "expedited";
				break;
			case BP_PRIORITY_RESERVED:
				prior = "reserved";
				break;
			default:
				prior = "unknown";
				break;
			}
			printf("\tacks priority       : %s\n", prior);
		}
		printf("\n");

	}

	//Ctrl+C handler
	signal(SIGINT, server_handler);

	// create dir where dtnperf server will save incoming bundles
	// command should be: mkdir -p "dest_dir"
	if(debug && debug_level > 0)
		printf("[debug] initializing shell command...");
	command = malloc(sizeof(char) * (30 + strlen(perf_opt->dest_dir)));
	sprintf(command, "mkdir -p %s && rm /tmp/ion_*", perf_opt->dest_dir);
	if(debug && debug_level > 0)
		printf("done. Shell command = %s\n", command);

	// execute shell command
	if(debug && debug_level > 0)
		printf("[debug] executing shell command...");
	if (system(command) < 0)
	{
		perror("[DTNperf error] in opening bundle destination dir");
		exit(-1);
	}
	free(command);
	if(debug && debug_level > 0)
		printf("done\n");

	// create dir where dtnperf server will save incoming files
	// command should be: mkdir -p "file_dir"
	if(debug && debug_level > 0)
		printf("[debug] initializing shell command...");
	command = malloc(sizeof(char) * (10 + strlen(perf_opt->file_dir)));
	sprintf(command, "mkdir -p %s", perf_opt->file_dir);
	if(debug && debug_level > 0)
		printf("done. Shell command = %s\n", command);

	// execute shell command
	if(debug && debug_level > 0)
		printf("[debug] executing shell command...");
	if (system(command) < 0)
	{
		perror("[DTNperf error] in opening transferred files destination dir");
		exit(-1);
	}
	free(command);
	if(debug && debug_level > 0)
		printf("done\n");

	//open the connection to the bundle protocol router
	if(debug && debug_level > 0)
		printf("[debug] opening connection to bundle protocol router...");
	if (perf_opt->use_ip)
		error = al_bp_open_with_ip(perf_opt->ip_addr, perf_opt->ip_port, &handle);
	else
		error = al_bp_open(&handle);
	if (error != BP_SUCCESS)
	{
		fflush(stdout);
		fprintf(stderr, "[DTNperf fatal error] in opening bp handle: %s\n", al_bp_strerror(error));
		exit(1);
	}
	else
	{
		bp_handle_open = TRUE;
	}
	if(debug && debug_level > 0)
		printf("done\n");

	//build a local eid
	if(debug && debug_level > 0)
	{
		printf("[debug] building a local eid in format ");
		if (perf_opt->eid_format_forced == 'D')
			printf("forced DTN...");
		else if (perf_opt->eid_format_forced == 'I')
			printf("forced IPN...");
		else
			printf("standard...");
	}

	if(perf_opt->bp_implementation == BP_ION && perf_opt->eid_format_forced == 'N')
		// Use ION implementation with standard eid scheme
		error = al_bp_build_local_eid(handle, &local_eid, SERV_EP_NUM_SERVICE,CBHE_SCHEME);
	else if(perf_opt->bp_implementation == BP_DTN && perf_opt->eid_format_forced == 'N')
		// Use DTN2 implementation with standard eid scheme
		error = al_bp_build_local_eid(handle, &local_eid, SERV_EP_STRING,DTN_SCHEME);
	else if(perf_opt->bp_implementation == BP_ION && perf_opt->eid_format_forced == 'D')
		// Use ION implementation with forced DTN scheme
		error = al_bp_build_local_eid(handle, &local_eid, SERV_EP_STRING,DTN_SCHEME);
	else if(perf_opt->bp_implementation == BP_DTN && perf_opt->eid_format_forced == 'I')
		// Use DTN2 implementation with forced IPN scheme
	{
		//in this case the api al_bp_build_local_eid() wants ipn_local_number.service_number
		sprintf(temp, "%d.%s", perf_opt->ipn_local_num, SERV_EP_NUM_SERVICE);
		error = al_bp_build_local_eid(handle, &local_eid, temp, CBHE_SCHEME);
	}

	if(debug && debug_level > 0)
		printf("done\n");
	if (debug)
		printf("local_eid = %s\n", local_eid.uri);
	if (error != BP_SUCCESS)
	{
		fflush(stdout);
		fprintf(stderr, "[DTNperf fatal error] in building local EID: '%s'\n", al_bp_strerror(error));
		server_clean_exit(1);
	}

	// checking if there is already a registration
	if(debug && debug_level > 0)
		printf("[debug] checking for existing registration...");
	error = al_bp_find_registration(handle, &local_eid, &regid);
	if ( (error == BP_SUCCESS && perf_opt->bp_implementation == BP_DTN)
			|| (perf_opt->bp_implementation == BP_ION && (error == BP_EBUSY || error == BP_EPARSEEID)))
	{
		fflush(stdout);
		fprintf(stderr, "[DTNperf error] existing a registration with the same eid.\n");
		fprintf(stderr, "regid 0x%x\n", (unsigned int) regid);
		server_clean_exit(1);
	}
	if ((debug) && (debug_level > 0))
		printf(" done\n");

	//create a new registration to the local router based on this eid
	if(debug && debug_level > 0)
		printf("[debug] registering to local daemon...");
	memset(&reginfo, 0, sizeof(reginfo));
	al_bp_copy_eid(&reginfo.endpoint, &local_eid);
	reginfo.flags = BP_REG_DEFER;
	reginfo.regid = BP_REGID_NONE;
	reginfo.expiration = 0;
	if ((error = al_bp_register(&handle, &reginfo, &regid)) != 0)
	{
		fflush(stdout);
		fprintf(stderr, "[DTNperf error] in creating registration: %d (%s)\n",
				error, al_bp_strerror(al_bp_errno(handle)));
		server_clean_exit(1);
	}
	if ((debug) && (debug_level > 0))
		printf(" done\n");
	if (debug)
		printf("regid 0x%x\n", (unsigned int) regid);

	// set bundle destination type
	if ((debug) && (debug_level > 0))
		printf("[debug] choosing bundle destination type...");
	if (perf_opt->use_file)
		pl_location = BP_PAYLOAD_FILE;
	else
		pl_location = BP_PAYLOAD_MEM;
	if ((debug) && (debug_level > 0))
		printf(" done. Bundles will be saved into %s\n", perf_opt->use_file ? "file" : "memory");

	// start thread
	pthread_mutex_init (&mutexdata, NULL);
	pthread_create(&file_exp_timer, NULL, file_expiration_timer, NULL);



	if ((debug) && (debug_level > 0))
		printf("[debug] entering infinite loop...\n");

	// start infinite loop
	while(1)
	{

		// create a bundle object
		if ((debug) && (debug_level > 0))
			printf("[debug] initiating memory for bundles...\n");

		error = al_bp_bundle_create(&bundle_object);
		if (error != BP_SUCCESS)
		{
			fflush(stdout);
			fprintf(stderr, "[DTNperf fatal error] in initiating memory for bundles: %s\n", al_bp_strerror(error));
			server_clean_exit(1);
		}
		if(debug && debug_level > 0)
			printf("done\n");

		// reset file transfer indicators
		is_file_transfer_bundle = FALSE;

		// wait until receive a bundle
		if ((debug) && (debug_level > 0))
			printf("[debug] waiting for bundles...\n");

		error = al_bp_bundle_receive(handle, bundle_object, pl_location, -1);
		if(error == BP_ERECVINT || error == BP_ETIMEOUT)
		{
			if(error == BP_ERECVINT )
				fprintf(stderr, "[DTNperf warning] bundle reception interrupted\n");
			if(error == BP_ETIMEOUT )
				fprintf(stderr, "[DTNperf warning] bundle reception timeout expired\n");

			// free memory for bundle
			al_bp_bundle_free(&bundle_object);
		}
		else
		{
			if (error != BP_SUCCESS)
			{
				fflush(stdout);
				fprintf(stderr, "error getting recv reply: %d (%s)\n",
						error, al_bp_strerror(al_bp_errno(handle)));
				server_clean_exit(1);
			}
			if ((debug) && (debug_level > 0))
				printf(" bundle received\n");

			// find payload size
			if ((debug) && (debug_level > 0))
				printf("[debug] calculating bundle payload size...");
			error = al_bp_bundle_get_payload_size(bundle_object, (u32_t *) &bundle_payload_len);
			if (error != BP_SUCCESS)
			{
				fflush(stdout);
				fprintf(stderr, "[DTNperf fatal error] in getting bundle payload size: %s\n",
						al_bp_strerror(error));
				server_clean_exit(1);
			}
			if(debug && debug_level > 0)
				printf("done\n");

			// mark current time
			if ((debug) && (debug_level > 0))
				printf("[debug] marking time...");
			current = time(NULL);
			if ((debug) && (debug_level > 0))
				printf(" done\n");

			// print bundle arrival
			printf("%s : %zu bytes from %s\n",
					ctime(&current),
					bundle_payload_len,
					bundle_object.spec->source.uri);

			// get bundle header and options
			if ((debug) && (debug_level > 0))
				printf("[debug]\tgetting bundle header and options...");
			if (get_bundle_header_and_options(&bundle_object, &bundle_header, &bundle_ack_options) < 0)
			{
				printf("[DTNperf warning] in getting bundle header and options\n");
				continue;
			}

			if ((debug) && (debug_level > 0))
			{
				printf(" done.\n");
			}

			// get SOURCE eid
			if ((debug) && (debug_level > 0))
				printf("[debug]\tgetting source eid...");
			error = al_bp_bundle_get_source(bundle_object, &bundle_source_addr);
			if (error != BP_SUCCESS)
			{
				fflush(stdout);
				fprintf(stderr, "[DTNperf fatal error] in getting bundle source eid: %s\n",
						al_bp_strerror(error));
				server_clean_exit(1);
			}
			if ((debug) && (debug_level > 0))
			{
				printf(" done:\n");
				printf("\tbundle_source_addr = %s\n", bundle_source_addr.uri);
				printf("\n");
			}

			// get DEST eid
			if ((debug) && (debug_level > 0))
				printf("[debug]\tgetting destination eid...");
			error = al_bp_bundle_get_dest(bundle_object, &bundle_dest_addr);
			if (error != BP_SUCCESS)
			{
				fflush(stdout);
				fprintf(stderr, "[DTNperf fatal error] in getting bundle destination eid: %s\n",
						al_bp_strerror(error));
				server_clean_exit(1);
			}
			if ((debug) && (debug_level > 0))
			{
				printf(" done:\n");
				printf("\tbundle_dest_eid = %s\n", bundle_dest_addr.uri);
				printf("\n");
			}

			// get REPLY TO eid
			if ((debug) && (debug_level > 0))
				printf("[debug]\tgetting reply to eid...");
			error = al_bp_bundle_get_replyto(bundle_object, &bundle_replyto_addr);
			if (error != BP_SUCCESS)
			{
				fflush(stdout);
				fprintf(stderr, "error getting bundle reply to eid: %s\n",
						al_bp_strerror(error));
				exit(1);
			}
			if ((debug) && (debug_level > 0))
			{
				printf(" done:\n");
				printf("\tbundle_replyto_eid = %s\n", bundle_replyto_addr.uri);
				printf("\n");
			}

			// get bundle creation timestamp
			if ((debug) && (debug_level > 0))
				printf("[debug]\tgetting bundle creation timestamp...");
			error = al_bp_bundle_get_creation_timestamp(bundle_object, &bundle_creation_timestamp);
			if (error != BP_SUCCESS)
			{
				fflush(stdout);
				fprintf(stderr, "[DTNperf fatal error] in getting bundle creation timestamp: %s\n",
						al_bp_strerror(error));
				server_clean_exit(1);
			}
			if ((debug) && (debug_level > 0))
			{
				printf(" done:\n");
				printf("\tbundle creation timestamp:\n"
						"\tsecs = %d\n\tseqno= %d\n",
						(int)bundle_creation_timestamp.secs, (int)bundle_creation_timestamp.seqno);
				printf("\n");
			}

			// get bundle payload filename
			if(perf_opt->use_file)
			{
				if ((debug) && (debug_level > 0))
					printf("[debug]\tgetting bundle payload filename...");
				error = al_bp_bundle_get_payload_file(bundle_object, &pl_filename, (u32_t *) &pl_filename_len);
				if (error != BP_SUCCESS)
				{
					fflush(stdout);
					fprintf(stderr, "[DTNperf fatal error] in getting bundle payload filename: %s\n",
							al_bp_strerror(error));
					server_clean_exit(1);
				}
				if ((debug) && (debug_level > 0))
				{
					printf(" done:\n");
				}
			}

			if ((debug))
			{
				printf ("======================================\n");
				printf (" Bundle received at %s\n", ctime(&current));
				printf ("  source: %s\n", bundle_source_addr.uri);
				if (perf_opt->use_file)
				{
					printf ("  saved into    : %s\n", pl_filename);
				}

				printf ("--------------------------------------\n");
			};

			// check if is file transfer bundle
			if ((debug) && (debug_level > 0))
				printf("[debug]\tchecking if this is a file transfer bundle...");
			if (bundle_header == FILE_HEADER)
			{
				is_file_transfer_bundle = TRUE;
			}
			if ((debug) && (debug_level > 0))
			{
				printf(" done.\n");
				printf("\tbundle is%sa file transfer bundle\n",
						is_file_transfer_bundle ? " " : " not ");
				printf("\n");
			}

			int crc_ok = 1;
			if (bundle_ack_options.crc_enabled==TRUE)
			{

				FILE *pl_stream;
				char *transfer;
				int transfer_len;
				u32_t pl_size;
				uint32_t local_crc;

				local_crc = 0;
				crc_ok = 0;

				// get info about bundle size
				al_bp_bundle_get_payload_size(bundle_object, &pl_size);

				if (open_payload_stream_read(bundle_object, &pl_stream) < 0)
				{
					fflush(stdout);
					fprintf(stderr, "[DTNperf fatal error] i can't open the bundle file\n");
					server_clean_exit(1);
				}
/*
				fseek(pl_stream, HEADER_SIZE + BUNDLE_OPT_SIZE, SEEK_SET);
				if (is_file_transfer_bundle)
				{
					fseek
				}*/
				
				transfer_len = HEADER_SIZE + BUNDLE_OPT_SIZE+sizeof(al_bp_timeval_t);
				transfer = (char*) malloc(transfer_len);
				memset(transfer, 0, transfer_len);
				if (fread(transfer, transfer_len, 1, pl_stream) != 1 && ferror(pl_stream)!=0)
				{
					fprintf(stderr, "[DTNperf warning] in processing file transfer bundle: %s\n", strerror(errno));
				}
				local_crc = calc_crc32_d8(local_crc, (uint8_t*) transfer, transfer_len);
				free(transfer);

				fseek(pl_stream, BUNDLE_CRC_SIZE, SEEK_CUR);

				transfer_len = pl_size-transfer_len-BUNDLE_CRC_SIZE;
				transfer = (char*) malloc(transfer_len);
				memset(transfer, 0, transfer_len);
				if (fread(transfer, transfer_len, 1, pl_stream) != 1 && ferror(pl_stream)!=0)
				{
					fprintf(stderr, "[DTNperf warning] in processing file transfer bundle: %s\n", strerror(errno));
				}

				local_crc = calc_crc32_d8(local_crc, (uint8_t*) transfer, transfer_len);

				if (debug)
					printf("CRC received: %"PRIu32" GENERATED: %"PRIu32"\n", bundle_object.payload->buf.buf_crc, local_crc);

				if (local_crc != bundle_object.payload->buf.buf_crc)
					bundle_ack_options.crc_enabled=TRUE;
				else
					bundle_ack_options.crc_enabled=FALSE;

				if (bundle_ack_options.crc_enabled==FALSE)
				{
					crc_ok = 1;
				}

				free(transfer);
				close_payload_stream_read(pl_stream);

			}

			// process file transfer bundle
			if(is_file_transfer_bundle && crc_ok == 1)
			{
				if ((debug) && (debug_level > 0))
					printf("[debug]\tprocessing file transfer bundle...");

				pthread_mutex_lock(&mutexdata);
				indicator = process_incoming_file_transfer_bundle(&file_transfer_info_list,
						&bundle_object,perf_opt->file_dir, (bundle_ack_options.crc_enabled == TRUE ? &bundle_object.payload->buf.buf_crc : (uint32_t *) NULL));

				pthread_mutex_unlock(&mutexdata);
				sched_yield();

				// WRONG CRC
				//if (indicator == -2)
				//{
				//	if (debug)
				//		printf("CRC differs from the received one.\n");
				//	bundle_ack_options.crc_enabled=TRUE;
				//}
				//else
				//	bundle_ack_options.crc_enabled=FALSE;

				if (indicator < 0) // error in processing bundle
				{
					fprintf(stderr, "[DTNperf warning] in processing file transfer bundle: %s\n", strerror(errno));
				}
				if ((debug) && (debug_level > 0))
				{
					printf("done.\n");
					if (indicator == 1)
						printf("Transfer Completed\n");
				}
			}
			

			// get bundle expiration time
			if (bundle_ack_options.set_ack_expiration)
			{
				// 	al_bp_bundle_get_expiration(bundle_object, &bundle_expiration);
				//  is setted the smaller
				if( conn_opt->expiration < bundle_ack_options.ack_expiration)
					bundle_expiration = conn_opt->expiration;
				else
					bundle_expiration = bundle_ack_options.ack_expiration;
			}
			else
				bundle_expiration = conn_opt->expiration;

			// get bundle priority
			bundle_priority.ordinal = 0;
			if( bundle_ack_options.set_ack_priority)
			{
				// is setted the smaller
				if( conn_opt->priority.priority < bundle_ack_options.ack_priority.priority)
					bundle_priority.priority = conn_opt->priority.priority;
				else
					bundle_priority.priority = bundle_ack_options.ack_priority.priority;
			}
			else
				bundle_priority.priority = conn_opt->priority.priority;

			// send acks to the client only if requested by client
			// send acks to the monitor if:
			// ack requested by client AND ack-to-monitor option set AND bundle_ack_options.ack_to_mon == ATM_NORMAL
			// OR client forced server to send ack to monitor

			boolean_t send_ack_to_client = bundle_ack_options.ack_to_client;
			boolean_t send_ack_to_monitor = FALSE;
			send_ack_to_monitor = (bundle_ack_options.ack_to_client && (bundle_ack_options.ack_to_mon == ATM_NORMAL) && bundle_ack_options.ack_to_client && perf_opt->acks_to_mon)
					|| (bundle_ack_options.ack_to_mon == ATM_FORCE_YES);
			if (send_ack_to_client || send_ack_to_monitor)
			{

				// create bundle ack to send
				if ((debug) && (debug_level > 0))
					printf("[debug] initiating memory for bundle ack...");
				error = al_bp_bundle_create(&bundle_ack_object);
				if (error != BP_SUCCESS)
				{
					fflush(stdout);
					fprintf(stderr, "[DTNperf fatal error] in initiating memory for bundle ack: %s\n", al_bp_strerror(error));
					server_clean_exit(1);
				}
				if(debug && debug_level > 0)
					printf("done\n");


				// initiate server ack payload
				// set server ack payload source
				server_ack_payload.bundle_source = bundle_source_addr;
				// set server ack payload timestamp
				server_ack_payload.bundle_creation_ts = bundle_creation_timestamp;
				// preparing the bundle ack payload
				if ((debug) && (debug_level > 0))
					printf("[debug] preparing the payload of the bundle ack...");
				error = prepare_server_ack_payload(server_ack_payload, &bundle_ack_options, &pl_buffer, &pl_buffer_size);

				if (error != BP_SUCCESS)
				{
					fflush(stdout);
					fprintf(stderr, "[DTNperf fatal error] in preparing the payload of the bundle ack: %s\n", al_bp_strerror(error));
					server_clean_exit(1);
				}
				if(debug && debug_level > 0)
					printf("done\n");

				// setting the bundle ack payload
				if ((debug) && (debug_level > 0))
					printf("[debug] setting the payload of the bundle ack...");
				// For DTN2 implementation ack payload in in memory
				if(perf_opt->bp_implementation == BP_DTN)
				{
					error = al_bp_bundle_set_payload_mem(&bundle_ack_object, pl_buffer, pl_buffer_size);
				}
				else if(perf_opt->bp_implementation == BP_ION)
				{
					char filename_ack[256];
					FILE * fd_ack;
					u32_t filename_ack_len;
					sprintf(filename_ack,"%s_%d",SOURCE_FILE_ACK,num_ack);
					filename_ack_len = strlen(filename_ack)+1;
					fd_ack = fopen(filename_ack,"w");
					if(fd_ack == NULL)
					{
						fflush(stdout);
						fprintf(stderr, "[DTNperf fatal error] in creating the payload of the bundle ack: %s\n", strerror(errno));
						server_clean_exit(1);
					}
					if(fwrite(pl_buffer, pl_buffer_size, 1, fd_ack)<0){
						fflush(stdout);
						fprintf(stderr, "[DTNperf fatal error] in writing the payload of the bundle ack: %s\n", strerror(errno));
						//server_clean_exit(1);
					}
					if (fclose(fd_ack) != 0){
						fflush(stdout);
						fprintf(stderr, "[DTNperf fatal error] in closing the payload file of the bundle ack: %s\n", strerror(errno));
						server_clean_exit(1);
					}

					if (debug && debug_level > 0)
					{
						printf("\n[debug] bundle payload ack saved in: %s ... ", filename_ack);
					}
					num_ack++;
					if (num_ack == 10000) //reset ack counter when it arrives at 10000
						num_ack = 0;
					error = al_bp_bundle_set_payload_file(&bundle_ack_object,filename_ack,filename_ack_len);
				}
				if (error != BP_SUCCESS)
				{
					fflush(stdout);
					fprintf(stderr, "\n[DTNperf fatal error] in setting the payload of the bundle ack: %s\n", al_bp_strerror(error));
					server_clean_exit(1);
				}
				if(debug && debug_level > 0)
					printf("done\n");

				// setting the bundle ack options
				if (debug && debug_level > 0)
				{
					printf("[debug] setting source of the bundle ack: %s ...", local_eid.uri);
				}
				error = al_bp_bundle_set_source(& bundle_ack_object, local_eid);
				if (error != BP_SUCCESS)
				{
					fflush(stdout);
					fprintf(stderr, "[DTNperf fatal error] in setting the source of the bundle ack: %s\n", al_bp_strerror(error));
					server_clean_exit(1);
				}
				if(debug && debug_level > 0)
					printf("done\n");

				if (debug && debug_level > 0)
				{
					printf("[debug] setting destination of the bundle ack: %s ...", bundle_source_addr.uri);
				}
				error = al_bp_bundle_set_dest(& bundle_ack_object, bundle_source_addr);
				if (error != BP_SUCCESS)
				{
					fflush(stdout);
					fprintf(stderr, "[DTNperf fatal error] in setting the destination of the bundle ack: %s\n", al_bp_strerror(error));
					server_clean_exit(1);
				}
				if(debug && debug_level > 0)
					printf("done\n");

				if (debug && debug_level > 0)
				{
					printf("[debug] setting replyto eid of the bundle ack: %s ...", bundle_replyto_addr.uri);
				}
				error = al_bp_bundle_set_replyto(& bundle_ack_object, bundle_replyto_addr);
				if (error != BP_SUCCESS)
				{
					fflush(stdout);
					fprintf(stderr, "[DTNperf fatal error] in setting the reply to eid of the bundle ack: %s\n", al_bp_strerror(error));
					server_clean_exit(1);
				}
				if(debug && debug_level > 0)
					printf("done\n");

				if (debug && debug_level > 0)
				{
					printf("[debug] setting priority of the bundle ack...");
				}
				error = al_bp_bundle_set_priority(& bundle_ack_object, bundle_priority);
				if (error != BP_SUCCESS)
				{
					fflush(stdout);
					fprintf(stderr, "[DTNperf fatal error] in setting priority of the bundle ack: %s\n", al_bp_strerror(error));
					server_clean_exit(1);
				}
				if(debug && debug_level > 0)
					printf("done\n");
	/**************************************************************/
				bundle_ack_object.spec->priority.ordinal = 0;
				bundle_ack_object.spec->critical = FALSE;
				bundle_ack_object.spec->flow_label = 0;
				bundle_ack_object.spec->unreliable = FALSE;
	/**************************************************************/
				if (debug && debug_level > 0)
				{
					printf("[debug] setting expiration time of the bundle ack...");
				}
				error = al_bp_bundle_set_expiration(& bundle_ack_object, bundle_expiration);
				if (error != BP_SUCCESS)
				{
					fflush(stdout);
					fprintf(stderr, "[DTNperf fatal error] in setting expiration time of the bundle ack: %s\n", al_bp_strerror(error));
					server_clean_exit(1);
				}
				if(debug && debug_level > 0)
					printf("done\n");

				if (debug && debug_level > 0)
				{
					printf("[debug] setting delivery options of the bundle ack...");
				}
				//bundle_ack_dopts = BP_DOPTS_CUSTODY;
				bundle_ack_dopts = 0;
				al_bp_bundle_set_delivery_opts(& bundle_ack_object, bundle_ack_dopts);
				if (error != BP_SUCCESS)
				{
					fflush(stdout);
					fprintf(stderr, "[DTNperf fatal error] in setting delivery options of the bundle ack: %s\n", al_bp_strerror(error));
					server_clean_exit(1);
				}
				if(debug && debug_level > 0)
					printf("done\n");

				// send the bundle ack to the client
				if (send_ack_to_client)
				{
					if ((debug) && (debug_level > 0))
						printf("[debug] sending bundle ack to client...");
					error = al_bp_bundle_send(handle, regid, & bundle_ack_object);
					if (error != BP_SUCCESS)
					{
						fflush(stdout);
						fprintf(stderr, "[DTNperf fatal error] in sending bundle ack to client: %d (%s)\n",
								error, al_bp_strerror(al_bp_errno(handle)));
						server_clean_exit(1);
					}
					if ((debug) && (debug_level > 0))
						printf(" bundle ack sent to client\n");
				}
				printf("Send bundle to client ok\n");

				// send the bundle ack to the monitor
				if (send_ack_to_monitor)
				{
					al_bp_bundle_set_dest(& bundle_ack_object, bundle_replyto_addr);
					if ((debug) && (debug_level > 0))
						printf("[debug] sending bundle ack to monitor...");
					error = al_bp_bundle_send(handle, regid, & bundle_ack_object);
					if (error != BP_SUCCESS)
					{
						fflush(stdout);
						fprintf(stderr, "[DTNperf fatal error] in sending bundle ack to monitor: %d (%s)\n",
								error, al_bp_strerror(al_bp_errno(handle)));
						server_clean_exit(1);
					}
					if ((debug) && (debug_level > 0))
						printf(" bundle ack sent to monitor\n");
				}
				//free memory for bundle ack
				al_bp_bundle_free(&bundle_ack_object);
				free(pl_buffer);
				pl_buffer_size = 0;
			}
			// free memory for bundle
			al_bp_bundle_free(&bundle_object);

			free(pl_filename);
			pl_filename_len = 0;
		}

	}// while(1)

	al_bp_close(handle);
	//al_bp_unregister(handle,regid,local_eid);
	bp_handle_open = FALSE;


}