summaryrefslogtreecommitdiff
path: root/src/task_proto.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/task_proto.cc')
-rw-r--r--src/task_proto.cc347
1 files changed, 347 insertions, 0 deletions
diff --git a/src/task_proto.cc b/src/task_proto.cc
new file mode 100644
index 0000000..af1e31d
--- /dev/null
+++ b/src/task_proto.cc
@@ -0,0 +1,347 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set et sw=2 ts=2: */
+/***************************************************************************
+ * task_proto.cc
+ *
+ * Fri Feb 24 08:23:16 CET 2012
+ * Copyright 2012 Bent Bisballe Nyeng
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This file is part of Munia.
+ *
+ * Munia is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Munia is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Munia; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+#include "task_proto.h"
+
+#include <stdio.h>
+#include <string.h>
+
+#include <queue>
+
+#include "task.h"
+
+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;
+ fprintf(stderr, " %s = ", token_names[n]);
+ if(fwrite(lwst[n].token, 1, lwst[n].token_len, stderr)) {}
+ fprintf(stderr, "\n");
+ }
+}
+
+#define MAX_MESSAGE_QUEUE 1024
+
+struct a_message {
+ void *payload;
+ size_t len;
+};
+
+typedef std::list<struct libwebsocket*> ClientList;
+
+std::queue<std::string> msgqueue;
+
+/*
+static struct a_message ringbuffer[MAX_MESSAGE_QUEUE];
+static int ringbuffer_head;
+*/
+
+static ClientList clientlist;
+static int id_count = 0;
+
+int callback_lws_task(struct libwebsocket_context * context,
+ struct libwebsocket *wsi,
+ enum libwebsocket_callback_reasons reason,
+ void *user, void *in, size_t len)
+{
+ int n;
+ struct per_session_data__lws_task *pss =
+ (struct per_session_data__lws_task *)user;
+
+ printf("Current number of clients: %d\n", clientlist.size());
+
+ switch (reason) {
+ printf("============= Reason %d\n", reason);
+ case LWS_CALLBACK_ESTABLISHED:
+ {
+ fprintf(stderr, "callback_lws_task: LWS_CALLBACK_ESTABLISHED\n");
+ // pss->ringbuffer_tail = ringbuffer_head;
+ pss->wsi = wsi;
+ clientlist.push_back(wsi);
+
+ // send all current tasks
+ char buf[32];
+ std::string init_str;
+ TaskList::iterator it;
+ for(it = tasklist.begin(); it != tasklist.end(); it++) {
+ struct task t = *it;
+
+ sprintf(buf, "add %d %s %s %d %d;",
+ t.id, t.title.c_str(), t.desc.c_str(), t.x, t.y);
+ init_str.append(buf);
+ }
+
+ std::string msg;
+ msg.append((size_t)LWS_SEND_BUFFER_PRE_PADDING, ' ');
+ msg.append(init_str);
+ msg.append((size_t)LWS_SEND_BUFFER_POST_PADDING, ' ');
+ msgqueue.push(msg);
+
+ /*
+ n = libwebsocket_write(wsi, (unsigned char*) init_str.data(),
+ init_str.length(), LWS_WRITE_TEXT);
+ if(n < 0) {
+ fprintf(stderr, "ERROR writing to socket");
+ exit(1);
+ }
+ */
+ libwebsocket_rx_flow_control(wsi, 1);
+ }
+ break;
+
+ case LWS_CALLBACK_CLOSED:
+ {
+ printf("Closing connection\n");
+ clientlist.remove(wsi);
+ }
+
+ case LWS_CALLBACK_SERVER_WRITEABLE:
+ {
+ printf("LWS_CALLBACK_SERVER_WRITEABLE\n");
+
+ // if(pss->ringbuffer_tail != ringbuffer_head) {
+ if(msgqueue.size() > 0) {
+ std::string msg = msgqueue.front();
+ msgqueue.pop();
+ n = libwebsocket_write(wsi, (unsigned char *)
+ msg.c_str() +
+ LWS_SEND_BUFFER_PRE_PADDING,
+ msg.length() - LWS_SEND_BUFFER_POST_PADDING - LWS_SEND_BUFFER_PRE_PADDING,
+ LWS_WRITE_TEXT);
+ if(n < 0) {
+ fprintf(stderr, "ERROR writing to socket");
+ exit(1);
+ }
+
+ /*
+ if(((ringbuffer_head - pss->ringbuffer_tail) % MAX_MESSAGE_QUEUE)
+ < (MAX_MESSAGE_QUEUE - 15))
+ libwebsocket_rx_flow_control(wsi, 1);
+ */
+
+ // libwebsocket_rx_flow_control(wsi,msgqueue.size() > 0);
+
+ libwebsocket_callback_on_writable(context, wsi);
+ usleep(200);
+ }
+ }
+ break;
+
+ case LWS_CALLBACK_BROADCAST:
+ printf("LWS_CALLBACK_BROADCAST\n");
+ n = libwebsocket_write(wsi, (unsigned char*)in, len, LWS_WRITE_TEXT);
+ if (n < 0) fprintf(stderr, "task write failed\n");
+ break;
+
+ case LWS_CALLBACK_RECEIVE:
+ {
+ printf("LWS_CALLBACK_RECEIVE\n");
+
+ printf("%s\n", (char*)in);
+ std::string data;
+ data.append((char*)in, len);
+
+ /*
+ struct a_message &msg = ringbuffer[ringbuffer_head];
+ if(msg.payload) {
+ free(msg.payload);
+ msg.payload = NULL;
+ }
+
+ */
+ char buf[1024];
+ size_t buf_len = 0;
+
+ std::string cmd = data.substr(0, data.find(' '));
+ printf("Cmd: %s\n", cmd.c_str());
+
+ if(cmd == "add") {
+ printf("Handling add cmd:\n");
+ int offset = cmd.length() + 1;
+ std::string title = data.substr(offset, data.find(' ', offset) - offset);
+ offset += title.length() + 1;
+ std::string desc = data.substr(offset, data.find(' ', offset) - offset);
+ offset += desc.length() + 1;
+ std::string x_str = data.substr(offset, data.find(' ', offset) - offset);
+ int x = atoi(x_str.c_str());
+ offset += x_str.length() + 1;
+ std::string y_str = data.substr(offset, data.find(' ', offset) - offset);
+ int y = atoi(y_str.c_str());
+
+ struct task t;
+ t.x = x;
+ t.y = y;
+ t.title = title;
+ t.desc = desc;
+ t.id = id_count; id_count++;
+ tasklist.push_back(t);
+
+ buf_len = sprintf(buf, "add %d %s %s %d %d;",
+ t.id, t.title.c_str(), t.desc.c_str(),
+ t.x, t.y);
+
+ printf("Adding task: %s\n", buf);
+
+ } else if(cmd == "del") {
+ printf("Delete\n");
+ int offset = cmd.length() + 1;
+ std::string id_str = data.substr(offset, data.find(' ', offset) - offset);
+ int id = atoi(id_str.c_str());
+ printf("Deleting task with id %d\n", id);
+
+ bool id_found = false;
+ TaskList::iterator it;
+ for(it = tasklist.begin(); it != tasklist.end(); it++) {
+ struct task t = *it;
+ if(t.id == id) {
+ id_found = true;
+ tasklist.erase(it);
+ break;
+ }
+ }
+
+ if(!id_found) {
+ printf("\t!!!Could not locate task with id %d\n", id);
+ }
+
+ buf_len = sprintf(buf, "del %d;", id);
+ printf("Deleting task: %s\n", buf);
+
+ } else if(cmd == "move") {
+ printf("Move\n");
+
+ int offset = cmd.length() + 1;
+ std::string s_id = data.substr(offset, data.find(' ', offset) - offset);
+ int id = atoi(s_id.c_str());
+ offset += s_id.length() + 1;
+ std::string x_str = data.substr(offset, data.find(' ', offset) - offset);
+ int x = atoi(x_str.c_str());
+ offset += x_str.length() + 1;
+ std::string y_str = data.substr(offset, data.find(' ', offset) - offset);
+ int y = atoi(y_str.c_str());
+
+ printf("Moving task with id %d to (%d,%d)\n", id, x, y);
+
+ bool id_found = false;
+ TaskList::iterator it;
+ for(it = tasklist.begin(); it != tasklist.end(); it++) {
+ struct task t = *it;
+ if(t.id == id) {
+ id_found = true;
+ t.x = x;
+ t.y = y;
+ break;
+ }
+ }
+
+ if(!id_found) {
+ printf("\t!!!Could not locate task with id %d\n", id);
+ }
+
+ buf_len = sprintf(buf, "move %d %d %d;", id, x / 300 * 300, y);
+ printf("Moving task: %s\n", buf);
+ } else if(cmd == "update") {
+ printf("Update\n");
+ }
+ else { // unknown command
+ printf("Unknown command :(\n");
+ break;
+ }
+
+// msg.payload = malloc(LWS_SEND_BUFFER_PRE_PADDING + len + LWS_SEND_BUFFER_POST_PADDING);
+// msg.len = len;
+// memcpy((char *)msg.payload + LWS_SEND_BUFFER_PRE_PADDING, in, len);
+// if(ringbuffer_head == (MAX_MESSAGE_QUEUE - 1)) ringbuffer_head = 0;
+// else ringbuffer_head++;
+/*
+ msg.payload = malloc(LWS_SEND_BUFFER_PRE_PADDING + buf_len
+ + LWS_SEND_BUFFER_POST_PADDING);
+ msg.len = buf_len;
+ memcpy((char *)msg.payload + LWS_SEND_BUFFER_PRE_PADDING,
+ buf, buf_len);
+ if(ringbuffer_head == (MAX_MESSAGE_QUEUE - 1)) ringbuffer_head = 0;
+ else ringbuffer_head++;
+*/
+ std::string msg;
+ msg.append((size_t)LWS_SEND_BUFFER_PRE_PADDING, ' ');
+ msg.append(buf, buf_len);
+ msg.append((size_t)LWS_SEND_BUFFER_POST_PADDING, ' ');
+ msgqueue.push(msg);
+ /*
+ if(((ringbuffer_head - pss->ringbuffer_tail) % MAX_MESSAGE_QUEUE) > (MAX_MESSAGE_QUEUE - 10))
+ libwebsocket_rx_flow_control(wsi, 0);
+ */
+ libwebsocket_callback_on_writable_all_protocol(libwebsockets_get_protocol(wsi));
+ //libwebsocket_rx_flow_control(wsi, 0);
+ }
+ break;
+ /*
+ * this just demonstrates how to use the protocol filter. If you won't
+ * study and reject connections based on header content, you don't need
+ * to handle this callback
+ */
+
+ case LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION:
+ printf("LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION\n");
+ dump_handshake_info((struct lws_tokens *)(long)user);
+ /* you could return non-zero here and kill the connection */
+ break;
+
+ default:
+ break;
+ }
+
+ return 0;
+}