Beispiel #1
0
/*
 * Usage:
 *
 * new UART("platform_specific_name")
 *
 */
static enum v7_err UART_ctor(struct v7 *v7, v7_val_t *res) {
  (void) res;
  enum v7_err rcode = V7_OK;
  v7_val_t this_obj = v7_get_this(v7);
  v7_val_t dev = v7_arg(v7, 0);
  struct user_data *ud;
  void *uart;
  const char *name;
  size_t len;

  if (!v7_is_string(dev)) {
    rcode = v7_throwf(v7, "Error", "device must be string");
    goto clean;
  }

  ud = (struct user_data *) calloc(1, sizeof(struct user_data));
  ud->v7 = v7;
  ud->want = 0;
  ud->cb = V7_UNDEFINED;
  v7_own(v7, &ud->cb);

  name = v7_get_string(v7, &dev, &len);
  uart = sj_hal_open_uart(name, (void *) ud);
  if (uart == NULL) {
    rcode = v7_throwf(v7, "Error", "cannot open uart");
    goto clean;
  }

  v7_def(v7, this_obj, "_ud", ~0, _V7_DESC_HIDDEN(1), v7_mk_foreign(v7, ud));
  v7_def(v7, this_obj, "_dev", ~0, _V7_DESC_HIDDEN(1), v7_mk_foreign(v7, uart));

clean:
  return rcode;
}
Beispiel #2
0
V7_PRIVATE
v7_val_t mk_cfunction_obj(struct v7 *v7, v7_cfunction_t *f, int num_args) {
  val_t obj = mk_object(v7, v7->vals.function_prototype);
  struct gc_tmp_frame tf = new_tmp_frame(v7);
  tmp_stack_push(&tf, &obj);
  v7_def(v7, obj, "", 0, _V7_DESC_HIDDEN(1), v7_mk_cfunction(f));
  if (num_args >= 0) {
    v7_def(v7, obj, "length", 6, (V7_DESC_ENUMERABLE(0) | V7_DESC_WRITABLE(0) |
                                  V7_DESC_CONFIGURABLE(0)),
           v7_mk_number(v7, num_args));
  }
  tmp_frame_cleanup(&tf);
  return obj;
}
Beispiel #3
0
V7_PRIVATE v7_val_t mk_cfunction_obj_with_proto(struct v7 *v7,
                                                v7_cfunction_t *f, int num_args,
                                                v7_val_t proto) {
  struct gc_tmp_frame tf = new_tmp_frame(v7);
  v7_val_t res = mk_cfunction_obj(v7, f, num_args);

  tmp_stack_push(&tf, &res);

  v7_def(v7, res, "prototype", 9, (V7_DESC_ENUMERABLE(0) | V7_DESC_WRITABLE(0) |
                                   V7_DESC_CONFIGURABLE(0)),
         proto);
  v7_def(v7, proto, "constructor", 11, V7_DESC_ENUMERABLE(0), res);
  tmp_frame_cleanup(&tf);
  return res;
}
Beispiel #4
0
Datei: js_oop.c Projekt: QUSIR/v7
int main(void) {
    enum v7_err rcode = V7_OK;
    struct v7 *v7 = v7_create();
    v7_val_t ctor_func, proto, eval_result;

    proto = v7_mk_object(v7);
    ctor_func = v7_mk_function_with_proto(v7, MyThing_ctor, proto);
    v7_def(v7, ctor_func, "MY_CONST", ~0,
           (V7_DESC_WRITABLE(0) | V7_DESC_CONFIGURABLE(0)), v7_mk_number(123));
    v7_set_method(v7, proto, "myMethod", &MyThing_myMethod);
    v7_set(v7, v7_get_global(v7), "MyThing", ~0, ctor_func);

    rcode = v7_exec(v7,
                    "\
      print('MyThing.MY_CONST = ', MyThing.MY_CONST); \
      var t = new MyThing(456); \
      print('t.MY_CONST = ', t.MY_CONST); \
      print('t.myMethod = ', t.myMethod); \
      print('t.myMethod() = ', t.myMethod());",
                    &eval_result);
    if (rcode != V7_OK) {
        fprintf(stderr, "exec error: %d\n", (int) rcode);
    }

    v7_destroy(v7);
    return (int) rcode;
}
Beispiel #5
0
/*
 * `on` method on a mqtt client object registers an event handler
 * for a given event type. Recognized event types:
 *
 * - `connect`: invoked on sucessfull connection (mqtt connack message)
 * - `error`: invoked on connection error
 * - `close`: invoked when the connection gets closed
 * - `message`: invoked when a new message is received. The callback
 *              receives (topic, message) arguments, both strings
 */
