[PATCH] lib: Return number of written bytes on flow_write

  • From: Dimitri Staessens <dimitri@ouroboros.rocks>
  • To: ouroboros@xxxxxxxxxxxxx
  • Date: Sat, 14 Mar 2020 17:52:06 +0100

This is more in line with the write() system call and prepares for
partial writes. Partial writes are disabled by default (and not yet
implemented).

Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks>
---
 doc/man/fccntl.3               |  5 ++++-
 doc/man/flow_read.3            | 22 ++++++++++++----------
 include/ouroboros/fccntl.h     | 19 ++++++++++---------
 src/ipcpd/broadcast/enroll.c   |  6 +++---
 src/ipcpd/unicast/enroll.c     |  6 +++---
 src/lib/dev.c                  |  5 ++---
 src/tools/obc/obc.c            |  5 +++--
 src/tools/ocbr/ocbr_client.c   |  2 +-
 src/tools/oecho/oecho.c        |  6 +++---
 src/tools/operf/operf_client.c |  4 ++--
 src/tools/oping/oping_client.c |  2 +-
 src/tools/ovpn/ovpn.c          |  2 +-
 12 files changed, 45 insertions(+), 39 deletions(-)

diff --git a/doc/man/fccntl.3 b/doc/man/fccntl.3
index b0f1b3f..87e2307 100644
--- a/doc/man/fccntl.3
+++ b/doc/man/fccntl.3
@@ -60,7 +60,10 @@ argument. Supported flags are:
 
 \fIFLOWFRNOPART\fR  - disable partial reading.
 
-\fIFLOWFDEFAULT\fR  - set flow defaults (blocking, read-write).
+\fIFLOWFWNOPART\fR  - disable partial writing.
+
+\fIFLOWFDEFAULT\fR  - set flow defaults (blocking, read-write,
+no partial writes).
 
 .RE
 
diff --git a/doc/man/flow_read.3 b/doc/man/flow_read.3
index 655f50b..1a6c8ea 100644
--- a/doc/man/flow_read.3
+++ b/doc/man/flow_read.3
@@ -12,9 +12,9 @@ flow_read, flow_write \- read and write from/to a flow
 
 .B #include <ouroboros/dev.h>
 
-\fBint flow_read(int \fIfd\fB, void * \fIbuf\fB, size_t \fIcount\fB);\fR
+\fBssize_t flow_read(int \fIfd\fB, void * \fIbuf\fB, size_t \fIcount\fB);\fR
 
-\fBint flow_write(int \fIfd\fB, const void * \fIbuf\fB, size_t \fIcount\fB);\fR
+\fBssize_t flow_write(int \fIfd\fB, const void * \fIbuf\fB, size_t 
\fIcount\fB);\fR
 
 Compile and link with \fI-louroboros-dev\fR.
 
@@ -30,15 +30,17 @@ from the supplied buffer \fIbuf\fR to the flow specified by 
\fIfd\fR.
 .SH RETURN VALUE
 
 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.
+failure, a negative value indicating the error will be
+returned. Partial reads are enabled by default. 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.
 
-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.
+On success, \fBflow_write\fR() returns the number of bytes written. On
+failure, a negative value indicating the error will be returned.
+Partial writes needs to be explicitly enabled. Passing a
+NULL pointer for \fIbuf\fR returns 0 with no other effects.
 
 .SH ERRORS
 .B -EINVAL
diff --git a/include/ouroboros/fccntl.h b/include/ouroboros/fccntl.h
index fac9013..965e281 100644
--- a/include/ouroboros/fccntl.h
+++ b/include/ouroboros/fccntl.h
@@ -28,19 +28,20 @@
 #include <sys/time.h>
 
 /* Flow flags, same values as fcntl.h */
-#define FLOWFRDONLY   00000000 /* Read-only flow        */
-#define FLOWFWRONLY   00000001 /* Write-only flow       */
-#define FLOWFRDWR     00000002 /* Read-write flow       */
-#define FLOWFACCMODE  00000003 /* Access mask           */
+#define FLOWFRDONLY   00000000 /* Read-only flow         */
+#define FLOWFWRONLY   00000001 /* Write-only flow        */
+#define FLOWFRDWR     00000002 /* Read-write flow        */
+#define FLOWFACCMODE  00000003 /* Access mask            */
 
-#define FLOWFDOWN     00000004 /* Flow is down          */
+#define FLOWFDOWN     00000004 /* Flow is down           */
 
