Select Git revision
proto-xaal.c 3.76 KiB
/* xaaws - xAAL web interface
* Part of the 'xaaws' software
* (c) 2019 Christophe Lohr <christophe.lohr@imt-atlantique.fr>
*
* This program 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 3 of the License, or
* (at your option) any later version.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <libwebsockets.h>
#include <sys/queue.h>
#include <json-c/json.h>
#include <sys/queue.h>
#include "proto-xaal.h"
#include "db.h"
#include "xaaws.h"
#include "xaagent.h"
int callback_xaal_ctl(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) {
struct per_session_data__xaal_ctl *pss = (struct per_session_data__xaal_ctl *)user;
switch (reason) {
case LWS_CALLBACK_ESTABLISHED: {
req_t *req = (req_t *) malloc( sizeof(req_t) );
req->wsi = wsi;
TAILQ_INSERT_TAIL(&(db.jattrreqs), req, entries);
pss->janswer = NULL;
pss->tok = json_tokener_new();
lws_callback_on_writable(wsi);
break; }
case LWS_CALLBACK_SERVER_WRITEABLE:
if (pss->janswer) {
if ( serve_ws_stream(wsi, pss->janswer) ) {
json_object_put(pss->janswer);
pss->janswer = NULL;
break;
} else {
lwsl_err("Can't feed WebSocket 'xaal-ctl'\n");
return -1;
}
}
break;
case LWS_CALLBACK_RECEIVE: {
json_object *jinput;
enum json_tokener_error jerr;
jinput = json_tokener_parse_ex(pss->tok, in, len);
jerr = json_tokener_get_error(pss->tok);
switch (jerr) {
case json_tokener_success:
if (jinput) {
if ( !ws_xAAL_json_request(&bus, &me, jinput) )
lwsl_err("Can't forward xAAL request from 'xaal-ctl'\n");
json_object_put(jinput);
}
json_tokener_free(pss->tok);
pss->tok = json_tokener_new();
break;
case json_tokener_continue:
break;
default:
lwsl_err("Can't read WebSocket 'xaal-ctl'. JSON error: %s\n", json_tokener_error_desc(jerr));
json_object_put(jinput);
json_tokener_free(pss->tok);
pss->tok = json_tokener_new();
}
break; }
case LWS_CALLBACK_CLOSED:
json_tokener_free(pss->tok);
break;
default:
break;
}
return 0;
}
int callback_xaal_dump(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) {
struct per_session_data__xaal_dump *pss = (struct per_session_data__xaal_dump *)user;
switch (reason) {
case LWS_CALLBACK_ESTABLISHED: {
req_t *req = (req_t *) malloc( sizeof(req_t) );
req->wsi = wsi;
TAILQ_INSERT_TAIL(&(db.jmsgreqs), req, entries);
pss->janswer = NULL;
lws_callback_on_writable(wsi);
break; }
case LWS_CALLBACK_SERVER_WRITEABLE:
if (pss->janswer) {
if ( serve_ws_stream(wsi, pss->janswer) ) {
json_object_put(pss->janswer);
pss->janswer = NULL;
break;
} else {
lwsl_err("Can't feed WebSocket\n");
return -1;
}
}
break;
default:
break;
}
return 0;
}
bool serve_ws_stream(struct lws *wsi, json_object *jobj) {
const char *json = json_object_to_json_string_ext(jobj, JSON_C_TO_STRING_PLAIN|JSON_C_TO_STRING_NOZERO);
char buf[ LWS_PRE + strlen(json) + 1 ];
char *p = &buf[LWS_PRE];
int n, m;
n = sprintf((char *)p, "%s", json);
m = lws_write(wsi, (unsigned char *)p, n, LWS_WRITE_TEXT);
return (m >= n);
}