]> git.meshlink.io Git - meshlink/commitdiff
Add an example chat program for the C++ API.
authorGuus Sliepen <guus@meshlink.io>
Tue, 10 Jun 2014 11:34:04 +0000 (13:34 +0200)
committerGuus Sliepen <guus@meshlink.io>
Tue, 10 Jun 2014 11:34:04 +0000 (13:34 +0200)
configure.ac
examples/Makefile.am
examples/chatpp.cc [new file with mode: 0644]

index f668719c5d7ed4c2c98537e1f6d7980782faa626..2f1caa68fedc14e811c3fa324190749085253ade 100644 (file)
@@ -15,6 +15,7 @@ AC_DEFINE([__USE_BSD], 1, [Enable BSD extensions])
 
 dnl Checks for programs.
 AC_PROG_CC_C99
+AC_PROG_CXX
 AC_PROG_CPP
 AC_PROG_INSTALL
 AC_PROG_LN_S
index baa03715855ad4bf487dd75944f3c7fcb88e248f..af8f0f45d22cb04319e0f36b4a4f5212c8bf076f 100644 (file)
@@ -1,4 +1,4 @@
-bin_PROGRAMS = meshlinkapp chat
+bin_PROGRAMS = meshlinkapp chat chatpp
 
 AM_CPPFLAGS = -I../src
 
@@ -7,3 +7,6 @@ meshlinkapp_LDADD = ../src/libmeshlink.la
 
 chat_SOURCES = chat.c
 chat_LDADD = ../src/libmeshlink.la
