示例#1
0
static void http_write_headers(struct v7 *v7, v7_val_t headers_obj,
                               struct mg_connection *c) {
  if (v7_is_object(headers_obj)) {
    void *h = NULL;
    v7_val_t name, value;
    v7_prop_attr_t attrs;
    while ((h = v7_next_prop(h, headers_obj, &name, &value, &attrs)) != NULL) {
      size_t n1, n2;
      const char *s1 = v7_get_string_data(v7, &name, &n1);
      const char *s2 = v7_get_string_data(v7, &value, &n2);
      mg_printf(c, "%.*s: %.*s\r\n", (int) n1, s1, (int) n2, s2);
    }
  }
}
示例#2
0
/*
 * Serve static files.
 *
 * Takes an object containing mongoose http server options.
 * Commonly used properties:
 * - `document_root`: Path to the web root directory
 * - `enable_directory_listing`: Set to "no" to disable directory listing.
 *   Enabled by default.
 * - `extra_headers`: Extra HTTP headers to add to each server response.
 *
 * For the full option object definition see:
 * https://docs.cesanta.com/mongoose/dev/index.html#/c-api/http.h/struct_mg_serve_http_opts/
 */
SJ_PRIVATE enum v7_err Http_response_serve(struct v7 *v7, v7_val_t *res) {
  struct mg_serve_http_opts opts;
  struct http_message hm;
  enum v7_err rcode = V7_OK;
  DECLARE_CONN();

  size_t i, n;
  v7_val_t request = v7_get(v7, v7_get_this(v7), "_r", ~0);
  v7_val_t url_v = v7_get(v7, request, "url", ~0);
  const char *url = v7_get_string_data(v7, &url_v, &n);
  const char *quest = strchr(url, '?');

  memset(&opts, 0, sizeof(opts));
  memset(&hm, 0, sizeof(hm));

  /* Set up "fake" parsed HTTP message */
  hm.uri.p = url;
  hm.uri.len = quest == NULL ? n : n - (quest - url);

  if (v7_argc(v7) > 0) {
    populate_opts_from_js_argument(v7, v7_arg(v7, 0), &opts);
  }
  mg_serve_http(c, &hm, opts);
  for (i = 0; i < ARRAY_SIZE(s_map); i++) {
    free(*(char **) ((char *) &opts + s_map[i].offset));
  }

  *res = v7_get_this(v7);

clean:
  return rcode;
}
示例#3
0
文件: sj_uart.c 项目: ifzz/smart.js
/*
 * Usage:
 *
 * new UART("platform_specific_name")
 *
 */
