diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 4 | ||||
-rw-r--r-- | src/connectionhandler.cc | 172 | ||||
-rw-r--r-- | src/connectionhandler.h | 33 | ||||
-rw-r--r-- | src/http.cc | 169 | ||||
-rw-r--r-- | src/http.h | 12 | ||||
-rw-r--r-- | src/message.h | 103 | ||||
-rw-r--r-- | src/messagehandler.cc | 340 | ||||
-rw-r--r-- | src/messagehandler.h | 6 | ||||
-rw-r--r-- | src/messageparser.cc | 599 | ||||
-rw-r--r-- | src/messageparser.h | 7 | ||||
-rw-r--r-- | src/munia_proto.cc | 496 | ||||
-rw-r--r-- | src/munia_proto.h | 15 | ||||
-rw-r--r-- | src/muniacli.cc | 799 | ||||
-rw-r--r-- | src/muniad.cc | 138 | ||||
-rw-r--r-- | src/saxparser.cc | 246 | ||||
-rw-r--r-- | src/saxparser.h | 206 | ||||
-rw-r--r-- | src/task.h | 14 | ||||
-rw-r--r-- | src/taskmanager.cc | 546 | ||||
-rw-r--r-- | src/taskmanager.h | 169 | ||||
-rw-r--r-- | src/tasktree.cc | 596 | ||||
-rw-r--r-- | src/tasktree.h | 58 | ||||
-rw-r--r-- | src/testclient.cc | 206 | ||||
-rw-r--r-- | src/testclient.h | 4 | ||||
-rw-r--r-- | src/xml_encode_decode.cc | 79 | ||||
-rw-r--r-- | src/xml_encode_decode.h | 5 | ||||
-rw-r--r-- | src/xmlparser.cc | 78 | ||||
-rw-r--r-- | src/xmlparser.h | 33 |
27 files changed, 2698 insertions, 2435 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 02c0fe0..c977d97 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -4,8 +4,8 @@ bin_PROGRAMS = muniad muniacli muniad_LDADD = $(LIBWEBSOCKETS_LIBS) $(EXPAT_LIBS) -muniad_CXXFLAGS = $(LIBWEBSOCKETS_CFLAGS) $(EXPAT_CFLAGS) -I../hugin \ - -I/usr/local/include +muniad_CXXFLAGS = -std=c++17 $(LIBWEBSOCKETS_CFLAGS) $(EXPAT_CFLAGS) \ + -I../hugin muniad_SOURCES = \ muniad.cc \ diff --git a/src/connectionhandler.cc b/src/connectionhandler.cc index 1a4dce1..d264abe 100644 --- a/src/connectionhandler.cc +++ b/src/connectionhandler.cc @@ -40,72 +40,76 @@ ConnectionHandler::ConnectionHandler() void ConnectionHandler::init(clientid_t clientid) { - DEBUG(conn, "Adding client %p to connection list\n", clientid); - connlist[clientid] = std::set<taskid_t>(); + DEBUG(conn, "Adding client %p to connection list\n", clientid); + connlist[clientid] = std::set<taskid_t>(); - DEBUG(conn, "Connections (%d):\n", (int)connlist.size()); - ConnectionList::iterator it; - for(it = connlist.begin(); it != connlist.end(); it++) { - DEBUG(conn, "\t%p\n", it->first); - } + DEBUG(conn, "Connections (%d):\n", (int)connlist.size()); + ConnectionList::iterator it; + for(it = connlist.begin(); it != connlist.end(); it++) + { + DEBUG(conn, "\t%p\n", it->first); + } } void ConnectionHandler::close(clientid_t clientid) { - connlist.erase(clientid); - DEBUG(conn, "Removed connection\n"); + connlist.erase(clientid); + DEBUG(conn, "Removed connection\n"); } void ConnectionHandler::login(clientid_t clientid, std::string user, std::string password) { - authlist[clientid] = (password == "hundemad"); - DEBUG(conn, "Authentication %d\n", authlist[clientid]); + authlist[clientid] = (password == "hundemad"); + DEBUG(conn, "Authentication %d\n", authlist[clientid]); } void ConnectionHandler::logout(clientid_t clientid) { - authlist[clientid] = false; - DEBUG(conn, "Authentication %d\n", authlist[clientid]); + authlist[clientid] = false; + DEBUG(conn, "Authentication %d\n", authlist[clientid]); } bool ConnectionHandler::authenticated(clientid_t clientid) { - return authlist.find(clientid) != authlist.end() && authlist[clientid]; + return authlist.find(clientid) != authlist.end() && authlist[clientid]; } void ConnectionHandler::observe(clientid_t clientid, taskid_t taskid) { - connlist[clientid].insert(taskid); - DEBUG(conn, "Added observer of %d\n", taskid); + connlist[clientid].insert(taskid); + DEBUG(conn, "Added observer of %d\n", taskid); } void ConnectionHandler::unobserve(clientid_t clientid, taskid_t taskid) { - connlist[clientid].erase(taskid); + connlist[clientid].erase(taskid); } ObserverList ConnectionHandler::observerlist(TaskIdList tasks) { - DEBUG(conn, "Observerlist request (#tasks: %d)\n", (int)tasks.size()); - ObserverList clients; + DEBUG(conn, "Observerlist request (#tasks: %d)\n", (int)tasks.size()); + ObserverList clients; - for(TaskIdList::iterator i = tasks.begin(); i != tasks.end(); i++) { - taskid_t tid = *i; + for(TaskIdList::iterator i = tasks.begin(); i != tasks.end(); i++) + { + taskid_t tid = *i; - DEBUG(conn, "Locating observers of node %d\n", tid); - for(ConnectionList::iterator ci = connlist.begin(); - ci != connlist.end(); ci++) { - std::set<taskid_t>::iterator ti = ci->second.find(tid); - if(ti != ci->second.end()) { - std::pair<clientid_t, taskid_t> m; - m.first = ci->first; - m.second = tid; - clients.push_back(m); - } - } - } + DEBUG(conn, "Locating observers of node %d\n", tid); + for(ConnectionList::iterator ci = connlist.begin(); + ci != connlist.end(); ci++) + { + std::set<taskid_t>::iterator ti = ci->second.find(tid); + if(ti != ci->second.end()) + { + std::pair<clientid_t, taskid_t> m; + m.first = ci->first; + m.second = tid; + clients.push_back(m); + } + } + } - return clients; + return clients; } @@ -132,84 +136,84 @@ h.init((clientid_t)3); h.observe((clientid_t)3, (taskid_t)3); { - TaskIdList tasks; - tasks.push_back((taskid_t)1); - ObserverList clst = h.observerlist(tasks); + TaskIdList tasks; + tasks.push_back((taskid_t)1); + ObserverList clst = h.observerlist(tasks); - TEST_TRUE(clst.find((clientid_t)1) != clst.end(), "Got client 1?"); - TEST_TRUE(clst.find((clientid_t)2) != clst.end(), "Got client 2?"); - TEST_FALSE(clst.find((clientid_t)3) != clst.end(), "Got client 3?"); + TEST_TRUE(clst.find((clientid_t)1) != clst.end(), "Got client 1?"); + TEST_TRUE(clst.find((clientid_t)2) != clst.end(), "Got client 2?"); + TEST_FALSE(clst.find((clientid_t)3) != clst.end(), "Got client 3?"); } { - TaskIdList tasks; - tasks.push_back((taskid_t)3); - ObserverList clst = h.observerlist(tasks); + TaskIdList tasks; + tasks.push_back((taskid_t)3); + ObserverList clst = h.observerlist(tasks); - TEST_FALSE(clst.find((clientid_t)1) != clst.end(), "Got client 1?"); - TEST_FALSE(clst.find((clientid_t)2) != clst.end(), "Got client 2?"); - TEST_TRUE(clst.find((clientid_t)3) != clst.end(), "Got client 3?"); + TEST_FALSE(clst.find((clientid_t)1) != clst.end(), "Got client 1?"); + TEST_FALSE(clst.find((clientid_t)2) != clst.end(), "Got client 2?"); + TEST_TRUE(clst.find((clientid_t)3) != clst.end(), "Got client 3?"); } { - TaskIdList tasks; - tasks.push_back((taskid_t)4); - ObserverList clst = h.observerlist(tasks); + TaskIdList tasks; + tasks.push_back((taskid_t)4); + ObserverList clst = h.observerlist(tasks); - TEST_FALSE(clst.find((clientid_t)1) != clst.end(), "Got client 1?"); - TEST_FALSE(clst.find((clientid_t)2) != clst.end(), "Got client 2?"); - TEST_FALSE(clst.find((clientid_t)3) != clst.end(), "Got client 3?"); + TEST_FALSE(clst.find((clientid_t)1) != clst.end(), "Got client 1?"); + TEST_FALSE(clst.find((clientid_t)2) != clst.end(), "Got client 2?"); + TEST_FALSE(clst.find((clientid_t)3) != clst.end(), "Got client 3?"); } { - TaskIdList tasks; - tasks.push_back((taskid_t)1); - tasks.push_back((taskid_t)2); - tasks.push_back((taskid_t)3); - ObserverList clst = h.observerlist(tasks); + TaskIdList tasks; + tasks.push_back((taskid_t)1); + tasks.push_back((taskid_t)2); + tasks.push_back((taskid_t)3); + ObserverList clst = h.observerlist(tasks); - TEST_TRUE(clst.find((clientid_t)1) != clst.end(), "Got client 1?"); - TEST_TRUE(clst.find((clientid_t)2) != clst.end(), "Got client 2?"); - TEST_TRUE(clst.find((clientid_t)3) != clst.end(), "Got client 3?"); + TEST_TRUE(clst.find((clientid_t)1) != clst.end(), "Got client 1?"); + TEST_TRUE(clst.find((clientid_t)2) != clst.end(), "Got client 2?"); + TEST_TRUE(clst.find((clientid_t)3) != clst.end(), "Got client 3?"); } h.close((clientid_t)1); { - TaskIdList tasks; - tasks.push_back((taskid_t)1); - tasks.push_back((taskid_t)2); - tasks.push_back((taskid_t)3); - ObserverList clst = h.observerlist(tasks); + TaskIdList tasks; + tasks.push_back((taskid_t)1); + tasks.push_back((taskid_t)2); + tasks.push_back((taskid_t)3); + ObserverList clst = h.observerlist(tasks); - TEST_FALSE(clst.find((clientid_t)1) != clst.end(), "Got client 1?"); - TEST_TRUE(clst.find((clientid_t)2) != clst.end(), "Got client 2?"); - TEST_TRUE(clst.find((clientid_t)3) != clst.end(), "Got client 3?"); + TEST_FALSE(clst.find((clientid_t)1) != clst.end(), "Got client 1?"); + TEST_TRUE(clst.find((clientid_t)2) != clst.end(), "Got client 2?"); + TEST_TRUE(clst.find((clientid_t)3) != clst.end(), "Got client 3?"); } h.close((clientid_t)2); { - TaskIdList tasks; - tasks.push_back((taskid_t)1); - tasks.push_back((taskid_t)2); - tasks.push_back((taskid_t)3); - ObserverList clst = h.observerlist(tasks); + TaskIdList tasks; + tasks.push_back((taskid_t)1); + tasks.push_back((taskid_t)2); + tasks.push_back((taskid_t)3); + ObserverList clst = h.observerlist(tasks); - TEST_FALSE(clst.find((clientid_t)1) != clst.end(), "Got client 1?"); - TEST_FALSE(clst.find((clientid_t)2) != clst.end(), "Got client 2?"); - TEST_TRUE(clst.find((clientid_t)3) != clst.end(), "Got client 3?"); + TEST_FALSE(clst.find((clientid_t)1) != clst.end(), "Got client 1?"); + TEST_FALSE(clst.find((clientid_t)2) != clst.end(), "Got client 2?"); + TEST_TRUE(clst.find((clientid_t)3) != clst.end(), "Got client 3?"); } h.close((clientid_t)3); { - TaskIdList tasks; - tasks.push_back((taskid_t)1); - tasks.push_back((taskid_t)2); - tasks.push_back((taskid_t)3); - ObserverList clst = h.observerlist(tasks); + TaskIdList tasks; + tasks.push_back((taskid_t)1); + tasks.push_back((taskid_t)2); + tasks.push_back((taskid_t)3); + ObserverList clst = h.observerlist(tasks); - TEST_FALSE(clst.find((clientid_t)1) != clst.end(), "Got client 1?"); - TEST_FALSE(clst.find((clientid_t)2) != clst.end(), "Got client 2?"); - TEST_FALSE(clst.find((clientid_t)3) != clst.end(), "Got client 3?"); + TEST_FALSE(clst.find((clientid_t)1) != clst.end(), "Got client 1?"); + TEST_FALSE(clst.find((clientid_t)2) != clst.end(), "Got client 2?"); + TEST_FALSE(clst.find((clientid_t)3) != clst.end(), "Got client 3?"); } TEST_END; diff --git a/src/connectionhandler.h b/src/connectionhandler.h index 402f531..0e28cd3 100644 --- a/src/connectionhandler.h +++ b/src/connectionhandler.h @@ -25,8 +25,7 @@ * along with Munia; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#ifndef __MUNIA_CONNECTIONHANDLER_H__ -#define __MUNIA_CONNECTIONHANDLER_H__ +#pragma once #include <list> #include <set> @@ -36,35 +35,33 @@ #include "task.h" -typedef struct libwebsocket* clientid_t; +typedef struct lws* clientid_t; typedef std::map<clientid_t, bool> AuthList; typedef std::map<clientid_t, std::set<taskid_t> > ConnectionList; typedef std::list<std::pair<clientid_t, taskid_t> > ObserverList; -class ConnectionHandler { +class ConnectionHandler +{ public: - ConnectionHandler(); + ConnectionHandler(); - void init(clientid_t clientid); - void close(clientid_t clientid); + void init(clientid_t clientid); + void close(clientid_t clientid); - void login(clientid_t clientid, std::string user, std::string password); - void logout(clientid_t clientid); - bool authenticated(clientid_t clientid); + void login(clientid_t clientid, std::string user, std::string password); + void logout(clientid_t clientid); + bool authenticated(clientid_t clientid); - void observe(clientid_t clientid, taskid_t taskid); - void unobserve(clientid_t clientid, taskid_t taskid); + void observe(clientid_t clientid, taskid_t taskid); + void unobserve(clientid_t clientid, taskid_t taskid); - - ObserverList observerlist(TaskIdList tasklist); + ObserverList observerlist(TaskIdList tasklist); private: - ConnectionList connlist; - AuthList authlist; + ConnectionList connlist; + AuthList authlist; }; // Global ConnectionHandler extern ConnectionHandler connection_handler; - -#endif/*__MUNIA_CONNECTIONHANDLER_H__*/ diff --git a/src/http.cc b/src/http.cc index f00cbb7..43d09bc 100644 --- a/src/http.cc +++ b/src/http.cc @@ -29,107 +29,102 @@ #include <stdio.h> #include <string.h> +#include <string> #include "hugin.hpp" -int callback_http(struct libwebsocket_context * context, - struct libwebsocket *wsi, - enum libwebsocket_callback_reasons reason, void *user, - void *i, size_t len) +int serveFile(struct lws *wsi, + const std::string& file, const std::string& mimeType) { - char *in = (char*)i; - // char client_name[128]; - // char client_ip[128]; - - switch(reason) { - case LWS_CALLBACK_HTTP: - DEBUG(httpd,"serving HTTP URI %s\n", (char *)in); - - while(*in == '/') in++; // skip trailing slashes - - // add favicon later - if(in && strcmp((const char *)in, "favicon.ico") == 0) { - if(libwebsockets_serve_http_file(context, wsi, - LOCAL_RESOURCE_PATH"/favicon.ico", - "image/x-icon")) - DEBUG(httpd,"Failed to send favicon\n"); - break; - } + std::string fileWithPath = LOCAL_RESOURCE_PATH; + fileWithPath += "/" + file; + auto ret = lws_serve_http_file(wsi, fileWithPath.data(), + mimeType.data(), nullptr, 0); + if(ret < 0) + { + DEBUG(httpd, "Failed to serve %s\n", file.data()); + return 1; // error!? + } - // css - if(in && strcmp((const char *)in, "munia.css") == 0) { - if(libwebsockets_serve_http_file(context, wsi, - LOCAL_RESOURCE_PATH"/munia.css", - "text/css")) - DEBUG(httpd,"Failed to send css\n"); - break; + if(ret > 0) + { + if(lws_http_transaction_completed(wsi) < 0) + { + DEBUG(httpd, "Failed to complete http transaction %s\n", file.data()); + return 1; } + } - // script - if(in && strcmp((const char *)in, "proto.js") == 0) { - if(libwebsockets_serve_http_file(context, wsi, - LOCAL_RESOURCE_PATH"/proto.js", - "text/javascript")) - DEBUG(httpd,"Failed to send javascript\n"); - break; - } + if(ret == 0) + { + DEBUG(httpd, "Http transaction of %s in progress\n", file.data()); + } - if(in && strcmp((const char *)in, "handler.js") == 0) { - if(libwebsockets_serve_http_file(context, wsi, - LOCAL_RESOURCE_PATH"/handler.js", - "text/javascript")) - DEBUG(httpd,"Failed to send javascript\n"); - break; - } + return 0; +} - if(in && strcmp((const char *)in, "view.js") == 0) { - if(libwebsockets_serve_http_file(context, wsi, - LOCAL_RESOURCE_PATH"/view.js", - "text/javascript")) - DEBUG(httpd,"Failed to send javascript\n"); - break; - } +int callback_http(struct lws *wsi, + enum lws_callback_reasons reason, void *user, + void *i, size_t len) +{ + // char client_name[128]; + // char client_ip[128]; - if(in && strcmp((const char *)in, "task.js") == 0) { - if(libwebsockets_serve_http_file(context, wsi, - LOCAL_RESOURCE_PATH"/task.js", - "text/javascript")) - DEBUG(httpd,"Failed to send javascript\n"); - break; - } + if(reason != LWS_CALLBACK_HTTP) + { + return 0; // We only serve http here + } + const char* in = (char*)i; + while(*in == '/') + { + in++; // skip trailing slashes + } - /* send the script... when it runs it'll start websockets */ - if(libwebsockets_serve_http_file(context, wsi, - LOCAL_RESOURCE_PATH"/munia.html", - "text/html")) - DEBUG(httpd,"Failed to send HTTP file\n"); - break; + std::string file; + file.append(in, len - (in - (char*)i)); + DEBUG(httpd,"serving HTTP URI %s\n", file.data()); - /* - * callback for confirming to continue with client IP appear in - * protocol 0 callback since no websocket protocol has been agreed - * yet. You can just ignore this if you won't filter on client IP - * since the default uhandled callback return is 0 meaning let the - * connection continue. - */ + // add favicon later + if(file == "favicon.ico") + { + return serveFile(wsi, file, "image/x-icon"); + } - case LWS_CALLBACK_FILTER_NETWORK_CONNECTION: - /* - libwebsockets_get_peer_addresses((int)(long)user, - client_name, - sizeof(client_name), - client_ip, - sizeof(client_ip)); - DEBUG(httpd,"Received network connect from %s (%s)\n", - client_name, client_ip); - */ - /* if we returned non-zero from here, we kill the connection */ - break; + // css + if(file == "munia.css") + { + return serveFile(wsi, file, "text/css"); + } - default: - break; + // script + if(file == "proto.js" || + file == "handler.js" || + file == "task.js" || + file == "view.js") + { + return serveFile(wsi, file,"text/javascript"); } - - return 0; + + return serveFile(wsi, "munia.html", "text/html"); + +#if 0 + // callback for confirming to continue with client IP appear in + // protocol 0 callback since no websocket protocol has been agreed + // yet. You can just ignore this if you won't filter on client IP + // since the default uhandled callback return is 0 meaning let the + // connection continue. + + case LWS_CALLBACK_FILTER_NETWORK_CONNECTION: + //lws_get_peer_addresses((int)(long)user, + // client_name, + // sizeof(client_name), + // client_ip, + // sizeof(client_ip)); + //DEBUG(httpd,"Received network connect from %s (%s)\n", + // client_name, client_ip); + + // if we returned non-zero from here, we kill the connection + break; +#endif } @@ -25,8 +25,7 @@ * along with Munia; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#ifndef __MUNIA_HTTP_H__ -#define __MUNIA_HTTP_H__ +#pragma once #include <stdlib.h> @@ -34,10 +33,7 @@ #define LOCAL_RESOURCE_PATH "." -/* this protocol server (always the first one) just knows how to do HTTP */ -int callback_http(struct libwebsocket_context * context, - struct libwebsocket *wsi, - enum libwebsocket_callback_reasons reason, void *user, +// this protocol server (always the first one) just knows how to do HTTP +int callback_http(struct lws *wsi, + enum lws_callback_reasons reason, void *user, void *in, size_t len); - -#endif/*__MUNIA_HTTP_H__*/ diff --git a/src/message.h b/src/message.h index 6e1804d..ea1c444 100644 --- a/src/message.h +++ b/src/message.h @@ -25,81 +25,86 @@ * along with Munia; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#ifndef __MUNIA_MESSAGE_H__ -#define __MUNIA_MESSAGE_H__ +#pragma once #include <list> #include <string> #include "task.h" -namespace cmd { - typedef enum { - observe, - unobserve, - update, - move, - create, - remove, - login, - logout, - error, - } cmd_t; +namespace cmd +{ +typedef enum { + observe, + unobserve, + update, + move, + create, + remove, + login, + logout, + error, +} cmd_t; }; -typedef struct { - std::string user; - std::string password; +typedef struct +{ + std::string user; + std::string password; } login_t; -typedef struct { - taskid_t id; +typedef struct +{ + taskid_t id; } observe_t; -typedef struct { - taskid_t id; +typedef struct +{ + taskid_t id; } unobserve_t; -typedef struct { - taskid_t id; - taskid_t parentid; +typedef struct +{ + taskid_t id; + taskid_t parentid; } create_t; -typedef struct { - taskid_t id; +typedef struct +{ + taskid_t id; } remove_t; -typedef struct { - taskid_t id; - taskid_t parentid; +typedef struct +{ + taskid_t id; + taskid_t parentid; } move_t; -typedef struct { - taskid_t id; - std::string name; - std::string value; +typedef struct +{ + taskid_t id; + std::string name; + std::string value; } update_t; -typedef struct { - cmd::cmd_t cmd; +typedef struct +{ + cmd::cmd_t cmd; - observe_t observe; - unobserve_t unobserve; - create_t create; - remove_t remove; - move_t move; - update_t update; - login_t login; + observe_t observe; + unobserve_t unobserve; + create_t create; + remove_t remove; + move_t move; + update_t update; + login_t login; - TaskIdList nodes; + TaskIdList nodes; - // tagret node id (observed task id) used for transmissions only. - taskid_t tid; - -} message_t; + // tagret node id (observed task id) used for transmissions only. + taskid_t tid; +} message_t; typedef std::list<message_t> MessageList; - -#endif/*__MUNIA_MESSAGE_H__*/ diff --git a/src/messagehandler.cc b/src/messagehandler.cc index b061cc9..ad9b8bb 100644 --- a/src/messagehandler.cc +++ b/src/messagehandler.cc @@ -34,167 +34,185 @@ #include "messageparser.h" -MessageList handle_msg(MessageList msgList, clientid_t wsi) { - - MessageList outmsgs; - - MessageList::iterator it; - for(it = msgList.begin(); - it != msgList.end(); - it++) { - message_t &m = *it; - - if(m.cmd == cmd::login) { - connection_handler.login(wsi, m.login.user, m.login.password); - } - - // If client is not authenticated; do not continue beyond this point... - if(!connection_handler.authenticated(wsi)) continue; - - switch(m.cmd) { - case cmd::create: - { - INFO(messagehandler, "Handling create command\n"); - try { - taskid_t id = m.create.id; - m.nodes = task_manager.createTask(m.create.parentid, &id); - m.create.id = id; - outmsgs.push_back(m); - } - catch (std::exception& e) { - DEBUG(messagehandler, "Error creating task\n"); - } - } - break; - - case cmd::remove: - { - INFO(messagehandler, "Handling remove command\n"); - try { - TaskIdList ids = task_manager.subTasks(m.remove.id); - TaskIdList::reverse_iterator id = ids.rbegin(); - while(id != ids.rend()) { - task_t task = task_manager.task(*id); - - message_t m = create_msg_remove(task); - m.nodes = task_manager.removeTask(task.id); - - outmsgs.push_back(m); - id++; - } - } - catch (std::exception& e) { - DEBUG(messagehandler, "Error remove task\n"); - } - } - break; - - case cmd::move: - { - INFO(messagehandler, "Handling move command\n"); - try { - task_t removetask = task_manager.task(m.move.id); - TaskIdListPair tilpair = - task_manager.moveTask(m.move.id, m.move.parentid); - task_t createtask = task_manager.task(m.move.id); - - /* - TaskIdList commonAncestors; - TaskIdList removeAncestors; - TaskIdList createAncestors; - - // find command ancestors and fill ancestors for remove command - for(TaskIdList::iterator it_remove = tilpair.first.begin(); - it_remove != tilpair.first.end(); it_remove++) { - taskid_t removeid = *it; - bool common = false; - for(TaskIdList::iterator it_create = tilpair.second.begin(); - it_create = != tilpair.second.end(); it_create++) { - taskid_t createid = *id; - if(removeid == createid) { - commandAncestors.push_back(removeid); - common = true; - } - } - if(!common) { - removeAncestors.push_back(removeid); - } - } - - // fill ancestors for create command - for(TaskIdList::iterator it_create = tilpair.second.begin(); - it_create = != tilpair.second.end(); it_create++) { - taskid_t createid = *id; - if(removeid == createid) { - commandAncestors.push_back(removeid); - common = true; - } - } - */ - - message_t removemsg = create_msg_remove(removetask); - removemsg.nodes = tilpair.first; - message_t createmsg = create_msg_create(createtask); - createmsg.nodes = tilpair.second; - - outmsgs.push_back(removemsg); - outmsgs.push_back(createmsg); - } - catch (std::exception& e) { - DEBUG(messagehandler, "Error moving task\n"); - } - } - break; - - case cmd::observe: - { - //connection_handler.observe(wsi, m.observe.id); - outmsgs.push_back(m); - } - break; - - case cmd::unobserve: - //connection_handler.unobserve(wsi, m.observe.id); - outmsgs.push_back(m); - DEBUG(handler, "unobserve: %d\n", m.unobserve.id); - break; - - case cmd::update: - { - INFO(messagehandler, "Handling update command\n"); - try { - m.nodes = task_manager.updateTask(m.update.id, - m.update.name, m.update.value); - outmsgs.push_back(m); - } - catch (std::exception& e) { - DEBUG(messagehandler, "Error updating task\n"); - } - } - break; - - case cmd::login: - // Already handled, before this switch ... case - break; - - case cmd::logout: - connection_handler.logout(wsi); - break; - - case cmd::error: - ERR(messagehandler, "An error occurred.\n"); - break; - - default: - WARN(messagehandler, "!!! Unknown command %d\n", m.cmd); - break; - } - task_manager.tree.toStdOut(); - DEBUG(messagehandler, "%d affected nodes registered\n", - (int)m.nodes.size()); - } - - return outmsgs; +MessageList handle_msg(MessageList msgList, clientid_t wsi) +{ + + MessageList outmsgs; + + MessageList::iterator it; + for(it = msgList.begin(); it != msgList.end(); it++) + { + message_t &m = *it; + + if(m.cmd == cmd::login) + { + connection_handler.login(wsi, m.login.user, m.login.password); + } + + // If client is not authenticated; do not continue beyond this point... + if(!connection_handler.authenticated(wsi)) + { + continue; + } + + switch(m.cmd) + { + case cmd::create: + { + INFO(messagehandler, "Handling create command\n"); + try + { + taskid_t id = m.create.id; + m.nodes = task_manager.createTask(m.create.parentid, &id); + m.create.id = id; + outmsgs.push_back(m); + } + catch (std::exception& e) + { + DEBUG(messagehandler, "Error creating task\n"); + } + } + break; + + case cmd::remove: + { + INFO(messagehandler, "Handling remove command\n"); + try + { + TaskIdList ids = task_manager.subTasks(m.remove.id); + TaskIdList::reverse_iterator id = ids.rbegin(); + while(id != ids.rend()) + { + task_t task = task_manager.task(*id); + + message_t m = create_msg_remove(task); + m.nodes = task_manager.removeTask(task.id); + + outmsgs.push_back(m); + id++; + } + } + catch (std::exception& e) + { + DEBUG(messagehandler, "Error remove task\n"); + } + } + break; + + case cmd::move: + { + INFO(messagehandler, "Handling move command\n"); + try + { + task_t removetask = task_manager.task(m.move.id); + TaskIdListPair tilpair = + task_manager.moveTask(m.move.id, m.move.parentid); + task_t createtask = task_manager.task(m.move.id); + +// TaskIdList commonAncestors; +// TaskIdList removeAncestors; +// TaskIdList createAncestors; +// +// // find command ancestors and fill ancestors for remove command +// for(TaskIdList::iterator it_remove = tilpair.first.begin(); +// it_remove != tilpair.first.end(); it_remove++) +// { +// taskid_t removeid = *it; +// bool common = false; +// for(TaskIdList::iterator it_create = tilpair.second.begin(); +// it_create = != tilpair.second.end(); it_create++) +// { +// taskid_t createid = *id; +// if(removeid == createid) +// { +// commandAncestors.push_back(removeid); +// common = true; +// } +// } +// if(!common) +// { +// removeAncestors.push_back(removeid); +// } +// } +// +// // fill ancestors for create command +// for(TaskIdList::iterator it_create = tilpair.second.begin(); +// it_create = != tilpair.second.end(); it_create++) +// { +// taskid_t createid = *id; +// if(removeid == createid) +// { +// commandAncestors.push_back(removeid); +// common = true; +// } +// } + + message_t removemsg = create_msg_remove(removetask); + removemsg.nodes = tilpair.first; + message_t createmsg = create_msg_create(createtask); + createmsg.nodes = tilpair.second; + + outmsgs.push_back(removemsg); + outmsgs.push_back(createmsg); + } + catch (std::exception& e) + { + DEBUG(messagehandler, "Error moving task\n"); + } + } + break; + + case cmd::observe: + { + //connection_handler.observe(wsi, m.observe.id); + outmsgs.push_back(m); + } + break; + + case cmd::unobserve: + //connection_handler.unobserve(wsi, m.observe.id); + outmsgs.push_back(m); + DEBUG(handler, "unobserve: %d\n", m.unobserve.id); + break; + + case cmd::update: + { + INFO(messagehandler, "Handling update command\n"); + try + { + m.nodes = task_manager.updateTask(m.update.id, + m.update.name, m.update.value); + outmsgs.push_back(m); + } + catch (std::exception& e) + { + DEBUG(messagehandler, "Error updating task\n"); + } + } + break; + + case cmd::login: + // Already handled, before this switch ... case + break; + + case cmd::logout: + connection_handler.logout(wsi); + break; + + case cmd::error: + ERR(messagehandler, "An error occurred.\n"); + break; + + default: + WARN(messagehandler, "!!! Unknown command %d\n", m.cmd); + break; + } + task_manager.tree.toStdOut(); + DEBUG(messagehandler, "%d affected nodes registered\n", + (int)m.nodes.size()); + } + + return outmsgs; } #ifdef TEST_MSGHANDLER diff --git a/src/messagehandler.h b/src/messagehandler.h index cc2c8a0..52020bc 100644 --- a/src/messagehandler.h +++ b/src/messagehandler.h @@ -25,14 +25,10 @@ * along with Munia; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#ifndef __MUNIA_MSGHANDLER_H__ -#define __MUNIA_MSGHANDLER_H__ +#pragma once #include "messageparser.h" #include "connectionhandler.h" MessageList handle_msg(MessageList inMsgList, clientid_t wsi); - - -#endif/*__MUNIA_MSGHANDLER_H__*/ diff --git a/src/messageparser.cc b/src/messageparser.cc index 55cfe34..d59cccc 100644 --- a/src/messageparser.cc +++ b/src/messageparser.cc @@ -39,306 +39,365 @@ typedef std::vector<std::string> TokenVector; typedef std::list<TokenVector> MsgTokensList; -inline static void parse_into_msg_tokens(std::string& data, - MsgTokensList& msgTokensList) { - TokenVector tokenVector; - std::string token; - bool inside_quote = false; - char prev_ch = '0'; - for(size_t i = 0; i < data.length(); i++) { - char ch = data[i]; - - switch(ch) { - case '\"': - if(prev_ch != '\\') { - inside_quote = !inside_quote; - } else { - token += ch; - } - break; - case ' ': - if(inside_quote) { - DEBUG(msgparser, "Appending %c\n", ch); - token += ch; - } else { - if(token.empty()) continue; // skip multiple white spaces and pre white space - DEBUG(msgparser, "Adding token %s\n", token.c_str()); - tokenVector.push_back(token); - token.clear(); - } - break; - case ';': - if(inside_quote) { - token += ch; - } else { - tokenVector.push_back(token); - msgTokensList.push_back(tokenVector); - tokenVector.clear(); - token.clear(); - } - break; - default: - token += ch; - break; - } - prev_ch = ch; - } - - if(token != "") { - tokenVector.push_back(token); - token.clear(); - } - - if(!tokenVector.empty()) { - msgTokensList.push_back(tokenVector); - tokenVector.clear(); - } - - /* // WARNING: Enabling this will print passwords in plaintext... - // Debug: print tokens - DEBUG(parser, "tokenlists: %d\n", msgTokensList.size()); - MsgTokensList::iterator j = msgTokensList.begin(); - while(j != msgTokensList.end()) { - DEBUG(parser, " tokens: %d\n", j->size()); - int idx = 0; - TokenVector::iterator i = j->begin(); - while(i != j->end()) { - DEBUG(parser, " token[%d]: '%s'\n", idx++, i->c_str()); - i++; - } - j++; - } - */ +inline static void parse_into_msg_tokens(std::string& data, + MsgTokensList& msgTokensList) +{ + TokenVector tokenVector; + std::string token; + bool inside_quote = false; + char prev_ch = '0'; + for(size_t i = 0; i < data.length(); i++) + { + char ch = data[i]; + + switch(ch) + { + case '\"': + if(prev_ch != '\\') + { + inside_quote = !inside_quote; + } + else + { + token += ch; + } + break; + case ' ': + if(inside_quote) + { + DEBUG(msgparser, "Appending %c\n", ch); + token += ch; + } + else + { + if(token.empty()) + { + continue; // skip multiple white spaces and pre white space + } + DEBUG(msgparser, "Adding token %s\n", token.c_str()); + tokenVector.push_back(token); + token.clear(); + } + break; + case ';': + if(inside_quote) + { + token += ch; + } + else + { + tokenVector.push_back(token); + msgTokensList.push_back(tokenVector); + tokenVector.clear(); + token.clear(); + } + break; + default: + token += ch; + break; + } + prev_ch = ch; + } + + if(token != "") + { + tokenVector.push_back(token); + token.clear(); + } + + if(!tokenVector.empty()) + { + msgTokensList.push_back(tokenVector); + tokenVector.clear(); + } + + //// WARNING: Enabling this will print passwords in plaintext... + //// Debug: print tokens + //DEBUG(parser, "tokenlists: %d\n", msgTokensList.size()); + //MsgTokensList::iterator j = msgTokensList.begin(); + //while(j != msgTokensList.end()) + //{ + // DEBUG(parser, " tokens: %d\n", j->size()); + // int idx = 0; + // TokenVector::iterator i = j->begin(); + // while(i != j->end()) + // { + // DEBUG(parser, " token[%d]: '%s'\n", idx++, i->c_str()); + // i++; + // } + // j++; + //} + } static taskid_t getId(std::map<std::string, taskid_t> &sym, std::string token) { - bool isnumeric = true; - for(size_t i = 0; i < token.size(); i++) { - isnumeric &= (token[i] >= '0' && token[i] <= '9'); - } - - DEBUG(getid, "======= %d %s\n", isnumeric, token.c_str()); - - if(isnumeric) { - taskid_t id = atoi(token.c_str()); - DEBUG(getid, "======= id: %d\n", id); - return id; - } - - if(sym.find(token) == sym.end()) sym[token] = task_manager.createId(); - return sym[token]; + bool isnumeric = true; + for(size_t i = 0; i < token.size(); i++) + { + isnumeric &= (token[i] >= '0' && token[i] <= '9'); + } + + DEBUG(getid, "======= %d %s\n", isnumeric, token.c_str()); + + if(isnumeric) + { + taskid_t id = atoi(token.c_str()); + DEBUG(getid, "======= id: %d\n", id); + return id; + } + + if(sym.find(token) == sym.end()) + { + sym[token] = task_manager.createId(); + } + + return sym[token]; } inline static void create_msg_list(MsgTokensList& msgTokensList, MessageList& msgList, - bool clientmode) { - size_t origin = 0; - if(clientmode) { - origin = 1; - } + bool clientmode) +{ + size_t origin = 0; + if(clientmode) + { + origin = 1; + } + + std::map<std::string, taskid_t> sym; - std::map<std::string, taskid_t> sym; + MsgTokensList::iterator it_msg; + for(it_msg = msgTokensList.begin(); it_msg != msgTokensList.end(); it_msg++) + { + TokenVector t = *it_msg; - MsgTokensList::iterator it_msg; - for(it_msg = msgTokensList.begin(); it_msg != msgTokensList.end(); it_msg++) { - TokenVector t = *it_msg; + //malformed msg + if(t.size() < origin+1) + { + continue; + } - //malformed msg - if(t.size() < origin+1) continue; - - message_t m; + message_t m; - DEBUG(msgparser, "t[%d] : %s, running in clientmode: %d\n", - (int)origin, t[origin].c_str(), clientmode); + DEBUG(msgparser, "t[%d] : %s, running in clientmode: %d\n", + (int)origin, t[origin].c_str(), clientmode); // DEBUG(msgparser, "%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] == "login") m.cmd = cmd::login; - else if(t[origin] == "logout") m.cmd = cmd::logout; - 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; - - switch(m.cmd) { - case cmd::observe: { - if(t.size() != origin+1+1) { - DEBUG(msgparser, "Wrong number of parameters\n"); - continue; - } - m.observe.id = getId(sym, t[origin+1]);//atoi(t[origin+1].c_str()); - break; - } - case cmd::unobserve: { - if(t.size() != origin+1+1) { - DEBUG(msgparser, "Wrong number of parameters\n"); - continue; - } - m.unobserve.id = getId(sym, t[origin+1]);//atoi(t[origin+1].c_str()); - DEBUG(msgparser, "unobserve @ %d\n", m.unobserve.id); - break; - } - case cmd::login: { - if(t.size() != origin+1+2) { - DEBUG(msgparser, "Wrong number of parameters\n"); - continue; - } - m.login.user = t[origin+1]; - m.login.password = t[origin+2]; - DEBUG(msgparser, "login %s\n", m.login.user.c_str()); - break; - } - case cmd::logout: - if(t.size() != origin+1) { - DEBUG(msgparser, "Wrong number of parameters\n"); - continue; - } - break; - case cmd::create: { - if(!clientmode && t.size() != origin+1+2) { - DEBUG(msgparser, "Wrong number of parameters\n"); - continue; - } - if(clientmode && t.size() != origin+1+2) { - DEBUG(msgparser, "Wrong number of parameters\n"); - continue; - } - if(clientmode) { - m.create.id = getId(sym, t[origin+1]);//atoi(t[origin+1].c_str()); - m.create.parentid = getId(sym, t[origin+2]);// atoi(t[origin+2].c_str()); - } - else { - m.create.id = getId(sym, t[origin+1]);//atoi(t[origin+1].c_str()); - m.create.parentid = getId(sym, t[origin+2]);//atoi(t[origin+1].c_str()); - } - break; - } - case cmd::remove: { - if(t.size() != origin+1+1) { - DEBUG(msgparser, "Wrong number of parameters\n"); - continue; - } - m.remove.id = getId(sym, t[origin+1]);//atoi(t[origin+1].c_str()); - break; - } - case cmd::move: { - if(t.size() != origin+2+1) { - DEBUG(msgparser, "Wrong number of parameters\n"); - continue; - } - m.move.id = getId(sym, t[origin+1]);//atoi(t[origin+1].c_str()); - m.move.parentid = getId(sym, t[origin+2]);//atoi(t[origin+2].c_str()); - break; - } - case cmd::update: { - if(t.size() != origin+3+1) { - DEBUG(msgparser, "Wrong number of parameters\n"); - continue; - } - m.update.id = getId(sym, t[origin+1]);//atoi(t[origin+1].c_str()); - m.update.name = t[origin+2]; - m.update.value = t[origin+3]; - break; - } - default: - break; - }; - msgList.push_back(m); - } + if(t[origin] == "observe") m.cmd = cmd::observe; + else if(t[origin] == "unobserve") m.cmd = cmd::unobserve; + else if(t[origin] == "login") m.cmd = cmd::login; + else if(t[origin] == "logout") m.cmd = cmd::logout; + 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; + + switch(m.cmd) + { + case cmd::observe: + { + if(t.size() != origin+1+1) + { + DEBUG(msgparser, "Wrong number of parameters\n"); + continue; + } + m.observe.id = getId(sym, t[origin+1]);//atoi(t[origin+1].c_str()); + } + break; + + case cmd::unobserve: + { + if(t.size() != origin+1+1) + { + DEBUG(msgparser, "Wrong number of parameters\n"); + continue; + } + m.unobserve.id = getId(sym, t[origin+1]);//atoi(t[origin+1].c_str()); + DEBUG(msgparser, "unobserve @ %d\n", m.unobserve.id); + } + break; + + case cmd::login: + { + if(t.size() != origin+1+2) + { + DEBUG(msgparser, "Wrong number of parameters\n"); + continue; + } + m.login.user = t[origin+1]; + m.login.password = t[origin+2]; + DEBUG(msgparser, "login %s\n", m.login.user.c_str()); + } + break; + + case cmd::logout: + if(t.size() != origin+1) + { + DEBUG(msgparser, "Wrong number of parameters\n"); + continue; + } + break; + + case cmd::create: + { + if(!clientmode && t.size() != origin+1+2) + { + DEBUG(msgparser, "Wrong number of parameters\n"); + continue; + } + if(clientmode && t.size() != origin+1+2) + { + DEBUG(msgparser, "Wrong number of parameters\n"); + continue; + } + if(clientmode) + { + m.create.id = getId(sym, t[origin+1]);//atoi(t[origin+1].c_str()); + m.create.parentid = getId(sym, t[origin+2]);// atoi(t[origin+2].c_str()); + } + else + { + m.create.id = getId(sym, t[origin+1]);//atoi(t[origin+1].c_str()); + m.create.parentid = getId(sym, t[origin+2]);//atoi(t[origin+1].c_str()); + } + break; + } + case cmd::remove: + { + if(t.size() != origin+1+1) + { + DEBUG(msgparser, "Wrong number of parameters\n"); + continue; + } + m.remove.id = getId(sym, t[origin+1]);//atoi(t[origin+1].c_str()); + } + break; + case cmd::move: + { + if(t.size() != origin+2+1) + { + DEBUG(msgparser, "Wrong number of parameters\n"); + continue; + } + m.move.id = getId(sym, t[origin+1]);//atoi(t[origin+1].c_str()); + m.move.parentid = getId(sym, t[origin+2]);//atoi(t[origin+2].c_str()); + } + break; + case cmd::update: + { + if(t.size() != origin+3+1) + { + DEBUG(msgparser, "Wrong number of parameters\n"); + continue; + } + m.update.id = getId(sym, t[origin+1]);//atoi(t[origin+1].c_str()); + m.update.name = t[origin+2]; + m.update.value = t[origin+3]; + } + break; + default: + break; + }; + msgList.push_back(m); + } } -MessageList parse_msg(std::string data) { - DEBUG(msgparser, "Parsing: '%s'\n", data.c_str()); +MessageList parse_msg(std::string data) +{ + DEBUG(msgparser, "Parsing: '%s'\n", data.c_str()); + + MsgTokensList msgTokensList; + parse_into_msg_tokens(data, msgTokensList); - MsgTokensList msgTokensList; - parse_into_msg_tokens(data, msgTokensList); - - MessageList msgList; - create_msg_list(msgTokensList, msgList, false); - - return msgList; + MessageList msgList; + create_msg_list(msgTokensList, msgList, false); + + return msgList; } -MessageList parse_msg_client(std::string data) { - DEBUG(msgparser, "Parsing: '%s'\n", data.c_str()); - MsgTokensList msgTokensList; - parse_into_msg_tokens(data, msgTokensList); - - MessageList msgList; - create_msg_list(msgTokensList, msgList, true); - - return msgList; +MessageList parse_msg_client(std::string data) +{ + DEBUG(msgparser, "Parsing: '%s'\n", data.c_str()); + MsgTokensList msgTokensList; + parse_into_msg_tokens(data, msgTokensList); + + MessageList msgList; + create_msg_list(msgTokensList, msgList, true); + + return msgList; } -std::string msg_tostring(message_t m) { - char* buf = NULL; - switch(m.cmd) { - case cmd::create: { - asprintf(&buf, "create %d %d;", - m.create.id, - m.create.parentid); - break; - } - case cmd::remove: { - asprintf(&buf, "remove %d;", m.remove.id); - break; - } - case cmd::move: { - asprintf(&buf, "move %d %d;", m.move.id, m.move.parentid); - break; - } - case cmd::update: { - asprintf(&buf, "update %d \"%s\" \"%s\";", - m.update.id, m.update.name.c_str(), m.update.value.c_str()); - break; - }; - default: - break; - } - - std::string r; - if(buf) { - r = buf; - free(buf); - } - - return r; +std::string msg_tostring(message_t m) +{ + char* buf = NULL; + switch(m.cmd) + { + case cmd::create: + asprintf(&buf, "create %d %d;", + m.create.id, + m.create.parentid); + break; + case cmd::remove: + asprintf(&buf, "remove %d;", m.remove.id); + break; + case cmd::move: + asprintf(&buf, "move %d %d;", m.move.id, m.move.parentid); + break; + case cmd::update: + asprintf(&buf, "update %d \"%s\" \"%s\";", + m.update.id, m.update.name.c_str(), m.update.value.c_str()); + break; + default: + break; + } + + std::string r; + if(buf) + { + r = buf; + free(buf); + } + + return r; } -message_t create_msg_create(task_t t) { - message_t m; - m.cmd = cmd::create; - m.create.id = t.id; - m.create.parentid = t.parentid; - return m; +message_t create_msg_create(task_t t) +{ + message_t m; + m.cmd = cmd::create; + m.create.id = t.id; + m.create.parentid = t.parentid; + return m; } -message_t create_msg_update(task_t t, const std::string &attr) { - message_t m; - m.cmd = cmd::update; - m.update.id = t.id; - m.update.name = attr; - m.update.value = t.attributes[attr]; - return m; +message_t create_msg_update(task_t t, const std::string &attr) +{ + message_t m; + m.cmd = cmd::update; + m.update.id = t.id; + m.update.name = attr; + m.update.value = t.attributes[attr]; + return m; } -message_t create_msg_remove(task_t t) { - message_t m; - m.cmd = cmd::remove; - m.remove.id = t.id; - return m; +message_t create_msg_remove(task_t t) +{ + message_t m; + m.cmd = cmd::remove; + m.remove.id = t.id; + return m; } -message_t create_msg_move(taskid_t id, taskid_t to) { - message_t m; - m.cmd = cmd::move; - m.move.id = id; - m.move.parentid = to; - return m; +message_t create_msg_move(taskid_t id, taskid_t to) +{ + message_t m; + m.cmd = cmd::move; + m.move.id = id; + m.move.parentid = to; + return m; } #ifdef TEST_MSGPARSER diff --git a/src/messageparser.h b/src/messageparser.h index 4cbacfa..bb9d10f 100644 --- a/src/messageparser.h +++ b/src/messageparser.h @@ -25,8 +25,7 @@ * along with Munia; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#ifndef __MUNIA_MESSAGEPARSER_H__ -#define __MUNIA_MESSAGEPARSER_H__ +#pragma once #include "message.h" @@ -41,6 +40,4 @@ std::string msg_tostring(message_t msg); message_t create_msg_create(task_t task); message_t create_msg_update(task_t task, const std::string &attr); message_t create_msg_remove(task_t task); -message_t create_msg_move(taskid_t id, taskid_t to); - -#endif/*__MUNIA_MESSAGEPARSER_H__*/ +message_t create_msg_move(taskid_t id, taskid_t to); diff --git a/src/munia_proto.cc b/src/munia_proto.cc index 0f03a84..6e944cf 100644 --- a/src/munia_proto.cc +++ b/src/munia_proto.cc @@ -46,246 +46,272 @@ #if 0 static void dump_handshake_info(struct lws_tokens *lwst) { - int n; - static const char *token_names[WSI_TOKEN_COUNT] = { - /*[WSI_TOKEN_GET_URI] =*/ "GET URI", - /*[WSI_TOKEN_HOST] =*/ "Host", - /*[WSI_TOKEN_CONNECTION] =*/ "Connection", - /*[WSI_TOKEN_KEY1] =*/ "key 1", - /*[WSI_TOKEN_KEY2] =*/ "key 2", - /*[WSI_TOKEN_PROTOCOL] =*/ "Protocol", - /*[WSI_TOKEN_UPGRADE] =*/ "Upgrade", - /*[WSI_TOKEN_ORIGIN] =*/ "Origin", - /*[WSI_TOKEN_DRAFT] =*/ "Draft", - /*[WSI_TOKEN_CHALLENGE] =*/ "Challenge", - - /* new for 04 */ - /*[WSI_TOKEN_KEY] =*/ "Key", - /*[WSI_TOKEN_VERSION] =*/ "Version", - /*[WSI_TOKEN_SWORIGIN] =*/ "Sworigin", - - /* new for 05 */ - /*[WSI_TOKEN_EXTENSIONS] =*/ "Extensions", - - /* client receives these */ - /*[WSI_TOKEN_ACCEPT] =*/ "Accept", - /*[WSI_TOKEN_NONCE] =*/ "Nonce", - /*[WSI_TOKEN_HTTP] =*/ "Http", - /*[WSI_TOKEN_MUXURL] =*/ "MuxURL", - }; - - for (n = 0; n < WSI_TOKEN_COUNT; n++) { - if (lwst[n].token == NULL || lwst[n].token_len == 0) continue; - DEBUG(proto," %s = ", token_names[n]); - if(fwrite(lwst[n].token, 1, lwst[n].token_len, stderr)) {} - DEBUG(proto,"\n"); - } + int n; + static const char *token_names[WSI_TOKEN_COUNT] = { + /*[WSI_TOKEN_GET_URI] =*/ "GET URI", + /*[WSI_TOKEN_HOST] =*/ "Host", + /*[WSI_TOKEN_CONNECTION] =*/ "Connection", + /*[WSI_TOKEN_KEY1] =*/ "key 1", + /*[WSI_TOKEN_KEY2] =*/ "key 2", + /*[WSI_TOKEN_PROTOCOL] =*/ "Protocol", + /*[WSI_TOKEN_UPGRADE] =*/ "Upgrade", + /*[WSI_TOKEN_ORIGIN] =*/ "Origin", + /*[WSI_TOKEN_DRAFT] =*/ "Draft", + /*[WSI_TOKEN_CHALLENGE] =*/ "Challenge", + + /* new for 04 */ + /*[WSI_TOKEN_KEY] =*/ "Key", + /*[WSI_TOKEN_VERSION] =*/ "Version", + /*[WSI_TOKEN_SWORIGIN] =*/ "Sworigin", + + /* new for 05 */ + /*[WSI_TOKEN_EXTENSIONS] =*/ "Extensions", + + /* client receives these */ + /*[WSI_TOKEN_ACCEPT] =*/ "Accept", + /*[WSI_TOKEN_NONCE] =*/ "Nonce", + /*[WSI_TOKEN_HTTP] =*/ "Http", + /*[WSI_TOKEN_MUXURL] =*/ "MuxURL", + }; + + for (n = 0; n < WSI_TOKEN_COUNT; n++) + { + if (lwst[n].token == NULL || lwst[n].token_len == 0) + { + continue; + } + DEBUG(proto," %s = ", token_names[n]); + if(fwrite(lwst[n].token, 1, lwst[n].token_len, stderr)) + { + } + DEBUG(proto,"\n"); + } } #endif typedef std::list<message_t> msgqueue_t; -static std::map<struct libwebsocket *, msgqueue_t > msgqueue; -struct libwebsocket *current_client = NULL; +static std::map<struct lws *, msgqueue_t > msgqueue; +struct lws *current_client = NULL; -int callback_lws_task(struct libwebsocket_context * context, - struct libwebsocket *wsi, - enum libwebsocket_callback_reasons reason, +int callback_lws_task(struct lws *wsi, + enum lws_callback_reasons reason, void *user, void *in, size_t len) { - task_manager.tree.toStdOut(); - - DEBUG(proto, "Callback on %p\n", wsi); - - switch (reason) { - case LWS_CALLBACK_ESTABLISHED: - connection_handler.init(wsi); - break; - - case LWS_CALLBACK_CLOSED: - connection_handler.close(wsi); - break; - - case LWS_CALLBACK_SERVER_WRITEABLE: - { - // - // Find and collapse remove/create msg's into single move msg at - // the position of the remove msg. - // - msgqueue_t::iterator i = msgqueue[wsi].begin(); - while(i != msgqueue[wsi].end()) { - message_t &msg = *i; - if(msg.cmd == cmd::remove) { - - msgqueue_t::iterator j = msgqueue[wsi].begin(); - while(j != msgqueue[wsi].end()) { - message_t m = *j; - if(m.cmd == cmd::create && // msg was a create msg? - // created with same ids as we just removed? - msg.remove.id == m.create.id && - msg.tid == m.tid) { - break; - } - j++; - } - - // collapse into move msg - if(j != msgqueue[wsi].end()) { - taskid_t id = j->create.id; - taskid_t parentid = j->create.parentid; - msgqueue[wsi].erase(j); // erase create msg - msg.cmd = cmd::move; - msg.move.id = id; - msg.move.parentid = parentid; - } - } - i++; - } - - std::string msgstr; - msgstr.append((size_t)LWS_SEND_BUFFER_PRE_PADDING, ' '); - - if(msgqueue[wsi].size() == 0 && wsi == current_client) msgstr += ";"; - - while(msgqueue[wsi].size() > 0) { - message_t msg = msgqueue[wsi].front(); - msgqueue[wsi].pop_front(); - char buf[32]; - sprintf(buf, "%d", msg.tid); - if(msgstr.size() > LWS_SEND_BUFFER_PRE_PADDING) msgstr += " "; - msgstr += std::string(buf) + " " + msg_tostring(msg); - } - - - msgstr.append((size_t)LWS_SEND_BUFFER_POST_PADDING, ' '); - - int n = libwebsocket_write(wsi, (unsigned char *) - msgstr.c_str() + - LWS_SEND_BUFFER_PRE_PADDING, - msgstr.length() - - LWS_SEND_BUFFER_POST_PADDING - - LWS_SEND_BUFFER_PRE_PADDING, - LWS_WRITE_TEXT); - if(n < 0) { - DEBUG(proto,"ERROR writing to socket"); - exit(1); - } - } - - break; - - /* - case LWS_CALLBACK_BROADCAST: - printf("LWS_CALLBACK_BROADCAST\n"); - n = libwebsocket_write(wsi, (unsigned char*)in, len, LWS_WRITE_TEXT); - if (n < 0) DEBUG(proto, "task write failed\n"); - break; - */ - - case LWS_CALLBACK_RECEIVE: - { - DEBUG(proto, "LWS_CALLBACK_RECEIVE\n"); - - current_client = wsi; - - DEBUG(proto, "%s\n", (char*)in); - std::string data; - data.append((char*)in, len); - - MessageList mlst = parse_msg(data); - DEBUG(proto, "Handling %d incoming message\n", (int)mlst.size()); - MessageList omsgs = handle_msg(mlst, wsi); - DEBUG(proto, "Handling %d outgoing messages\n", (int)omsgs.size()); - - MessageList::iterator omi = omsgs.begin(); - while(omi != omsgs.end()) { - DEBUG(proto, "Message\n"); - if(omi->cmd == cmd::observe) { - connection_handler.observe(wsi, omi->observe.id); - TaskIdList ids; - try { - ids = task_manager.subTasks(omi->observe.id); - } catch(...) { - DEBUG(proto, "No such node %d\n", omi->observe.id); - omi++; - continue; - } - TaskIdList::iterator id = ids.begin(); - while(id != ids.end()) { - task_t task = task_manager.task(*id); - - message_t createmsg = create_msg_create(task); - createmsg.tid = omi->observe.id; - msgqueue[wsi].push_back(createmsg); - - std::map<std::string, std::string>::iterator ai = - task.attributes.begin(); - while(ai != task.attributes.end()) { - message_t updatemsg = create_msg_update(task, ai->first); - DEBUG(observe, "%s\n", ai->first.c_str()); - updatemsg.tid = omi->observe.id; - msgqueue[wsi].push_back(updatemsg); - ai++; - } - - id++; - } - - } else if(omi->cmd == cmd::unobserve) { - connection_handler.unobserve(wsi, omi->unobserve.id); - TaskIdList ids; - try { - ids = task_manager.subTasks(omi->unobserve.id); - } catch(...) { - DEBUG(proto, "No such node %d\n", omi->unobserve.id); - omi++; - continue; - } - TaskIdList::reverse_iterator id = ids.rbegin(); - while(id != ids.rend()) { - task_t task = task_manager.task(*id); - - message_t removemsg = create_msg_remove(task); - removemsg.tid = omi->unobserve.id; - msgqueue[wsi].push_back(removemsg); - DEBUG(unobserve, "remove id: %d\n", *id); - - id++; - } - - } else { - DEBUG(proto, "%d nodes affected by command\n", - (int)omi->nodes.size()); - - ObserverList clients = connection_handler.observerlist(omi->nodes); - DEBUG(proto, "Writing message to %d clients\n", (int)clients.size()); - - ObserverList::iterator ci = clients.begin(); - while(ci != clients.end()) { - clientid_t clientid = (*ci).first; - taskid_t tid = (*ci).second; - - DEBUG(proto, "Observer id of task: %d\n", tid); - - message_t msg = *omi; - msg.tid = tid; - - msgqueue[clientid].push_back(msg); - - ci++; - } - } - - omi++; - } - - libwebsocket_callback_on_writable_all_protocol( - libwebsockets_get_protocol(wsi)); - } - break; - - default: - break; - } - - return 0; + task_manager.tree.toStdOut(); + + DEBUG(proto, "Callback on %p\n", wsi); + + switch (reason) + { + case LWS_CALLBACK_ESTABLISHED: + connection_handler.init(wsi); + break; + + case LWS_CALLBACK_CLOSED: + connection_handler.close(wsi); + break; + + case LWS_CALLBACK_SERVER_WRITEABLE: + { + // + // Find and collapse remove/create msg's into single move msg at + // the position of the remove msg. + // + msgqueue_t::iterator i = msgqueue[wsi].begin(); + while(i != msgqueue[wsi].end()) { + message_t &msg = *i; + if(msg.cmd == cmd::remove) + { + msgqueue_t::iterator j = msgqueue[wsi].begin(); + while(j != msgqueue[wsi].end()) + { + message_t m = *j; + if(m.cmd == cmd::create && // msg was a create msg? + // created with same ids as we just removed? + msg.remove.id == m.create.id && + msg.tid == m.tid) + { + break; + } + j++; + } + + // collapse into move msg + if(j != msgqueue[wsi].end()) + { + taskid_t id = j->create.id; + taskid_t parentid = j->create.parentid; + msgqueue[wsi].erase(j); // erase create msg + msg.cmd = cmd::move; + msg.move.id = id; + msg.move.parentid = parentid; + } + } + i++; + } + + std::string msgstr; + msgstr.append((size_t)LWS_SEND_BUFFER_PRE_PADDING, ' '); + + if(msgqueue[wsi].size() == 0 && wsi == current_client) msgstr += ";"; + + while(msgqueue[wsi].size() > 0) + { + message_t msg = msgqueue[wsi].front(); + msgqueue[wsi].pop_front(); + char buf[32]; + sprintf(buf, "%d", msg.tid); + if(msgstr.size() > LWS_SEND_BUFFER_PRE_PADDING) + { + msgstr += " "; + } + msgstr += std::string(buf) + " " + msg_tostring(msg); + } + + msgstr.append((size_t)LWS_SEND_BUFFER_POST_PADDING, ' '); + + int n = lws_write(wsi, (unsigned char *) + msgstr.c_str() + + LWS_SEND_BUFFER_PRE_PADDING, + msgstr.length() - + LWS_SEND_BUFFER_POST_PADDING - + LWS_SEND_BUFFER_PRE_PADDING, + LWS_WRITE_TEXT); + if(n < 0) + { + DEBUG(proto,"ERROR writing to socket"); + exit(1); + } + } + + break; + +// case LWS_CALLBACK_BROADCAST: +// printf("LWS_CALLBACK_BROADCAST\n"); +// n = lws_write(wsi, (unsigned char*)in, len, LWS_WRITE_TEXT); +// if (n < 0) DEBUG(proto, "task write failed\n"); +// break; + + case LWS_CALLBACK_RECEIVE: + { + DEBUG(proto, "LWS_CALLBACK_RECEIVE\n"); + + current_client = wsi; + + DEBUG(proto, "%s\n", (char*)in); + std::string data; + data.append((char*)in, len); + + MessageList mlst = parse_msg(data); + DEBUG(proto, "Handling %d incoming message\n", (int)mlst.size()); + MessageList omsgs = handle_msg(mlst, wsi); + DEBUG(proto, "Handling %d outgoing messages\n", (int)omsgs.size()); + + MessageList::iterator omi = omsgs.begin(); + while(omi != omsgs.end()) + { + DEBUG(proto, "Message\n"); + if(omi->cmd == cmd::observe) + { + connection_handler.observe(wsi, omi->observe.id); + TaskIdList ids; + try + { + ids = task_manager.subTasks(omi->observe.id); + } + catch(...) + { + DEBUG(proto, "No such node %d\n", omi->observe.id); + omi++; + continue; + } + TaskIdList::iterator id = ids.begin(); + while(id != ids.end()) + { + task_t task = task_manager.task(*id); + + message_t createmsg = create_msg_create(task); + createmsg.tid = omi->observe.id; + msgqueue[wsi].push_back(createmsg); + + std::map<std::string, std::string>::iterator ai = + task.attributes.begin(); + while(ai != task.attributes.end()) + { + message_t updatemsg = create_msg_update(task, ai->first); + DEBUG(observe, "%s\n", ai->first.c_str()); + updatemsg.tid = omi->observe.id; + msgqueue[wsi].push_back(updatemsg); + ai++; + } + + id++; + } + } + else if(omi->cmd == cmd::unobserve) + { + connection_handler.unobserve(wsi, omi->unobserve.id); + TaskIdList ids; + try + { + ids = task_manager.subTasks(omi->unobserve.id); + } + catch(...) + { + DEBUG(proto, "No such node %d\n", omi->unobserve.id); + omi++; + continue; + } + TaskIdList::reverse_iterator id = ids.rbegin(); + while(id != ids.rend()) + { + task_t task = task_manager.task(*id); + + message_t removemsg = create_msg_remove(task); + removemsg.tid = omi->unobserve.id; + msgqueue[wsi].push_back(removemsg); + DEBUG(unobserve, "remove id: %d\n", *id); + + id++; + } + + } + else + { + DEBUG(proto, "%d nodes affected by command\n", + (int)omi->nodes.size()); + + ObserverList clients = connection_handler.observerlist(omi->nodes); + DEBUG(proto, "Writing message to %d clients\n", (int)clients.size()); + + ObserverList::iterator ci = clients.begin(); + while(ci != clients.end()) + { + clientid_t clientid = (*ci).first; + taskid_t tid = (*ci).second; + + DEBUG(proto, "Observer id of task: %d\n", tid); + + message_t msg = *omi; + msg.tid = tid; + + msgqueue[clientid].push_back(msg); + + ci++; + } + } + + omi++; + } + + lws_callback_on_writable_all_protocol(lws_get_context(wsi), + lws_get_protocol(wsi)); + } + break; + + default: + break; + } + + return 0; } diff --git a/src/munia_proto.h b/src/munia_proto.h index db10c16..a2ad38f 100644 --- a/src/munia_proto.h +++ b/src/munia_proto.h @@ -25,20 +25,17 @@ * along with Munia; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#ifndef __MUNIA_MUNIA_PROTO_H__ -#define __MUNIA_MUNIA_PROTO_H__ +#pragma once #include <stdlib.h> #include <libwebsockets.h> -int callback_lws_task(struct libwebsocket_context *context, - struct libwebsocket *wsi, - enum libwebsocket_callback_reasons reason, +int callback_lws_task(struct lws *wsi, + enum lws_callback_reasons reason, void *user, void *in, size_t len); -struct per_session_data__lws_task { - struct libwebsocket *wsi; +struct per_session_data__lws_task +{ + struct lws *wsi; }; - -#endif/*__MUNIA_MUNIA_PROTO_H__*/ diff --git a/src/muniacli.cc b/src/muniacli.cc index 9583957..f28c810 100644 --- a/src/muniacli.cc +++ b/src/muniacli.cc @@ -42,53 +42,53 @@ static bool run; static std::string msgs; -struct per_session_data__lws_task { - struct libwebsocket *wsi; +struct per_session_data__lws_task +{ + struct lws *wsi; }; -static int callback_lws_task(struct libwebsocket_context *me, - struct libwebsocket *wsi, - enum libwebsocket_callback_reasons reason, - void *user, void *in, size_t len) +static int callback_lws_task(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]; + LWS_SEND_BUFFER_POST_PADDING]; int l; - std::string r; + std::string r; - switch (reason) { + switch (reason) + { case LWS_CALLBACK_CLOSED: -// fprintf(stderr, "mirror: LWS_CALLBACK_CLOSED\n"); + //fprintf(stderr, "mirror: LWS_CALLBACK_CLOSED\n"); break; case LWS_CALLBACK_CLIENT_ESTABLISHED: - libwebsocket_callback_on_writable(me, wsi); + lws_callback_on_writable(wsi); break; case LWS_CALLBACK_CLIENT_RECEIVE: -// pretty_print((char*)in); - printf("%s\n", (char*)in); - libwebsocket_callback_on_writable(me, wsi); + //pretty_print((char*)in); + printf("%s\n", (char*)in); + lws_callback_on_writable(wsi); -// if(!interactive) run = false; + //if(!interactive) run = false; run = false; - break; + 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()); - - libwebsocket_write(wsi, &buf[LWS_SEND_BUFFER_PRE_PADDING], - l, LWS_WRITE_TEXT); + //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; } @@ -96,124 +96,138 @@ static int callback_lws_task(struct libwebsocket_context *me, return 0; } -static struct libwebsocket_protocols protocols[] = { - { "lws-task-protocol", callback_lws_task, - sizeof(struct per_session_data__lws_task) - }, - { NULL, NULL, 0 } // End of list +static struct lws_protocols protocols[] = +{ + { "lws-task-protocol", callback_lws_task, + sizeof(struct per_session_data__lws_task) + }, + { nullptr, nullptr, 0 } // End of list }; int client(const char *address, int port) { // printf("Connection to %s on port %d\n", address, port); - struct libwebsocket_context *context; - struct libwebsocket *wsi_task = NULL; + struct lws_context *context; + struct lws *wsi_task = nullptr; int ietf_version = -1; // latest - lws_set_log_level(0, NULL); - struct lws_context_creation_info info; - memset(&info, 0, sizeof info); - info.port = CONTEXT_PORT_NO_LISTEN; - info.iface = NULL; // What is this? - info.protocols = protocols; - info.extensions = libwebsocket_get_internal_extensions(); + 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 = libwebsocket_create_context(&info); + context = lws_create_context(&info); - if (context == NULL) { - fprintf(stderr, "Creating libwebsocket context failed\n"); + 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 = libwebsocket_service(context, 10); - - if (wsi_task == NULL) { - wsi_task = libwebsocket_client_connect(context, address, port, - 0, "/", address, address, - "lws-task-protocol", - ietf_version); - - if (wsi_task == NULL) { - fprintf(stderr, "libwebsocket task connect failed\n"); + // 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_task == nullptr) + { + wsi_task = lws_client_connect(context, address, port, + 0, "/", address, address, + "lws-task-protocol", + ietf_version); + + if(wsi_task == nullptr) + { + fprintf(stderr, "lws task connect failed\n"); return -1; } - else { - } + else + { + //... + } - } else { -// fprintf(stderr, "closing mirror session\n"); -// libwebsocket_close_and_free_session(context, -// wsi_mirror, LWS_CLOSE_STATUS_GOINGAWAY); + } + else + { + //fprintf(stderr, "closing mirror session\n"); + //lws_close_and_free_session(context, + // wsi_mirror, LWS_CLOSE_STATUS_GOINGAWAY); } - if(!run) break; + if(!run) + { + break; + } } - libwebsocket_context_destroy(context); + lws_context_destroy(context); return 0; } static struct option options[] = { - { "command", required_argument, NULL, 'c'}, - { "help", no_argument, NULL, 'h' }, - { "host", required_argument, NULL, 'H'}, - { "port", required_argument, NULL, 'p' }, - { "raw", no_argument, NULL, 'r'}, - { NULL, 0, 0, 0 } + { "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]... TASK COMMAND\n" - "Commandline client to munia." - "Options:\n" - " -p, --port Port on host\n" - " -H, --host Host\n" - " -c, --command Command\n"; +static const char* USAGE = + "Usage: muniacli [OPTION]... TASK 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; + 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, NULL); - 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; + 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 @@ -221,12 +235,13 @@ enum demo_protocols { PROTOCOL_TASK }; -enum cmd_t { - DEFAULT, - CREATE, - LIST, - REMOVE, - UPDATE +enum cmd_t +{ + DEFAULT, + CREATE, + LIST, + REMOVE, + UPDATE }; static bool run; @@ -240,114 +255,124 @@ 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 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(taskid); + +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(taskid); } -static int callback_task(struct libwebsocket_context *me, - struct libwebsocket *wsi, - enum libwebsocket_callback_reasons reason, +static int callback_task(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) { + char msg[4096]; + std::string r; + switch (reason) + { case LWS_CALLBACK_CLOSED: - fprintf(stderr, "mirror: LWS_CALLBACK_CLOSED\n"); - // wsi_mirror = NULL; + fprintf(stderr, "mirror: LWS_CALLBACK_CLOSED\n"); + // wsi_mirror = nullptr; break; case LWS_CALLBACK_CLIENT_ESTABLISHED: - libwebsocket_callback_on_writable(me, wsi); + 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); - libwebsocket_callback_on_writable(me, wsi); - - if(!interactive) run = false; + //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()); - - libwebsocket_write(wsi, &buf[LWS_SEND_BUFFER_PRE_PADDING], - l, LWS_WRITE_TEXT); - - msgs.clear(); - } + 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; } @@ -355,207 +380,221 @@ static int callback_task(struct libwebsocket_context *me, return 0; } -static struct libwebsocket_protocols protocols[] = { +static struct lws_protocols protocols[] = +{ { "lws-task-protocol", callback_task, 0, }, - { NULL, NULL, 0 } + { nullptr, nullptr, 0 } }; int client(const char *address, int port) { - struct libwebsocket_context *context; - struct libwebsocket *wsi_task = NULL; + struct lws_context *context; + struct lws *wsi_task = nullptr; int ietf_version = -1; // latest - - context = libwebsocket_create_context(CONTEXT_PORT_NO_LISTEN, NULL, - protocols, - libwebsocket_internal_extensions, - NULL, NULL, -1, -1, 0); - if (context == NULL) { - fprintf(stderr, "Creating libwebsocket context failed\n"); + 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 = libwebsocket_service(context, 10); - - if (wsi_task == NULL) { - wsi_task = libwebsocket_client_connect(context, address, port, - 0, "/", address, address, - protocols[lws-task-protocol].name, - ietf_version); - - if (wsi_task == NULL) { - fprintf(stderr, "libwebsocket task connect failed\n"); + // 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_task == nullptr) + { + wsi_task = lws_client_connect(context, address, port, + 0, "/", address, address, + protocols[lws-task-protocol].name, + ietf_version); + + if(wsi_task == nullptr) + { + fprintf(stderr, "lws task connect failed\n"); return -1; } - } else { - - /* - fprintf(stderr, "closing mirror session\n"); - libwebsocket_close_and_free_session(context, - wsi_mirror, LWS_CLOSE_STATUS_GOINGAWAY); - */ + } + else + { + //fprintf(stderr, "closing mirror session\n"); + //lws_close_and_free_session(context, + // wsi_mirror, LWS_CLOSE_STATUS_GOINGAWAY); } - if(!run) break; + if(!run) + { + break; + } } - // fprintf(stderr, "Exiting\n"); + //fprintf(stderr, "Exiting\n"); - libwebsocket_context_destroy(context); + lws_context_destroy(context); return 0; } -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 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]... 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"; +static const 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) { - int port = 7681; - std::string host = "localhost"; - 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:CLRU: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(!interactive && cmd == DEFAULT) { - fprintf(stderr, "%s\n", USAGE); - exit(1); - } - - if(!interactive && !taskbyname.empty()) { - taskbyid = -1; - fprintf(stderr, "Option '-N, --name' is not yet supported\n"); - fprintf(stderr, "%s\n", USAGE); - exit(1); - } - - if(!interactive && taskbyid.empty()) { - fprintf(stderr, "%s\n", USAGE); - exit(1); - } - - taskid = atoi(taskbyid.c_str()); - - switch(cmd) { - case CREATE: - msgs = "observe " + taskbyid + ";"; - msgs += "create " + taskbyid + ";"; - break; - case LIST: - msgs = "observe " + taskbyid + ";"; //+ - // "; unobserve " + task + ";"; - break; - case REMOVE: - msgs = "remove " + taskbyid + ";"; - break; - case UPDATE: - msgs = "observe " + taskbyid + ";"; - msgs += "update " + taskbyid + " \"" + cmd_opts + "\"; "; - break; - case DEFAULT: - break; - } + int port = 7681; + std::string host = "localhost"; + 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: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': + 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(!interactive && cmd == DEFAULT) + { + fprintf(stderr, "%s\n", USAGE); + exit(1); + } + + if(!interactive && !taskbyname.empty()) + { + taskbyid = -1; + fprintf(stderr, "Option '-N, --name' is not yet supported\n"); + fprintf(stderr, "%s\n", USAGE); + exit(1); + } + + if(!interactive && taskbyid.empty()) + { + fprintf(stderr, "%s\n", USAGE); + exit(1); + } + + taskid = atoi(taskbyid.c_str()); + + switch(cmd) + { + case CREATE: + msgs = "observe " + taskbyid + ";"; + msgs += "create " + taskbyid + ";"; + break; + case LIST: + msgs = "observe " + taskbyid + ";"; //+ + // "; unobserve " + task + ";"; + break; + case REMOVE: + msgs = "remove " + taskbyid + ";"; + break; + case UPDATE: + msgs = "observe " + taskbyid + ";"; + msgs += "update " + taskbyid + " \"" + 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; +// 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*/ diff --git a/src/muniad.cc b/src/muniad.cc index b478484..b5685c2 100644 --- a/src/muniad.cc +++ b/src/muniad.cc @@ -40,71 +40,76 @@ #include "hugin.hpp" #include "taskmanager.h" -static struct libwebsocket_protocols protocols[] = { +static struct lws_protocols protocols[] = +{ // first protocol must always be HTTP handler { "http-only", callback_http, 0 }, - { "lws-task-protocol", callback_lws_task, - sizeof(struct per_session_data__lws_task) - }, - { NULL, NULL, 0 } // End of list + { "lws-task-protocol", callback_lws_task, sizeof(struct per_session_data__lws_task) }, + { nullptr, nullptr, 0 } // End of list }; static struct option options[] = { - { "help", no_argument, NULL, 'h' }, - { "port", required_argument, NULL, 'p' }, - { "file", required_argument, NULL, 'f' }, - { "ssl", no_argument, NULL, 's' }, - { "killmask", no_argument, NULL, 'k' }, - { "interface", required_argument, NULL, 'i' }, -// { "dumpfile", required_argument, NULL, 'd'}, - { NULL, 0, 0, 0 } + { "help", no_argument, nullptr, 'h' }, + { "port", required_argument, nullptr, 'p' }, + { "file", required_argument, nullptr, 'f' }, + { "ssl", no_argument, nullptr, 's' }, + { "killmask", no_argument, nullptr, 'k' }, + { "interface", required_argument, nullptr, 'i' }, +// { "dumpfile", required_argument, nullptr, 'd'}, + { nullptr, 0, 0, 0 } }; int main(int argc, char **argv) { - const char *db_filename = "/tmp/munia.xml"; + const char *db_filename = "/tmp/munia.xml"; int n = 0; const char *cert_path = - LOCAL_RESOURCE_PATH"/libwebsockets-test-server.pem"; + LOCAL_RESOURCE_PATH"/libwebsockets-test-server.pem"; const char *key_path = - LOCAL_RESOURCE_PATH"/libwebsockets-test-server.key.pem"; + LOCAL_RESOURCE_PATH"/libwebsockets-test-server.key.pem"; int port = 7681; int use_ssl = 0; - struct libwebsocket_context *context; + struct lws_context *context; int opts = 0; char interface_name[128] = ""; - const char * interface = NULL; + const char * interface = nullptr; // std::string dumpfile; fprintf(stderr, "Munia test server\n" - "(C) Copyright 2012 Bent Bisballe Nyeng (deva@aasimon.org)\n" - " & Jonas Suhr Christensen (jsc@umbraculum.org)\n" - "License GPLv3+: GNU GPL version 3 or later " - "<http://gnu.org/licenses/gpl.html>\n" - "\n" - "This is free software; you are free to change and redistribute it.\n" - "There is NO WARRANTY, to the extent permitted by law.\n"); - - while(n >= 0) { - n = getopt_long(argc, argv, "ci:khsp:f:", options, NULL); - if(n < 0) continue; - switch(n) { + "(C) Copyright 2012-2019 Bent Bisballe Nyeng (deva@aasimon.org)\n" + " & Jonas Suhr Christensen (jsc@umbraculum.org)\n" + "License GPLv3+: GNU GPL version 3 or later " + "<http://gnu.org/licenses/gpl.html>\n" + "\n" + "This is free software; you are free to change and redistribute it.\n" + "There is NO WARRANTY, to the extent permitted by law.\n"); + + while(n >= 0) + { + n = getopt_long(argc, argv, "ci:khsp:f:", options, nullptr); + if(n < 0) + { + continue; + } + + switch(n) + { case 's': use_ssl = 1; break; -// case 'd': -// dumpfile = optarg; +// case 'd': +// dumpfile = optarg; case 'k': //opts = LWS_SERVER_OPTION_DEFEAT_CLIENT_MASK; break; case 'p': port = atoi(optarg); break; - case 'f': - db_filename = strdup(optarg); - break; - case 'i': + case 'f': + db_filename = strdup(optarg); + break; + case 'i': strncpy(interface_name, optarg, sizeof interface_name); interface_name[(sizeof interface_name) - 1] = '\0'; interface = interface_name; @@ -115,44 +120,51 @@ int main(int argc, char **argv) } } - //_parse("+all"); + //_parse("+all"); - task_manager.init(db_filename); + task_manager.init(db_filename); - if(!use_ssl) cert_path = key_path = NULL; + if(!use_ssl) + { + cert_path = key_path = nullptr; + } - struct lws_context_creation_info info; - memset(&info, 0, sizeof info); - info.port = port; - info.iface = interface; - info.protocols = protocols; - info.extensions = libwebsocket_get_internal_extensions(); + struct lws_context_creation_info info{}; + info.port = port; + info.iface = interface; + info.protocols = protocols; + //info.extensions = lws_get_internal_extensions(); // DEPRECATED - if (!use_ssl) { - info.ssl_cert_filepath = cert_path; - info.ssl_private_key_filepath = NULL; - } else { - info.ssl_cert_filepath = - LOCAL_RESOURCE_PATH"/libwebsockets-test-server.pem"; - info.ssl_private_key_filepath = - LOCAL_RESOURCE_PATH"/libwebsockets-test-server.key.pem"; - } + if(!use_ssl) + { + info.ssl_cert_filepath = cert_path; + info.ssl_private_key_filepath = nullptr; + } + else + { + info.ssl_cert_filepath = + LOCAL_RESOURCE_PATH"/libwebsockets-test-server.pem"; + info.ssl_private_key_filepath = + LOCAL_RESOURCE_PATH"/libwebsockets-test-server.key.pem"; + } - info.gid = -1; - info.uid = -1; - info.options = opts; + info.gid = -1; + info.uid = -1; + info.options = opts; - context = libwebsocket_create_context(&info); - if (context == NULL) { + context = lws_create_context(&info); + if(context == nullptr) + { fprintf(stderr, "libwebsocket init failed\n"); return -1; } - while (1) { - libwebsocket_service(context, 50); - } + while(1) + { + lws_service(context, 50); + } - libwebsocket_context_destroy(context); + lws_context_destroy(context); return 0; } diff --git a/src/saxparser.cc b/src/saxparser.cc index 42b1bfd..ae0adff 100644 --- a/src/saxparser.cc +++ b/src/saxparser.cc @@ -33,157 +33,199 @@ static void character_hndl(void *p, const XML_Char *s, int len) { - SAXParser *parser = (SAXParser*)XML_GetUserData(p); - std::string chars; - chars.append(s, len); - parser->characterData(chars); + SAXParser *parser = (SAXParser*)XML_GetUserData(p); + std::string chars; + chars.append(s, len); + parser->characterData(chars); } static void start_hndl(void *p, const char *el, const char **attr) { - SAXParser *parser = (SAXParser*)XML_GetUserData(p); + SAXParser *parser = (SAXParser*)XML_GetUserData(p); - // Convert to comfy C++ values... - std::string name = el; - std::map< std::string, std::string > attributes; + // Convert to comfy C++ values... + std::string name = el; + std::map< std::string, std::string > attributes; - while(*attr) { - std::string at_name = *attr; - attr++; - std::string at_value = *attr; - attr++; + while(*attr) + { + std::string at_name = *attr; + attr++; + std::string at_value = *attr; + attr++; - attributes.insert(make_pair(at_name, at_value)); - } + attributes.insert(make_pair(at_name, at_value)); + } - if(parser->outertag == "") parser->outertag = name; + if(parser->outertag == "") + { + parser->outertag = name; + } - parser->startTag(name, attributes); + parser->startTag(name, attributes); } static void end_hndl(void *p, const char *el) { - SAXParser *parser = (SAXParser*)XML_GetUserData(p); - std::string name = el; + SAXParser *parser = (SAXParser*)XML_GetUserData(p); + std::string name = el; - if(name == parser->outertag) parser->done = true; + if(name == parser->outertag) + { + parser->done = true; + } - parser->endTag(name); + parser->endTag(name); } SAXParser::SAXParser() { - p = XML_ParserCreate(NULL); - if(!p) { - ERR(sax, "Couldn't allocate memory for parser\n"); - // throw Exception(...); - return; - } - - // XML_SetEncoding(p, "UTF-8"); - XML_SetUserData(p, this); - XML_UseParserAsHandlerArg(p); - XML_SetElementHandler(p, start_hndl, end_hndl); - XML_SetCharacterDataHandler(p, character_hndl); - - bufferbytes = 0; - totalbytes = 0; - done = false; - + p = XML_ParserCreate(NULL); + if(!p) + { + ERR(sax, "Couldn't allocate memory for parser\n"); + // throw Exception(...); + return; + } + + // XML_SetEncoding(p, "UTF-8"); + XML_SetUserData(p, this); + XML_UseParserAsHandlerArg(p); + XML_SetElementHandler(p, start_hndl, end_hndl); + XML_SetCharacterDataHandler(p, character_hndl); + + bufferbytes = 0; + totalbytes = 0; + done = false; } SAXParser::~SAXParser() { - if(p) XML_ParserFree(p); + if(p) + { + XML_ParserFree(p); + } } int SAXParser::parse() { - char buf[32]; - int len; - - do { - len = readData(buf, sizeof(buf) - 1); - if (! XML_Parse(p, buf, len, len == 0)) { - parseError(buf, len, XML_ErrorString(XML_GetErrorCode(p)), - (int)XML_GetCurrentLineNumber(p)); - return 1; - } - - memset(buf, 0, sizeof(buf)); - } while(len); - - return 0; + char buf[32]; + int len; + + do + { + len = readData(buf, sizeof(buf) - 1); + if(! XML_Parse(p, buf, len, len == 0)) + { + parseError(buf, len, XML_ErrorString(XML_GetErrorCode(p)), + (int)XML_GetCurrentLineNumber(p)); + return 1; + } + + memset(buf, 0, sizeof(buf)); + } + while(len); + + return 0; } static bool iswhitespace(const char *buf, size_t size) { - for(size_t i = 0; i < size; i++) - if(buf[i] != ' ' && buf[i] != '\n' && buf[i] != '\t' && buf[i] != '\r') - return false; - return true; + for(size_t i = 0; i < size; i++) + { + if(buf[i] != ' ' && buf[i] != '\n' && buf[i] != '\t' && buf[i] != '\r') + { + return false; + } + } + return true; } bool SAXParser::parse(const char *data, size_t size) { - std::string xml; - xml.append(data, size); - DEBUG(sax, "parse %d bytes [%s]\n", (int)size, xml.c_str()); - - if(data == NULL || size == 0) return done; - - bufferbytes = size; - totalbytes += bufferbytes; - - if(! XML_Parse(p, data, size, false) ) { - if(XML_GetErrorCode(p) == XML_ERROR_JUNK_AFTER_DOC_ELEMENT) return true; - if(XML_GetErrorCode(p) == XML_ERROR_FINISHED && - iswhitespace(data, size)) return true; - if(done && XML_GetErrorCode(p) == XML_ERROR_UNCLOSED_TOKEN) return true; - parseError(data, size, XML_ErrorString(XML_GetErrorCode(p)), - (int)XML_GetCurrentLineNumber(p)); - return false; - } - - if(done) { - if(! XML_Parse(p, data, 0, true) ) { - if(XML_GetErrorCode(p) == XML_ERROR_JUNK_AFTER_DOC_ELEMENT) return true; - if(XML_GetErrorCode(p) == XML_ERROR_FINISHED && - iswhitespace(data, size)) return true; - if(XML_GetErrorCode(p) == XML_ERROR_UNCLOSED_TOKEN) return true; - parseError(data, 0, XML_ErrorString(XML_GetErrorCode(p)), - (int)XML_GetCurrentLineNumber(p)); - return false; - } - } - - if(done) { - DEBUG(sax, "Got END_OF_DOCUMENT [%s] at %ld\n", - outertag.c_str(), XML_GetCurrentByteIndex(p)); - } - - return done; + std::string xml; + xml.append(data, size); + DEBUG(sax, "parse %d bytes [%s]\n", (int)size, xml.c_str()); + + if(data == NULL || size == 0) + { + return done; + } + + bufferbytes = size; + totalbytes += bufferbytes; + + if(! XML_Parse(p, data, size, false)) + { + if(XML_GetErrorCode(p) == XML_ERROR_JUNK_AFTER_DOC_ELEMENT) + { + return true; + } + if(XML_GetErrorCode(p) == XML_ERROR_FINISHED && + iswhitespace(data, size)) + { + return true; + } + if(done && XML_GetErrorCode(p) == XML_ERROR_UNCLOSED_TOKEN) + { + return true; + } + parseError(data, size, XML_ErrorString(XML_GetErrorCode(p)), + (int)XML_GetCurrentLineNumber(p)); + return false; + } + + if(done) + { + if(!XML_Parse(p, data, 0, true)) + { + if(XML_GetErrorCode(p) == XML_ERROR_JUNK_AFTER_DOC_ELEMENT) + { + return true; + } + if(XML_GetErrorCode(p) == XML_ERROR_FINISHED && + iswhitespace(data, size)) + { + return true; + } + if(XML_GetErrorCode(p) == XML_ERROR_UNCLOSED_TOKEN) + { + return true; + } + parseError(data, 0, XML_ErrorString(XML_GetErrorCode(p)), + (int)XML_GetCurrentLineNumber(p)); + return false; + } + } + + if(done) + { + DEBUG(sax, "Got END_OF_DOCUMENT [%s] at %ld\n", + outertag.c_str(), XML_GetCurrentByteIndex(p)); + } + + return done; } void SAXParser::parseError(const char *buf, size_t len, std::string error, int lineno) { - fprintf(stderr, "SAXParser error at line %d: %s\n", lineno, error.c_str()); - fprintf(stderr, "\tBuffer %u bytes: [", (int)len); - if(fwrite(buf, len, 1, stderr) != len) {} - fprintf(stderr, "]\n"); - fflush(stderr); + fprintf(stderr, "SAXParser error at line %d: %s\n", lineno, error.c_str()); + fprintf(stderr, "\tBuffer %u bytes: [", (int)len); + if(fwrite(buf, len, 1, stderr) != len) {} + fprintf(stderr, "]\n"); + fflush(stderr); } unsigned int SAXParser::usedBytes() { - return bufferbytes + (XML_GetCurrentByteIndex(p) - totalbytes); + return bufferbytes + (XML_GetCurrentByteIndex(p) - totalbytes); } int SAXParser::readData(char *, size_t) { - return 0; + return 0; } void SAXParser::endTag(std::string) diff --git a/src/saxparser.h b/src/saxparser.h index b027b30..cdc108c 100644 --- a/src/saxparser.h +++ b/src/saxparser.h @@ -24,8 +24,7 @@ * along with Pracro; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#ifndef __PRACRO_SAXPARSER_H__ -#define __PRACRO_SAXPARSER_H__ +#pragma once #include <string> #include <map> @@ -33,120 +32,97 @@ typedef std::map< std::string, std::string> attributes_t; -/** - * This class implements a SAX Parser, utilising the eXpat XML parser library. - * It uses virtual methods for the callbacks, and transforms tagnames and - * attributes into C++ values (std::string and std::vector). - */ -class SAXParser { +//! This class implements a SAX Parser, utilising the eXpat XML parser library. +//! It uses virtual methods for the callbacks, and transforms tagnames and +//! attributes into C++ values (std::string and std::vector). +class SAXParser +{ public: - /** - * Constructor. - * It initialises the eXpat library. - */ - SAXParser(); - - /** - * Destructor. - * It frees the eXpat library resources. - */ - virtual ~SAXParser(); - - /** - * Call this method to use the reimplemented readData method for input. - * The entire document is parsed through this single call. - * @return An integer wityh value 0 on success, or 1 on failure. - * @see int readData(char *data, size_t size) - */ - int parse(); - - /** - * Character data callback method. - * Reimplement this to get character callbacks. - * This callback might be called several times, if a character block is big. - * In that cae it might be nessecary to buffer to received bytes. - * @param data A std::string containing the character data. - */ - virtual void characterData(const std::string &data); - - /** - * Start tag callback mehtod. - * Reimplement this to get start tag callbacks. - * It is called each time a new start tag is seen. - * @param name A std::string containing the tag name. - * @param attributes A std::map of std::string to std::string containing all - * attributes for the tag. - */ - virtual void startTag(std::string name, attributes_t &attr); - - /** - * End tag callback mehtod. - * Reimplement this to get end tag callbacks. - * It is called each time an end tag is seen. - * @param name A std::string containing the tag name. - */ - virtual void endTag(std::string name); - - /** - * Error callback method. - * Reimplement this to handle error messages. - * A default implementation prints out the current buffer, linenumber and - * error message to the screen. - * @param buf A char* containing the current buffer being parsed. - * @param len A size_t containing the length of the current buffer being - * parsed. - * @param error A std::string containing the error message. - * @param lineno An integer containing the line number on which the error - * occurred. - */ - virtual void parseError(const char *buf, size_t len, std::string error, - int lineno); - - /** - * Buffer parse method. - * Use this method to parse an external buffer with xml data. - * This method can be called several times (ie. in a read loop). - * @param buf A char* containing the buffer to parse. - * @param size A size_t comntaining the size of the buffer to parse. - * @return A boolean with the value true if a complete document has been seen. - * false otherwise. - * @see bool parse(char *buf, size_t size) - */ - bool parse(const char *buf, size_t size); - - /** - * Get the number of bytes used from the last buffer. - * If the buffer parse method is used, and the buffer comes from a stream of - * xml doxuments, this method can be used to figure out how many bytes from - * the stream should be replayed, to another parser. - * @return an integer containing the number of bytes used from the last - * buffer. - * @see bool parse(char *buf, size_t size) - */ - unsigned int usedBytes(); - - // private stuff that needs to be public! - std::string outertag; - bool done; + //! Constructor. + //! It initialises the eXpat library. + SAXParser(); + + //! Destructor. + //! It frees the eXpat library resources. + virtual ~SAXParser(); + + //! Call this method to use the reimplemented readData method for input. + //! The entire document is parsed through this single call. + //! \return An integer with value 0 on success, or 1 on failure. + //! \see int readData(char *data, size_t size) + int parse(); + + //! Character data callback method. + //! Reimplement this to get character callbacks. + //! This callback might be called several times, if a character block is big. + //! In that cae it might be nessecary to buffer to received bytes. + //! \param data A std::string containing the character data. + virtual void characterData(const std::string &data); + + //! Start tag callback mehtod. + //! Reimplement this to get start tag callbacks. + //! It is called each time a new start tag is seen. + //! \param name A std::string containing the tag name. + //! \param attributes A std::map of std::string to std::string containing all + //! attributes for the tag. + virtual void startTag(std::string name, attributes_t &attr); + + //! End tag callback mehtod. + //! Reimplement this to get end tag callbacks. + //! It is called each time an end tag is seen. + //! \param name A std::string containing the tag name. + virtual void endTag(std::string name); + + //! Error callback method. + //! Reimplement this to handle error messages. + //! A default implementation prints out the current buffer, linenumber and + //! error message to the screen. + //! \param buf A char* containing the current buffer being parsed. + //! \param len A size_t containing the length of the current buffer being + //! parsed. + //! \param error A std::string containing the error message. + //! \param lineno An integer containing the line number on which the error + //! occurred. + virtual void parseError(const char *buf, size_t len, std::string error, + int lineno); + + //! Buffer parse method. + //! Use this method to parse an external buffer with xml data. + //! This method can be called several times (ie. in a read loop). + //! \param buf A char* containing the buffer to parse. + //! \param size A size_t comntaining the size of the buffer to parse. + //! \return A boolean with the value true if a complete document has been + //! seen. false otherwise. + //! \see bool parse(char *buf, size_t size) + bool parse(const char *buf, size_t size); + + //! Get the number of bytes used from the last buffer. + //! If the buffer parse method is used, and the buffer comes from a stream of + //! xml doxuments, this method can be used to figure out how many bytes from + //! the stream should be replayed, to another parser. + //! \return an integer containing the number of bytes used from the last + //! buffer. + //! \see bool parse(char *buf, size_t size) + unsigned int usedBytes(); + + // private stuff that needs to be public! + std::string outertag; + bool done; protected: - /** - * Read data callback method. - * This method is used when the parse() method is used. - * It can be used to connect the parser with eg. a file. - * @param data A char* containing the buffer to be filled. - * @param size A size_t containing the maximum number of bytes to be filled - * (ie. the size of data) - * @return An integer contaning the actual number of bytes filled. 0 if no - * more bytes are available. - * @see int parse() - */ - virtual int readData(char *data, size_t size); - - XML_Parser p; - - unsigned int bufferbytes; - unsigned int totalbytes; + //! Read data callback method. + //! This method is used when the parse() method is used. + //! It can be used to connect the parser with eg. a file. + //! \param data A char* containing the buffer to be filled. + //! \param size A size_t containing the maximum number of bytes to be filled + //! (ie. the size of data) + //! \return An integer contaning the actual number of bytes filled. 0 if no + //! more bytes are available. + //! \see int parse() + virtual int readData(char *data, size_t size); + + XML_Parser p; + + unsigned int bufferbytes; + unsigned int totalbytes; }; - -#endif/*__PRACRO_SAXPARSER_H__*/ @@ -25,8 +25,7 @@ * along with Munia; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#ifndef __MUNIA_TASK_H__ -#define __MUNIA_TASK_H__ +#pragma once #include <string> #include <list> @@ -35,10 +34,9 @@ typedef unsigned int taskid_t; typedef std::list<taskid_t> TaskIdList; -typedef struct { - taskid_t id; - taskid_t parentid; - std::map<std::string, std::string> attributes; +typedef struct +{ + taskid_t id; + taskid_t parentid; + std::map<std::string, std::string> attributes; } task_t; - -#endif/*__MUNIA_TASK_H__*/ diff --git a/src/taskmanager.cc b/src/taskmanager.cc index 38d7893..3fafb4e 100644 --- a/src/taskmanager.cc +++ b/src/taskmanager.cc @@ -43,317 +43,365 @@ TaskManager task_manager; static bool isProtected(taskid_t id) { - return id < FIRST_TASK_ID; + return id < FIRST_TASK_ID; } -TaskManager::TaskManager() { - idCount = FIRST_TASK_ID; +TaskManager::TaskManager() +{ + idCount = FIRST_TASK_ID; } -TaskManager::~TaskManager() { +TaskManager::~TaskManager() +{ } void TaskManager::init(std::string filename) { - DEBUG(taskmgr, "Reading tasks from file: %s\n", filename.c_str()); - file = filename; - - FILE *fp = fopen(file.c_str(), "r"); - if(fp) { - std::string xml; - while(!feof(fp)) { - char buf[64]; - size_t sz = fread(buf, 1, sizeof(buf), fp); - xml.append(buf, sz); - } - tree.fromXML(xml); - fclose(fp); - } else { - - // Create new basis config - task_t t; - - t.attributes["title"] = "root"; - t.id = ROOT_ID; - tree.insertAsChild(0, ROOT_ID, t); - - t.attributes["title"] = "Finished"; - t.id = FINISHED_ID; - tree.insertAsChild(ROOT_ID, FINISHED_ID, t); - - t.attributes["title"] = "Backlog"; - t.id = BACKLOG_ID; - tree.insertAsChild(ROOT_ID, BACKLOG_ID, t); - - t.attributes["title"] = "Lost+Found"; - t.id = LOSTFOUND_ID; - tree.insertAsChild(ROOT_ID, LOSTFOUND_ID, t); - - t.attributes["title"] = "Projects"; - t.id = PROJECTS_ID; - tree.insertAsChild(ROOT_ID, PROJECTS_ID, t); - } - - tree.toStdOut(); + DEBUG(taskmgr, "Reading tasks from file: %s\n", filename.c_str()); + file = filename; + + FILE *fp = fopen(file.c_str(), "r"); + if(fp) + { + std::string xml; + while(!feof(fp)) + { + char buf[64]; + size_t sz = fread(buf, 1, sizeof(buf), fp); + xml.append(buf, sz); + } + tree.fromXML(xml); + fclose(fp); + } + else + { + + // Create new basis config + task_t t; + + t.attributes["title"] = "root"; + t.id = ROOT_ID; + tree.insertAsChild(0, ROOT_ID, t); + + t.attributes["title"] = "Finished"; + t.id = FINISHED_ID; + tree.insertAsChild(ROOT_ID, FINISHED_ID, t); + + t.attributes["title"] = "Backlog"; + t.id = BACKLOG_ID; + tree.insertAsChild(ROOT_ID, BACKLOG_ID, t); + + t.attributes["title"] = "Lost+Found"; + t.id = LOSTFOUND_ID; + tree.insertAsChild(ROOT_ID, LOSTFOUND_ID, t); + + t.attributes["title"] = "Projects"; + t.id = PROJECTS_ID; + tree.insertAsChild(ROOT_ID, PROJECTS_ID, t); + } + + tree.toStdOut(); } -task_t TaskManager::task(taskid_t t) { - return tree.data(t); +task_t TaskManager::task(taskid_t t) +{ + return tree.data(t); } -taskid_t TaskManager::createId() { - return tree.createId(); +taskid_t TaskManager::createId() +{ + return tree.createId(); } -TaskIdListPair TaskManager::moveTask(taskid_t id, taskid_t to) - throw (std::exception) { - - if(isProtected(id)) return TaskIdListPair(); +TaskIdListPair TaskManager::moveTask(taskid_t id, taskid_t to) + throw (std::exception) +{ + if(isProtected(id)) + { + return TaskIdListPair(); + } - if(id == to) throw std::exception(); // Node and new parent are the same node. + if(id == to) + { + throw std::exception(); // Node and new parent are the same node. + } - //task_t t = tree.data(id); + //task_t t = tree.data(id); - // Make sure the new parent exists. This will throw an exception if it doesn't - //task_t t_ = tree.data(to); + // Make sure the new parent exists. This will throw an exception if it doesn't + //task_t t_ = tree.data(to); - // t.parentid = to; + //t.parentid = to; - // TaskIdList tilremove = tree.remove(id); - TaskIdList tilremove; - tilremove.push_back(id); - TaskIdList ancestors = tree.ancestorList(id); - tilremove.insert(tilremove.end(), ancestors.begin(), ancestors.end()); + //TaskIdList tilremove = tree.remove(id); + TaskIdList tilremove; + tilremove.push_back(id); + TaskIdList ancestors = tree.ancestorList(id); + tilremove.insert(tilremove.end(), ancestors.begin(), ancestors.end()); - // TaskIdList tilcreate = tree.insertAsChild(to, id, t); - TaskIdList tilcreate; - tilcreate.push_back(to); - ancestors = tree.ancestorList(to); - tilcreate.insert(tilcreate.end(), ancestors.begin(), ancestors.end()); + // TaskIdList tilcreate = tree.insertAsChild(to, id, t); + TaskIdList tilcreate; + tilcreate.push_back(to); + ancestors = tree.ancestorList(to); + tilcreate.insert(tilcreate.end(), ancestors.begin(), ancestors.end()); - tree.move(id, to); + tree.move(id, to); - TaskIdListPair tilpair; - tilpair.first = tilremove; - tilpair.second = tilcreate; + TaskIdListPair tilpair; + tilpair.first = tilremove; + tilpair.second = tilcreate; - flushTasks(); + flushTasks(); - return tilpair; + return tilpair; } -TaskIdList TaskManager::removeTask(taskid_t id) - throw (std::exception) { - - if(isProtected(id)) return TaskIdList(); - - TaskIdList affectedTasks; - - if(tree.bfs(id).size() > 1) throw std::exception(); - - try { - affectedTasks = tree.remove(id); - } - catch(std::exception& e) { - throw e; - } - - flushTasks(); - - return affectedTasks; +TaskIdList TaskManager::removeTask(taskid_t id) + throw (std::exception) +{ + if(isProtected(id)) + { + return TaskIdList(); + } + + TaskIdList affectedTasks; + + if(tree.bfs(id).size() > 1) + { + throw std::exception(); + } + + try + { + affectedTasks = tree.remove(id); + } + catch(std::exception& e) + { + throw e; + } + + flushTasks(); + + return affectedTasks; } TaskIdList TaskManager::updateTask(taskid_t id, const std::string &name, - const std::string &value) - throw (std::exception) { - - if(isProtected(id)) return TaskIdList(); + const std::string &value) + throw (std::exception) +{ + if(isProtected(id)) + { + return TaskIdList(); + } - TaskIdList affectedTasks; + TaskIdList affectedTasks; - try { - affectedTasks = tree.updateData(id, name, value); - } - catch (std::exception& e) { - throw e; - } + try + { + affectedTasks = tree.updateData(id, name, value); + } + catch(std::exception& e) + { + throw e; + } - flushTasks(); + flushTasks(); - return affectedTasks; + return affectedTasks; } TaskIdList TaskManager::createTask(taskid_t parentid, taskid_t *pid) - throw (std::exception) { - TaskIdList affectedTasks; - - task_t t; - taskid_t id = *pid;//createId(); - t.attributes["title"] = ""; - t.id = id; - if(pid) *pid = id; - - try { - affectedTasks = tree.insertAsChild(parentid, id, t); - } - catch (std::exception& e) { - throw e; - } - - flushTasks(); - - return affectedTasks; + throw (std::exception) +{ + TaskIdList affectedTasks; + + task_t t; + taskid_t id = *pid;//createId(); + t.attributes["title"] = ""; + t.id = id; + if(pid) + { + *pid = id; + } + + try + { + affectedTasks = tree.insertAsChild(parentid, id, t); + } + catch(std::exception& e) + { + throw e; + } + + flushTasks(); + + return affectedTasks; } TaskIdList TaskManager::subTasks(taskid_t t) - throw (std::exception) { - - TaskIdList affectedTasks; - - try { - affectedTasks = tree.bfs(t); - } - catch (std::exception& e) { - throw e; - } - - return affectedTasks; + throw (std::exception) +{ + TaskIdList affectedTasks; + + try + { + affectedTasks = tree.bfs(t); + } + catch(std::exception& e) + { + throw e; + } + + return affectedTasks; } -/* -TaskIdList TaskManager::ancestorList(taskid_t id) - throw (std::exception) { - TaskIdList ancestors; - - try { - ancestors = tree.ancestorList(id); - goto finish; - } - catch (std::exception& e) { - throw e; - } - - finish: - return ancestors; -} -*/ +//TaskIdList TaskManager::ancestorList(taskid_t id) +// throw (std::exception) +//{ +// TaskIdList ancestors; +// +// try +// { +// ancestors = tree.ancestorList(id); +// goto finish; +// } +// catch(std::exception& e) +// { +// throw e; +// } +// +//finish: +// return ancestors; +//} void TaskManager::flushTasks() { - FILE *fp = fopen(file.c_str(), "w"); - if(!fp) return; - std::string xml = tree.toXML(); - fwrite(xml.c_str(), xml.size(), 1, fp); - fclose(fp); + FILE *fp = fopen(file.c_str(), "w"); + if(!fp) + { + return; + } + std::string xml = tree.toXML(); + fwrite(xml.c_str(), xml.size(), 1, fp); + fclose(fp); } - #if 0 TaskList tasklist; -task_t create_task(std::string title, std::string desc) { - - task_t t; - t.parent_id = current_id_count(); - t.attributes["title"] = title; - t.desc = desc; - t.id = id_count; id_count++; - - return t; -} - -TaskList load_tasklist_from_file(std::string file) { - TaskList list; - - // create MuniaDb class which handles tasks, db-flush and db-init. +task_t create_task(std::string title, std::string desc) +{ + task_t t; + t.parent_id = current_id_count(); + t.attributes["title"] = title; + t.desc = desc; + t.id = id_count; id_count++; - return list; + return t; } -bool save_tasklist_to_file(TaskList list, std::string file) { - - FILE* fp; - - if(! (fp = fopen(file.c_str(), "w"))) { - return false; - } - - if(!fprintf(fp, "<tasklist>\n")) { - fclose(fp); - return false; - } - - TaskList::iterator it; - for(it = tasklist.begin(); it != tasklist.end(); it++) { - task_t t = *it; - int r = 1; - -// printf("Flushing task %d\n", t.id); - - r |= fprintf(fp, " <task id=\"%d\" parent_id=\"%d\">\n", t.id, t.parent_id); - r |= fprintf(fp, " <title>%s</title>\n", xml_encode(t.attributes["title"]).c_str()); - r |= fprintf(fp, " <desc>%s</desc>\n", xml_encode(t.attributes["description"]).c_str()); - r |= fprintf(fp, " </task>)\n"); +TaskList load_tasklist_from_file(std::string file) +{ + TaskList list; - if(!r) { - fclose(fp); - return false; - } - } + // create MuniaDb class which handles tasks, db-flush and db-init. - if(!fprintf(fp, "</tasklist>\n")) { - fclose(fp); - return false; - } + return list; +} - fclose(fp); - return true; +bool save_tasklist_to_file(TaskList list, std::string file) +{ + FILE* fp; + + if(! (fp = fopen(file.c_str(), "w"))) + { + return false; + } + + if(!fprintf(fp, "<tasklist>\n")) + { + fclose(fp); + return false; + } + + TaskList::iterator it; + for(it = tasklist.begin(); it != tasklist.end(); it++) + { + task_t t = *it; + int r = 1; + + //printf("Flushing task %d\n", t.id); + r |= fprintf(fp, " <task id=\"%d\" parent_id=\"%d\">\n", t.id, t.parent_id); + r |= fprintf(fp, " <title>%s</title>\n", xml_encode(t.attributes["title"]).c_str()); + r |= fprintf(fp, " <desc>%s</desc>\n", xml_encode(t.attributes["description"]).c_str()); + r |= fprintf(fp, " </task>)\n"); + + if(!r) + { + fclose(fp); + return false; + } + } + + if(!fprintf(fp, "</tasklist>\n")) + { + fclose(fp); + return false; + } + + fclose(fp); + return true; } static void delete_task(task_t t, TaskList& graveyard); -static void delete_children(task_t t, TaskList& graveyard) { - TaskList::iterator it; - for(it = tasklist.begin(); it != tasklist.end(); it++) { - if(it->parent_id == t.id) { - delete_task(*it, graveyard); - } - } +static void delete_children(task_t t, TaskList& graveyard) +{ + TaskList::iterator it; + for(it = tasklist.begin(); it != tasklist.end(); it++) + { + if(it->parent_id == t.id) { + delete_task(*it, graveyard); + } + } } - -static void delete_task(task_t t, TaskList& graveyard) { - - TaskList::iterator it; - for(it = tasklist.begin(); it != tasklist.end(); it++) { - if(it->id == t.id) { - break; - } - } - - if(it != tasklist.end()) { - graveyard.push_back(*it); - delete_children(*it, graveyard); - } - +static void delete_task(task_t t, TaskList& graveyard) +{ + TaskList::iterator it; + for(it = tasklist.begin(); it != tasklist.end(); it++) + { + if(it->id == t.id) + { + break; + } + } + + if(it != tasklist.end()) + { + graveyard.push_back(*it); + delete_children(*it, graveyard); + } } -void delete_task(int id, TaskList& graveyard) { - task_t t; - t.id = id; - delete_task(t, graveyard); - - for(TaskList::iterator it = graveyard.begin(); - it != graveyard.end(); it++) { - - for(TaskList::iterator it_tl = tasklist.begin(); - it_tl != tasklist.end(); it_tl++) { - - if(it_tl->id == it->id) { - tasklist.erase(it_tl); - break; - } - } - } +void delete_task(int id, TaskList& graveyard) +{ + task_t t; + t.id = id; + delete_task(t, graveyard); + + for(TaskList::iterator it = graveyard.begin(); + it != graveyard.end(); it++) + { + for(TaskList::iterator it_tl = tasklist.begin(); + it_tl != tasklist.end(); it_tl++) + { + if(it_tl->id == it->id) + { + tasklist.erase(it_tl); + break; + } + } + } } #endif diff --git a/src/taskmanager.h b/src/taskmanager.h index 11601a4..99143f5 100644 --- a/src/taskmanager.h +++ b/src/taskmanager.h @@ -25,8 +25,7 @@ * along with Munia; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#ifndef __MUNIA_TASKMANAGER_H__ -#define __MUNIA_TASKMANAGER_H__ +#pragma once #include <list> #include <string> @@ -38,36 +37,37 @@ typedef std::pair<TaskIdList, TaskIdList> TaskIdListPair; -class TaskManager { +class TaskManager +{ public: - TaskManager(); - ~TaskManager(); + TaskManager(); + ~TaskManager(); - void init(std::string filename); + void init(std::string filename); - TaskIdList createTask(taskid_t parentid, taskid_t *id) throw (std::exception); - TaskIdList updateTask(taskid_t id, const std::string &name, - const std::string &value) throw (std::exception); - TaskIdList removeTask(taskid_t id) throw (std::exception); - - TaskIdListPair moveTask(taskid_t id, taskid_t newParent) throw (std::exception); + TaskIdList createTask(taskid_t parentid, taskid_t *id) throw (std::exception); + TaskIdList updateTask(taskid_t id, const std::string &name, + const std::string &value) throw (std::exception); + TaskIdList removeTask(taskid_t id) throw (std::exception); - TaskIdList subTasks(taskid_t) throw (std::exception); + TaskIdListPair moveTask(taskid_t id, taskid_t newParent) throw (std::exception); - TaskTree tree; + TaskIdList subTasks(taskid_t) throw (std::exception); - task_t task(taskid_t t); + TaskTree tree; - void flushTasks(); + task_t task(taskid_t t); - taskid_t createId(); + void flushTasks(); + + taskid_t createId(); private: - // TaskIdList ancestorList(taskid_t task); - taskid_t idCount; - task_t nextTask(); + // TaskIdList ancestorList(taskid_t task); + taskid_t idCount; + task_t nextTask(); - std::string file; + std::string file; }; #ifndef FOOBAR @@ -128,66 +128,78 @@ protocol: //typedef std::list<task_t> TaskList; -class CompareByParentid { +class CompareByParentid +{ public: - bool operator()(const task_t &a, const task_t &b) const { - return a.parent_id < b.parent_id; - } + bool operator()(const task_t &a, const task_t &b) const + { + return a.parent_id < b.parent_id; + } }; - - - -class TaskList : public std::list<task_t>{ +class TaskList + : public std::list<task_t> +{ public: - TaskList() {} - ~TaskList(){} - - void insert(task_t t) { - if(t.id == t.parent_id) return; - printf("inserting task %d with parent %d\n", t.id, t.parent_id); - - if(t.parent_id == -1) { - std::list<task_t>::push_front(t); - return; - } - - std::list<task_t>::iterator it; - for(it = begin(); it != end(); ++it) { - printf("\tcomparing %d and %d\n", t.parent_id, it->id); - if(t.parent_id == it->id) { - break; - } - } - assert(it != end()); - - std::list<task_t>::insert(++it, t); - -// std::list<task_t>::push_back(t); -// std::list<task_t>::sort(CompareByParentid()); - - } - - void move(task_t t) { - std::list<task_t>::iterator it; - for(it = begin(); it != end(); it++) { - if(t.id == it->id) { - break; - } - } - assert(it != end()); - // if(it != end()) { - std::list<task_t>::erase(it); - // } - insert(t); - } - - void push_back(task_t t) { - insert(t); - } + TaskList() {} + ~TaskList(){} + + void insert(task_t t) + { + if(t.id == t.parent_id) + { + return; + } + printf("inserting task %d with parent %d\n", t.id, t.parent_id); + + if(t.parent_id == -1) + { + std::list<task_t>::push_front(t); + return; + } + + std::list<task_t>::iterator it; + for(it = begin(); it != end(); ++it) + { + printf("\tcomparing %d and %d\n", t.parent_id, it->id); + if(t.parent_id == it->id) + { + break; + } + } + assert(it != end()); + + std::list<task_t>::insert(++it, t); + + //std::list<task_t>::push_back(t); + //std::list<task_t>::sort(CompareByParentid()); + } + + void move(task_t t) + { + std::list<task_t>::iterator it; + for(it = begin(); it != end(); it++) + { + if(t.id == it->id) + { + break; + } + } + assert(it != end()); + //if(it != end()) + //{ + std::list<task_t>::erase(it); + //} + insert(t); + } + + void push_back(task_t t) + { + insert(t); + } private: - std::list<task_t> list; + std::list<task_t> list; }; @@ -195,11 +207,8 @@ extern TaskList tasklist; //typedef std::priority_queue<task_t, std::vector<task_t>, CompareByParentid> TaskList; -task_t create_task(std::string title, std::string desc, - /*int x, int y*/ int parent_id); +task_t create_task(std::string title, std::string desc, /*int x, int y*/ int parent_id); TaskList load_tasklist_from_file(std::string file); bool save_tasklist_to_file(TaskList t, std::string file); -#endif - -#endif/*__MUNIA_TASK_H__*/ +#endif/*0*/ diff --git a/src/tasktree.cc b/src/tasktree.cc index 39cee98..30494e9 100644 --- a/src/tasktree.cc +++ b/src/tasktree.cc @@ -39,348 +39,396 @@ static inline std::string id2str(taskid_t id) { - char buf[32]; - sprintf(buf, "%u", id); - return buf; + char buf[32]; + sprintf(buf, "%u", id); + return buf; } std::string node::toXML(std::string prefix) { - std::string xml; - - xml += prefix + "<task id=\""+id2str(id)+"\">\n"; - xml += prefix + " <attributes>\n"; - std::map<std::string, std::string>::iterator ai = data.attributes.begin(); - while(ai != data.attributes.end()) { - xml += prefix + " <attribute name=\"" + xml_encode(ai->first) + "\">" - + xml_encode(ai->second) + "</attribute>\n"; - ai++; - } - xml += prefix + " </attributes>\n"; - xml += prefix + " <children>\n"; - NodeList::iterator ni = children.begin(); - while(ni != children.end()) { - xml += (*ni)->toXML(prefix + " "); - ni++; - } - xml += prefix + " </children>\n"; - xml += prefix + "</task>\n"; - - return xml; + std::string xml; + + xml += prefix + "<task id=\""+id2str(id)+"\">\n"; + xml += prefix + " <attributes>\n"; + std::map<std::string, std::string>::iterator ai = data.attributes.begin(); + while(ai != data.attributes.end()) + { + xml += prefix + " <attribute name=\"" + xml_encode(ai->first) + "\">" + + xml_encode(ai->second) + "</attribute>\n"; + ai++; + } + xml += prefix + " </attributes>\n"; + xml += prefix + " <children>\n"; + NodeList::iterator ni = children.begin(); + while(ni != children.end()) + { + xml += (*ni)->toXML(prefix + " "); + ni++; + } + xml += prefix + " </children>\n"; + xml += prefix + "</task>\n"; + + return xml; } -static void concatTaskIdLists(TaskIdList& pre, TaskIdList& post) { - pre.insert(pre.end(), post.begin(), post.end()); - // for(TaskIdList::iterator it = post.begin(); - // it != post.end(); it++) { - // pre.push_back( - // } +static void concatTaskIdLists(TaskIdList& pre, TaskIdList& post) +{ + pre.insert(pre.end(), post.begin(), post.end()); + //for(TaskIdList::iterator it = post.begin(); + //it != post.end(); it++) + //{ + // pre.push_back( + //} } -TaskTree::TaskTree() { - root = NULL; - nextid = 10; +TaskTree::TaskTree() +{ + root = NULL; + nextid = 10; } -TaskTree::~TaskTree() { - // cleanup tree +TaskTree::~TaskTree() +{ + // cleanup tree } -taskid_t TaskTree::createId() { - taskid_t taskid; +taskid_t TaskTree::createId() +{ + taskid_t taskid; - do { - taskid = nextid++; - } while(id2node.find(taskid) != id2node.end()); + do + { + taskid = nextid++; + } + while(id2node.find(taskid) != id2node.end()); - return taskid; + return taskid; } static taskid_t rootid = -1; -TaskIdList TaskTree::insertAsChild(taskid_t parentid, taskid_t id, task_t data) - throw (std::exception) +TaskIdList TaskTree::insertAsChild(taskid_t parentid, taskid_t id, task_t data) + throw (std::exception) { - - TaskIdList affectedNodes; - - // Initialize - if(!root) { - rootid = id; - node_t* node = createNode(id); - root = node; - node->data = data; - affectedNodes.push_back(id); - - } else { - - try { - node_t* parent = id2node.at(parentid); - node_t* child = createNode(id); -// DEBUG(tasktree, "!!!!!!!id in insert: %d\n", data.id); - child->data = data; - insertChild(parent, child); - - // affectedNodes.push_back(parentid); - affectedNodes.push_back(id); - TaskIdList ancestors = ancestorList(id); - concatTaskIdLists(affectedNodes, ancestors); - } - catch(std::exception& e) { - throw e; - } - } - -// DEBUG(tasktree, "Child %d added to %d, affecting %d nodes\n", -// id, parentid, affectedNodes.size()); - return affectedNodes; + TaskIdList affectedNodes; + + // Initialize + if(!root) + { + rootid = id; + node_t* node = createNode(id); + root = node; + node->data = data; + affectedNodes.push_back(id); + } + else + { + try + { + node_t* parent = id2node.at(parentid); + node_t* child = createNode(id); + //DEBUG(tasktree, "!!!!!!!id in insert: %d\n", data.id); + child->data = data; + insertChild(parent, child); + + //affectedNodes.push_back(parentid); + affectedNodes.push_back(id); + TaskIdList ancestors = ancestorList(id); + concatTaskIdLists(affectedNodes, ancestors); + } + catch(std::exception& e) + { + throw e; + } + } + + //DEBUG(tasktree, "Child %d added to %d, affecting %d nodes\n", + // id, parentid, affectedNodes.size()); + return affectedNodes; } -TaskIdList TaskTree::remove(taskid_t id) - throw (std::exception) +TaskIdList TaskTree::remove(taskid_t id) + throw (std::exception) { - TaskIdList affectedNodes; - affectedNodes.push_back(id); - TaskIdList ancestors = ancestorList(id); - concatTaskIdLists(affectedNodes, ancestors); - -// DEBUG(tasktree, "Removing %d\n", id); - -// DEBUG(tasktree, "!!!!!affected nodes %d\n", affectedNodes.size()); - - node_t* node = id2node[id]; - -// DEBUG(tasktree, "node: %p, id %d, parent %p\n", node, node->data.id, node->parent); - -// DEBUG(tasktree, "!!!!!size %d\n", node->parent->children.size()); - node->parent->children.remove(node); - for(NodeList::iterator it = node->parent->children.begin(); - it != node->parent->children.end(); - it++) { -// DEBUG(tasktree, "%p\n", *it); - } -// DEBUG(tasktree, "!!!!!size %d\n", node->parent->children.size()); - - TaskIdList idlist = bfs(id); - TaskIdList::reverse_iterator it = idlist.rbegin(); - while(it != idlist.rend()) { - task_t task = data(*it); -// node_t* n = id2node[task.id]; -// delete(n); - it++; - } - - return affectedNodes; + TaskIdList affectedNodes; + affectedNodes.push_back(id); + TaskIdList ancestors = ancestorList(id); + concatTaskIdLists(affectedNodes, ancestors); + + //DEBUG(tasktree, "Removing %d\n", id); + //DEBUG(tasktree, "!!!!!affected nodes %d\n", affectedNodes.size()); + + node_t* node = id2node[id]; + + //DEBUG(tasktree, "node: %p, id %d, parent %p\n", node, node->data.id, node->parent); + + //DEBUG(tasktree, "!!!!!size %d\n", node->parent->children.size()); + node->parent->children.remove(node); + for(NodeList::iterator it = node->parent->children.begin(); + it != node->parent->children.end(); + it++) + { + //DEBUG(tasktree, "%p\n", *it); + } + //DEBUG(tasktree, "!!!!!size %d\n", node->parent->children.size()); + + TaskIdList idlist = bfs(id); + TaskIdList::reverse_iterator it = idlist.rbegin(); + while(it != idlist.rend()) + { + task_t task = data(*it); + //node_t* n = id2node[task.id]; + //delete(n); + it++; + } + + return affectedNodes; } static bool findNode(node_t *needle, node_t *haystack) { - if(needle == haystack) return true; - NodeList::iterator i = haystack->children.begin(); - while(i != haystack->children.end()) { - if(findNode(needle, *i)) return true; - i++; - } - return false; + if(needle == haystack) return true; + NodeList::iterator i = haystack->children.begin(); + while(i != haystack->children.end()) + { + if(findNode(needle, *i)) + { + return true; + } + i++; + } + return false; } -TaskIdList TaskTree::move(taskid_t id, taskid_t toid) - throw (std::exception) +TaskIdList TaskTree::move(taskid_t id, taskid_t toid) + throw (std::exception) { - - TaskIdList affectedNodes; - - try { - node_t* child = id2node.at(id); - node_t* newparent = id2node.at(toid); - - // Test if new parent is a child of the node itself... - if(findNode(newparent, child)) throw std::exception(); - - if(!child->parent) { - throw std::exception(); - } - - child->parent->children.remove(child); - newparent->children.push_back(child); - - child->parent = newparent; - - affectedNodes.push_back(id); - // affectedNodes.push_back(child->parent->id); - TaskIdList ancestors = ancestorList(id); - concatTaskIdLists(affectedNodes, ancestors); - affectedNodes.push_back(toid); - ancestors = ancestorList(toid); - } - catch(std::exception& e) { - throw e; - } - - return affectedNodes; + TaskIdList affectedNodes; + + try + { + node_t* child = id2node.at(id); + node_t* newparent = id2node.at(toid); + + // Test if new parent is a child of the node itself... + if(findNode(newparent, child)) + { + throw std::exception(); + } + + if(!child->parent) + { + throw std::exception(); + } + + child->parent->children.remove(child); + newparent->children.push_back(child); + + child->parent = newparent; + + affectedNodes.push_back(id); + // affectedNodes.push_back(child->parent->id); + TaskIdList ancestors = ancestorList(id); + concatTaskIdLists(affectedNodes, ancestors); + affectedNodes.push_back(toid); + ancestors = ancestorList(toid); + } + catch(std::exception& e) + { + throw e; + } + + return affectedNodes; } TaskIdList TaskTree::updateData(taskid_t id, const std::string &name, - const std::string &value) - throw (std::exception) + const std::string &value) + throw (std::exception) { - - TaskIdList affectedNodes; - - try { - node_t* node = id2node.at(id); - node->data.attributes[name] = value; - - affectedNodes.push_back(id); - TaskIdList ancestors = ancestorList(id); - concatTaskIdLists(affectedNodes, ancestors); - } - catch(std::exception& e) { - throw e; - } - - return affectedNodes; + TaskIdList affectedNodes; + + try + { + node_t* node = id2node.at(id); + node->data.attributes[name] = value; + + affectedNodes.push_back(id); + TaskIdList ancestors = ancestorList(id); + concatTaskIdLists(affectedNodes, ancestors); + } + catch(std::exception& e) + { + throw e; + } + + return affectedNodes; } -task_t TaskTree::data(taskid_t id) - throw (std::exception) +task_t TaskTree::data(taskid_t id) + throw (std::exception) { - - task_t t; - - try { - node_t* node = id2node.at(id); - task_t tmp = node->data; - t.id = node->id; - t.attributes = tmp.attributes; -// DEBUG(tasktree, "!!!!t.id and tmp.id in data: %d and %d\n", t.id, tmp.id); - if(node->parent) t.parentid = node->parent->id; - else { - if(t.id != rootid) throw std::exception(); - t.parentid = -1; - } - } - catch(std::exception& e) { - throw e; - } - - return t; + task_t t; + + try + { + node_t* node = id2node.at(id); + task_t tmp = node->data; + t.id = node->id; + t.attributes = tmp.attributes; + //DEBUG(tasktree, "!!!!t.id and tmp.id in data: %d and %d\n", t.id, tmp.id); + if(node->parent) + { + t.parentid = node->parent->id; + } + else + { + if(t.id != rootid) + { + throw std::exception(); + } + t.parentid = -1; + } + } + catch(std::exception& e) + { + throw e; + } + + return t; } // bfs search from id in tree -TaskIdList TaskTree::bfs(taskid_t id) - throw (std::exception) +TaskIdList TaskTree::bfs(taskid_t id) + throw (std::exception) { - - TaskIdList lst; - lst.push_back(id); - - std::list<node_t*> queue; - node_t* current = id2node.at(id); - while(true) { - NodeList children = current->children; - for(NodeList::iterator it = children.begin(); it != children.end(); it++) { - node_t* child = *it; - queue.push_back(child); - lst.push_back(child->id); - } - - if(!queue.empty()) { - current = queue.front(); - queue.pop_front(); - } - else { - break; - } - } - - return lst; + TaskIdList lst; + lst.push_back(id); + + std::list<node_t*> queue; + node_t* current = id2node.at(id); + while(true) + { + NodeList children = current->children; + for(NodeList::iterator it = children.begin(); it != children.end(); it++) + { + node_t* child = *it; + queue.push_back(child); + lst.push_back(child->id); + } + + if(!queue.empty()) + { + current = queue.front(); + queue.pop_front(); + } + else + { + break; + } + } + + return lst; } TaskIdList TaskTree::ancestorList(taskid_t id) - throw (std::exception) + throw (std::exception) { - - TaskIdList ancestors; - - try { - node_t* current = id2node.at(id); - while(current->parent) { - ancestors.push_back(current->parent->id); - current = current->parent; - } - } - catch(std::exception& e) { - throw e; - } - -// DEBUG(tasktree, "Collected %d ancestors to %u\n", ancestors.size(), id); -// for(TaskIdList::iterator it = ancestors.begin(); -// it != ancestors.end(); it++) { -// DEBUG(tasktree, "\tancestor %u\n", *it); -// } - return ancestors; + TaskIdList ancestors; + + try + { + node_t* current = id2node.at(id); + while(current->parent) + { + ancestors.push_back(current->parent->id); + current = current->parent; + } + } + catch(std::exception& e) + { + throw e; + } + + //DEBUG(tasktree, "Collected %d ancestors to %u\n", ancestors.size(), id); + //for(TaskIdList::iterator it = ancestors.begin(); + // it != ancestors.end(); it++) + //{ + // DEBUG(tasktree, "\tancestor %u\n", *it); + //} + return ancestors; } -node_t* TaskTree::createNode(taskid_t id) { - node_t* node = new node_t(); - node->parent = NULL; - node->id = id; - id2node[id] = node; - return node; +node_t* TaskTree::createNode(taskid_t id) +{ + node_t* node = new node_t(); + node->parent = NULL; + node->id = id; + id2node[id] = node; + return node; } -void TaskTree::insertChild(node_t* parent, node_t* child) { - if(parent) parent->children.push_back(child); - else { - rootid = child->id; - root = child; - } - child->parent = parent; +void TaskTree::insertChild(node_t* parent, node_t* child) +{ + if(parent) + { + parent->children.push_back(child); + } + else + { + rootid = child->id; + root = child; + } + child->parent = parent; } -static void printNode(node_t* node, std::string prefix) { - if(!node) return; - task_t t = node->data; - DEBUG(tasktree, "%s- %u - %s (%p)\n", prefix.c_str(), node->id, - t.attributes["title"].c_str(), node); - - NodeList::iterator it; - for(it = node->children.begin(); it != node->children.end(); it++) { - node_t* child = *it; - printNode(child, " " + prefix); - } +static void printNode(node_t* node, std::string prefix) +{ + if(!node) + { + return; + } + task_t t = node->data; + DEBUG(tasktree, "%s- %u - %s (%p)\n", prefix.c_str(), node->id, + t.attributes["title"].c_str(), node); + + NodeList::iterator it; + for(it = node->children.begin(); it != node->children.end(); it++) + { + node_t* child = *it; + printNode(child, " " + prefix); + } } -void TaskTree::toStdOut() { - printNode(root, ""); +void TaskTree::toStdOut() +{ + printNode(root, ""); } std::string TaskTree::toXML() { - node_t *root = id2node.at(rootid); + node_t *root = id2node.at(rootid); - std::string xml; - xml += "<?xml version='1.0' encoding='UTF-8'?>\n"; - xml += "<tasktree nextid=\""+id2str(nextid)+"\">\n"; - xml += root->toXML(" "); - xml += "</tasktree>"; + std::string xml; + xml += "<?xml version='1.0' encoding='UTF-8'?>\n"; + xml += "<tasktree nextid=\""+id2str(nextid)+"\">\n"; + xml += root->toXML(" "); + xml += "</tasktree>"; - return xml; + return xml; } void TaskTree::fromXML(std::string xml) { - XmlParser p(this); - p.parse(xml.c_str(), xml.size()); + XmlParser p(this); + p.parse(xml.c_str(), xml.size()); } #ifdef TEST_TASKTREE //Additional dependency files -//deps: debug.cc log.cc +//deps: debug.cc log.cc //Required cflags (autoconf vars may be used) -//cflags: -I.. +//cflags: -I.. //Required link options (autoconf vars may be used) //libs: #include "test.h" diff --git a/src/tasktree.h b/src/tasktree.h index 8efadeb..e33cd61 100644 --- a/src/tasktree.h +++ b/src/tasktree.h @@ -25,8 +25,7 @@ * along with Munia; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#ifndef __MUNIA_TASKTREE_H__ -#define __MUNIA_TASKTREE_H__ +#pragma once #include <list> #include <map> @@ -40,48 +39,47 @@ typedef std::list<class node*> NodeList; class node { public: - taskid_t id; - node* parent; - task_t data; - NodeList children; + taskid_t id; + node* parent; + task_t data; + NodeList children; - std::string toXML(std::string prefix); + std::string toXML(std::string prefix); }; typedef node node_t; -class TaskTree { - friend class XmlParser; +class TaskTree +{ + friend class XmlParser; public: - TaskTree(); - ~TaskTree(); + TaskTree(); + ~TaskTree(); - taskid_t createId(); + taskid_t createId(); - TaskIdList insertAsChild(taskid_t parentid, taskid_t id, task_t data) throw (std::exception); - TaskIdList remove(taskid_t id) throw (std::exception); - TaskIdList move(taskid_t id, taskid_t newParentId) throw (std::exception); - TaskIdList updateData(taskid_t id, const std::string &name, - const std::string &value) throw (std::exception); - task_t data(taskid_t id) throw (std::exception); + TaskIdList insertAsChild(taskid_t parentid, taskid_t id, task_t data) throw (std::exception); + TaskIdList remove(taskid_t id) throw (std::exception); + TaskIdList move(taskid_t id, taskid_t newParentId) throw (std::exception); + TaskIdList updateData(taskid_t id, const std::string &name, + const std::string &value) throw (std::exception); + task_t data(taskid_t id) throw (std::exception); - TaskIdList bfs(taskid_t id) throw (std::exception); + TaskIdList bfs(taskid_t id) throw (std::exception); - TaskIdList ancestorList(taskid_t id) throw (std::exception); + TaskIdList ancestorList(taskid_t id) throw (std::exception); - void toStdOut(); + void toStdOut(); - std::string toXML(); - void fromXML(std::string xml); + std::string toXML(); + void fromXML(std::string xml); - taskid_t nextid; + taskid_t nextid; private: - node_t* createNode(taskid_t id); - void insertChild(node_t* parent, node_t* child); + node_t* createNode(taskid_t id); + void insertChild(node_t* parent, node_t* child); - node_t* root; - std::map<int, node_t*> id2node; + node_t* root; + std::map<int, node_t*> id2node; }; - -#endif/*__MUNIA_TASKTREE_H__*/ diff --git a/src/testclient.cc b/src/testclient.cc index f608ce0..58e55a1 100644 --- a/src/testclient.cc +++ b/src/testclient.cc @@ -41,80 +41,74 @@ #include <libwebsockets.h> -struct test { - const char *command; - const char *result; - bool success; +struct test +{ + const char *command; + const char *result; + bool success; }; -enum demo_protocols { +enum demo_protocols +{ PROTOCOL_TASK, }; -struct test *current_test = NULL; +struct test *current_test = nullptr; -static int callback_task(struct libwebsocket_context *me, - struct libwebsocket *wsi, - enum libwebsocket_callback_reasons reason, +static int callback_task(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]; + LWS_SEND_BUFFER_POST_PADDING]; int l; - switch (reason) { - + switch (reason) + { case LWS_CALLBACK_CLOSED: - fprintf(stderr, "mirror: LWS_CALLBACK_CLOSED\n"); - // wsi_mirror = NULL; + fprintf(stderr, "mirror: LWS_CALLBACK_CLOSED\n"); + // wsi_mirror = nullptr; break; case LWS_CALLBACK_CLIENT_ESTABLISHED: - - /* - * start the ball rolling, - * LWS_CALLBACK_CLIENT_WRITEABLE will come next service - */ - - libwebsocket_callback_on_writable(me, wsi); + // start the ball rolling, + // LWS_CALLBACK_CLIENT_WRITEABLE will come next service + 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"); - current_test->success = strncmp(current_test->result, (char*)in, len) == 0; - - current_test++; - libwebsocket_callback_on_writable(me, wsi); + fprintf(stderr, "rx %d '", (int)len); + fwrite(in, len, 1, stderr); + fprintf(stderr, "'\n"); + current_test->success = strncmp(current_test->result, (char*)in, len) == 0; + current_test++; + lws_callback_on_writable(me, wsi); break; case LWS_CALLBACK_CLIENT_WRITEABLE: - - l = sprintf((char *)&buf[LWS_SEND_BUFFER_PRE_PADDING], - "%s", current_test->command); + "%s", current_test->command); - fprintf(stderr, "sx '%s'\n", &buf[LWS_SEND_BUFFER_PRE_PADDING]); + fprintf(stderr, "sx '%s'\n", &buf[LWS_SEND_BUFFER_PRE_PADDING]); - libwebsocket_write(wsi, &buf[LWS_SEND_BUFFER_PRE_PADDING], - l, LWS_WRITE_TEXT); + lws_write(wsi, &buf[LWS_SEND_BUFFER_PRE_PADDING], + l, LWS_WRITE_TEXT); - if(current_test->result == NULL) { - current_test->success = true; - current_test++; - libwebsocket_callback_on_writable(me, wsi); - } + if(current_test->result == nullptr) + { + current_test->success = true; + current_test++; + lws_callback_on_writable(me, wsi); + } - /* - * without at least this delay, we choke the browser - * and the connection stalls, despite we now take care about - * flow control - */ + // without at least this delay, we choke the browser + // and the connection stalls, despite we now take care about + // flow control - // usleep(200); - // sleep(1); + //usleep(200); + //sleep(1); break; default: @@ -124,61 +118,61 @@ static int callback_task(struct libwebsocket_context *me, return 0; } -static struct libwebsocket_protocols protocols[] = { - { "lws-task-protocol", callback_task, 0, }, - { NULL, NULL, 0 } +static struct lws_protocols protocols[] = +{ + { "lws-task-protocol", callback_task, 0, }, + { nullptr, nullptr, 0 } }; int client(const char *address, int port, struct test tests[]) { - current_test = &tests[0]; + current_test = &tests[0]; - struct libwebsocket_context *context; - struct libwebsocket *wsi_task = NULL; + struct lws_context *context; + struct lws *wsi_task = nullptr; int ietf_version = -1; // latest - context = libwebsocket_create_context(CONTEXT_PORT_NO_LISTEN, NULL, - protocols, - libwebsocket_internal_extensions, - NULL, NULL, -1, -1, 0); - if (context == NULL) { - fprintf(stderr, "Creating libwebsocket context failed\n"); + 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 && current_test->command) { - n = libwebsocket_service(context, 1000); - - if (wsi_task == NULL) { - wsi_task = libwebsocket_client_connect(context, address, port, - 0, "/", address, address, - protocols[PROTOCOL_TASK].name, - ietf_version); - - if (wsi_task == NULL) { - fprintf(stderr, "libwebsocket task connect failed\n"); + // 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 && current_test->command) + { + n = lws_service(context, 1000); + + if(wsi_task == nullptr) + { + wsi_task = lws_client_connect(context, address, port, + 0, "/", address, address, + protocols[PROTOCOL_TASK].name, + ietf_version); + + if` (wsi_task == nullptr) + { + fprintf(stderr, "lws task connect failed\n"); return -1; } - - } else { - - /* - fprintf(stderr, "closing mirror session\n"); - libwebsocket_close_and_free_session(context, - wsi_mirror, LWS_CLOSE_STATUS_GOINGAWAY); - */ + } + else + { + //fprintf(stderr, "closing mirror session\n"); + //lws_close_and_free_session(context, + // wsi_mirror, LWS_CLOSE_STATUS_GOINGAWAY); } } fprintf(stderr, "Exiting\n"); - libwebsocket_context_destroy(context); + lws_context_destroy(context); return 0; } @@ -187,33 +181,33 @@ TEST_BEGIN; #define BASE "0 create 0 -1; 0 update 0 \"root\"; 0 create 1 0; 0 update 1 \"Finished\"; 0 create 2 0; 0 update 2 \"Backlog\"; 0 create 3 0; 0 update 3 \"Lost+Found\"; 0 create 4 0; 0 update 4 \"Projects\";" #define RMBASE "0 remove 4; 0 remove 3; 0 remove 2; 0 remove 1; 0 remove 0;" -static struct test tests[] = { - { "observe 0", BASE, false }, - { "unobserve 0", RMBASE, false }, - { "create 0", NULL, false }, - { "observe 0", BASE" 0 create 10 0; 0 update 10 \"\";", false }, - { "update 10 \"My title\"", "0 update 10 \"My title\";", false }, - { "unobserve 0", "0 remove 10; "RMBASE, false }, - { "observe 0", BASE" 0 create 10 0; 0 update 10 \"My title\";", false }, - { "move 10 1", "0 move 10 1;", false }, - { "create 10", "0 create 11 10;", false }, - { "remove 10", "0 remove 11; 0 remove 10;", false }, - /* - { "observe 0", BASE"0 add title description 5", false }, - { "add title2 description 0", BASE"0 add title2 description 6", false }, - { "unobserve 0", NULL, false }, - { "observe 0", BASE"0 add title description 5; add title description 6", false }, - { "unobserve 0", NULL, false }, - */ - { NULL, NULL, false } +static struct test tests[] = +{ + { "observe 0", BASE, false }, + { "unobserve 0", RMBASE, false }, + { "create 0", nullptr, false }, + { "observe 0", BASE" 0 create 10 0; 0 update 10 \"\";", false }, + { "update 10 \"My title\"", "0 update 10 \"My title\";", false }, + { "unobserve 0", "0 remove 10; "RMBASE, false }, + { "observe 0", BASE" 0 create 10 0; 0 update 10 \"My title\";", false }, + { "move 10 1", "0 move 10 1;", false }, + { "create 10", "0 create 11 10;", false }, + { "remove 10", "0 remove 11; 0 remove 10;", false }, + //{ "observe 0", BASE"0 add title description 5", false }, + //{ "add title2 description 0", BASE"0 add title2 description 6", false }, + //{ "unobserve 0", nullptr, false }, + //{ "observe 0", BASE"0 add title description 5; add title description 6", false }, + //{ "unobserve 0", nullptr, false }, + { nullptr, nullptr, false } }; client("localhost", 10001, tests); struct test *t = &tests[0]; -while(t->command) { - TEST_TRUE(t->success, "%s", t->command); - t++; +while(t->command) +{ + TEST_TRUE(t->success, "%s", t->command); + t++; } // TODO: Put some testcode here (see test.h for usable macros). //TEST_TRUE(false, "No tests yet!"); diff --git a/src/testclient.h b/src/testclient.h index d92bd9c..f9562f4 100644 --- a/src/testclient.h +++ b/src/testclient.h @@ -25,6 +25,4 @@ * along with Munia; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#ifndef __MUNIA_TESTCLIENT_H__ -#define __MUNIA_TESTCLIENT_H__ -#endif/*__MUNIA_TESTCLIENT_H__*/ +#pragma once diff --git a/src/xml_encode_decode.cc b/src/xml_encode_decode.cc index 1c0e377..b1777d9 100644 --- a/src/xml_encode_decode.cc +++ b/src/xml_encode_decode.cc @@ -26,59 +26,64 @@ */ #include "xml_encode_decode.h" #include <string.h> + /* char xml_map[][2][16] = - { - { "&", "&" }, // & must be first - { "\'", "'" }, - { "\"", "&qout;" }, - { ">", ">" }, - { "<", "<" }, - { "", "" } // End marker - }; +{ + { "&", "&" }, // & must be first + { "\'", "'" }, + { "\"", "&qout;" }, + { ">", ">" }, + { "<", "<" }, + { "", "" } // End marker +}; */ char xml_map[][2][16] = - { - { "&", "&" }, // & must be first - { "\'", "'" }, - { "\"", """ }, - { ">", ">" }, - { "<", "<" }, - { "", "" } // End marker - }; +{ + { "&", "&" }, // & must be first + { "\'", "'" }, + { "\"", """ }, + { ">", ">" }, + { "<", "<" }, + { "", "" } // End marker +}; #define MAX_MAPS 5 std::string xml_encode(std::string str) { - size_t pos; + size_t pos; - for( int map = 0; map < MAX_MAPS; map++ ) { - pos = 0; - while( ( pos = str.find(xml_map[map][0], pos) ) != std::string::npos) { - str.replace(pos, strlen(xml_map[map][0]), xml_map[map][1]); - pos += strlen(xml_map[map][1]); - } - } + for(int map = 0; map < MAX_MAPS; map++) + { + pos = 0; + while((pos = str.find(xml_map[map][0], pos)) != std::string::npos) + { + str.replace(pos, strlen(xml_map[map][0]), xml_map[map][1]); + pos += strlen(xml_map[map][1]); + } + } - return str; + return str; } std::string xml_decode(std::string str) { - size_t pos; - - // Traverse backwards, to handle '&' last. - for( int map = MAX_MAPS - 1; map > -1; map-- ) { - pos = 0; - while( ( pos = str.find(xml_map[map][1], pos) ) != std::string::npos) { - str.replace(pos, strlen(xml_map[map][1]), xml_map[map][0]); - pos += strlen(xml_map[map][0]); - } - } - - return str; + size_t pos; + + // Traverse backwards, to handle '&' last. + for(int map = MAX_MAPS - 1; map > -1; map--) + { + pos = 0; + while((pos = str.find(xml_map[map][1], pos)) != std::string::npos) + { + str.replace(pos, strlen(xml_map[map][1]), xml_map[map][0]); + pos += strlen(xml_map[map][0]); + } + } + + return str; } #ifdef TEST_XML_ENCODE_DECODE diff --git a/src/xml_encode_decode.h b/src/xml_encode_decode.h index 39b1407..848e674 100644 --- a/src/xml_encode_decode.h +++ b/src/xml_encode_decode.h @@ -24,12 +24,9 @@ * along with Pracro; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#ifndef __PRACRO_XML_ENCODE_DECODE_H__ -#define __PRACRO_XML_ENCODE_DECODE_H__ +#pragma once #include <string> std::string xml_encode(std::string str); std::string xml_decode(std::string str); - -#endif/*__PRACRO_XML_ENCODE_DECODE_H__*/ diff --git a/src/xmlparser.cc b/src/xmlparser.cc index 03a54a1..a087c62 100644 --- a/src/xmlparser.cc +++ b/src/xmlparser.cc @@ -41,46 +41,56 @@ XmlParser::~XmlParser() void XmlParser::characterData(const std::string &data) { - cdata += data; + cdata += data; } void XmlParser::startTag(std::string name, attributes_t &attr) { - if(name == "tasktree") { - tree->nextid = atoi(xml_decode(attr["nextid"]).c_str()); - } - - if(name == "task") { - taskid_t id = atoi(xml_decode(attr["id"]).c_str()); - - node_t* parent = NULL; - if(parents.size() != 0) parent = tree->id2node.at(parents.top()); - - node = tree->createNode(id); - tree->insertChild(parent, node); - } - - if(name == "children") { - parents.push(node->id); - } - - if(name == "attribute") { - attr_name = attr["name"]; - } - - cdata = ""; + if(name == "tasktree") + { + tree->nextid = atoi(xml_decode(attr["nextid"]).c_str()); + } + + if(name == "task") + { + taskid_t id = atoi(xml_decode(attr["id"]).c_str()); + + node_t* parent = NULL; + if(parents.size() != 0) + { + parent = tree->id2node.at(parents.top()); + } + + node = tree->createNode(id); + tree->insertChild(parent, node); + } + + if(name == "children") + { + parents.push(node->id); + } + + if(name == "attribute") + { + attr_name = attr["name"]; + } + + cdata = ""; } void XmlParser::endTag(std::string name) { - if(name == "task") { - } - - if(name == "children") { - parents.pop(); - } - - if(name == "attribute") { - node->data.attributes[attr_name] = cdata; - } + if(name == "task") + { + } + + if(name == "children") + { + parents.pop(); + } + + if(name == "attribute") + { + node->data.attributes[attr_name] = cdata; + } } diff --git a/src/xmlparser.h b/src/xmlparser.h index 92e0529..6247497 100644 --- a/src/xmlparser.h +++ b/src/xmlparser.h @@ -3,7 +3,7 @@ /*************************************************************************** * xmlparser.h * - * Wed Mar 21 09:15:51 CET 2012 + * Wed Mar 21 09:15:51 CET 2012 * Copyright 2012 Jonas Suhr Christensen * jsc@umbraculum.org ****************************************************************************/ @@ -25,8 +25,7 @@ * along with Munia; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#ifndef __MUNIA_XMLPARSER_H__ -#define __MUNIA_XMLPARSER_H__ +#pragma once #include "task.h" #include "saxparser.h" @@ -34,21 +33,21 @@ #include <stack> #include "tasktree.h" -class XmlParser : public SAXParser { +class XmlParser + : public SAXParser +{ public: - XmlParser(TaskTree *tree); - ~XmlParser(); - - void startTag(std::string name, attributes_t &attr); - void endTag(std::string name); - void characterData(const std::string &data); + XmlParser(TaskTree *tree); + ~XmlParser(); + + void startTag(std::string name, attributes_t &attr); + void endTag(std::string name); + void characterData(const std::string &data); private: - std::stack<taskid_t> parents; - std::string cdata; - node_t *node; - TaskTree *tree; - std::string attr_name; + std::stack<taskid_t> parents; + std::string cdata; + node_t *node; + TaskTree *tree; + std::string attr_name; }; - -#endif/*__MUNIA_XMLPARSER_H__*/ |