diff options
Diffstat (limited to 'src/task_proto.cc')
-rw-r--r-- | src/task_proto.cc | 347 |
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; +} |