+
+chatpp_SOURCES = chatpp.cc
+chatpp_LDADD = ../src/libmeshlink.la
diff --git a/examples/chatpp.cc b/examples/chatpp.cc
new file mode 100644 (file)
index 0000000..864a3e8
--- /dev/null
@@ -0,0 +1,211 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include "../src/meshlink++.h"
+
+static void log_message(meshlink::mesh *mesh, meshlink::log_level_t level, const char *text) {
+       const char *levelstr[] = {"DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"};
+       fprintf(stderr, "%s: %s\n", levelstr[level], text);
+}
+
+static void receive(meshlink::mesh *mesh, meshlink::node *source, const void *data, size_t len) {
+       const char *msg = (const char *)data;
+
+       if(!len || msg[len - 1]) {
+               fprintf(stderr, "Received invalid data from %s\n", source->name);
+               return;
+       }
+
+       printf("%s says: %s\n", source->name, msg);
+}
+
+static void node_status(meshlink::mesh *mesh, meshlink::node *node, bool reachable) {
+       if(reachable)
+               printf("%s joined.\n", node->name);
+       else
+               printf("%s left.\n", node->name);
+}
+
+static void parse_command(meshlink::mesh *mesh, char *buf) {
+       char *arg = strchr(buf, ' ');
+       if(arg)
+               *arg++ = 0;
+
+       if(!strcasecmp(buf, "invite")) {
+               char *invitation;
+
+               if(!arg) {
+                       fprintf(stderr, "/invite requires an argument!\n");
+                       return;
+               }
+
+               invitation = mesh->invite(arg);
+               if(!invitation) {
+                       fprintf(stderr, "Could not invite '%s': %s\n", arg, mesh->errstr);
+                       return;
+               }
+
+               printf("Invitation for %s: %s\n", arg, invitation);
+               free(invitation);
+       } else if(!strcasecmp(buf, "join")) {
+               if(!arg) {
+                       fprintf(stderr, "/join requires an argument!\n");
+                       return;
+               }
+
+               if(!mesh->join(arg))
+                       fprintf(stderr, "Could not join using invitation: %s\n", mesh->errstr);
+               else
+                       fprintf(stderr, "Invitation accepted!\n");
+       } else if(!strcasecmp(buf, "kick")) {
+               if(!arg) {
+                       fprintf(stderr, "/kick requires an argument!\n");
+                       return;
+               }
+
+               meshlink::node *node = mesh->get_node(arg);
+               if(!node) {
+                       fprintf(stderr, "Unknown node '%s'\n", arg);
+                       return;
+               }
+
+               mesh->blacklist(node);
+
+               printf("Node '%s' blacklisted.\n", arg);
+       } else if(!strcasecmp(buf, "who")) {
+               if(!arg) {
+                       meshlink::node *nodes[100];
+                       size_t n = mesh->get_all_nodes(nodes, 100);
+                       if(!n) {
+                               fprintf(stderr, "No nodes known!\n");
+                       } else {
+                               printf("Known nodes:");
+                               for(int i = 0; i < n && i < 100; i++)
+                                       printf(" %s", nodes[i]->name);
+                               if(n > 100)
+                                       printf(" (and %zu more)", n - 100);
+                               printf("\n");
+                       }
+               } else {
+                       meshlink::node *node = mesh->get_node(arg);
+                       if(!node) {
+                               fprintf(stderr, "Unknown node '%s'\n", arg);
+                       } else {
+                               printf("Node %s found\n", arg);
+                       }
+               }
+       } else if(!strcasecmp(buf, "quit")) {
+               printf("Bye!\n");
+               fclose(stdin);
+       } else if(!strcasecmp(buf, "help")) {
+               printf(
+                       "<name>: <message>     Send a message to the given node.\n"
+                       "                      Subsequent messages don't need the <name>: prefix.\n"
+                       "/invite <name>        Create an invitation for a new node.\n"
+                       "/join <invitation>    Join an existing mesh using an invitation.\n"
+                       "/kick <name>          Blacklist the given node.\n"
+                       "/who [<name>]         List all nodes or show information about the given node.\n"
+                       "/quit                 Exit this program.\n"
+                       );
+       } else {
+               fprintf(stderr, "Unknown command '/%s'\n", buf);
+       }
+}
+
+static void parse_input(meshlink::mesh *mesh, char *buf) {
+       static meshlink::node *destination;
+       size_t len;
+
+       if(!buf)
+               return;
+
+       // Remove newline.
+
+       len = strlen(buf);
+
+       if(len && buf[len - 1] == '\n')
+               buf[--len] = 0;
+
+       if(len && buf[len - 1] == '\r')
+               buf[--len] = 0;
+
+       // Ignore empty lines.
+
+       if(!len)
+               return;
+
+       // Commands start with '/'
+
+       if(*buf == '/')
+               return parse_command(mesh, buf + 1);
+
+       // Lines in the form "name: message..." set the destination node.
+
+       char *msg = buf;
+       char *colon = strchr(buf, ':');
+
+       if(colon) {
+               *colon = 0;
+               msg = colon + 1;
+               if(*msg == ' ')
+                       msg++;
+
+               destination = mesh->get_node(buf);
+               if(!destination) {
+                       fprintf(stderr, "Unknown node '%s'\n", buf);
+                       return;
+               }
+       }
+
+       if(!destination) {
+               fprintf(stderr, "Who are you talking to? Write 'name: message...'\n");
+               return;
+       }
+
+       if(!mesh->send(destination, msg, strlen(msg) + 1)) {
+               fprintf(stderr, "Could not send message to '%s': %s\n", destination->name, mesh->errstr);
+               return;
+       }
+
+       printf("Message sent to '%s'.\n", destination->name);
+}
+
+int main(int argc, char *argv[]) {
+       const char *confbase = ".chat";
+       const char *nick = NULL;
+       char buf[1024];
+
+       if(argc > 1)
+               confbase = argv[1];
+
+       if(argc > 2)
+               nick = argv[2];
+
+       meshlink::mesh *mesh = meshlink::open(confbase, nick);
+       if(!mesh) {
+               fprintf(stderr, "Could not open MeshLink!\n");
+               return 1;
+       }
+
+       mesh->set_receive_cb(receive);
+       mesh->set_node_status_cb(node_status);
+       mesh->set_log_cb(MESHLINK_INFO, log_message);
+
+       if(!mesh->start()) {
+               fprintf(stderr, "Could not start MeshLink: %s\n", mesh->errstr);
+               return 1;
+       }
+
+       printf("Chat started.\nType /help for a list of commands.\n");
+
+       while(fgets(buf, sizeof buf, stdin))
+               parse_input(mesh, buf);
+
+       printf("Chat stopping.\n");
+
+       mesh->stop();
+       meshlink::close(mesh);
+
+       return 0;
+}