enum v7_err MQTT_on(struct v7 *v7, v7_val_t *res) {
  enum v7_err rcode = V7_OK;
  v7_val_t evv = v7_arg(v7, 0);
  v7_val_t cb = v7_arg(v7, 1);
  const char *ev, *key = NULL;

  ev = v7_get_cstring(v7, &evv);
  if (strcmp(ev, "connect") == 0) {
    key = SJ_MQTT_CONNECT_CB;
  } else if (strcmp(ev, "message") == 0) {
    key = SJ_MQTT_MESSAGE_CB;
  } else if (strcmp(ev, "error") == 0) {
    key = SJ_MQTT_ERROR_CB;
  } else if (strcmp(ev, "close") == 0) {
    key = SJ_MQTT_CLOSE_CB;
  } else {
    rcode = v7_throwf(v7, "Error", "unsupported protocol");
    goto clean;
  }

  v7_def(v7, v7_get_this(v7), key, ~0, V7_DESC_ENUMERABLE(0), cb);

  (void) res;
clean:
  return rcode;
}
Beispiel #6
0
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);
}
Beispiel #7
0
V7_PRIVATE
val_t mk_js_function(struct v7 *v7, struct v7_generic_object *scope,
                     val_t proto) {
  struct v7_js_function *f;
  val_t fval = V7_NULL;
  struct gc_tmp_frame tf = new_tmp_frame(v7);
  tmp_stack_push(&tf, &proto);
  tmp_stack_push(&tf, &fval);

  f = new_function(v7);

  if (f == NULL) {
    /* fval is left `null` */
    goto cleanup;
  }

#if defined(V7_ENABLE_ENTITY_IDS)
  f->base.entity_id_base = V7_ENTITY_ID_PART_OBJ;
  f->base.entity_id_spec = V7_ENTITY_ID_PART_JS_FUNC;
#endif

  fval = js_function_to_value(f);

  f->base.properties = NULL;
  f->scope = scope;

  /*
   * Before setting a `V7_OBJ_FUNCTION` flag, make sure we don't have
   * `V7_OBJ_DENSE_ARRAY` flag set
   */
  assert(!(f->base.attributes & V7_OBJ_DENSE_ARRAY));
  f->base.attributes |= V7_OBJ_FUNCTION;

  /* TODO(mkm): lazily create these properties on first access */
  if (v7_is_object(proto)) {
    v7_def(v7, proto, "constructor", 11, V7_DESC_ENUMERABLE(0), fval);
    v7_def(v7, fval, "prototype", 9,
           V7_DESC_ENUMERABLE(0) | V7_DESC_CONFIGURABLE(0), proto);
  }

cleanup:
  tmp_frame_cleanup(&tf);
  return fval;
}
void init_updater_clubby(struct v7 *v7) {
  (void) v7;
#ifndef DISABLE_C_CLUBBY

#ifndef CS_DISABLE_JS
  s_v7 = v7;
  v7_val_t updater = v7_mk_object(v7);
  v7_val_t sys = v7_get(v7, v7_get_global(v7), "Sys", ~0);
  s_updater_notify_cb = V7_UNDEFINED;
  v7_own(v7, &s_updater_notify_cb);

  v7_def(v7, sys, "updater", ~0, V7_DESC_ENUMERABLE(0), updater);
  v7_set_method(v7, updater, "notify", Updater_notify);
  v7_set_method(v7, updater, "start", Updater_startupdate);

  v7_def(s_v7, updater, "GOT_REQUEST", ~0,
         (V7_DESC_WRITABLE(0) | V7_DESC_CONFIGURABLE(0)),
         v7_mk_number(v7, UJS_GOT_REQUEST));

  v7_def(s_v7, updater, "COMPLETED", ~0,
         (V7_DESC_WRITABLE(0) | V7_DESC_CONFIGURABLE(0)),
         v7_mk_number(v7, UJS_COMPLETED));

  v7_def(s_v7, updater, "NOTHING_TODO", ~0,
         (V7_DESC_WRITABLE(0) | V7_DESC_CONFIGURABLE(0)),
         v7_mk_number(v7, UJS_NOTHING_TODO));

  v7_def(s_v7, updater, "FAILED", ~0,
         (V7_DESC_WRITABLE(0) | V7_DESC_CONFIGURABLE(0)),
         v7_mk_number(v7, UJS_ERROR));
#endif

  sj_clubby_register_global_command("/v1/SWUpdate.Update", handle_update_req,
                                    NULL);

  sj_clubby_register_global_command(clubby_cmd_ready, handle_clubby_ready,
                                    NULL);
#endif
}
Beispiel #9
0
Datei: js_oop.c Projekt: QUSIR/v7
static enum v7_err MyThing_ctor(struct v7 *v7, v7_val_t *res) {
    v7_val_t this_obj = v7_get_this(v7);
    v7_val_t arg0 = v7_arg(v7, 0);
    v7_def(v7, this_obj, "__arg", ~0 /* = strlen */, V7_DESC_ENUMERABLE(0), arg0);

