/* Handle subscribe message */ static int web_subscribe(struct mg_connection *conn) { char *flag_start = conn->content + 2; char *id_start = strchr(flag_start, ' ') + 1; int len; cx_id id; cx_object o = NULL; web_wsconnection wc = web_wsconnection(conn->connection_param); /* Check if message is correct */ if ((id_start - conn->content) > (int)conn->content_len) { printf("error: message '%.*s' not correctly formatted\n", (int)conn->content_len, conn->content); goto error; } /* Copy identifier to buffer */ len = (int)conn->content_len - (id_start - conn->content); memcpy(id, id_start, len); id[len] = '\0'; /* Silence previous subscription */ if (wc->observing) { cx_silence(wc->observing, web_wsconnection_onUpdate_o, wc); cx_silence(wc->observing, web_wsconnection_onDelete_o, wc); } wc->eventCount = 0; /* Lookup object */ o = cx_resolve(NULL, id); if (!o) { goto error; } else if (!cx_checkAttr(o, CX_ATTR_OBSERVABLE)) { /* Can't listen if object is not observable, but can send the client the value */ cx_set(&wc->observing, NULL); web_wsconnection_send(wc, o, TRUE, TRUE, TRUE, TRUE, FALSE); wc->eventCount++; } else { /* Configure observer to listen for updates */ cx_set(&wc->observing, o); cx_listen(o, web_wsconnection_onUpdate_o, wc); cx_listen(o, web_wsconnection_onDelete_o, wc); } return 0; error: return -1; }
/* Serve a Cortex object */ static int web_serveObject(struct mg_connection *conn) { cx_object o = NULL; /* Resolve object based on URI */ o = cx_resolve(NULL, (cx_string)conn->uri + 2); if (!o) { mg_send_status(conn, 404); mg_printf_data(conn, "404: resource '%s' not found\n", conn->uri); } else { char option[6]; cx_bool value = 0; cx_bool meta = 0; cx_bool scope = 0; /* Set correct content type */ mg_send_header(conn, "Content-Type", "application/json; charset=utf-8"); /* Determine what to show */ mg_get_var(conn, "value", option, sizeof(option)); if (!strcmp(option, "true")) { value = TRUE; } mg_get_var(conn, "meta", option, sizeof(option)); if (!strcmp(option, "true")) { meta = TRUE; } mg_get_var(conn, "scope", option, sizeof(option)); if (!strcmp(option, "true")) { scope = TRUE; } if (!(value || meta || scope)) { value = TRUE; } { /* Serialize object-value to JSON */ struct cx_serializer_s serializer = cx_json_ser(CX_PRIVATE, CX_NOT, CX_SERIALIZER_TRACE_NEVER); if ((cx_typeof(o)->kind == CX_VOID) && (!meta && !scope)) { mg_printf_data(conn, "\n"); } else { mg_printf_data(conn, "["); /* Serialize metadata of parents */ if (meta) { if (web_printParents(conn, cx_parentof(o))) { mg_printf_data(conn, ","); } } /* Serialize value */ { cx_json_ser_t jsonData = {NULL, NULL, 0, 0, 0, meta, value, scope, TRUE}; cx_serialize(&serializer, o, &jsonData); mg_printf_data(conn, "%s", jsonData.buffer); cx_dealloc(jsonData.buffer); } mg_printf_data(conn, "]\n"); } } cx_free(o); } return MG_TRUE; }
/* ::cortex::lang::type::resolve(string name) */ cx_object cx_type_resolve(cx_any _this, cx_string name) { /* $begin(::cortex::lang::type::resolve) */ return cx_resolve(_this.value, name); /* $end */ }