예제 #1
0
static void stop_flow(struct request_stop_flow *request)
{
	DEBUG_MSG(LOG_DEBUG, "stop_flow forcefully unlocked mutex");
	pthread_mutex_unlock(&mutex);

	if (request->flow_id == -1) {
		/* Stop all flows */

		const struct list_node *node = fg_list_front(&flows);
		while (node) {
			struct flow *flow = node->data;
			node = node->next;

			flow->statistics[FINAL].has_tcp_info =
				get_tcp_info(flow,
					     &flow->statistics[FINAL].tcp_info)
					? 0 : 1;
			flow->pmtu = get_pmtu(flow->fd);

			if (flow->settings.reporting_interval)
				report_flow(flow, INTERVAL);
			report_flow(flow, FINAL);

			uninit_flow(flow);
			remove_flow(flow);
		}

		return;
	}

	const struct list_node *node = fg_list_front(&flows);
	while (node) {
		struct flow *flow = node->data;
		node = node->next;

		if (flow->id != request->flow_id)
			continue;

		/* On Other OSes than Linux or FreeBSD, tcp_info will contain all zeroes */
		flow->statistics[FINAL].has_tcp_info =
			get_tcp_info(flow,
				     &flow->statistics[FINAL].tcp_info)
				? 0 : 1;
		flow->pmtu = get_pmtu(flow->fd);

		if (flow->settings.reporting_interval)
			report_flow(flow, INTERVAL);
		report_flow(flow, FINAL);

		uninit_flow(flow);
		remove_flow(flow);
		return;
	}

	request_error(&request->r, "Unknown flow id");
}
예제 #2
0
파일: daemon.c 프로젝트: arnd/flowgrind
static void stop_flow(struct _request_stop_flow *request)
{
	DEBUG_MSG(LOG_DEBUG, "stop_flow forcefully unlocked mutex");
	pthread_mutex_unlock(&mutex);

	if (request->flow_id == -1) {
		/* Stop all flows */

		for (unsigned int i = 0; i < num_flows; i++) {
			struct _flow *flow = &flows[i];

			flow->statistics[FINAL].has_tcp_info =
				get_tcp_info(flow,
					     &flow->statistics[FINAL].tcp_info)
					? 0 : 1;
			flow->pmtu = get_pmtu(flow->fd);

			if (flow->settings.reporting_interval)
				report_flow(flow, INTERVAL);
			report_flow(flow, FINAL);

			uninit_flow(flow);
			remove_flow(i);
		}

		return;
	}

	for (unsigned int i = 0; i < num_flows; i++) {
		struct _flow *flow = &flows[i];

		if (flow->id != request->flow_id)
			continue;

		/* On Other OSes than Linux or FreeBSD, tcp_info will contain all zeroes */
		flow->statistics[FINAL].has_tcp_info =
			get_tcp_info(flow,
				     &flow->statistics[FINAL].tcp_info)
				? 0 : 1;
		flow->pmtu = get_pmtu(flow->fd);

		if (flow->settings.reporting_interval)
			report_flow(flow, INTERVAL);
		report_flow(flow, FINAL);

		uninit_flow(flow);
		remove_flow(i);
		return;
	}

	request_error(&request->r, "Unknown flow id");
}
예제 #3
0
파일: daemon.c 프로젝트: arnd/flowgrind
static void process_select(fd_set *rfds, fd_set *wfds, fd_set *efds)
{
	unsigned int i = 0;
	while (i < num_flows) {

		struct _flow *flow = &flows[i];

		DEBUG_MSG(LOG_DEBUG, "processing pselect() for flow %d",
			  flow->id);

		if (flow->listenfd_data != -1 &&
		    FD_ISSET(flow->listenfd_data, rfds)) {
			DEBUG_MSG(LOG_DEBUG, "ready for accept");
			if (flow->state == GRIND_WAIT_ACCEPT) {
				if (accept_data(flow) == -1) {
					DEBUG_MSG(LOG_ERR, "accept_data() "
						  "failed");
					goto remove;
				}
			}
		}

		if (flow->fd != -1) {
			if (FD_ISSET(flow->fd, efds)) {
				int error_number, rc;
				socklen_t error_number_size =
					sizeof(error_number);
				DEBUG_MSG(LOG_DEBUG, "sock of flow %d in efds",
					  flow->id);
				rc = getsockopt(flow->fd, SOL_SOCKET,
						SO_ERROR,
						(void *)&error_number,
						&error_number_size);
				if (rc == -1) {
					warn("failed to get errno for"
					     "non-blocking connect");
					goto remove;
				}
				if (error_number != 0) {
					warnc(error_number, "connect");
					goto remove;
				}
			}
			if (FD_ISSET(flow->fd, wfds))
				if (write_data(flow) == -1) {
					DEBUG_MSG(LOG_ERR, "write_data() failed");
					goto remove;
				}

			if (FD_ISSET(flow->fd, rfds))
				if (read_data(flow) == -1) {
					DEBUG_MSG(LOG_ERR, "read_data() failed");
					goto remove;
				}
		}
		i++;
		continue;
remove:
		if (flow->fd != -1) {
			flow->statistics[FINAL].has_tcp_info =
				get_tcp_info(flow,
					     &flow->statistics[FINAL].tcp_info)
					? 0 : 1;
		}
		flow->pmtu = get_pmtu(flow->fd);
		report_flow(flow, FINAL);
		uninit_flow(flow);
		remove_flow(i);
		DEBUG_MSG(LOG_ERR, "removed flow %d", flow->id);
	}
}
예제 #4
0
파일: daemon.c 프로젝트: arnd/flowgrind
static int prepare_fds() {

	DEBUG_MSG(LOG_DEBUG, "prepare_fds() called, num_flows: %d", num_flows);
	unsigned int i = 0;

	FD_ZERO(&rfds);
	FD_ZERO(&wfds);
	FD_ZERO(&efds);

	FD_SET(daemon_pipe[0], &rfds);
	maxfd = daemon_pipe[0];

	struct timespec now;
	gettime(&now);

	while (i < num_flows) {
		struct _flow *flow = &flows[i++];

		if (started &&
		    (flow->finished[READ] ||
		     !flow->settings.duration[READ] ||
		     (!flow_in_delay(&now, flow, READ) &&
		      !flow_sending(&now, flow, READ))) &&
		    (flow->finished[WRITE] ||
		     !flow->settings.duration[WRITE] ||
		     (!flow_in_delay(&now, flow, WRITE) &&
		      !flow_sending(&now, flow, WRITE)))) {

			/* On Other OSes than Linux or FreeBSD, tcp_info will contain all zeroes */
			flow->statistics[FINAL].has_tcp_info =
				get_tcp_info(flow,
					     &flow->statistics[FINAL].tcp_info)
					? 0 : 1;

			flow->pmtu = get_pmtu(flow->fd);

			if (flow->settings.reporting_interval)
				report_flow(flow, INTERVAL);
			report_flow(flow, FINAL);
			uninit_flow(flow);
			remove_flow(--i);
			continue;
		}

		if (flow->state == GRIND_WAIT_ACCEPT &&
		    flow->listenfd_data != -1) {
			FD_SET(flow->listenfd_data, &rfds);
			maxfd = MAX(maxfd, flow->listenfd_data);
		}

		if (!started)
			continue;

		if (flow->fd != -1) {
			FD_SET(flow->fd, &efds);
			maxfd = MAX(maxfd, flow->fd);
			prepare_wfds(&now, flow, &wfds);
			prepare_rfds(&now, flow, &rfds);
		}
	}

	return num_flows;
}
예제 #5
0
int add_flow_source(struct _request_add_flow_source *request)
{
#ifdef TCP_CONGESTION
    socklen_t opt_len = 0;
#endif /* TCP_CONGESTION */
    struct _flow *flow;

    if (num_flows >= MAX_FLOWS) {
        logging_log(LOG_WARNING, "Can not accept another flow, already handling MAX_FLOW flows.");
        request_error(&request->r, "Can not accept another flow, already handling MAX_FLOW flows.");
        return -1;
    }

    flow = &flows[num_flows++];
    init_flow(flow, 1);

    flow->settings = request->settings;
    flow->source_settings = request->source_settings;
    /* be greedy with buffer sizes */
    flow->write_block = calloc(1, flow->settings.maximum_block_size);
    flow->read_block = calloc(1, flow->settings.maximum_block_size);

    if (flow->write_block == NULL || flow->read_block == NULL) {
        logging_log(LOG_ALERT, "could not allocate memory for read/write blocks");
        request_error(&request->r, "could not allocate memory for read/write blocks");
        uninit_flow(flow);
        num_flows--;
        return -1;
    }
    if (flow->settings.byte_counting) {
        int byte_idx;
        for (byte_idx = 0; byte_idx < flow->settings.maximum_block_size; byte_idx++)
            *(flow->write_block + byte_idx) = (unsigned char)(byte_idx & 0xff);
    }

    flow->state = GRIND_WAIT_CONNECT;
    flow->fd = name2socket(flow, flow->source_settings.destination_host,
                           flow->source_settings.destination_port,
                           &flow->addr, &flow->addr_len, 0,
                           flow->settings.requested_read_buffer_size, &request->real_read_buffer_size,
                           flow->settings.requested_send_buffer_size, &request->real_send_buffer_size);
    if (flow->fd == -1) {
        logging_log(LOG_ALERT, "Could not create data socket: %s", flow->error);
        request_error(&request->r, "Could not create data socket: %s", flow->error);
        uninit_flow(flow);
        num_flows--;
        return -1;
    }

    if (set_flow_tcp_options(flow) == -1) {
        request->r.error = flow->error;
        flow->error = NULL;
        uninit_flow(flow);
        num_flows--;
        return -1;
    }

#ifdef TCP_CONGESTION
    opt_len = sizeof(request->cc_alg);
    if (getsockopt(flow->fd, IPPROTO_TCP, TCP_CONGESTION,
                   request->cc_alg, &opt_len) == -1) {
        request_error(&request->r, "failed to determine actual congestion control algorithm: %s",
                      strerror(errno));
        uninit_flow(flow);
        num_flows--;
        return -1;
    }
#endif /* TCP_CONGESTION */

#ifdef HAVE_LIBPCAP
    fg_pcap_go(flow);
#endif /* HAVE_LIBPCAP */
    if (!flow->source_settings.late_connect) {
        DEBUG_MSG(4, "(early) connecting test socket");
        connect(flow->fd, flow->addr, flow->addr_len);
        flow->connect_called = 1;
        flow->pmtu = get_pmtu(flow->fd);
    }

    request->flow_id = flow->id;

    return 0;
}