    /*
     * A constructor function can access the newly created object with
     * `v7_get_this()`. The constructor can override the result of the `new`
     * expression by explicitly setting `res` to another object. Any non-object
     * value set into `res` will be ignored. This matches the JavaScript
     * constructor return value semantics.
     */
    (void) res; /* no warning */
    return V7_OK;
}
Beispiel #10
0
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);
}
Beispiel #11
0
static void set_clubby(struct v7 *v7, v7_val_t obj, struct clubby *clubby) {
  v7_def(v7, obj, s_clubby_prop, sizeof(s_clubby_prop),
         (V7_DESC_WRITABLE(0) | V7_DESC_CONFIGURABLE(0) | _V7_DESC_HIDDEN(1)),
         v7_mk_foreign(v7, clubby));
}
Beispiel #12
0
static void mqtt_ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
  struct mg_mqtt_message *msg = (struct mg_mqtt_message *) ev_data;
  struct user_data *ud = (struct user_data *) nc->user_data;
  struct v7 *v7 = ud->v7;
  v7_val_t cb;
  (void) nc;
  (void) ev_data;

  switch (ev) {
    case MG_EV_CONNECT:
      if (*(int *) ev_data == 0) {
        mg_send_mqtt_handshake(nc, ud->client_id);
      } else {
        cb = v7_get(v7, ud->client, SJ_MQTT_ERROR_CB, ~0);
        if (!v7_is_undefined(cb)) {
          sj_invoke_cb0(v7, cb);
        }
      }
      break;
    case MG_EV_MQTT_CONNACK: {
      /*
       * Call connect or error cb if they were registered.
       */
      const char *key;
      if (msg->connack_ret_code == MG_EV_MQTT_CONNACK_ACCEPTED) {
        key = SJ_MQTT_CONNECT_CB;
      } else {
        key = SJ_MQTT_ERROR_CB;
      }
      cb = v7_get(v7, ud->client, key, ~0);
      if (!v7_is_undefined(cb)) {
        sj_invoke_cb0(v7, cb);
      }
      break;
    }
    case MG_EV_MQTT_PUBLISH:
      cb = v7_get(v7, ud->client, SJ_MQTT_MESSAGE_CB, ~0);

      if (!v7_is_undefined(cb)) {
        v7_val_t topic = v7_mk_string(v7, msg->topic, strlen(msg->topic), 1);
        v7_val_t payload =
            v7_mk_string(v7, msg->payload.p, msg->payload.len, 1);
        sj_invoke_cb2(v7, cb, topic, payload);
      }
      break;
    case MG_EV_CLOSE:
      /*
       * Invoke close cb and then destroys all mg state.
       */
      cb = v7_get(v7, ud->client, SJ_MQTT_CLOSE_CB, ~0);
      if (!v7_is_undefined(cb)) {
        sj_invoke_cb0(v7, cb);
      }

      v7_def(v7, ud->client, "_nc", ~0, _V7_DESC_HIDDEN(1), V7_UNDEFINED);
      v7_disown(v7, &ud->client);
      free(ud->client_id);
      free(ud);
      break;
  }
}
Beispiel #13
0
/*
 * Make a new MQTT client.
 *
 * Arguments:
 * url: url where to connect to
 * opts: option object
 *
 * Recognized option object properties:
 *
 * - clientId: string; mqtt client id. defaults to
 *             Math.random().toString(16).substr(2, 10)
 *
 * Example:
 *
 * var client = MQTT.connect('mqtt://test.mosquitto.org');
 *
 * client.on('connect', function () {
 *   client.subscribe('presence');
 *   client.publish('presence', 'Hello mqtt');
 * });
 *
 * client.on('message', function (topic, message) {
 *   console.log(message);
 * });
 *
 * TLS can be enabled by choosing the `mqtts://` protocol. In that
 * case the default port is 8883 as defined by IANA.
 *
 * The API is modeled after https://www.npmjs.com/package/mqtt.
 *
 */
