/* Read exactly n bytes from the DAC connection socket. * * This reads exactly len bytes into buf. Data is read in chunks from the * OS socket library and buffered in the dac_conn_t structure; individual * sections are then copied out. * * Returns 0 on success, -1 on error. If an error occurs, this will call * log_socket_error() to log the issue. The error code is also available * from WSAGetLastError(). */ int dac_read_bytes(dac_t *d, char *buf, int len) { while (d->conn.size < len) { // Wait for readability. int res = wait_for_activity(d, DEFAULT_TIMEOUT); if (res < 0) { closesocket(d->conn.sock); d->conn.sock = INVALID_SOCKET; return -1; } else if (res == 0) { flogd(d, "!! Read from DAC timed out.\n"); closesocket(d->conn.sock); d->conn.sock = INVALID_SOCKET; return -1; } res = recv(d->conn.sock, d->conn.buf + d->conn.size, len - d->conn.size, 0); if (res == 0 || res == SOCKET_ERROR) { log_socket_error(d, "recv"); return -1; } d->conn.size += res; } memcpy(buf, d->conn.buf, len); if (d->conn.size > len) { memmove(d->conn.buf, d->conn.buf + len, d->conn.size - len); } d->conn.size -= len; return 0; }
int dac_get_acks(dac_t *d, int wait) { /* Read any ACKs we are owed */ while (d->conn.pending_meta_acks || (d->conn.ackbuf_prod != d->conn.ackbuf_cons)) { int res; if (wait_for_activity(d, wait)) { if ((res = dac_read_resp(d, 1)) < 0) return res; if ((res = check_data_response(d)) < 0) return res; } else { break; } } return 0; }
int main( int argc, char **argv) { bool command_pipe_open; struct command_buffer_t command_buffer; struct net_state_t net_state; /* To minimize security risk, the only thing done prior to dropping SUID should be opening the network state for raw sockets. */ init_net_state_privileged(&net_state); if (drop_elevated_permissions()) { perror("Unable to drop elevated permissions"); exit(EXIT_FAILURE); } init_net_state(&net_state); init_command_buffer(&command_buffer, fileno(stdin)); command_pipe_open = true; /* Dispatch commands and respond to probe replies until the command stream is closed. */ while (true) { /* Ensure any responses are written before waiting */ fflush(stdout); wait_for_activity(&command_buffer, &net_state); /* Receive replies first so that the timestamps are as close to the response arrival time as possible. */ receive_replies(&net_state); if (command_pipe_open) { if (read_commands(&command_buffer)) { if (errno == EPIPE) { command_pipe_open = false; } } } check_probe_timeouts(&net_state); /* Dispatch commands late so that the window between probe departure and arriving replies is as small as possible. */ dispatch_buffer_commands(&command_buffer, &net_state); /* If the command pipe has been closed, exit after all in-flight probes have reported their status. */ if (!command_pipe_open) { if (net_state.outstanding_probe_count == 0) { break; } } } return 0; }