summary history branches tags files
commit:62f49120268a731385a84fd5c28311601fca4ebe
author:Trevor Bentley
committer:Trevor Bentley
date:Sat May 25 15:31:09 2019 +0200
parents:81c681c0a11e3f4d2d101df835be4a764e0b50f9
Clean up and document C client/server example
diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt
line changes: +1/-1
index 5b5c4dd..880c3f4
--- a/examples/CMakeLists.txt
+++ b/examples/CMakeLists.txt
@@ -1,7 +1,7 @@
 cmake_minimum_required(VERSION 3.12)
 project(ffi C)
 
-set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -flto -O3")
+set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -flto -O0 -g")
 
 add_executable (ffi ffi.c)
 target_include_directories (ffi PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../ffi)

diff --git a/examples/client.c b/examples/client.c
line changes: +72/-44
index 82a28fc..6ca25bb
--- a/examples/client.c
+++ b/examples/client.c
@@ -1,3 +1,14 @@
+// client.c
+//
+// Example of using Ossuary as a client in C
+//
+// This is the client half of a C client/server example for Ossuary.
+// Run the server first, then run this client to send encrypted messages
+// one way from client to server.
+//
+// The purpose of this example is to show the Ossuary FFI API, and demonstrate
+// how it sits 'in between' the read and write calls of a TCP connection.
+//
 #include <stdio.h>
 #include <stdint.h>
 #include <stdlib.h>
@@ -11,6 +22,8 @@
 #include <arpa/inet.h>
 #include "ossuary.h"
 
