void sj_init_uart(struct v7 *v7) { v7_val_t uart = v7_create_undefined(), uart_proto = v7_create_undefined(), uart_ctor = v7_create_undefined(); v7_own(v7, &uart); v7_own(v7, &uart_proto); v7_own(v7, &uart_ctor); uart = v7_create_object(v7); uart_proto = v7_create_object(v7); uart_ctor = v7_create_constructor(v7, uart_proto, UART_ctor); v7_set(v7, uart, "dev", ~0, V7_PROPERTY_HIDDEN, uart_ctor); v7_set_method(v7, uart_proto, "read", UART_read); v7_set_method(v7, uart_proto, "write", UART_write); v7_set_method(v7, uart_proto, "recv", UART_recv); v7_set(v7, v7_get_global(v7), "UART", ~0, 0, uart); { enum v7_err rcode = v7_exec( v7, "UART.open = function (d) { return new UART.dev(d); }", NULL); assert(rcode == V7_OK); #if defined(NDEBUG) (void) rcode; #endif } v7_disown(v7, &uart_ctor); v7_disown(v7, &uart_proto); v7_disown(v7, &uart); }
void sj_print_exception(struct v7 *v7, v7_val_t exc, const char *msg) { /* * TOD(mkm) add some API to hal to fetch the current debug mode * and avoid logging to stdout if according no error messages should go * there (e.g. because it's used to implement a serial protocol). */ FILE *fs[] = {stdout, stderr}; size_t i; v7_val_t msg_v = V7_UNDEFINED; /* * own because the exception could be a string, * and if not owned here, print_stack_trace could get * an unrelocated argument an ASN violation. */ v7_own(v7, &exc); v7_own(v7, &msg_v); msg_v = v7_get(v7, exc, "message", ~0); for (i = 0; i < sizeof(fs) / sizeof(fs[0]); i++) { fprintf(fs[i], "%s: ", msg); if (!v7_is_undefined(msg_v)) { v7_fprintln(fs[i], v7, msg_v); } else { v7_fprintln(fs[i], v7, exc); } v7_fprint_stack_trace(fs[i], v7, exc); } v7_disown(v7, &msg_v); v7_disown(v7, &exc); }
void sj_init_uart(struct v7 *v7) { v7_val_t uart = V7_UNDEFINED, uart_proto = V7_UNDEFINED, uart_ctor = V7_UNDEFINED; v7_own(v7, &uart); v7_own(v7, &uart_proto); v7_own(v7, &uart_ctor); uart = v7_mk_object(v7); uart_proto = v7_mk_object(v7); uart_ctor = v7_mk_function_with_proto(v7, UART_ctor, uart_proto); v7_def(v7, uart, "dev", ~0, _V7_DESC_HIDDEN(1), uart_ctor); v7_set_method(v7, uart_proto, "read", UART_read); v7_set_method(v7, uart_proto, "write", UART_write); v7_set_method(v7, uart_proto, "recv", UART_recv); v7_set(v7, v7_get_global(v7), "UART", ~0, uart); { enum v7_err rcode = v7_exec( v7, "UART.open = function (d) { return new UART.dev(d); }", NULL); assert(rcode == V7_OK); #if defined(NDEBUG) (void) rcode; #endif } v7_disown(v7, &uart_ctor); v7_disown(v7, &uart_proto); v7_disown(v7, &uart); }
/* * If resolved successfuly it will connect. Otherwise invokes * user callback as cb(undefined, error_message) */ static void http_get_dns_cb(const char *name, ip_addr_t *ipaddr, void *arg) { /* WIP: for now return the dns address as if it were the `get` response */ struct espconn *conn = (struct espconn *) arg; struct http_ctx *ctx = (struct http_ctx *) conn->proto.tcp; static char err_msg[] = "cannot resolve"; if (ipaddr == NULL) { v7_val_t res, cb_args = v7_create_object(v7); v7_own(v7, &cb_args); v7_array_set(v7, cb_args, 0, ctx->cb); v7_array_set(v7, cb_args, 1, v7_create_string(v7, err_msg, sizeof(err_msg), 1)); http_free(conn); if (v7_exec_with(v7, &res, "this[0](undefined, this[1])", cb_args) != V7_OK) { v7_fprintln(stderr, v7, res); } v7_disown(v7, &cb_args); v7_disown(v7, &ctx->body); /* body has not been sent yet */ v7_disown(v7, &ctx->cb); } else { memcpy(conn->proto.tcp->remote_ip, &ipaddr->addr, 4); conn->proto.tcp->remote_port = ctx->port; conn->proto.tcp->local_port = espconn_port(); espconn_regist_connectcb(conn, http_connect_cb); espconn_regist_disconcb(conn, http_disconnect_cb); espconn_regist_reconcb(conn, http_error_cb); espconn_connect(conn); } }
/* Invoke user callback as cb(data, undefined) */ static void http_disconnect_cb(void *arg) { struct espconn *conn = (struct espconn *) arg; struct http_ctx *ctx = (struct http_ctx *) conn->proto.tcp; v7_val_t data, cb_args; char *body; int i; v7_val_t res; body = ctx->resp; for (i = 0; i + 3 < ctx->resp_pos; i++) { if (memcmp(ctx->resp + i, "\r\n\r\n", 4) == 0) { body = ctx->resp + i + 4; break; } } cb_args = v7_create_object(v7); v7_own(v7, &cb_args); data = v7_create_string(v7, body, ctx->resp_pos - (body - ctx->resp), 1); v7_own(v7, &data); http_free(conn); v7_array_set(v7, cb_args, 0, ctx->cb); v7_array_set(v7, cb_args, 1, data); v7_disown(v7, &data); if (v7_exec_with(v7, &res, "this[0](this[1])", cb_args) != V7_OK) { v7_fprintln(stderr, v7, res); } v7_disown(v7, &cb_args); v7_disown(v7, &ctx->cb); }
void sj_invoke_cb0_this(struct v7 *v7, v7_val_t cb, v7_val_t this_obj) { v7_val_t args; v7_own(v7, &cb); args = v7_mk_array(v7); v7_own(v7, &args); sj_invoke_cb(v7, cb, this_obj, args); v7_disown(v7, &args); v7_disown(v7, &cb); }
/* * Mongoose event handler. If JavaScript callback was provided, call it */ static void http_ev_handler(struct mg_connection *c, int ev, void *ev_data) { struct user_data *ud = (struct user_data *) c->user_data; if (ev == MG_EV_HTTP_REQUEST) { /* HTTP request has arrived */ if (v7_is_callable(ud->v7, ud->handler)) { /* call provided JavaScript callback with `request` and `response` */ v7_val_t request = v7_mk_object(ud->v7); v7_own(ud->v7, &request); v7_val_t response = v7_mk_object(ud->v7); v7_own(ud->v7, &response); setup_request_object(ud->v7, request, ev_data); setup_response_object(ud->v7, response, c, request); sj_invoke_cb2_this(ud->v7, ud->handler, ud->obj, request, response); v7_disown(ud->v7, &request); v7_disown(ud->v7, &response); } else { /* * no JavaScript callback provided; serve the request with the default * options by `mg_serve_http()` */ struct mg_serve_http_opts opts; memset(&opts, 0, sizeof(opts)); mg_serve_http(c, ev_data, opts); } } else if (ev == MG_EV_HTTP_REPLY) { /* HTTP response has arrived */ /* if JavaScript callback was provided, call it with `response` */ if (v7_is_callable(ud->v7, ud->handler)) { v7_val_t response = v7_mk_object(ud->v7); v7_own(ud->v7, &response); setup_request_object(ud->v7, response, ev_data); sj_invoke_cb1_this(ud->v7, ud->handler, ud->obj, response); v7_disown(ud->v7, &response); } if (c->flags & MG_F_CLOSE_CONNECTION_AFTER_RESPONSE) { c->flags |= MG_F_CLOSE_IMMEDIATELY; } } else if (ev == MG_EV_TIMER) { sj_invoke_cb0_this(ud->v7, ud->timeout_callback, ud->obj); } else if (ev == MG_EV_CLOSE) { if (c->listener == NULL && ud != NULL) { v7_set(ud->v7, ud->obj, "_c", ~0, v7_mk_undefined()); v7_disown(ud->v7, &ud->obj); v7_disown(ud->v7, &ud->timeout_callback); free(ud); c->user_data = NULL; } } }
Bot::~Bot() { long i, l; TIMER* p; l = _timers.GetLength(); for (i = 0; i < l; i++) { p = (TIMER*)_timers.GetAt(i); v7_disown(v7, (v7_val_t*)p->pToFunc); delete (v7_val_t*)p->pToFunc; delete p; } l = _onTexts.GetLength(); for (i = 0; i < l; i++) { v7_disown(v7, (v7_val_t*)_onTexts.GetAt(i)); delete (v7_val_t*)_onTexts.GetAt(i); } l = _onJoin.GetLength(); for (i = 0; i < l; i++) { v7_disown(v7, (v7_val_t*)_onJoin.GetAt(i)); delete (v7_val_t*)_onJoin.GetAt(i); } l = _onLeft.GetLength(); for (i = 0; i < l; i++) { v7_disown(v7, (v7_val_t*)_onLeft.GetAt(i)); delete (v7_val_t*)_onLeft.GetAt(i); } l = _onTalk.GetLength(); for (i = 0; i < l; i++) { v7_disown(v7, (v7_val_t*)_onTalk.GetAt(i)); delete (v7_val_t*)_onTalk.GetAt(i); } l = _onMotd.GetLength(); for (i = 0; i < l; i++) { v7_disown(v7, (v7_val_t*)_onMotd.GetAt(i)); delete (v7_val_t*)_onMotd.GetAt(i); } l = _onIm.GetLength(); for (i = 0; i < l; i++) { v7_disown(v7, (v7_val_t*)_onIm.GetAt(i)); delete (v7_val_t*)_onIm.GetAt(i); } v7_disown(v7, botObj); v7_disown(v7, v7Obj); v7_destroy(v7); }
/* Free JSON parse frame, return the previous one (which may be NULL) */ static struct json_parse_frame *free_json_frame( struct json_parse_ctx *ctx, struct json_parse_frame *frame) { struct json_parse_frame *up = frame->up; v7_disown(ctx->v7, &frame->val); free(frame); return up; }
/* Called when successfully connected */ static void http_connect_cb(void *arg) { char *buf; struct espconn *conn = (struct espconn *) arg; struct http_ctx *ctx = (struct http_ctx *) conn->proto.tcp; if (strcmp(ctx->method, "GET") == 0) { const char *const reqfmt = "GET %s HTTP/1.0\r\n\r\n"; int buflen = strlen(ctx->path) + strlen(reqfmt) - 2 + 1; buf = (char *) malloc(buflen); snprintf(buf, buflen, reqfmt, ctx->path); } else { if (v7_is_string(ctx->body)) { const char *const reqfmt = "POST %s HTTP/1.0\r\ncontent-length: %d\r\n\r\n%s"; size_t len; const char *body = v7_to_string(v7, &ctx->body, &len); /* some space for content length and zero terminator */ int buflen = strlen(ctx->path) + strlen(reqfmt) + len + 10; buf = (char *) malloc(buflen); snprintf(buf, buflen, reqfmt, ctx->path, (int) len, body); v7_disown(v7, &ctx->body); } else { fprintf(stderr, "body not a string\n"); } } espconn_regist_recvcb(conn, http_recv_cb); espconn_regist_sentcb(conn, http_sent_cb); espconn_sent(conn, buf, strlen(buf)); free(buf); }
static void sj_timer_callback(TimerHandle_t t) { v7_val_t *cb = (v7_val_t *) pvTimerGetTimerID(t); xTimerDelete(t, 0); sj_invoke_cb0(s_v7, *cb); v7_disown(s_v7, cb); free(cb); }
void sj_invoke_cb2(struct v7 *v7, v7_val_t cb, v7_val_t arg1, v7_val_t arg2) { v7_val_t args; v7_own(v7, &cb); v7_own(v7, &arg1); v7_own(v7, &arg2); args = v7_create_array(v7); v7_own(v7, &args); v7_array_push(v7, args, arg1); v7_array_push(v7, args, arg2); sj_invoke_cb(v7, cb, v7_get_global(v7), args); v7_disown(v7, &args); v7_disown(v7, &arg2); v7_disown(v7, &arg1); v7_disown(v7, &cb); }
static enum v7_err isr_cb_proxy(struct v7 *v7, v7_val_t *res) { v7_val_t cb = v7_arg(v7, 0); v7_val_t args = v7_arg(v7, 1); v7_own(v7, &cb); v7_own(v7, &args); enum v7_err ret = v7_apply(v7, cb, v7_get_global(v7), args, res); sj_reenable_intr(v7_get_double(v7, v7_array_get(v7, args, 0))); v7_disown(v7, &args); v7_disown(v7, &cb); return ret; }
static void sj_timer_callback(xTimerHandle t) { struct timer_info *ti = (struct timer_info *) t; xTimerDelete(ti->t, 0); sj_invoke_cb0(v7, *ti->cb); v7_disown(v7, ti->cb); free(ti->cb); free(ti); }
void sj_wifi_ready_js(enum sj_wifi_status event, void *arg) { if (event != SJ_WIFI_IP_ACQUIRED) return; struct wifi_cb_arg *cba = (struct wifi_cb_arg *) arg; sj_invoke_cb0(cba->v7, cba->v); v7_disown(cba->v7, &cba->v); sj_wifi_remove_on_change_cb(sj_wifi_ready_js, arg); free(arg); }
void esp_timer_callback(void *arg) { struct timer_info *ti = (struct timer_info *) arg; os_timer_disarm(&ti->t); /* just in case */ sj_invoke_cb0(v7, *ti->cb); v7_disown(v7, ti->cb); free(ti->cb); free(ti); }
static void mg_lwip_task(os_event_t *e) { struct mg_mgr *mgr = NULL; DBG(("sig %d", e->sig)); poll_scheduled = 0; switch ((enum mg_sig_type) e->sig) { case MG_SIG_TOMBSTONE: break; case MG_SIG_POLL: { mgr = (struct mg_mgr *) e->par; break; } case MG_SIG_CONNECT_RESULT: { struct mg_connection *nc = (struct mg_connection *) e->par; mgr = nc->mgr; mg_if_connect_cb(nc, nc->err); break; } case MG_SIG_CLOSE_CONN: { struct mg_connection *nc = (struct mg_connection *) e->par; mgr = nc->mgr; nc->flags |= MG_F_CLOSE_IMMEDIATELY; mg_close_conn(nc); break; } case MG_SIG_SENT_CB: { struct mg_connection *nc = (struct mg_connection *) e->par; mgr = nc->mgr; mg_if_sent_cb(nc, nc->err); break; } case MG_SIG_V7_CALLBACK: { #ifndef NO_V7 struct v7_callback_args *cba = (struct v7_callback_args *) e->par; _sj_invoke_cb(cba->v7, cba->func, cba->this_obj, cba->args); v7_disown(cba->v7, &cba->func); v7_disown(cba->v7, &cba->this_obj); v7_disown(cba->v7, &cba->args); free(cba); #endif break; } } if (mgr != NULL) { mg_mgr_poll(mgr, 0); } }
void sj_invoke_cb2_this(struct v7 *v7, v7_val_t cb, v7_val_t this_obj, v7_val_t arg1, v7_val_t arg2) { v7_val_t args; v7_own(v7, &cb); v7_own(v7, &arg1); v7_own(v7, &arg2); args = v7_mk_array(v7); v7_own(v7, &args); v7_array_push(v7, args, arg1); v7_array_push(v7, args, arg2); sj_invoke_cb(v7, cb, this_obj, args); v7_disown(v7, &args); v7_disown(v7, &arg2); v7_disown(v7, &arg1); v7_disown(v7, &cb); }
void miot_console_api_setup(struct v7 *v7) { v7_val_t console_v = v7_mk_object(v7); v7_own(v7, &console_v); v7_set_method(v7, console_v, "log", Console_log); v7_set(v7, v7_get_global(v7), "console", ~0, console_v); v7_disown(v7, &console_v); }
static void ws_ev_handler(struct ns_connection *nc, int ev, void *ev_data) { struct websocket_message *wm = (struct websocket_message *) ev_data; struct user_data *ud = (struct user_data *) nc->user_data; struct v7 *v7 = ud->v7; switch (ev) { case NS_CONNECT: if (*(int *) ev_data == 0) { char *proto = NULL; if (ud->proto != NULL) { int tmp = asprintf(&proto, "Sec-WebSocket-Protocol: %s\n", ud->proto); (void) tmp; /* Shutup compiler */ } ns_send_websocket_handshake(nc, "/", proto); if (proto != NULL) { free(proto); } } else { invoke_cb(ud, "onerror", v7_create_null()); } break; case NS_WEBSOCKET_HANDSHAKE_DONE: v7_set(v7, ud->ws, "_nc", ~0, V7_PROPERTY_HIDDEN, v7_create_foreign(nc)); invoke_cb(ud, "onopen", v7_create_null()); break; case NS_WEBSOCKET_FRAME: { v7_val_t ev, data; ev = v7_create_object(v7); v7_own(v7, &ev); data = v7_create_string(v7, (char *) wm->data, wm->size, 1); v7_set(v7, ev, "data", ~0, 0, data); invoke_cb(ud, "onmessage", ev); v7_disown(v7, &ev); break; } case NS_CLOSE: invoke_cb(ud, "onclose", v7_create_null()); nc->user_data = NULL; v7_set(v7, ud->ws, "_nc", ~0, V7_PROPERTY_HIDDEN, v7_create_undefined()); v7_disown(v7, &ud->ws); free(ud); break; } }
static void disp_task(void *params) { struct rtos_event ev; while (1) { if (xQueueReceive(main_queue_handle, (void *) &ev, 500 / portTICK_RATE_MS)) { switch (ev.event_id) { case RTE_INIT: sjs_init(0); break; case RTE_UART_NEWCHAR: process_rx_buf(ev.params.uart_rx_params.tail); break; case RTE_CALLBACK: _sj_invoke_cb(ev.params.callback_params->v7, ev.params.callback_params->func, ev.params.callback_params->this_obj, ev.params.callback_params->args); v7_disown(ev.params.callback_params->v7, &ev.params.callback_params->func); v7_disown(ev.params.callback_params->v7, &ev.params.callback_params->this_obj); v7_disown(ev.params.callback_params->v7, &ev.params.callback_params->args); free(ev.params.callback_params); break; case RTE_GPIO_INTR_CALLBACK: ev.params.gpio_intr_callback_params.cb( ev.params.gpio_intr_callback_params.p1, ev.params.gpio_intr_callback_params.p2); break; default: printf("Unknown event_id: %d\n", ev.event_id); break; } } else { /* Put periodic event handlers here */ mongoose_poll(2); } } }
void sj_wifi_scan_done(const char **ssids, void *arg) { struct wifi_cb_arg *cba = (struct wifi_cb_arg *) arg; struct v7 *v7 = cba->v7; v7_val_t res = v7_mk_undefined(); const char **p; v7_own(v7, &res); if (ssids != NULL) { res = v7_mk_array(v7); for (p = ssids; *p != NULL; p++) { v7_array_push(v7, res, v7_mk_string(v7, *p, strlen(*p), 1)); } } /* Free the struct in case callback launches a new scan. */ cba->v7 = NULL; v7_disown(v7, &cba->v); sj_invoke_cb1(v7, cba->v, res); v7_disown(v7, &res); }
void sj_mqtt_api_setup(struct v7 *v7) { v7_val_t mqtt_proto = v7_mk_object(v7); v7_val_t mqtt_connect = v7_mk_function_with_proto(v7, sj_mqtt_connect, mqtt_proto); v7_val_t mqtt; v7_own(v7, &mqtt_connect); mqtt = v7_mk_object(v7); v7_own(v7, &mqtt); v7_set(v7, mqtt, "connect", ~0, mqtt_connect); v7_def(v7, mqtt, "proto", ~0, V7_DESC_ENUMERABLE(0), mqtt_proto); v7_set_method(v7, mqtt_proto, "publish", MQTT_publish); v7_set_method(v7, mqtt_proto, "subscribe", MQTT_subscribe); v7_set_method(v7, mqtt_proto, "on", MQTT_on); v7_set(v7, v7_get_global(v7), "MQTT", ~0, mqtt); v7_disown(v7, &mqtt); v7_disown(v7, &mqtt_connect); }
void sj_http_success_callback(struct v7 *v7, v7_val_t cb, const char *data, size_t data_len) { v7_val_t datav, cb_args; v7_val_t res; cb_args = v7_create_object(v7); v7_own(v7, &cb_args); datav = v7_create_string(v7, data, data_len, 1); v7_own(v7, &datav); v7_array_set(v7, cb_args, 0, cb); v7_array_set(v7, cb_args, 1, datav); v7_disown(v7, &datav); if (v7_exec_with(v7, &res, "this[0](this[1])", cb_args) != V7_OK) { v7_fprintln(stderr, v7, res); } v7_disown(v7, &cb_args); v7_disown(v7, &cb); }
void mg_dispatch_v7_callback(struct v7 *v7, v7_val_t func, v7_val_t this_obj, v7_val_t args) { struct v7_callback_args *cba = (struct v7_callback_args *) calloc(1, sizeof(*cba)); if (cba == NULL) { DBG(("OOM")); return; } cba->v7 = v7; cba->func = func; cba->this_obj = this_obj; cba->args = args; v7_own(v7, &cba->func); v7_own(v7, &cba->this_obj); v7_own(v7, &cba->args); if (!system_os_post(MG_TASK_PRIORITY, MG_SIG_V7_CALLBACK, (uint32_t) cba)) { LOG(LL_ERROR, ("MG queue overflow")); v7_disown(v7, &cba->func); v7_disown(v7, &cba->this_obj); v7_disown(v7, &cba->args); free(cba); } }
static v7_val_t OS_prof(struct v7 *v7, v7_val_t this_obj, v7_val_t args) { v7_val_t result = v7_create_object(v7); v7_own(v7, &result); v7_set(v7, result, "sysfree", 7, 0, v7_create_number(sj_get_free_heap_size())); v7_set(v7, result, "used_by_js", 10, 0, v7_create_number(v7_heap_stat(v7, V7_HEAP_STAT_HEAP_USED))); v7_set(v7, result, "used_by_fs", 10, 0, v7_create_number(sj_get_fs_memory_usage())); v7_disown(v7, &result); return result; }
void esp_timer_callback(void *arg) { struct timer_info *ti = (struct timer_info *) arg; if (ti->js_cb != NULL) { sj_invoke_cb0(v7, *ti->js_cb); v7_disown(v7, ti->js_cb); free(ti->js_cb); } if (ti->c_cb != NULL) { ti->c_cb(ti->c_cb_param); } free(ti); }
void sj_init_ws_client(struct v7 *v7) { v7_val_t ws_proto = v7_create_object(v7); v7_val_t ws = v7_create_constructor(v7, ws_proto, sj_ws_ctor, 1); v7_own(v7, &ws); v7_set_method(v7, ws_proto, "send", WebSocket_send); v7_set_method(v7, ws_proto, "close", WebSocket_close); v7_set(v7, ws_proto, "readyState", ~0, V7_PROPERTY_DONT_ENUM | V7_PROPERTY_GETTER, v7_create_function(v7, WebSocket_readyState, 0)); v7_set(v7, ws, "OPEN", ~0, 0, WEBSOCKET_OPEN); v7_set(v7, ws, "CLOSED", ~0, 0, WEBSOCKET_CLOSED); v7_set(v7, v7_get_global_object(v7), "WebSocket", ~0, 0, ws); v7_disown(v7, &ws); }
void sj_http_error_callback(struct v7 *v7, v7_val_t cb, int err_no) { char err_msg[128]; v7_val_t res, cb_args; cb_args = v7_create_object(v7); v7_own(v7, &cb_args); snprintf(err_msg, sizeof(err_msg), "connection error: %d\n", err_no); v7_array_set(v7, cb_args, 0, cb); v7_array_set(v7, cb_args, 1, v7_create_string(v7, err_msg, sizeof(err_msg), 1)); if (v7_exec_with(v7, &res, "this[0](undefined, this[1])", cb_args) != V7_OK) { v7_fprintln(stderr, v7, res); } v7_disown(v7, &cb_args); }
SJ_PRIVATE enum v7_err Wifi_changed(struct v7 *v7, v7_val_t *res) { enum v7_err rcode = V7_OK; v7_val_t cb = v7_arg(v7, 0); if (!v7_is_callable(v7, cb) && !v7_is_null(cb)) { *res = v7_mk_boolean(v7, 0); goto clean; } v7_disown(s_wifi_changed_cb.v7, &s_wifi_changed_cb.v); s_wifi_changed_cb.v7 = v7; s_wifi_changed_cb.v = cb; v7_own(s_wifi_changed_cb.v7, &s_wifi_changed_cb.v); *res = v7_mk_boolean(v7, 1); goto clean; clean: return rcode; }