summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDimitri Staessens <dimitri.staessens@ugent.be>2018-03-17 14:55:46 +0100
committerSander Vrijders <sander.vrijders@ugent.be>2018-03-19 10:29:21 +0100
commit4230103ff633904c69cc18d861bf42781f57bb64 (patch)
tree9b21ca4a648456863af30e21ea4c7b55ba3ddf77
parentc9747304271f63064687178938bf2a4060ef0180 (diff)
downloadouroboros-4230103ff633904c69cc18d861bf42781f57bb64.tar.gz
ouroboros-4230103ff633904c69cc18d861bf42781f57bb64.zip
lib: Allow disabling partial read
This allows disabling partial reads. It adds a flag FLOWFRNOPART that disables partial reads. Partial read is different from partial delivery (FRCTFPARTIAL), which allows delivery of fragments of an incomplete packet and thus potentially corrupted data. FLOWFRNOPART will never deliver corrupted data (unless FRCTFPARTIAL is also set). If FLOWFRNOPART is set and the buffer provided to flow_read is too small for the SDU, that SDU will be discarded and -EMSGSIZE is returned; Signed-off-by: Dimitri Staessens <dimitri.staessens@ugent.be> Signed-off-by: Sander Vrijders <sander.vrijders@ugent.be>
-rw-r--r--doc/man/fccntl.32
-rw-r--r--doc/man/flow_read.35
-rw-r--r--include/ouroboros/fccntl.h1
-rw-r--r--src/ipcpd/normal/pol/link_state.c8
-rw-r--r--src/lib/dev.c20
5 files changed, 25 insertions, 11 deletions
diff --git a/doc/man/fccntl.3 b/doc/man/fccntl.3
index 34e63e7d..bec506ec 100644
--- a/doc/man/fccntl.3
+++ b/doc/man/fccntl.3
@@ -58,6 +58,8 @@ argument. Supported flags are:
\fIFLOWFNONBLOCK\fR - set I/O to non-blocking read/write.
+\fIFLOWFRNOPART\fR - disable partial reading.
+
\fIFLOWFDEFAULT\fR - set flow defaults (blocking, read-write).
.RE
diff --git a/doc/man/flow_read.3 b/doc/man/flow_read.3
index 0110d0a2..20f5b976 100644
--- a/doc/man/flow_read.3
+++ b/doc/man/flow_read.3
@@ -33,15 +33,14 @@ On success, \fBflow_read\fR() returns the number of bytes read. On
failure, a negative value indicating the error will be returned. If
the number of bytes read equals count, a subsequent call to
\fBflow_read\fR() should be performed to check if there were more
-bytes to read. This call to \fBflow_read\fR will return 0 if there
-was no more data and mark the end of the datagram.
+bytes to read. This call to \fBflow_read\fR will return 0 if there was
+no more data and mark the end of the datagram.
On success, \fBflow_write\fR() returns 0. On failure, a negative value
indicating the error will be returned. Passing a NULL pointer for
\fIbuf\fR returns 0 with no other effects.
.SH ERRORS
-
.B -EINVAL
An invalid argument was passed.
diff --git a/include/ouroboros/fccntl.h b/include/ouroboros/fccntl.h
index 8940e6ef..5c3fc064 100644
--- a/include/ouroboros/fccntl.h
+++ b/include/ouroboros/fccntl.h
@@ -38,6 +38,7 @@
#define FLOWFRNOBLOCK 00001000 /* Non-blocking read */
#define FLOWFWNOBLOCK 00002000 /* Non-blocking write */
#define FLOWFNONBLOCK (FLOWFRNOBLOCK | FLOWFWNOBLOCK)
+#define FLOWFRNOPART 00004000 /* Disable partial reads */
#define FLOWFDEFAULT FLOWFRDWR
diff --git a/src/ipcpd/normal/pol/link_state.c b/src/ipcpd/normal/pol/link_state.c
index 7aa7faf7..cfe4faff 100644
--- a/src/ipcpd/normal/pol/link_state.c
+++ b/src/ipcpd/normal/pol/link_state.c
@@ -29,6 +29,7 @@
#include <ouroboros/endian.h>
#include <ouroboros/dev.h>
#include <ouroboros/errno.h>
+#include <ouroboros/fccntl.h>
#include <ouroboros/fqueue.h>
#include <ouroboros/list.h>
#include <ouroboros/logs.h>
@@ -655,7 +656,7 @@ static void * lsreader(void * o)
{
fqueue_t * fq;
int ret;
- uint8_t buf[sizeof(struct lsa) + 1];
+ uint8_t buf[sizeof(struct lsa)];
int fd;
qosspec_t qs;
struct lsa * msg;
@@ -680,7 +681,7 @@ static void * lsreader(void * o)
}
while ((fd = fqueue_next(fq)) >= 0) {
- len = flow_read(fd, buf, sizeof(*msg) + 1);
+ len = flow_read(fd, buf, sizeof(*msg));
if (len <= 0 || len != sizeof(*msg))
continue;
@@ -724,6 +725,7 @@ static void handle_event(void * self,
/* FIXME: Apply correct QoS on graph */
struct conn * c;
qosspec_t qs;
+ int flags;
(void) self;
@@ -759,6 +761,8 @@ static void handle_event(void * self,
flow_event(c->flow_info.fd, false);
break;
case NOTIFY_MGMT_CONN_ADD:
+ fccntl(c->flow_info.fd, FLOWGFLAGS, &flags);
+ fccntl(c->flow_info.fd, FLOWSFLAGS, flags | FLOWFRNOPART);
fset_add(ls.mgmt_set, c->flow_info.fd);
if (lsdb_add_nb(c->conn_info.addr, c->flow_info.fd, NB_MGMT))
log_warn("Failed to add mgmt neighbor to LSDB.");
diff --git a/src/lib/dev.c b/src/lib/dev.c
index 115cd565..d0766783 100644
--- a/src/lib/dev.c
+++ b/src/lib/dev.c
@@ -897,6 +897,7 @@ ssize_t flow_read(int fd,
struct timespec * abstime = NULL;
struct flow * flow;
bool noblock;
+ bool partrd;
if (fd < 0 || fd > PROG_MAX_FLOWS)
return -EBADF;
@@ -919,6 +920,7 @@ ssize_t flow_read(int fd,
rb = flow->rx_rb;
noblock = flow->oflags & FLOWFRNOBLOCK;
+ partrd = !(flow->oflags & FLOWFRNOPART);
if (ai.flows[fd].rcv_timesout) {
ts_add(&abs, &flow->rcv_timeo, &abs);
@@ -948,14 +950,20 @@ ssize_t flow_read(int fd,
if (n <= (ssize_t) count) {
memcpy(buf, sdu, n);
shm_rdrbuff_remove(ai.rdrb, idx);
- flow->part_idx = (n == (ssize_t) count) ? DONE_PART : NO_PART;
+ flow->part_idx = (partrd && n == (ssize_t) count) ?
+ DONE_PART : NO_PART;
return n;
} else {
- memcpy(buf, sdu, count);
- sdb = shm_rdrbuff_get(ai.rdrb, idx);
- shm_du_buff_head_release(sdb, n);
- flow->part_idx = idx;
- return count;
+ if (partrd) {
+ memcpy(buf, sdu, count);
+ sdb = shm_rdrbuff_get(ai.rdrb, idx);
+ shm_du_buff_head_release(sdb, n);
+ flow->part_idx = idx;
+ return count;
+ } else {
+ shm_rdrbuff_remove(ai.rdrb, idx);
+ return -EMSGSIZE;
+ }
}
}