summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--TODO4
-rw-r--r--src/Makefile.am1
-rw-r--r--src/messageparser.cc80
-rw-r--r--src/messageparser.h1
-rw-r--r--src/muniacli.cc257
5 files changed, 306 insertions, 37 deletions
diff --git a/TODO b/TODO
index fb95122..e818911 100644
--- a/TODO
+++ b/TODO
@@ -1,2 +1,6 @@
+Client observer lists to set instead of lists.
+
Add depth to observe and make default client connection "observe 0 2",
ie. observe root node with Projects visible.
+
+Handling of invalid values in incoming messages (default values?) \ No newline at end of file
diff --git a/src/Makefile.am b/src/Makefile.am
index 0e59695..c256f54 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -28,6 +28,7 @@ muniacli_LDADD = $(LIBWEBSOCKETS_LIBS)
muniacli_CXXFLAGS = $(LIBWEBSOCKETS_CFLAGS)
muniacli_SOURCES = \
+ messageparser.cc \
muniacli.cc
EXTRA_DIST = \
diff --git a/src/messageparser.cc b/src/messageparser.cc
index 62923be..bfaa033 100644
--- a/src/messageparser.cc
+++ b/src/messageparser.cc
@@ -98,75 +98,95 @@ inline static void parse_into_msg_tokens(std::string& data,
}
inline static void create_msg_list(MsgTokensList& msgTokensList,
- MessageList& msgList) {
+ MessageList& msgList,
+ bool clientmode) {
+ int origin = 0;
+ if(clientmode) {
+ origin = 1;
+ }
+
MsgTokensList::iterator it_msg;
for(it_msg = msgTokensList.begin(); it_msg != msgTokensList.end(); it_msg++) {
TokenVector t = *it_msg;
//malformed msg
- if(t.size() < 1) continue;
+ if(t.size() < origin+1) continue;
message_t m;
- if(t[0] == "observe") m.cmd = cmd::observe;
- else if(t[0] == "unobserve") m.cmd = cmd::unobserve;
- else if(t[0] == "create") m.cmd = cmd::create;
- else if(t[0] == "remove") m.cmd = cmd::remove;
- else if(t[0] == "move") m.cmd = cmd::move;
- else if(t[0] == "update") m.cmd = cmd::update;
+// printf("t[%d] : %s, running in clientmode: %d\n", origin, t[origin].c_str(), clientmode);
+
+// printf("%d\n", t.size());
+
+ if(t[origin] == "observe") m.cmd = cmd::observe;
+ else if(t[origin] == "unobserve") m.cmd = cmd::unobserve;
+ else if(t[origin] == "create") m.cmd = cmd::create;
+ else if(t[origin] == "remove") m.cmd = cmd::remove;
+ else if(t[origin] == "move") m.cmd = cmd::move;
+ else if(t[origin] == "update") m.cmd = cmd::update;
else m.cmd = cmd::error;
// printf("Number of tokens %d\n", t.size());
switch(m.cmd) {
case cmd::observe: {
- if(t.size() != 1+1) {
- printf("Wrong number of parameters\n");
+ if(t.size() != origin+1+1) {
+ printf("W1: rong number of parameters\n");
continue;
}
- m.observe.id = atoi(t[1].c_str());
+ m.observe.id = atoi(t[origin+1].c_str());
break;
}
case cmd::unobserve: {
- if(t.size() != 1+1) {
+ if(t.size() != origin+1+1) {
printf("Wrong number of parameters\n");
continue;
}
- m.unobserve.id = atoi(t[1].c_str());
+ m.unobserve.id = atoi(t[origin+1].c_str());
break;
}
case cmd::create: {
- if(t.size() != 1+1) {
+ if(!clientmode && t.size() != origin+1+1) {
printf("Wrong number of parameters\n");
continue;
}
- m.create.parentid = atoi(t[1].c_str());
+ if(clientmode && t.size() != origin+1+2) {
+ printf("Wrong number of parameters\n");
+ continue;
+ }
+ if(clientmode) {
+ m.create.id = atoi(t[origin+1].c_str());
+ m.create.parentid = atoi(t[origin+2].c_str());
+ }
+ else {
+ m.create.parentid = atoi(t[origin+1].c_str());
+ }
break;
}
case cmd::remove: {
- if(t.size() != 1+1) {
+ if(t.size() != origin+1+1) {
printf("Wrong number of parameters\n");
continue;
}
- m.remove.id = atoi(t[1].c_str());
+ m.remove.id = atoi(t[origin+1].c_str());
break;
}
case cmd::move: {
- if(t.size() != 2+1) {
+ if(t.size() != origin+2+1) {
printf("Wrong number of parameters\n");
continue;
}
- m.move.id = atoi(t[1].c_str());
- m.move.parentid = atoi(t[2].c_str());
+ m.move.id = atoi(t[origin+1].c_str());
+ m.move.parentid = atoi(t[origin+2].c_str());
break;
}
case cmd::update: {
- if(t.size() != 2+1) {
+ if(t.size() != origin+2+1) {
printf("Wrong number of parameters\n");
continue;
}
- m.update.id = atoi(t[1].c_str());
- sprintf(m.update.title, "%s", t[2].c_str());
+ m.update.id = atoi(t[origin+1].c_str());
+ sprintf(m.update.title, "%s", t[origin+2].c_str());
break;
}
default:
@@ -177,13 +197,23 @@ inline static void create_msg_list(MsgTokensList& msgTokensList,
}
MessageList parse_msg(std::string data) {
- printf("Parsing: %s\n", data.c_str());
+// printf("Parsing: %s\n", data.c_str());
+
+ MsgTokensList msgTokensList;
+ parse_into_msg_tokens(data, msgTokensList);
+
+ MessageList msgList;
+ create_msg_list(msgTokensList, msgList, false);
+
+ return msgList;
+}
+MessageList parse_msg_client(std::string data) {
MsgTokensList msgTokensList;
parse_into_msg_tokens(data, msgTokensList);
MessageList msgList;
- create_msg_list(msgTokensList, msgList);
+ create_msg_list(msgTokensList, msgList, true);
return msgList;
}
diff --git a/src/messageparser.h b/src/messageparser.h
index 11b11cb..95208f2 100644
--- a/src/messageparser.h
+++ b/src/messageparser.h
@@ -31,6 +31,7 @@
#include "message.h"
MessageList parse_msg(std::string msg);
+MessageList parse_msg_client(std::string msg);
//message_t create_msg(cmd::cmd_t type, task_t task);
std::string msg_tostring(message_t msg);
diff --git a/src/muniacli.cc b/src/muniacli.cc
index a84de65..30e0ecf 100644
--- a/src/muniacli.cc
+++ b/src/muniacli.cc
@@ -30,13 +30,94 @@
#include <unistd.h>
#include <getopt.h>
#include <string.h>
+#include <string>
+#include <list>
+#include <map>
+
+#include "message.h"
+#include "messageparser.h"
#include <libwebsockets.h>
+
enum demo_protocols {
PROTOCOL_TASK
};
+enum cmd_t {
+ DEFAULT,
+ CREATE,
+ LIST,
+ REMOVE,
+ UPDATE
+};
+
+static bool run;
+static bool interactive;
+static std::string msgs;
+static int taskid;
+
+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];
+ 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;
+ int prevtask = -1;
+
+ 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];
+ 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(taskid);
+}
+
static int callback_task(struct libwebsocket_context *me,
struct libwebsocket *wsi,
enum libwebsocket_callback_reasons reason,
@@ -46,6 +127,7 @@ static int callback_task(struct libwebsocket_context *me,
LWS_SEND_BUFFER_POST_PADDING];
int l;
char msg[4096];
+ std::string r;
switch (reason) {
@@ -59,21 +141,34 @@ static int callback_task(struct libwebsocket_context *me,
break;
case LWS_CALLBACK_CLIENT_RECEIVE:
- fprintf(stderr, "rx %d '", (int)len);
- fwrite(in, len, 1, stderr);
- fprintf(stderr, "'\n");
+ // fprintf(stderr, "rx %d '", (int)len);
+ // fwrite(in, len, 1, stderr);
+ // fprintf(stderr, "\n");
+ pretty_print((char*)in);
libwebsocket_callback_on_writable(me, wsi);
+
+ if(!interactive) run = false;
break;
case LWS_CALLBACK_CLIENT_WRITEABLE:
- fgets(msg, sizeof(msg), stdin);
- printf("send...\n");
- l = sprintf((char *)&buf[LWS_SEND_BUFFER_PRE_PADDING], "%s", msg);
+
+ if(interactive) {
+ fgets(msg, sizeof(msg), stdin);
+ msgs += msg;
+ printf("send...\n");
+ }
- libwebsocket_write(wsi, &buf[LWS_SEND_BUFFER_PRE_PADDING],
- l, LWS_WRITE_TEXT);
+ if(!msgs.empty()) {
+ // printf("Sending %s\n", msgs.c_str());
+ l = sprintf((char *)&buf[LWS_SEND_BUFFER_PRE_PADDING], "%s", msgs.c_str());
+
+ libwebsocket_write(wsi, &buf[LWS_SEND_BUFFER_PRE_PADDING],
+ l, LWS_WRITE_TEXT);
+
+ msgs.clear();
+ }
break;
-
+
default:
break;
}
@@ -92,6 +187,7 @@ int client(const char *address, int port)
struct libwebsocket *wsi_task = NULL;
int ietf_version = -1; // latest
+
context = libwebsocket_create_context(CONTEXT_PORT_NO_LISTEN, NULL,
protocols,
libwebsocket_internal_extensions,
@@ -108,6 +204,7 @@ int client(const char *address, int port)
*/
int n = 1;
while(n >= 0) {
+
n = libwebsocket_service(context, 1000);
if (wsi_task == NULL) {
@@ -129,17 +226,153 @@ int client(const char *address, int port)
wsi_mirror, LWS_CLOSE_STATUS_GOINGAWAY);
*/
}
+
+ if(!run) break;
}
- fprintf(stderr, "Exiting\n");
+ // fprintf(stderr, "Exiting\n");
libwebsocket_context_destroy(context);
return 0;
}
-int main()
+static struct option options[] = {
+ { "create", no_argument, NULL, 'C'},
+ { "help", no_argument, NULL, 'h' },
+ { "host", required_argument, NULL, 'H'},
+ { "interactive", no_argument, NULL, 'i'},
+ { "id", required_argument, NULL, 'I'},
+ { "list", no_argument, NULL, 'L'},
+ { "name", required_argument, NULL, 'n'},
+ { "port", required_argument, NULL, 'p' },
+ { "remove", no_argument, NULL, 'R'},
+ { "update", required_argument, NULL, 'U'},
+ { NULL, 0, 0, 0 }
+};
+
+static char* USAGE=
+ "Usage: muniacli [OPTION]... TASK 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"
+ "Task:\n"
+ " -N, --name Select task by name\n"
+ " -I, --id Select task by id\n"
+ "Commands:\n"
+ " -C, --create Create new subtask in TASK\n"
+ " -L, --list List subtasks in TASK\n"
+ " -R, --remove Remove subtask from TASK\n"
+ " -U, --update Update data in TASK";
+
+
+int main(int argc, char** argv)
{
- client("localhost", 10001);
+ int port = 7681;
+ struct libwebsocket_context *context;
+ int opts = 0;
+ std::string host = "localhost";
+ int optionscount = 0;
+ std::string taskbyid;
+ std::string taskbyname;
+ 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:CLR:U:hH:", options, NULL);
+ 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':
+ taskbyname = optarg;
+ break;
+ case 'I':
+ taskbyid = 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(cmd == DEFAULT) {
+ fprintf(stderr, "%s\n", USAGE);
+ exit(1);
+ }
+
+ if(!taskbyname.empty()) {
+ taskbyid = -1;
+ fprintf(stderr, "Option '-N, --name' is not yet supported\n");
+ fprintf(stderr, "%s\n", USAGE);
+ exit(1);
+ }
+
+ if(taskbyid.empty()) {
+ fprintf(stderr, "%s\n", USAGE);
+ exit(1);
+ }
+
+ taskid = atoi(taskbyid.c_str());
+
+ switch(cmd) {
+ case CREATE:
+ msgs = "create " + taskbyid + ";";
+ break;
+ case LIST:
+ msgs = "observe " + taskbyid; //+
+ // "; unobserve " + task + ";";
+ break;
+ case REMOVE:
+ msgs = "remove " + taskbyid + ";";
+ break;
+ case UPDATE:
+ msgs = "update " + taskbyid + " " + cmd_opts;
+ break;
+ }
+
+ /*
+ 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("localhost", port);
return 0;
}