V7_PRIVATE val_t Regex_ctor(struct v7 *v7, val_t this_obj, val_t args) { long argnum = v7_array_length(v7, args); if (argnum > 0) { val_t ro = to_string(v7, v7_array_get(v7, args, 0)); size_t re_len, flags_len = 0; const char *re = v7_to_string(v7, &ro, &re_len), *flags = NULL; struct slre_prog *p = NULL; struct v7_regexp *rp; (void) this_obj; if (argnum > 1) { val_t fl = to_string(v7, v7_array_get(v7, args, 1)); flags = v7_to_string(v7, &fl, &flags_len); } if (slre_compile(re, re_len, flags, flags_len, &p, 1) != SLRE_OK || p == NULL) { throw_exception(v7, TYPE_ERROR, "Invalid regex"); return v7_create_undefined(); } else { rp = (struct v7_regexp *) malloc(sizeof(*rp)); rp->regexp_string = v7_create_string(v7, re, re_len, 1); rp->compiled_regexp = p; rp->lastIndex = 0; return v7_pointer_to_value(rp) | V7_TAG_REGEXP; } } return v7_create_regexp(v7, "(?:)", 4, NULL, 0); }
ICACHE_FLASH_ATTR static v7_val_t Wifi_setup(struct v7 *v7, v7_val_t this_obj, v7_val_t args) { struct station_config stationConf; v7_val_t ssidv = v7_array_get(v7, args, 0); v7_val_t passv = v7_array_get(v7, args, 1); const char *ssid, *pass; size_t ssid_len, pass_len; int res; if (!v7_is_string(ssidv) || !v7_is_string(passv)) { printf("ssid/pass are not strings\n"); return v7_create_undefined(); } wifi_station_disconnect(); ssid = v7_to_string(v7, &ssidv, &ssid_len); pass = v7_to_string(v7, &passv, &pass_len); stationConf.bssid_set = 0; strncpy((char *) &stationConf.ssid, ssid, 32); strncpy((char *) &stationConf.password, pass, 64); res = v7_create_boolean(wifi_station_set_config(&stationConf)); if (!res) { printf("Failed to set station config\n"); return v7_create_boolean(0); } return v7_create_boolean(wifi_station_connect()); }
/* * Construct a new WebSocket object: * * url: url where to connect to * protocol: websocket subprotocol * * Example: * ws = new WebSocket('wss://localhost:1234'); * ws.onopen = function(ev) { * print("ON OPEN", ev); * } * * ws.onclose = function(ev) { * print("ON CLOSE", ev); * } * * ws.onmessage = function(ev) { * print("ON MESSAGE", ev); * } * * ws.onerror = function(ev) { * print("ON ERROR", ev); * } * */ static v7_val_t sj_ws_ctor(struct v7 *v7, v7_val_t this_obj, v7_val_t args) { struct mg_connection *nc; struct user_data *ud; v7_val_t urlv = v7_array_get(v7, args, 0); v7_val_t subprotov = v7_array_get(v7, args, 1); (void) this_obj; (void) args; if (!v7_is_string(urlv)) { v7_throw(v7, "invalid ws url string"); } if (v7_is_object(this_obj) && this_obj != v7_get_global_object(v7)) { int use_ssl = 0; size_t len; const char *url = v7_to_string(v7, &urlv, &len); if (strncmp(url, "ws://", 5) == 0) { url += 5; } else if (strncmp(url, "wss://", 6) == 0) { url += 6; use_ssl = 1; } nc = mg_connect(&sj_mgr, url, ws_ev_handler); if (nc == NULL) v7_throw(v7, "error creating the connection"); #ifdef NS_ENABLE_SSL if (use_ssl) { mg_set_ssl(nc, NULL, NULL); } #endif (void) use_ssl; mg_set_protocol_http_websocket(nc); ud = calloc(1, sizeof(*ud)); ud->v7 = v7; ud->ws = this_obj; nc->user_data = ud; v7_own(v7, &ud->ws); if (v7_is_string(subprotov)) { size_t len; const char *proto = v7_to_string(v7, &subprotov, &len); ud->proto = strdup(proto); } } else { v7_throw(v7, "WebSocket ctor called without new"); } return v7_create_undefined(); }
static void obj_v7_to_string(const struct v7_val *v, char *buf, int bsiz) { const struct v7_prop *m; int n = snprintf(buf, bsiz, "%s", "{"); for (m = v->v.props; m != NULL && n < bsiz - 1; m = m->next) { if (m != v->v.props) n += snprintf(buf + n , bsiz - n, "%s", ", "); v7_to_string(m->key, buf + n, bsiz - n); n = (int) strlen(buf); n += snprintf(buf + n , bsiz - n, "%s", ": "); v7_to_string(m->val, buf + n, bsiz - n); n = (int) strlen(buf); } n += snprintf(buf + n, bsiz - n, "%s", "}"); }
/* 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 v7_val_t sj_Wifi_setup(struct v7 *v7) { v7_val_t ssidv = v7_arg(v7, 0); v7_val_t passv = v7_arg(v7, 1); const char *ssid, *pass; size_t ssid_len, pass_len; if (!v7_is_string(ssidv) || !v7_is_string(passv)) { printf("ssid/pass are not strings\n"); return v7_create_undefined(); } ssid = v7_to_string(v7, &ssidv, &ssid_len); pass = v7_to_string(v7, &passv, &pass_len); return v7_create_boolean(sj_wifi_setup_sta(ssid, pass)); }
static void _WebSocket_send_string(struct v7 *v7, struct mg_connection *nc, v7_val_t s) { const char *data; size_t len; data = v7_to_string(v7, &s, &len); mg_send_websocket_frame(nc, WEBSOCKET_OP_TEXT, data, len); }
V7_PRIVATE val_t rx_exec(struct v7 *v7, val_t rx, val_t str, int lind) { if (v7_is_regexp(rx)) { val_t s = to_string(v7, str); size_t len; struct slre_loot sub; struct slre_cap *ptok = sub.caps; char *const str = (char *) v7_to_string(v7, &s, &len); const char *const end = str + len; const char *begin = str; struct v7_regexp *rp = v7_to_regexp(rx); int flag_g = slre_get_flags(rp->compiled_regexp) & SLRE_FLAG_G; if (rp->lastIndex < 0) rp->lastIndex = 0; if (flag_g || lind) begin = utfnshift(str, rp->lastIndex); if (!slre_exec(rp->compiled_regexp, 0, begin, end, &sub)) { int i; val_t arr = v7_create_array(v7); for (i = 0; i < sub.num_captures; i++, ptok++) v7_array_push(v7, arr, v7_create_string(v7, ptok->start, ptok->end - ptok->start, 1)); if (flag_g) rp->lastIndex = utfnlen(str, sub.caps->end - str); v7_set_property(v7, arr, "index", 5, V7_PROPERTY_READ_ONLY, v7_create_number(utfnlen(str, sub.caps->start - str))); return arr; } else rp->lastIndex = 0; } return v7_create_null(); }
static v7_val_t sj_http_call_helper(struct v7 *v7, v7_val_t urlv, v7_val_t bodyv, v7_val_t cb, const char *method) { const char *body = NULL; size_t url_len, body_len = 0; if (!v7_is_string(urlv)) { v7_throw(v7, "url should be a string"); } if (v7_is_string(bodyv)) { body = v7_to_string(v7, &bodyv, &body_len); } return v7_create_boolean(sj_http_call(v7, v7_to_string(v7, &urlv, &url_len), body, body_len, method, cb)); }
static void stdlib_print(struct v7 *v7, struct v7_val *this_obj, struct v7_val *result, struct v7_val **args, int num_args) { char buf[4000]; int i; (void) v7; (void) this_obj; (void) result; for (i = 0; i < num_args; i++) { printf("%s", v7_to_string(args[i], buf, sizeof(buf))); } }
static val_t Regex_source(struct v7 *v7, val_t this_obj, val_t args) { val_t r = i_value_of(v7, this_obj); const char *buf = 0; size_t len = 0; (void) args; if (v7_is_regexp(r)) buf = v7_to_string(v7, &v7_to_regexp(r)->regexp_string, &len); return v7_create_string(v7, buf, len, 1); }
static v7_val_t gsm_text(struct v7* v7) { VMWCHAR number[42]; VMWCHAR content[100]; v7_val_t numberv = v7_arg(v7, 0); v7_val_t messagev = v7_arg(v7, 1); const char* phone_number; const char* message; size_t len, message_len; if(!v7_is_string(numberv) || !v7_is_string(messagev)) { return v7_create_undefined(); } phone_number = v7_to_string(v7, &numberv, &len); message = v7_to_string(v7, &messagev, &message_len); vm_chset_ascii_to_ucs2(content, 100 * 2, message); vm_chset_ascii_to_ucs2(number, 42 * 2, phone_number); return v7_create_number(vm_gsm_sms_send(number, content, _gsm_text_callback, NULL)); }
static v7_val_t gsm_call(struct v7* v7) { v7_val_t numberv = v7_arg(v7, 0); const char* number; size_t len; if(!v7_is_string(numberv)) { return v7_create_undefined(); } number = v7_to_string(v7, &numberv, &len); return v7_create_number(_gsm_call(number)); }
int main(void) { size_t n; const char *domain_str; struct v7 *v7 = v7_create(); v7_val_t domain, port0, config; /* Load JSON configuration */ if (v7_exec_file(v7, &config, "config.json") != V7_OK) { printf("%s\n", "Cannot load JSON config"); return 1; } /* Lookup values in JSON configuration object */ domain = v7_get(v7, config, "domain", 6); port0 = v7_array_get(v7, v7_get(v7, config, "ports", 5), 0); domain_str = v7_to_string(v7, &domain, &n); printf("Domain: [%.*s], port 0: [%d]\n", (int) n, domain_str, (int) v7_to_number(port0)); v7_destroy(v7); return 0; }
static v7_val_t WebSocket_send(struct v7 *v7, v7_val_t this_obj, v7_val_t args) { v7_val_t datav = v7_array_get(v7, args, 0); v7_val_t ncv = v7_get(v7, this_obj, "_nc", ~0); struct ns_connection *nc; const char *data; size_t len; if (!v7_is_string(datav)) { v7_throw(v7, "non string data not implemented"); return v7_create_undefined(); } if (!v7_is_foreign(ncv) || (nc = (struct ns_connection *) v7_to_foreign(ncv)) == NULL) { v7_throw(v7, "ws not connected"); return v7_create_undefined(); } data = v7_to_string(v7, &datav, &len); ns_send_websocket_frame(nc, WEBSOCKET_OP_TEXT, data, len); return v7_create_undefined(); }
/* * Prints message to current debug output */ ICACHE_FLASH_ATTR v7_val_t Debug_print(struct v7 *v7, v7_val_t this_obj, v7_val_t args) { char *p, buf[512]; int i, num_args = v7_array_length(v7, args); (void) this_obj; for (i = 0; i < num_args; i++) { v7_val_t arg = v7_array_get(v7, args, i); if (v7_is_string(arg)) { size_t n; const char *s = v7_to_string(v7, &arg, &n); os_printf("%s", s); } else { p = v7_to_json(v7, arg, buf, sizeof(buf)); os_printf("%s", p); if (p != buf) { free(p); } } } os_printf("\n"); return v7_create_null(); }
static void _WebSocket_send_blob(struct v7 *v7, struct mg_connection *nc, v7_val_t blob) { const char *data; size_t len; unsigned long alen, i; v7_val_t chunks, chunk; chunks = v7_get(v7, blob, "a", ~0); alen = v7_array_length(v7, chunks); for (i = 0; i < alen; i++) { int op = i == 0 ? WEBSOCKET_OP_BINARY : WEBSOCKET_OP_CONTINUE; int flag = i == alen - 1 ? 0 : WEBSOCKET_DONT_FIN; chunk = v7_array_get(v7, chunks, i); /* * This hack allows us to skip the first or the last frame * while sending blobs. The effect of it is that it's possible to * concatenate more blobs into a single WS message composed of * several fragments. * * WebSocket.send(new Blob(["123", undefined])); * WebSocket.send(new Blob([undefined, "456"])); * * If the last blob component is undefined, the current message is thus * left open. In order to continue sending fragments of the same message * the next send call should have it's first component undefined. * * TODO(mkm): find a better API. */ if (!v7_is_undefined(chunk)) { data = v7_to_string(v7, &chunk, &len); mg_send_websocket_frame(nc, op | flag, data, len); } } }
static v7_val_t Http_call(struct v7 *v7, v7_val_t urlv, v7_val_t body, v7_val_t cb, const char *method) { const char *url, *sep; char *psep; size_t url_len; struct espconn *client; struct http_ctx *ctx; if (!v7_is_string(urlv)) { v7_throw(v7, "url is not a string"); } client = (struct espconn *) malloc(sizeof(struct espconn)); if (client == NULL) { printf("malloc failed Http_get\n"); return v7_create_undefined(); } client->type = ESPCONN_TCP; client->state = ESPCONN_NONE; ctx = (struct http_ctx *) calloc(sizeof(struct http_ctx), 1); if (ctx == NULL) { printf("malloc failed Http_get\n"); free(client); return v7_create_undefined(); } client->proto.tcp = (esp_tcp *) ctx; url = v7_to_string(v7, &urlv, &url_len); if (memcmp(url, "http://", 7) == 0) { url += 7; } ctx->host[0] = ctx->path[0] = '\0'; if ((sep = strchr(url, '/')) == NULL) { sep = url + strlen(url); ctx->path[0] = '/'; ctx->path[1] = '\0'; } strncpy(ctx->host, url, sep - url); ctx->host[sep - url] = '\0'; strcpy(ctx->path, sep); if (strlen(sep) == 0) strcpy(ctx->path, "/"); ctx->port = 80; if ((psep = strchr(ctx->host, ':')) != NULL) { *psep++ = '\0'; /* chop off port from host */ ctx->port = atoi(psep); } ctx->method = method; ctx->cb = cb; /* to be disowned after invoking the callback */ v7_own(v7, &ctx->cb); ctx->body = body; /* to be disowned after sending the request */ v7_own(v7, &ctx->body); espconn_gethostbyname(client, ctx->host, &probably_dns_ip, http_get_dns_cb); return v7_create_undefined(); }