Exemple #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;
}
Exemple #2
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);
}