static enum v7_err UART_ctor(struct v7 *v7, v7_val_t *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_create_undefined();
  v7_own(v7, &ud->cb);

  name = v7_get_string_data(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_set(v7, this_obj, "_ud", ~0, V7_PROPERTY_HIDDEN, v7_create_foreign(ud));
  v7_set(v7, this_obj, "_dev", ~0, V7_PROPERTY_HIDDEN, v7_create_foreign(uart));

clean:
  return rcode;
}
示例#4
0
/*
 * 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_to_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_data(v7, &messagev, &message_len);

  nc = v7_to_foreign(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;
}
示例#5
0
static void populate_opts_from_js_argument(struct v7 *v7, v7_val_t obj,
                                           struct mg_serve_http_opts *opts) {
  size_t i;
  for (i = 0; i < ARRAY_SIZE(s_map); i++) {
    v7_val_t v = v7_get(v7, obj, s_map[i].name, ~0);
    if (v7_is_string(v)) {
      size_t n;
      const char *str = v7_get_string_data(v7, &v, &n);
      *(char **) ((char *) opts + s_map[i].offset) = strdup(str);
    }
  }
}
示例#6
0
文件: sj_uart.c 项目: ifzz/smart.js
static enum v7_err UART_write(struct v7 *v7, v7_val_t *res) {
  v7_val_t this_obj = v7_get_this(v7);
  v7_val_t dev = v7_get(v7, this_obj, "_dev", ~0), data = v7_arg(v7, 0);
  size_t len;
  const char *d = v7_get_string_data(v7, &data, &len);

  (void) v7;
  (void) this_obj;

  sj_hal_write_uart(v7_to_foreign(dev), d, len);

  return V7_OK;
}
示例#7
0
static enum v7_err UART_send(struct v7 *v7, v7_val_t *res) {
  struct esp_sj_uart_state *us;
  enum v7_err ret = esp_sj_uart_get_state(v7, &us);
  if (ret != V7_OK) return ret;

  v7_val_t arg0 = v7_arg(v7, 0);
  if (!v7_is_string(arg0)) {
    return v7_throwf(v7, "Error", "String arg required");
  }
  size_t len = 0;
  const char *data = v7_get_string_data(v7, &arg0, &len);
  if (data != NULL && len > 0) {
    cs_rbuf_t *txb = esp_uart_tx_buf(us->uart_no);
    len = MIN(len, txb->avail);
    cs_rbuf_append(txb, (uint8_t *) data, len);
    esp_sj_uart_schedule_dispatcher(us->uart_no);
  }
  *res = v7_mk_number(len);
  return V7_OK;
}
示例#8
0
/*
 * Parse URL; used for:
 *
 * - `URL.parse()`
 * - `Http.request()` and `Http.get()`, when provided `opts` is a string.
 */
static enum v7_err sj_url_parse(struct v7 *v7, v7_val_t url_v, v7_val_t *res) {
  enum v7_err rcode = V7_OK;
  v7_val_t opts, protocol_v;
  size_t i, j, len;
  int state = 0;
  const char *url;

  if (!v7_is_string(url_v)) {
    rcode = v7_throwf(v7, "TypeError", "URL must be a string");
    goto clean;
  }

  url = v7_get_string_data(v7, &url_v, &len);
  opts = v7_mk_object(v7);
  for (i = j = 0; j < len; j++) {
    switch (state) {
      case 0:
        if (url[j] == '/') {
          protocol_v = v7_mk_string(v7, url + i, j - i - 1, 1);
          v7_set(v7, opts, "protocol", ~0, protocol_v);
          j += 1;
          i = j + 1;
          state = 1;
        }
        break;
      case 1:
        if (url[j] == '/' || (j > i && url[j] == ':') || j == len - 1) {
          int hl = j - i;
          if (j == len - 1 && url[j] != '/' && url[j] != ':') hl++;
          v7_set(v7, opts, "hostname", ~0, v7_mk_string(v7, url + i, hl, 1));
          if (url[j] == '/' || j == len - 1) {
            const char *protocol = v7_to_cstring(v7, &protocol_v);
            int port = strcasecmp(protocol, "https") == 0 ? 443 : 80;
            v7_set(v7, opts, "port", ~0, v7_mk_number(port));
            i = j;
            if (j == len - 1) j--;
            state = 3;
          } else {
            i = j + 1;
            state = 2;
          }
        }
        break;
      case 2:
        if (url[j] == '/' || j == len - 1) {
          char ps[6];
          size_t l = j - i;
          if (j == len - 1) l++;
          if (l > sizeof(ps) - 1) l = sizeof(ps) - 1;
          memcpy(ps, url + i, l);
          ps[l] = '\0';
          v7_set(v7, opts, "port", ~0, v7_mk_number(atoi(ps)));
          i = j;
          if (j == len - 1) j--;
          state = 3;
        }
        break;
      case 3:
        if (j == len - 1) {
          v7_val_t path_v = j - i > 0 ? v7_mk_string(v7, url + i, j - i + 1, 1)
                                      : v7_mk_string(v7, "/", 1, 1);
          v7_set(v7, opts, "path", ~0, path_v);
        }
        break;
    }
  }
  *res = opts;

clean:
  return rcode;
}
示例#9
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);
 * });
 *
 * 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;
  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_data(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) {
    rcode = v7_throwf(v7, "Error", "unsupported protocol");
    goto clean;
  }
  url += sizeof("mqtt://") - 1;

  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) {
    int ret =
        asprintf(&url_with_port, "%.*s%s", (int) host.len, host.p, ":1883");
    (void) ret;
  }

  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;
  }
  mg_set_protocol_mqtt(nc);

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

  ud = calloc(1, sizeof(*ud));
  ud->v7 = v7;
  ud->client = *res;
  ud->client_id = strdup(v7_to_cstring(v7, &client_id));
  nc->user_data = ud;
  v7_own(v7, &ud->client);

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

clean:
  free(url_with_port);

  return rcode;
}