diff options
author | Dimitri Staessens <dimitri.staessens@ugent.be> | 2018-03-17 14:55:46 +0100 |
---|---|---|
committer | Sander Vrijders <sander.vrijders@ugent.be> | 2018-03-19 10:29:21 +0100 |
commit | 4230103ff633904c69cc18d861bf42781f57bb64 (patch) | |
tree | 9b21ca4a648456863af30e21ea4c7b55ba3ddf77 | |
parent | c9747304271f63064687178938bf2a4060ef0180 (diff) | |
download | ouroboros-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.3 | 2 | ||||
-rw-r--r-- | doc/man/flow_read.3 | 5 | ||||
-rw-r--r-- | include/ouroboros/fccntl.h | 1 | ||||
-rw-r--r-- | src/ipcpd/normal/pol/link_state.c | 8 | ||||
-rw-r--r-- | src/lib/dev.c | 20 |
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; + } } } |