This source file includes following definitions.
- safe_write
- transfer_to_fd
- transfer_to_buffer
- checked_open
- transfer_measurement
- acquire_sample
- poll_content
- content_collection
- main
#include <errno.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include "base/logging.h"
struct Context {
size_t nb_files;
int* file_fds;
int poll_rate;
};
void safe_write(int fd, const char* buffer, int size) {
const char* index = buffer;
size_t to_write = size;
while (to_write > 0) {
int written = write(fd, index, to_write);
if (written < 0)
PLOG(FATAL);
index += written;
to_write -= written;
}
}
void transfer_to_fd(int fd_in, int fd_out) {
char buffer[1024];
int n;
while ((n = read(fd_in, buffer, sizeof(buffer))) > 0)
safe_write(fd_out, buffer, n);
}
int transfer_to_buffer(int fd_in, char* bufffer, size_t size) {
char* index = bufffer;
size_t to_read = size;
int n;
while (to_read > 0 && ((n = read(fd_in, index, to_read)) > 0)) {
index += n;
to_read -= n;
}
if (n < 0)
PLOG(FATAL);
return size - to_read;
}
int checked_open(const char* path) {
int fd = open(path, O_RDONLY);
if (fd < 0)
PLOG(FATAL);
return fd;
}
void transfer_measurement(int fd_in, int fd_out, bool last) {
char buffer[1024];
if (lseek(fd_in, 0, SEEK_SET) < 0)
PLOG(FATAL);
int n = transfer_to_buffer(fd_in, buffer, sizeof(buffer));
safe_write(fd_out, buffer, n - 1);
safe_write(fd_out, last ? "\n" : " ", 1);
}
void acquire_sample(int fd, const Context& context) {
struct timeval tv;
gettimeofday(&tv, NULL);
char buffer[1024];
int n = snprintf(buffer, sizeof(buffer), "%d.%06d ", tv.tv_sec, tv.tv_usec);
safe_write(fd, buffer, n);
for (int i = 0; i < context.nb_files; ++i)
transfer_measurement(context.file_fds[i], fd, i == (context.nb_files - 1));
}
void poll_content(const Context& context) {
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in socket_info;
socket_info.sin_family = AF_INET;
socket_info.sin_addr.s_addr = htonl(INADDR_ANY);
socket_info.sin_port = htons(0);
if (bind(sockfd, (struct sockaddr*)&socket_info, sizeof(socket_info)) < 0)
PLOG(FATAL);
socklen_t size = sizeof(socket_info);
getsockname(sockfd, (struct sockaddr*)&socket_info, &size);
printf("%d\n", ntohs(socket_info.sin_port));
int pipes[2];
pipe(pipes);
pid_t pid = fork();
if (pid < 0)
PLOG(FATAL);
if (pid != 0) {
close(pipes[1]);
read(pipes[0], NULL, 1);
signal(SIGCHLD, SIG_IGN);
return;
}
setsid();
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
close(pipes[0]);
if (listen(sockfd, 1) < 0)
PLOG(FATAL);
close(pipes[1]);
int fd;
char filename[] = "/data/local/tmp/fileXXXXXX";
fd = mkstemp(filename);
unlink(filename);
fd_set rfds;
struct timeval timeout;
do {
acquire_sample(fd, context);
timeout.tv_sec = 0;
timeout.tv_usec = 1000000 / context.poll_rate;
FD_ZERO(&rfds);
FD_SET(sockfd, &rfds);
} while (select(sockfd + 1, &rfds, NULL, NULL, &timeout) == 0);
acquire_sample(fd, context);
struct sockaddr_in remote_socket_info;
int rfd = accept(sockfd, (struct sockaddr*)&remote_socket_info, &size);
if (rfd < 0)
PLOG(FATAL);
if (lseek(fd, 0, SEEK_SET) < 0)
PLOG(FATAL);
transfer_to_fd(fd, rfd);
}
void content_collection(int port) {
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in socket_info;
socket_info.sin_family = AF_INET;
socket_info.sin_addr.s_addr = htonl(0x7f000001);
socket_info.sin_port = htons(port);
if (connect(sockfd, (struct sockaddr*)&socket_info, sizeof(socket_info)) <
0) {
PLOG(FATAL);
}
transfer_to_fd(sockfd, STDOUT_FILENO);
}
int main(int argc, char** argv) {
if (argc == 1) {
fprintf(stderr,
"Usage: \n"
" %s port\n"
" %s rate FILE...\n",
argv[0],
argv[0]);
exit(EXIT_FAILURE);
}
if (argc == 2) {
content_collection(atoi(argv[1]));
} else {
Context context;
context.poll_rate = atoi(argv[1]);
context.nb_files = argc - 2;
context.file_fds = new int[context.nb_files];
for (int i = 2; i < argc; ++i)
context.file_fds[i - 2] = checked_open(argv[i]);
poll_content(context);
}
return EXIT_SUCCESS;
}