-#define FLOWFRNOBLOCK 00001000 /* Non-blocking read     */
-#define FLOWFWNOBLOCK 00002000 /* Non-blocking write    */
+#define FLOWFRNOBLOCK 00001000 /* Non-blocking read      */
+#define FLOWFWNOBLOCK 00002000 /* Non-blocking write     */
 #define FLOWFNONBLOCK (FLOWFRNOBLOCK | FLOWFWNOBLOCK)
-#define FLOWFRNOPART  00004000 /* Disable partial reads */
+#define FLOWFRNOPART  00010000 /* Disable partial reads  */
+#define FLOWFWNOPART  00020000 /* Disable partial writes */
 
-#define FLOWFDEFAULT  FLOWFRDWR
+#define FLOWFDEFAULT  (FLOWFRDWR | FLOWFWNOPART)
 
 #define FLOWFINVALID  (FLOWFWRONLY | FLOWFRDWR)
 
diff --git a/src/ipcpd/broadcast/enroll.c b/src/ipcpd/broadcast/enroll.c
index 36b82af..511892b 100644
--- a/src/ipcpd/broadcast/enroll.c
+++ b/src/ipcpd/broadcast/enroll.c
@@ -87,7 +87,7 @@ static int send_rcv_enroll_msg(int fd)
 
         clock_gettime(CLOCK_REALTIME, &t0);
 
