Skip to content

Commit

Permalink
Introduce a rsync transfer timeout
Browse files Browse the repository at this point in the history
Default set to 900 (same as rpki-client)

Fixes NICMx#74
  • Loading branch information
job committed Aug 22, 2024
1 parent e5a80e5 commit a51ba5a
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 12 deletions.
14 changes: 14 additions & 0 deletions docs/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ description: Guide to use arguments of FORT Validator.
51. [`--rsync.priority`](#--rsyncpriority)
53. [`--rsync.retry.count`](#--rsyncretrycount)
54. [`--rsync.retry.interval`](#--rsyncretryinterval)
40. [`--rsync.transfer-timeout`](#--rsynctransfer-timeout)
55. [`--configuration-file`](#--configuration-file)
56. [`rsync.program`](#rsyncprogram)
57. [`rsync.arguments-recursive`](#rsyncarguments-recursive)
Expand Down Expand Up @@ -103,6 +104,7 @@ description: Guide to use arguments of FORT Validator.
[--rsync.priority=<unsigned integer>]
[--rsync.retry.count=<unsigned integer>]
[--rsync.retry.interval=<unsigned integer>]
[--rsync.transfer-timeout=<unsigned integer>]
[--http.enabled=true|false]
[--http.priority=<unsigned integer>]
[--http.retry.count=<unsigned integer>]
Expand Down Expand Up @@ -931,6 +933,17 @@ Whenever is necessary to execute an RSYNC, the validator will try at least one t

Period of time (in seconds) to wait between each retry to execute an RSYNC.

### `--rsync.transfer-timeout`

- **Type:** Integer
- **Availability:** `argv` and JSON
- **Default:** 900
- **Range:** [0, [`UINT_MAX`](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/limits.h.html)]

Maximum time in seconds that the rsync transfer can last.

Once the connection is established with the server, the request will last a maximum of `rsync.transfer-timeout` seconds. A value of 0 means unlimited time.

### `--configuration-file`

- **Type:** String (Path to file)
Expand Down Expand Up @@ -974,6 +987,7 @@ The configuration options are mostly the same as the ones from the `argv` interf
"<a href="#--rsyncretrycount">count</a>": 1,
"<a href="#--rsyncretryinterval">interval</a>": 4
},
"<a href="#--rsynctransfer-timeout">transfer-timeout</a>": 0,
"<a href="#rsyncprogram">program</a>": "rsync",
"<a href="#rsyncarguments-recursive">arguments-recursive</a>": [
"-rtz",
Expand Down
1 change: 1 addition & 0 deletions examples/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
"count": 2,
"interval": 5
},
"transfer-timeout": 900,
"program": "rsync",
"arguments-recursive": [
"--recursive",
Expand Down
12 changes: 12 additions & 0 deletions man/fort.8
Original file line number Diff line number Diff line change
Expand Up @@ -1009,6 +1009,18 @@ By default, the value is \fI5\fR.
.RE
.P

.B \-\-rsync.transfer\-timeout=\fIUNSIGNED_INTEGER\fR
.RS 4
Maximum time in seconds that the rsync process can last.
.P
Once the connection is established with the server, the request will last a
maximum of \fBrsync.transfer-timeout\fR seconds. A value of \fI0\fR means
unlimited time (default value).
.P
By default, it has a value of \fI900\fR.
.RE
.P

.B \-\-output.roa=\fIFILE\fR
.RS 4
File where the ROAs will be printed in the configured format (see
Expand Down
16 changes: 16 additions & 0 deletions src/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ struct rpki_config {
/* Interval (in seconds) between each retry */
unsigned int interval;
} retry;
unsigned int transfer_timeout;
char *program;
struct {
struct string_array flat; /* Deprecated */
Expand Down Expand Up @@ -486,6 +487,14 @@ static const struct option_field options[] = {
/* Unlimited */
.max = 0,
.deprecated = true,
}, {
.id = 3008,
.name = "rsync.transfer-timeout",
.type = &gt_uint,
.offset = offsetof(struct rpki_config, rsync.transfer_timeout),
.doc = "Maximum transfer time before killing the rsync process",
.min = 0,
.max = UINT_MAX,
},

/* HTTP requests parameters */
Expand Down Expand Up @@ -946,6 +955,7 @@ set_default_values(void)
rpki_config.rsync.strategy = pstrdup("<deprecated>");
rpki_config.rsync.retry.count = 1;
rpki_config.rsync.retry.interval = 4;
rpki_config.rsync.transfer_timeout = 900;
rpki_config.rsync.program = pstrdup("rsync");
string_array_init(&rpki_config.rsync.args.flat,
flat_rsync_args, ARRAY_LEN(flat_rsync_args));
Expand Down Expand Up @@ -1342,6 +1352,12 @@ config_get_rsync_retry_interval(void)
return rpki_config.rsync.retry.interval;
}

long
config_get_rsync_transfer_timeout(void)
{
return rpki_config.rsync.transfer_timeout;
}

char *
config_get_rsync_program(void)
{
Expand Down
1 change: 1 addition & 0 deletions src/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ bool config_get_rsync_enabled(void);
unsigned int config_get_rsync_priority(void);
unsigned int config_get_rsync_retry_count(void);
unsigned int config_get_rsync_retry_interval(void);
long config_get_rsync_transfer_timeout(void);
char *config_get_rsync_program(void);
struct string_array const *config_get_rsync_args(void);
bool config_get_http_enabled(void);
Expand Down
44 changes: 32 additions & 12 deletions src/rsync/rsync.c
Original file line number Diff line number Diff line change
Expand Up @@ -154,21 +154,41 @@ read_pipe(int fd_pipe[2][2], int type)
{
char buffer[4096];
ssize_t count;
int error;
struct timeval timeout;
fd_set read_fds;
int error, res;

while (1) {
count = read(fd_pipe[type][0], buffer, sizeof(buffer));
if (count == -1) {
error = errno;
if (error == EINTR)
timeout.tv_sec = config_get_rsync_transfer_timeout();
timeout.tv_usec = 0;

FD_ZERO(&read_fds);
FD_SET(fd_pipe[type][0], &read_fds);

res = select(fd_pipe[type][0] + 1, &read_fds, NULL, NULL, &timeout);
if (res == 0) {
pr_val_err("rsync transfer timeout reached");
close(fd_pipe[type][0]);
return 1;
} else if (res < 0) {
if (res == EINTR)
continue;
close(fd_pipe[type][0]); /* Close read end */
pr_val_err("rsync buffer read error: %s",
strerror(error));
return -error;
close(fd_pipe[type][0]);
return 1;
} else {
count = read(fd_pipe[type][0], buffer, sizeof(buffer));
if (count == -1) {
error = errno;
if (error == EINTR)
continue;
close(fd_pipe[type][0]); /* Close read end */
pr_val_err("rsync buffer read error: %s",
strerror(error));
return -error;
}
if (count == 0)
break;
}
if (count == 0)
break;

log_buffer(buffer, count, type);
}
Expand Down Expand Up @@ -276,7 +296,7 @@ rsync_download(char const *src, char const *dst, bool is_directory)
/* This code is run by us. */
error = read_pipes(fork_fds);
if (error)
kill(child_pid, SIGCHLD); /* Stop the child */
kill(child_pid, SIGTERM); /* Stop the child */

error = waitpid(child_pid, &child_status, 0);
do {
Expand Down

0 comments on commit a51ba5a

Please sign in to comment.