static void prepare_wfds(struct timespec *now, struct _flow *flow, fd_set *wfds) { int rc = 0; if (flow_in_delay(now, flow, WRITE)) { DEBUG_MSG(LOG_WARNING, "flow %i not started yet (delayed)", flow->id); return; } if (flow_sending(now, flow, WRITE)) { #ifdef DEBUG assert(!flow->finished[WRITE]); #endif if (flow_block_scheduled(now, flow)) { DEBUG_MSG(LOG_DEBUG, "adding sock of flow %d to wfds", flow->id); FD_SET(flow->fd, wfds); } else { DEBUG_MSG(LOG_DEBUG, "no block for flow %d scheduled " "yet", flow->id); } } else if (!flow->finished[WRITE]) { flow->finished[WRITE] = 1; if (flow->settings.shutdown) { DEBUG_MSG(LOG_WARNING, "shutting down flow %d (WR)", flow->id); rc = shutdown(flow->fd,SHUT_WR); if (rc == -1) warn("shutdown() SHUT_WR failed"); } } return; }
static int prepare_rfds(struct timespec *now, struct flow *flow, fd_set *rfds) { int rc = 0; if (!flow_in_delay(now, flow, READ) && !flow_sending(now, flow, READ)) { if (!flow->finished[READ] && flow->settings.shutdown) { warnx("server flow %u missed to shutdown", flow->id); rc = shutdown(flow->fd, SHUT_RD); if (rc == -1) warn("shutdown SHUT_RD failed"); flow->finished[READ] = 1; } } if (flow->source_settings.late_connect && !flow->connect_called ) { DEBUG_MSG(LOG_ERR, "late connecting test socket for flow %d " "after %.3fs delay", flow->id, flow->settings.delay[WRITE]); if (do_connect(flow) == -1) { return -1; } } /* Altough the server flow might be finished we keep the socket in * rfd in order to check for buggy servers */ if (flow->connect_called && !flow->finished[READ]) { DEBUG_MSG(LOG_DEBUG, "adding sock of flow %d to rfds", flow->id); FD_SET(flow->fd, rfds); } return 0; }
/* * Prepare a report. type is either INTERVAL or FINAL */ static void report_flow(struct _flow* flow, int type) { DEBUG_MSG(LOG_DEBUG, "report_flow called for flow %d (type %d)", flow->id, type); struct _report* report = (struct _report*)malloc(sizeof(struct _report)); report->id = flow->id; report->type = type; if (type == INTERVAL) report->begin = flow->last_report_time; else report->begin = flow->first_report_time; gettime(&report->end); flow->last_report_time = report->end; /* abort if we were scheduled way to early for a interval report */ if (time_diff(&report->begin,&report->end) < 0.2 * flow->settings.reporting_interval && type == INTERVAL){ free(report); return; } report->bytes_read = flow->statistics[type].bytes_read; report->bytes_written = flow->statistics[type].bytes_written; report->request_blocks_read = flow->statistics[type].request_blocks_read; report->response_blocks_read = flow->statistics[type].response_blocks_read; report->request_blocks_written = flow->statistics[type].request_blocks_written; report->response_blocks_written = flow->statistics[type].response_blocks_written; report->rtt_min = flow->statistics[type].rtt_min; report->rtt_max = flow->statistics[type].rtt_max; report->rtt_sum = flow->statistics[type].rtt_sum; report->iat_min = flow->statistics[type].iat_min; report->iat_max = flow->statistics[type].iat_max; report->iat_sum = flow->statistics[type].iat_sum; report->delay_min = flow->statistics[type].delay_min; report->delay_max = flow->statistics[type].delay_max; report->delay_sum = flow->statistics[type].delay_sum; /* Currently this will only contain useful information on Linux * and FreeBSD */ report->tcp_info = flow->statistics[type].tcp_info; if (flow->fd != -1) { /* Get latest MTU */ flow->pmtu = get_pmtu(flow->fd); report->pmtu = flow->pmtu; if (type == FINAL) report->imtu = get_imtu(flow->fd); else report->imtu = 0; } else { report->imtu = 0; report->pmtu = 0; } /* Add status flags to report */ report->status = 0; if (flow->statistics[type].bytes_read == 0) { if (flow_in_delay(&report->end, flow, READ)) report->status |= 'd'; else if (flow_sending(&report->end, flow, READ)) report->status |= 'l'; else if (flow->settings.duration[READ] == 0) report->status |= 'o'; else report->status |= 'f'; } else { if (!flow_sending(&report->end, flow, READ) && !flow->finished) report->status |= 'c'; else report->status |= 'n'; } report->status <<= 8; if (flow->statistics[type].bytes_written == 0) { if (flow_in_delay(&report->end, flow, WRITE)) report->status |= 'd'; else if (flow_sending(&report->end, flow, WRITE)) report->status |= 'l'; else if (flow->settings.duration[WRITE] == 0) report->status |= 'o'; else report->status |= 'f'; } else { if (!flow_sending(&report->end, flow, WRITE) && !flow->finished) report->status |= 'c'; else report->status |= 'n'; } /* New report interval, reset old data */ if (type == INTERVAL) { flow->statistics[INTERVAL].bytes_read = 0; flow->statistics[INTERVAL].bytes_written = 0; flow->statistics[INTERVAL].request_blocks_read = 0; flow->statistics[INTERVAL].response_blocks_read = 0; flow->statistics[INTERVAL].request_blocks_written = 0; flow->statistics[INTERVAL].response_blocks_written = 0; flow->statistics[INTERVAL].rtt_min = FLT_MAX; flow->statistics[INTERVAL].rtt_max = FLT_MIN; flow->statistics[INTERVAL].rtt_sum = 0.0F; flow->statistics[INTERVAL].iat_min = FLT_MAX; flow->statistics[INTERVAL].iat_max = FLT_MIN; flow->statistics[INTERVAL].iat_sum = 0.0F; flow->statistics[INTERVAL].delay_min = FLT_MAX; flow->statistics[INTERVAL].delay_max = FLT_MIN; flow->statistics[INTERVAL].delay_sum = 0.0F; } add_report(report); DEBUG_MSG(LOG_DEBUG, "report_flow finished for flow %d (type %d)", flow->id, type); }
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; }