enum v7_err sj_mqtt_connect(struct v7 *v7, v7_val_t *res) {
  enum v7_err rcode = V7_OK;
  const char *url;
  size_t len;
  struct mg_str host, scheme;
  unsigned int port;
  struct mg_connection *nc;
  struct user_data *ud;
  char *url_with_port = NULL;
  int use_ssl = 0;
  v7_val_t urlv = v7_arg(v7, 0), opts = v7_arg(v7, 1);
  v7_val_t client_id;
  v7_val_t proto =
      v7_get(v7, v7_get(v7, v7_get_global(v7), "MQTT", ~0), "proto", ~0);

  if (!v7_is_string(urlv)) {
    rcode = v7_throwf(v7, "Error", "invalid url string");
    goto clean;
  }

  url = v7_get_string(v7, &urlv, &len);

  if (mg_parse_uri(mg_mk_str(url), &scheme, NULL, &host, &port, NULL, NULL,
                   NULL) < 0) {
    rcode = v7_throwf(v7, "Error", "invalid url string");
    goto clean;
  }

  if (mg_vcmp(&scheme, "mqtt") == 0) {
    url += sizeof("mqtt://") - 1;
  } else if (mg_vcmp(&scheme, "mqtts") == 0) {
    url += sizeof("mqtts://") - 1;
    use_ssl = 1;
  } else {
    rcode = v7_throwf(v7, "Error", "unsupported protocol");
    goto clean;
  }

  client_id = v7_get(v7, opts, "clientId", ~0);
  if (v7_is_undefined(client_id)) {
    rcode = v7_exec(v7, "Math.random().toString(16).substr(2,8)", &client_id);
    if (rcode != V7_OK) {
      goto clean;
    }
  }

  if (port == 0) {
    if (asprintf(&url_with_port, "%.*s%s", (int) host.len, host.p,
                 (use_ssl ? ":8883" : ":1883")) < 0) {
      rcode = v7_throwf(v7, "Error", "Out of memory");
      goto clean;
    }
  }

  nc =
      mg_connect(&sj_mgr, url_with_port ? url_with_port : url, mqtt_ev_handler);
  if (nc == NULL) {
    rcode = v7_throwf(v7, "Error", "cannot create connection");
    goto clean;
  }

  if (use_ssl) {
#ifdef MG_ENABLE_SSL
    mg_set_ssl(nc, NULL, NULL);
#else
    rcode = v7_throwf(v7, "Error", "SSL not enabled");
    goto clean;
#endif
  }
  mg_set_protocol_mqtt(nc);

  *res = v7_mk_object(v7);
  v7_set_proto(v7, *res, proto);

  ud = calloc(1, sizeof(*ud));
  if (ud == NULL) {
    rcode = v7_throwf(v7, "Error", "Out of memory");
    goto clean;
  }
  ud->v7 = v7;
  ud->client = *res;
  ud->client_id = strdup(v7_get_cstring(v7, &client_id));
  if (ud->client_id == NULL) {
    free(ud);
    rcode = v7_throwf(v7, "Error", "Out of memory");
    goto clean;
  }
  nc->user_data = ud;
  v7_own(v7, &ud->client);

  v7_def(v7, *res, "_nc", ~0, _V7_DESC_HIDDEN(1), v7_mk_foreign(v7, nc));

clean:
  free(url_with_port);

  return rcode;
}