From 4849a829913ef4f7fb73ab528aabf6925a330dc2 Mon Sep 17 00:00:00 2001 From: Bent Bisballe Nyeng Date: Sat, 27 Jun 2020 16:12:18 +0200 Subject: Rename muniacli to just munia. --- src/munia.cc | 608 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 608 insertions(+) create mode 100644 src/munia.cc (limited to 'src/munia.cc') 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 +#include +#include +#include +#include +#include +#include +#include + +//#include "message.h" +//#include "messageparser.h" + +#include + +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 > structuremap; +static std::map titlemap; + +static std::string indent; + + +static void rec_pretty_print(int node) +{ + // printf("pretty printing %d\n", node); + // for(std::map>::iterator it = structuremap.begin(); + // it != structuremap.end(); it++) { + // std::list childlist = *it; + + printf("%s%d - %s\n", indent.c_str(), node, titlemap[node].c_str()); + std::list childlist = structuremap[node]; + childlist.unique(); + if(!childlist.empty()) + { + for(std::list::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 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*/ -- cgit v1.2.3