+int net_connect();
+
 uint8_t secret_key[] = {
   0x10, 0x86, 0x6e, 0xc4, 0x8a, 0x11, 0xf3, 0xc5,
   0x6d, 0x77, 0xa6, 0x4b, 0x2f, 0x54, 0xaa, 0x06,
@@ -26,92 +39,75 @@ uint8_t public_key[32] = {
 };
 
 int main(int argc, char **argv) {
-  uint8_t read_buf[1024];
-  uint8_t write_buf[1024];
-  struct sockaddr_in addr;
-  struct in_addr inaddr;
+  uint8_t read_buf[1024];  // data received from network socket
+  uint8_t write_buf[1024]; // data to send on network socket
+  uint8_t text_buf[1024];  // data received and decrypted by ossuary
   OssuaryConnection *client_conn = NULL;
   int sock;
-  int flags;
   int read_len;
   int handshake;
   uint16_t read_buf_len;
   uint16_t write_buf_len;
-  printf("Connecting to localhost port 9981...\n");
-  if ((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
-    fprintf(stderr, "ERROR: could not create IPv4 socket\n");
-    exit(1);
-  }
-  memset(&addr, 0, sizeof(struct sockaddr_in));
-  addr.sin_family = AF_INET;
-  addr.sin_port = htons(9981);
-  inaddr.s_addr = inet_addr("127.0.0.1");
-  addr.sin_addr = inaddr;
+  uint16_t text_buf_len;
 
-  if (connect(sock, (const struct sockaddr*)&addr, sizeof(struct sockaddr_in)) < 0) {
-    fprintf(stderr, "ERROR: could not connect to 127.0.0.1:9981\n");
-    exit(1);
-  }
+  // Wait for a TCP connection from a client
+  sock = net_connect();
 
+  // Create an Ossuary client
   if ((client_conn = ossuary_create_connection(OSSUARY_CONN_TYPE_CLIENT, NULL)) == NULL) {
     fprintf(stderr, "ERROR: could not create Ossuary connection\n");
     exit(1);
   }
   ossuary_add_authorized_key(client_conn, public_key);
 
-  flags = fcntl(sock, F_GETFL, 0);
-  if (fcntl(sock, F_SETFL, flags | O_NONBLOCK) < 0) {
-    fprintf(stderr, "ERROR: could not set non-blocking\n");
-    exit(1);
-  }
-
-  printf("Connected!\n");
   while (1) {
+    // Read from network socket
     if ((read_len = read(sock, read_buf, sizeof(read_buf))) <= 0) {
       if (errno != EAGAIN) {
         fprintf(stderr, "ERROR: read failed: %d\n", read_len);
         exit(1);
       }
+      read_len = 0;
     }
+    read_buf_len += read_len;
 
+    // Ossuary handshake
     if ((handshake = ossuary_handshake_done(client_conn)) == 0) {
       write_buf_len = sizeof(write_buf);
+      // Check if we have any handshake packets to send
       if (ossuary_send_handshake(client_conn, write_buf, &write_buf_len) < 0) {
         fprintf(stderr, "ERROR: handshake send failed\n");
         exit(1);
       }
-      if (read_len > 0) {
-        read_buf_len = read_len;
-        if (ossuary_recv_handshake(client_conn, read_buf, &read_buf_len) < 0) {
+      // Check if we have any received handshake packets to parse
+      if (read_buf_len > 0) {
+        read_len = read_buf_len;
+        if (ossuary_recv_handshake(client_conn, read_buf, (uint16_t*)&read_len) < 0) {
           fprintf(stderr, "ERROR: handshake recv failed\n");
           exit(1);
         }
-        memmove(read_buf, read_buf + read_buf_len, read_len - read_buf_len);
-        read_buf_len = 0;
+        // Consume bytes from read_buf
+        memmove(read_buf, read_buf + read_len, read_buf_len - read_len);
+        read_buf_len -= read_len;
       }
     }
+    // Ossuary handshake failed
     else if (handshake < 0) {
       fprintf(stderr, "ERROR: handshake failed: %d\n", handshake);
       exit(1);
     }
+    // Ossuary data exchange over established connection
     else {
-      if (read_len > 0) {
-        write_buf_len = 0;
-        if (ossuary_recv_data(client_conn, read_buf, read_buf_len, write_buf, &write_buf_len) > 0) {
-          memmove(read_buf, read_buf + read_buf_len, read_len - read_buf_len);
-          read_buf_len = 0;
-          printf("Received %d encrypted bytes\n", read_len);
-          write_buf_len = 0;
-        }
-      }
+      // Ask for a message from the user and encrypt it with Ossuary
       printf("Enter message: ");
-      read_buf[0] = 0;
-      gets((char *)read_buf);
-      read_buf_len = strlen((char *)read_buf) + 1;
+      text_buf[0] = 0;
+      gets((char *)text_buf);
+      text_buf_len = strlen((char *)text_buf) + 1;
       write_buf_len = sizeof(write_buf);
-      ossuary_send_data(client_conn, read_buf, read_buf_len, write_buf, &write_buf_len);
+      ossuary_send_data(client_conn, text_buf, text_buf_len, write_buf, &write_buf_len);
     }
 
+    // Write any encrypted messages generated by Ossuary
     if (write_buf_len > 0) {
       if (write(sock, write_buf, write_buf_len) != write_buf_len) {
         fprintf(stderr, "ERROR: write failed\n");
@@ -124,3 +120,35 @@ int main(int argc, char **argv) {
   close(sock);
 
 }
+
+int net_connect() {
+  struct sockaddr_in addr;
+  struct in_addr inaddr;
+  int sock;
+  int flags;
+
+  printf("Connecting to localhost port 9981...\n");
+  if ((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
+    fprintf(stderr, "ERROR: could not create IPv4 socket\n");
+    exit(1);
+  }
+  memset(&addr, 0, sizeof(struct sockaddr_in));
+  addr.sin_family = AF_INET;
+  addr.sin_port = htons(9981);
+  inaddr.s_addr = inet_addr("127.0.0.1");
+  addr.sin_addr = inaddr;
+
+  if (connect(sock, (const struct sockaddr*)&addr, sizeof(struct sockaddr_in)) < 0) {
+    fprintf(stderr, "ERROR: could not connect to 127.0.0.1:9981\n");
+    exit(1);
+  }
+
+  flags = fcntl(sock, F_GETFL, 0);
+  if (fcntl(sock, F_SETFL, flags | O_NONBLOCK) < 0) {
+    fprintf(stderr, "ERROR: could not set non-blocking\n");
+    exit(1);
+  }
+
+  printf("Connected!\n");
+  return sock;
+}

diff --git a/examples/server.c b/examples/server.c
line changes: +96/-56
index d77c187..ebc2816
--- a/examples/server.c
+++ b/examples/server.c
@@ -1,3 +1,14 @@
+// server.c
+//
+// Example of using Ossuary as a server in C
+//
+// This is the server half of a C client/server example for Ossuary.
+// Run this server first, then run the client to send encrypted messages
+// one way from client to server.
+//
+// The purpose of this example is to show the Ossuary FFI API, and demonstrate
+// how it sits 'in between' the read and write calls of a TCP connection.
+//
 #include <stdio.h>
 #include <stdint.h>
 #include <stdlib.h>
@@ -10,6 +21,8 @@
 #include <netinet/in.h>
 #include "ossuary.h"
 
+int net_connect();
+
 uint8_t secret_key[] = {
   0x10, 0x86, 0x6e, 0xc4, 0x8a, 0x11, 0xf3, 0xc5,
   0x6d, 0x77, 0xa6, 0x4b, 0x2f, 0x54, 0xaa, 0x06,
@@ -25,97 +38,79 @@ uint8_t public_key[32] = {
 };
 
 int main(int argc, char **argv) {
-  uint8_t read_buf[1024];
-  uint8_t write_buf[1024];
-  struct sockaddr_in addr;
-  struct in_addr inaddr;
-  socklen_t addr_len;
+  uint8_t read_buf[1024];  // data received from network socket
+  uint8_t write_buf[1024]; // data to send on network socket
+  uint8_t text_buf[1024];  // data received and decrypted by ossuary
   OssuaryConnection *server_conn = NULL;
-  int sock;
-  int conn;
-  int flags;
-  int client;
   int read_len;
-  uint16_t read_buf_len;
-  uint16_t write_buf_len;
-  printf("Starting on localhost port 9981...\n");
-  if ((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
-    fprintf(stderr, "ERROR: could not create IPv4 socket\n");
-    exit(1);
-  }
-  memset(&addr, 0, sizeof(struct sockaddr_in));
-  addr.sin_family = AF_INET;
-  addr.sin_port = htons(9981);
-  inaddr.s_addr = 0;
-  addr.sin_addr = inaddr;
+  int client;
+  int handshake;
+  uint16_t read_buf_len = 0;
+  uint16_t write_buf_len = 0;
+  uint16_t text_buf_len = 0;
 
-  if ((conn = bind(sock, (const struct sockaddr*)&addr, sizeof(struct sockaddr_in))) < 0) {
-    fprintf(stderr, "ERROR: could not bind to 127.0.0.1:9981\n");
-    exit(1);
-  }
-  if (listen(sock, 3) < 0) {
-    fprintf(stderr, "ERROR: could not listen on 127.0.0.1:9981\n");
-    exit(1);
-  }
-  addr_len = sizeof(struct sockaddr_in);
-  if ((client = accept(sock, (struct sockaddr*)&addr, &addr_len)) < 0) {
-    fprintf(stderr, "ERROR: could not listen on 127.0.0.1:9981\n");
-    exit(1);
-  }
+  // Wait for a TCP connection from a client
+  client = net_connect();
 
+  // Create an Ossuary server
   if ((server_conn = ossuary_create_connection(OSSUARY_CONN_TYPE_UNAUTHENTICATED_SERVER, NULL)) == NULL) {
     fprintf(stderr, "ERROR: could not create Ossuary connection\n");
     exit(1);
   }
   ossuary_set_secret_key(server_conn, secret_key);
 
-  flags = fcntl(client, F_GETFL, 0);
-  if (fcntl(client, F_SETFL, flags | O_NONBLOCK) < 0) {
-    fprintf(stderr, "ERROR: could not set non-blocking\n");
-    exit(1);
-  }
-
-  printf("Connected!\n");
   while (1) {
-    if ((read_len = read(client, read_buf, sizeof(read_buf))) <= 0) {
+    // Read from network socket
+    if ((read_len = read(client, read_buf + read_buf_len, sizeof(read_buf) - read_buf_len)) <= 0) {
       if (errno != EAGAIN) {
         fprintf(stderr, "ERROR: read failed\n");
         exit(1);
       }
+      read_len = 0;
     }
+    read_buf_len += read_len;
 
-    if (ossuary_handshake_done(server_conn) == 0) {
+    // Ossuary handshake
+    if ((handshake = ossuary_handshake_done(server_conn)) == 0) {
       write_buf_len = sizeof(write_buf);
+      // Check if we have any handshake packets to send
       if (ossuary_send_handshake(server_conn, write_buf, &write_buf_len) < 0) {
         fprintf(stderr, "ERROR: handshake send failed\n");
         exit(1);
       }
-      if (read_len > 0) {
-        read_buf_len = read_len;
-        if (ossuary_recv_handshake(server_conn, read_buf, &read_buf_len) < 0) {
+      // Check if we have any received handshake packets to parse
+      if (read_buf_len > 0) {
+        read_len = read_buf_len;
+        if (ossuary_recv_handshake(server_conn, read_buf, (uint16_t*)&read_len) < 0) {
           fprintf(stderr, "ERROR: handshake recv failed\n");
           exit(1);
         }
-        memmove(read_buf, read_buf + read_buf_len, read_len - read_buf_len);
-        read_buf_len = 0;
+        // Consume bytes from read_buf
+        memmove(read_buf, read_buf + read_len, read_buf_len - read_len);
+        read_buf_len -= read_len;
       }
     }
+    // Ossuary handshake failed
+    else if (handshake < 0) {
+      fprintf(stderr, "ERROR: handshake failed: %d\n", handshake);
+      exit(1);
+    }
+    // Ossuary data exchange over established connection
     else {
-      if (read_len > 0) {
-        read_buf_len += read_len;
-        write_buf_len = sizeof(write_buf);
-        if ((read_len = ossuary_recv_data(server_conn, read_buf, read_buf_len, write_buf, &write_buf_len)) > 0) {
+      // If data has been received, decrypt and print it.
+      if (read_buf_len > 0) {
+        text_buf_len = sizeof(text_buf);
+        if ((read_len = ossuary_recv_data(server_conn, read_buf, read_buf_len, text_buf, &text_buf_len)) > 0) {
           memmove(read_buf, read_buf + read_len, read_buf_len - read_len);
           read_buf_len -= read_len;
-          if (write_buf_len > 0) {
-            printf("MSG: %s\n", write_buf);
+          if (text_buf_len > 0) {
+            printf("MSG: %s\n", text_buf);
           }
-          write_buf_len = 0;
-          read_len = 0;
         }
       }
     }
 
+    // Write any encrypted messages generated by Ossuary
     if (write_buf_len) {
       if (write(client, write_buf, write_buf_len) != write_buf_len) {
         fprintf(stderr, "ERROR: write failed\n");
@@ -126,5 +121,50 @@ int main(int argc, char **argv) {
   }
 
   close(client);
+}
+
+int net_connect() {
+  struct sockaddr_in addr;
+  struct in_addr inaddr;
+  socklen_t addr_len;
+  int sock;
+  int conn;
+  int flags;
+  int client;
+
+  printf("Starting on localhost port 9981...\n");
+  if ((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
+    fprintf(stderr, "ERROR: could not create IPv4 socket\n");
+    exit(1);
+  }
+  memset(&addr, 0, sizeof(struct sockaddr_in));
+  addr.sin_family = AF_INET;
+  addr.sin_port = htons(9981);
+  inaddr.s_addr = 0;
+  addr.sin_addr = inaddr;
+
+  if ((conn = bind(sock, (const struct sockaddr*)&addr, sizeof(struct sockaddr_in))) < 0) {
+    fprintf(stderr, "ERROR: could not bind to 127.0.0.1:9981\n");
+    exit(1);
+  }
+  if (listen(sock, 3) < 0) {
+    fprintf(stderr, "ERROR: could not listen on 127.0.0.1:9981\n");
+    exit(1);
+  }
+  addr_len = sizeof(struct sockaddr_in);
+  printf("Waiting for client...\n");
+  if ((client = accept(sock, (struct sockaddr*)&addr, &addr_len)) < 0) {
+    fprintf(stderr, "ERROR: could not listen on 127.0.0.1:9981\n");
+    exit(1);
+  }
+
+  flags = fcntl(client, F_GETFL, 0);
+  if (fcntl(client, F_SETFL, flags | O_NONBLOCK) < 0) {
+    fprintf(stderr, "ERROR: could not set non-blocking\n");
+    exit(1);
+  }
+
   close(sock);
+  printf("Client connected!\n");
+  return client;
 }