summaryrefslogtreecommitdiff
path: root/src/munia.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/munia.cc')
-rw-r--r--src/munia.cc608
1 files changed, 608 insertions, 0 deletions
diff --git a/src/munia.cc b/src/munia.cc
new file mode 100644
index 0000000..34cb820
--- /dev/null
+++ b/src/munia.cc
@@ -0,0 +1,608 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set et sw=2 ts=2: */
+/***************************************************************************
+ * muniacli.cc
+ *
+ * Fri May 4 15:39:06 CEST 2012
+ * Copyright 2012 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of Munia.
+ *
+ * Munia is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Munia is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Munia; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <string.h>
+#include <string>
+#include <list>
+#include <map>
+
+//#include "message.h"
+//#include "messageparser.h"
+
+#include <libwebsockets.h>
+
+static bool run;
+static std::string msgs;
+
+struct per_session_data__lws_node
+{
+ struct lws *wsi;
+};
+
+static int callback_lws_node(struct lws *wsi,
+ enum lws_callback_reasons reason,
+ void *user, void *in, size_t len)
+{
+ unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + 4096 +
+ LWS_SEND_BUFFER_POST_PADDING];
+ int l;
+ std::string r;
+
+ switch (reason)
+ {
+
+ case LWS_CALLBACK_CLOSED:
+ //fprintf(stderr, "mirror: LWS_CALLBACK_CLOSED\n");
+ break;
+
+ case LWS_CALLBACK_CLIENT_ESTABLISHED:
+ lws_callback_on_writable(wsi);
+ break;
+
+ case LWS_CALLBACK_CLIENT_RECEIVE:
+ //pretty_print((char*)in);
+ printf("%s\n", (char*)in);
+ lws_callback_on_writable(wsi);
+
+ //if(!interactive) run = false;
+ run = false;
+ break;
+
+ case LWS_CALLBACK_CLIENT_WRITEABLE:
+ //if(interactive)
+ //{
+ // fgets(msg, sizeof(msg), stdin);
+ // msgs += msg;
+ // printf("send...\n");
+ //}
+
+ l = sprintf((char *)&buf[LWS_SEND_BUFFER_PRE_PADDING], "%s", msgs.c_str());
+
+ lws_write(wsi, &buf[LWS_SEND_BUFFER_PRE_PADDING], l, LWS_WRITE_TEXT);
+ break;
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static struct lws_protocols protocols[] =
+{
+ { "lws-node-protocol", callback_lws_node,
+ sizeof(struct per_session_data__lws_node)
+ },
+ { nullptr, nullptr, 0 } // End of list
+};
+
+int client(const char *address, int port)
+{
+// printf("Connection to %s on port %d\n", address, port);
+ struct lws_context *context;
+ struct lws *wsi_node = nullptr;
+ int ietf_version = -1; // latest
+
+ lws_set_log_level(0, nullptr);
+ struct lws_context_creation_info info{};
+ info.port = CONTEXT_PORT_NO_LISTEN;
+ info.iface = nullptr; // What is this?
+ info.protocols = protocols;
+ //info.extensions = lws_get_internal_extensions();
+
+ context = lws_create_context(&info);
+
+ if(context == nullptr)
+ {
+ fprintf(stderr, "Creating lws context failed\n");
+ return 1;
+ }
+
+ // sit there servicing the websocket context to handle incoming
+ // packets, and drawing random circles on the mirror protocol websocket
+ int n = 1;
+ while(n >= 0)
+ {
+ n = lws_service(context, 10);
+
+ if(wsi_node == nullptr)
+ {
+ lws_client_connect_info info;
+ memset(&info, 0, sizeof(info));
+ info.context = context;
+ info.address = address;
+ info.port = port;
+ info.ssl_connection = 0;
+ info.path = "/";
+ info.host = address;
+ info.origin = address;
+ info.protocol = "lws-node-protocol";
+ info.ietf_version_or_minus_one = ietf_version;
+ wsi_node = lws_client_connect_via_info(&info);
+
+ if(wsi_node == nullptr)
+ {
+ fprintf(stderr, "lws node connect failed\n");
+ return -1;
+ }
+ else
+ {
+ //...
+ }
+
+ }
+ else
+ {
+ //fprintf(stderr, "closing mirror session\n");
+ //lws_close_and_free_session(context,
+ // wsi_mirror, LWS_CLOSE_STATUS_GOINGAWAY);
+ }
+
+ if(!run)
+ {
+ break;
+ }
+ }
+
+ lws_context_destroy(context);
+
+ return 0;
+}
+
+static struct option options[] = {
+ { "command", required_argument, nullptr, 'c'},
+ { "help", no_argument, nullptr, 'h' },
+ { "host", required_argument, nullptr, 'H'},
+ { "port", required_argument, nullptr, 'p' },
+ { "raw", no_argument, nullptr, 'r'},
+ { nullptr, 0, 0, 0 }
+};
+
+static const char* USAGE =
+ "Usage: muniacli [OPTION]... NODE COMMAND\n"
+ "Commandline client to munia."
+ "Options:\n"
+ " -p, --port Port on host\n"
+ " -H, --host Host\n"
+ " -c, --command Command\n";
+
+int main(int argc, char** argv)
+{
+ int port = 7681;
+ std::string host = "localhost";
+ std::string cmd;
+// bool raw = true;
+
+ run = true;
+
+ int n = 0;
+ while(n >= 0)
+ {
+ n = getopt_long(argc, argv, "c:H:p:r", options, nullptr);
+ if(n < 0)
+ {
+ continue;
+ }
+
+ switch(n)
+ {
+ case 'c':
+ cmd = optarg;
+ break;
+ case 'p':
+ port = atoi(optarg);
+ break;
+ case 'H':
+ host = optarg;
+ break;
+ case 'r':
+ //raw = true;
+ break;
+ case 'h':
+ fprintf(stderr, "%s\n", USAGE);
+ exit(1);
+ break;
+ }
+ }
+ msgs = cmd;
+
+ client(host.c_str(), port);
+ return 0;
+}
+
+#if 0
+enum demo_protocols {
+ PROTOCOL_NODE
+};
+
+enum cmd_t
+{
+ DEFAULT,
+ CREATE,
+ LIST,
+ REMOVE,
+ UPDATE
+};
+
+static bool run;
+static bool interactive;
+static std::string msgs;
+static int nodeid;
+
+static std::map<int, std::list<int> > structuremap;
+static std::map<int, std::string> titlemap;
+
+static std::string indent;
+
+
+static void rec_pretty_print(int node)
+{
+ // printf("pretty printing %d\n", node);
+ // for(std::map<int, std::list<int>>::iterator it = structuremap.begin();
+ // it != structuremap.end(); it++) {
+ // std::list<int> childlist = *it;
+
+ printf("%s%d - %s\n", indent.c_str(), node, titlemap[node].c_str());
+ std::list<int> childlist = structuremap[node];
+ childlist.unique();
+ if(!childlist.empty())
+ {
+ for(std::list<int>::iterator it = childlist.begin();
+ it != childlist.end(); it++)
+ {
+ int child = *it;
+ indent += " ";
+ rec_pretty_print(child);
+ }
+ }
+
+ indent = indent.substr(0, indent.length()-2);
+}
+
+static void pretty_print(std::string msgs)
+{
+ // printf("%s\n", msgs.c_str());
+ MessageList list = parse_msg_client(msgs);
+
+ std::string indent;
+
+ std::list<int> childlist;
+
+ for(MessageList::iterator it = list.begin();
+ it != list.end(); it++)
+ {
+ message_t msg = *it;
+
+ switch(msg.cmd)
+ {
+ case cmd::create:
+ // printf("Parent %d, id %d\n", msg.create.parentid, msg.create.id);
+ childlist = structuremap[msg.create.parentid];
+ //if(childlist.find(msg.create.id) == childlist.end())
+ //{
+ childlist.push_back(msg.create.id);
+ //}
+ structuremap[msg.create.parentid] = childlist;
+ //printf("Childlist size of %d = %d\n", msg.create.parentid, childlist.size());
+ break;
+ case cmd::update:
+ //char buf[256];
+ //sprintf(buf, "%s", msg.update.title);
+ titlemap[msg.update.id] = msg.update.title;
+ //printf("%s\n", buf);
+ break;
+ default:
+ break;
+ }
+ }
+
+ rec_pretty_print(nodeid);
+}
+
+static int callback_node(struct lws_context *me,
+ struct lws *wsi,
+ enum lws_callback_reasons reason,
+ void *user, void *in, size_t len)
+{
+ unsigned char buf[LWS_SEND_BUFFER_PRE_PADDING + 4096 +
+ LWS_SEND_BUFFER_POST_PADDING];
+ int l;
+ char msg[4096];
+ std::string r;
+
+ switch (reason)
+ {
+ case LWS_CALLBACK_CLOSED:
+ fprintf(stderr, "mirror: LWS_CALLBACK_CLOSED\n");
+ // wsi_mirror = nullptr;
+ break;
+
+ case LWS_CALLBACK_CLIENT_ESTABLISHED:
+ lws_callback_on_writable(me, wsi);
+ break;
+
+ case LWS_CALLBACK_CLIENT_RECEIVE:
+ //fprintf(stderr, "rx %d '", (int)len);
+ //fwrite(in, len, 1, stderr);
+ //fprintf(stderr, "\n");
+ pretty_print((char*)in);
+ lws_callback_on_writable(me, wsi);
+
+ if(!interactive)
+ {
+ run = false;
+ }
+ break;
+
+ case LWS_CALLBACK_CLIENT_WRITEABLE:
+ if(interactive)
+ {
+ fgets(msg, sizeof(msg), stdin);
+ msgs += msg;
+ printf("send...\n");
+ }
+
+ if(!msgs.empty())
+ {
+ // printf("Sending %s\n", msgs.c_str());
+ l = sprintf((char *)&buf[LWS_SEND_BUFFER_PRE_PADDING], "%s", msgs.c_str());
+ lws_write(wsi, &buf[LWS_SEND_BUFFER_PRE_PADDING],
+ l, LWS_WRITE_TEXT);
+
+ msgs.clear();
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static struct lws_protocols protocols[] =
+{
+ { "lws-node-protocol", callback_node, 0, },
+ { nullptr, nullptr, 0 }
+};
+
+int client(const char *address, int port)
+{
+ struct lws_context *context;
+ struct lws *wsi_node = nullptr;
+ int ietf_version = -1; // latest
+
+ context = lws_create_context(CONTEXT_PORT_NO_LISTEN, nullptr,
+ protocols,
+ lws_internal_extensions,
+ nullptr, nullptr, -1, -1, 0);
+ if (context == nullptr)
+ {
+ fprintf(stderr, "Creating lws context failed\n");
+ return 1;
+ }
+
+ // sit there servicing the websocket context to handle incoming
+ // packets, and drawing random circles on the mirror protocol websocket
+ int n = 1;
+ while(n >= 0)
+ {
+ n = lws_service(context, 10);
+
+ if (wsi_node == nullptr)
+ {
+ wsi_node = lws_client_connect(context, address, port,
+ 0, "/", address, address,
+ protocols[lws-node-protocol].name,
+ ietf_version);
+
+ if(wsi_node == nullptr)
+ {
+ fprintf(stderr, "lws node connect failed\n");
+ return -1;
+ }
+
+ }
+ else
+ {
+ //fprintf(stderr, "closing mirror session\n");
+ //lws_close_and_free_session(context,
+ // wsi_mirror, LWS_CLOSE_STATUS_GOINGAWAY);
+ }
+
+ if(!run)
+ {
+ break;
+ }
+ }
+
+ //fprintf(stderr, "Exiting\n");
+
+ lws_context_destroy(context);
+
+ return 0;
+}
+
+static struct option options[] =
+{
+ { "create", no_argument, nullptr, 'C'},
+ { "help", no_argument, nullptr, 'h' },
+ { "host", required_argument, nullptr, 'H'},
+ { "interactive", no_argument, nullptr, 'i'},
+ { "id", required_argument, nullptr, 'I'},
+ { "list", no_argument, nullptr, 'L'},
+ { "name", required_argument, nullptr, 'n'},
+ { "port", required_argument, nullptr, 'p' },
+ { "remove", no_argument, nullptr, 'R'},
+ { "update", required_argument, nullptr, 'U'},
+ { nullptr, 0, 0, 0 }
+};
+
+static const char* USAGE =
+ "Usage: muniacli [OPTION]... NODE COMMAND\n"
+ "Commandline client to munia."
+ "Options:\n"
+ " -p, --port Port on host\n"
+ " -H, --host Host\n"
+ " -i, --interactive Run in interactive/shell mode\n"
+ "Node:\n"
+ " -N, --name Select node by name\n"
+ " -I, --id Select node by id\n"
+ "Commands:\n"
+ " -C, --create Create new subnode in NODE\n"
+ " -L, --list List subnodes in NODE\n"
+ " -R, --remove Remove subnode from NODE\n"
+ " -U, --update Update data in NODE";
+
+
+int main(int argc, char** argv)
+{
+ int port = 7681;
+ std::string host = "localhost";
+ std::string nodebyid;
+ std::string nodebyname;
+ cmd_t cmd = DEFAULT;
+ std::string cmd_opts;
+
+ interactive = false;
+ run = true;
+
+ int n = 0;
+ while(n >= 0)
+ {
+ n = getopt_long(argc, argv, "p:iN:I:CLRU:hH:", options, nullptr);
+ if(n < 0)
+ {
+ continue;
+ }
+ switch(n)
+ {
+ case 'i':
+ interactive = true;
+ break;
+ case 'p':
+ port = atoi(optarg);
+ break;
+ case 'H':
+ host = optarg;
+ break;
+ case 'h':
+ fprintf(stderr, "%s\n", USAGE);
+ exit(1);
+ case 'N':
+ nodebyname = optarg;
+ break;
+ case 'I':
+ nodebyid = optarg;
+ break;
+ case 'C':
+ cmd = CREATE;
+ break;
+ case 'L':
+ cmd = LIST;
+ break;
+ case 'R':
+ cmd = REMOVE;
+ break;
+ case 'U':
+ cmd = UPDATE;
+ cmd_opts = optarg;
+ break;
+ }
+ }
+
+ if(!interactive && cmd == DEFAULT)
+ {
+ fprintf(stderr, "%s\n", USAGE);
+ exit(1);
+ }
+
+ if(!interactive && !nodebyname.empty())
+ {
+ nodebyid = -1;
+ fprintf(stderr, "Option '-N, --name' is not yet supported\n");
+ fprintf(stderr, "%s\n", USAGE);
+ exit(1);
+ }
+
+ if(!interactive && nodebyid.empty())
+ {
+ fprintf(stderr, "%s\n", USAGE);
+ exit(1);
+ }
+
+ nodeid = atoi(nodebyid.c_str());
+
+ switch(cmd)
+ {
+ case CREATE:
+ msgs = "subscribe " + nodebyid + ";";
+ msgs += "create " + nodebyid + ";";
+ break;
+ case LIST:
+ msgs = "subscribe " + nodebyid + ";"; //+
+ // "; unsubscribe " + node + ";";
+ break;
+ case REMOVE:
+ msgs = "remove " + nodebyid + ";";
+ break;
+ case UPDATE:
+ msgs = "subscribe " + nodebyid + ";";
+ msgs += "update " + nodebyid + " \"" + cmd_opts + "\"; ";
+ break;
+ case DEFAULT:
+ break;
+ }
+
+// printf("msgs: %s\n", msgs.c_str());
+
+// if(!interactive && argc - optionscount < 3)
+// {
+// fprintf(stderr, "%s", USAGE);
+// exit(1);
+// }
+// else if (interactive && argc - optionscount < 2)
+// {
+// fprintf(stderr, "%s", USAGE);
+// exit(1);
+// }
+//
+// if(!interactive)
+// {
+// //printf("cmd: %s\n", argv[3]);
+// msgs = argv[3];
+// }
+
+ client(host.c_str(), port);
+ return 0;
+}
+
+#endif/*0*/