-        if (flow_write(fd, buf, len)) {
+        if (flow_write(fd, buf, len) < 0) {
                 log_dbg("Failed to send request message.");
                 return -1;
         }
@@ -222,7 +222,7 @@ static void * enroll_handle(void * o)
 
                 log_dbg("Sending enrollment info (%zd bytes).", len);
 
-                if (flow_write(conn.flow_info.fd, reply, len)) {
+                if (flow_write(conn.flow_info.fd, reply, len) < 0) {
                         log_err("Failed respond to enrollment request.");
                         connmgr_dealloc(COMPID_ENROLL, &conn);
                         free(reply);
@@ -296,7 +296,7 @@ int enroll_done(struct conn * conn,
 
         enroll_msg__pack(&msg, buf);
 
-        if (flow_write(conn->flow_info.fd, buf, len)) {
+        if (flow_write(conn->flow_info.fd, buf, len) < 0) {
                 log_dbg("Failed to send acknowledgment.");
                 return -1;
         }
diff --git a/src/ipcpd/unicast/enroll.c b/src/ipcpd/unicast/enroll.c
index 6a612ff..3b4a5a8 100644
--- a/src/ipcpd/unicast/enroll.c
+++ b/src/ipcpd/unicast/enroll.c
@@ -87,7 +87,7 @@ static int send_rcv_enroll_msg(int fd)
 
         clock_gettime(CLOCK_REALTIME, &t0);
 
-        if (flow_write(fd, buf, len)) {
+        if (flow_write(fd, buf, len) < 0) {
                 log_dbg("Failed to send request message.");
                 return -1;
         }
@@ -238,7 +238,7 @@ static void * enroll_handle(void * o)
 
                 log_dbg("Sending enrollment info (%zd bytes).", len);
 
-                if (flow_write(conn.flow_info.fd, reply, len)) {
+                if (flow_write(conn.flow_info.fd, reply, len) < 0) {
                         log_err("Failed respond to enrollment request.");
                         connmgr_dealloc(COMPID_ENROLL, &conn);
                         free(reply);
@@ -312,7 +312,7 @@ int enroll_done(struct conn * conn,
 
         enroll_msg__pack(&msg, buf);
 
-        if (flow_write(conn->flow_info.fd, buf, len)) {
+        if (flow_write(conn->flow_info.fd, buf, len) < 0) {
                 log_dbg("Failed to send acknowledgment.");
                 return -1;
         }
diff --git a/src/lib/dev.c b/src/lib/dev.c
index c427e20..e9145fc 100644
--- a/src/lib/dev.c
+++ b/src/lib/dev.c
@@ -1007,6 +1007,7 @@ ssize_t flow_write(int          fd,
         if ((flags & FLOWFACCMODE) == FLOWFRDONLY)
                 return -EPERM;
 
+        /* TODO: partial writes. */
         if (flags & FLOWFWNOBLOCK)
                 idx = shm_rdrbuff_alloc(ai.rdrb,
                                         count,
@@ -1056,9 +1057,7 @@ ssize_t flow_write(int          fd,
 
         pthread_rwlock_unlock(&ai.lock);
 
-        assert(ret <= 0);
-
-        return ret;
+        return ret < 0 ? (ssize_t) ret : (ssize_t) count;
 }
 
 ssize_t flow_read(int    fd,
diff --git a/src/tools/obc/obc.c b/src/tools/obc/obc.c
index eb5a42c..256cb84 100644
--- a/src/tools/obc/obc.c
+++ b/src/tools/obc/obc.c
@@ -88,7 +88,8 @@ static int reader_main(const char * dst)
 static int writer_main(const char * dst,
                        const char * message)
 {
-        int     fd      = 0;
+        int     fd  = 0;
+        size_t  len = strlen(message) + 1;
 
         fd = flow_join(dst, NULL, NULL);
         if (fd < 0) {
@@ -96,7 +97,7 @@ static int writer_main(const char * dst,
                 return -1;
         }
 
-        if (flow_write(fd, message, strlen(message) + 1) < 0) {
+        if (flow_write(fd, message, len) < 0) {
                 printf("Failed to write packet.\n");
                 flow_dealloc(fd);
                 return -1;
diff --git a/src/tools/ocbr/ocbr_client.c b/src/tools/ocbr/ocbr_client.c
index 6381a23..6120e1f 100644
--- a/src/tools/ocbr/ocbr_client.c
+++ b/src/tools/ocbr/ocbr_client.c
@@ -135,7 +135,7 @@ int client_main(char * server,
         } else { /* flood */
                 while (!stop) {
                         clock_gettime(CLOCK_REALTIME, &end);
-                        if (flow_write(fd, buf, (size_t) size) < 0) {
+                        if (flow_write(fd, buf, size) < 0) {
                                 stop = true;
                                 continue;
                         }
diff --git a/src/tools/oecho/oecho.c b/src/tools/oecho/oecho.c
index f52f53d..a44b8b7 100644
--- a/src/tools/oecho/oecho.c
+++ b/src/tools/oecho/oecho.c
@@ -79,7 +79,7 @@ static int server_main(void)
 
                 printf("Message from client is %.*s.\n", (int) count, buf);
 
-                if (flow_write(fd, buf, count) == -1) {
+                if (flow_write(fd, buf, count) < 0) {
                         printf("Failed to write packet.\n");
                         flow_dealloc(fd);
                         continue;
@@ -93,10 +93,10 @@ static int server_main(void)
 
 static int client_main(void)
 {
-        int     fd      = 0;
+        int     fd;
         char    buf[BUF_SIZE];
         char *  message = "Client says hi!";
-        ssize_t count   = 0;
+        ssize_t count;
 
         fd = flow_alloc("oecho", NULL, NULL);
         if (fd < 0) {
diff --git a/src/tools/operf/operf_client.c b/src/tools/operf/operf_client.c
index 3b0ff2a..004a896 100644
--- a/src/tools/operf/operf_client.c
+++ b/src/tools/operf/operf_client.c
@@ -141,7 +141,7 @@ void * writer(void * o)
 
                 msg->id = client.sent;
 
-                if (flow_write(*fdp, buf, client.size) == -1) {
+                if (flow_write(*fdp, buf, client.size) < 0) {
                         printf("Failed to send packet.\n");
                         flow_dealloc(*fdp);
                         free(buf);
@@ -204,7 +204,7 @@ int client_main(void)
         else
                 printf("Doing a unidirectional test.\n");
 
-        if (flow_write(fd, &client.conf, sizeof(client.conf))) {
+        if (flow_write(fd, &client.conf, sizeof(client.conf)) < 0) {
                 printf("Failed to send configuration.\n");
                 flow_dealloc(fd);
                 return -1;
diff --git a/src/tools/oping/oping_client.c b/src/tools/oping/oping_client.c
index aa92be5..d0255b7 100644
--- a/src/tools/oping/oping_client.c
+++ b/src/tools/oping/oping_client.c
@@ -175,7 +175,7 @@ void * writer(void * o)
                 msg->tv_sec = now.tv_sec;
                 msg->tv_nsec = now.tv_nsec;
 
-                if (flow_write(*fdp, buf, client.size) == -1) {
+                if (flow_write(*fdp, buf, client.size) < 0) {
                         printf("Failed to send packet.\n");
                         flow_dealloc(*fdp);
                         free(buf);
diff --git a/src/tools/ovpn/ovpn.c b/src/tools/ovpn/ovpn.c
index a3dd2ec..02501d5 100644
--- a/src/tools/ovpn/ovpn.c
+++ b/src/tools/ovpn/ovpn.c
@@ -163,7 +163,7 @@ void * t_reader(void * o)
                 if (len <= 0)
                         continue;
 
-                if (flow_write(o_fd, buf, len))
+                if (flow_write(o_fd, buf, len) < 0)
                         continue;
         }
 }
-- 
2.25.1


Other related posts:

  • » [PATCH] lib: Return number of written bytes on flow_write - Dimitri Staessens