コード例 #1
0
ファイル: sj_mqtt.c プロジェクト: 2bright/mongoose-iot
/*
 * `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;
}
コード例 #2
0
ファイル: sj_mqtt.c プロジェクト: 2bright/mongoose-iot
/*
 * Subscribes a mqtt client to a topic.
 */
enum v7_err MQTT_subscribe(struct v7 *v7, v7_val_t *res) {
  enum v7_err rcode = V7_OK;
  struct user_data *ud;
  struct mg_connection *nc;
  struct mg_mqtt_topic_expression expr;
  v7_val_t topicv = v7_arg(v7, 0);
  const char *topic;

  nc = v7_get_ptr(v7, v7_get(v7, v7_get_this(v7), "_nc", ~0));
  if (nc == NULL) {
    rcode = v7_throwf(v7, "Error", "unsupported protocol");
    goto clean;
  }
  ud = (struct user_data *) nc->user_data;

  topic = v7_get_cstring(v7, &topicv);
  if (topic == NULL || strlen(topic) == 0) {
    rcode = v7_throwf(v7, "TypeError", "invalid topic");
    goto clean;
  }

  expr.topic = topic;
  expr.qos = 0;
  mg_mqtt_subscribe(nc, &expr, 1, ud->msgid++);

  *res = v7_mk_boolean(v7, 1);
clean:
  return rcode;
}
コード例 #3
0
ファイル: sj_mqtt.c プロジェクト: 2bright/mongoose-iot
/*
 * Publishes a message to a topic.
 *
 * Args:
 * - `topic`: topic, string.
 * - `message`: message, string.
 *
 * Only QOS 0 is implemented at the moment.
 */
enum v7_err MQTT_publish(struct v7 *v7, v7_val_t *res) {
  enum v7_err rcode = V7_OK;
  struct user_data *ud;
  struct mg_connection *nc;
  const char *topic;
  const char *message;
  size_t message_len;
  v7_val_t topicv = v7_arg(v7, 0), messagev = v7_arg(v7, 1);
  (void) res;

  topic = v7_get_cstring(v7, &topicv);
  if (topic == NULL || strlen(topic) == 0) {
    rcode = v7_throwf(v7, "TypeError", "invalid topic");
    goto clean;
  }

  if (!v7_is_string(messagev)) {
    rcode = v7_throwf(v7, "TypeError", "invalid message");
    goto clean;
  }
  message = v7_get_string(v7, &messagev, &message_len);

  nc = v7_get_ptr(v7, v7_get(v7, v7_get_this(v7), "_nc", ~0));
  if (nc == NULL) {
    rcode = v7_throwf(v7, "Error", "invalid connection");
    goto clean;
  }
  ud = (struct user_data *) nc->user_data;

  mg_mqtt_publish(nc, topic, ud->msgid++, MG_MQTT_QOS(0), message, message_len);

clean:
  return rcode;
}
コード例 #4
0
ファイル: sj_utils.c プロジェクト: 2bright/mongoose-iot
enum v7_err fill_ssl_connect_opts(struct v7 *v7, v7_val_t opts, int force_ssl,
                                  struct mg_connect_opts *copts) {
  enum v7_err rcode = V7_OK;

  v7_val_t v_use_ssl = v7_get(v7, opts, "use_ssl", ~0);
  v7_val_t v_ca_cert = v7_get(v7, opts, "ssl_ca_cert", ~0);
  v7_val_t v_cert = v7_get(v7, opts, "ssl_cert", ~0);
  v7_val_t v_server_name = v7_get(v7, opts, "ssl_server_name", ~0);

  if (!v7_is_undefined(v_ca_cert) && !v7_is_string(v_ca_cert)) {
    rcode = v7_throwf(v7, "TypeError", "ssl_ca_cert must be a string");
    goto clean;
  }
  if (!v7_is_undefined(v_cert) && !v7_is_string(v_cert)) {
    rcode = v7_throwf(v7, "TypeError", "ssl_cert must be a string");
    goto clean;
  }
  if (!v7_is_undefined(v_server_name) && !v7_is_string(v_server_name)) {
    rcode = v7_throwf(v7, "TypeError", "ssl_server_name must be a string");
    goto clean;
  }

  copts->ssl_ca_cert = v7_get_cstring(v7, &v_ca_cert);
  copts->ssl_cert = v7_get_cstring(v7, &v_cert);
  copts->ssl_server_name = v7_get_cstring(v7, &v_server_name);

  if ((force_ssl ||
       (v7_is_boolean(v_use_ssl) && v7_get_bool(v7, v_use_ssl) != 0)) &&
      copts->ssl_ca_cert == NULL) {
    /* Defaults to configuration */
    copts->ssl_ca_cert = get_cfg()->tls.ca_file;
  }

clean:
  return rcode;
}
コード例 #5
0
static enum v7_err Updater_startupdate(struct v7 *v7, v7_val_t *res) {
  enum v7_err rcode = V7_OK;

  v7_val_t manifest_url_v = v7_arg(v7, 0);
  if (!v7_is_string(manifest_url_v)) {
    rcode = v7_throwf(v7, "Error", "URL is not a string");
  } else {
    struct update_context *ctx = updater_context_create();
    if (ctx == NULL) {
      rcode = v7_throwf(v7, "Error", "Failed to init updater");
    } else if (start_update_download(ctx, v7_get_cstring(v7, &manifest_url_v)) <
               0) {
      rcode = v7_throwf(v7, "Error", ctx->status_msg);
    }
  }

  *res = v7_mk_boolean(v7, rcode == V7_OK);
  return rcode;
}
コード例 #6
0
ファイル: sj_mqtt.c プロジェクト: 2bright/mongoose-iot
/*
 * 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;
}