Beispiel #1
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;
}
Beispiel #2
0
SJ_PRIVATE enum v7_err Http_response_writeHead(struct v7 *v7, v7_val_t *res) {
  enum v7_err rcode = V7_OK;
  DECLARE_CONN();

  unsigned long code = 200;
  v7_val_t arg0 = v7_arg(v7, 0), arg1 = v7_arg(v7, 1);

  if (v7_is_truthy(v7, v7_get(v7, v7_get_this(v7), "_whd", ~0))) {
    rcode = v7_throwf(v7, "Error", "Headers already sent");
    goto clean;
  }

  if (v7_is_number(arg0)) {
    code = v7_to_number(arg0);
  }

  write_http_status(c, code);
  http_write_headers(v7, arg1, c);
  mg_send(c, "\r\n", 2);
  v7_set(v7, v7_get_this(v7), "_whd", ~0, v7_mk_boolean(1));
  *res = v7_get_this(v7);

clean:
  return rcode;
}
Beispiel #3
0
SJ_PRIVATE enum v7_err Http_response_write(struct v7 *v7, v7_val_t *res) {
  enum v7_err rcode = V7_OK;
  DECLARE_CONN();

  if (!v7_is_truthy(v7, v7_get(v7, v7_get_this(v7), "_whd", ~0))) {
    write_http_status(c, 200);
    mg_send(c, "\r\n", 2);
    v7_set(v7, v7_get_this(v7), "_whd", ~0, v7_mk_boolean(1));
  }
  Http_write_data(v7, c);
  *res = v7_get_this(v7);

clean:
  return rcode;
}
Beispiel #4
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 #5
0
/*
 * 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;
}
Beispiel #6
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_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;
}
Beispiel #7
0
/*
 * 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;
}
Beispiel #8
0
/*
 * Read the content of the UART. It does not block.
 * Optional `max_len` parameter, defaults to max size_t.
 */
static enum v7_err UART_read(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), maxv = v7_arg(v7, 0);
  size_t max = v7_is_number(maxv) ? (size_t) v7_to_number(maxv) : ~0;
  *res = sj_hal_read_uart(v7, v7_to_foreign(dev), max);

  return V7_OK;
}
Beispiel #9
0
static enum v7_err esp_sj_uart_get_state(struct v7 *v7,
                                         struct esp_sj_uart_state **us) {
  int uart_no = v7_to_number(v7_get(v7, v7_get_this(v7), "_u", 2));
  if (uart_no < 0 || uart_no > 1) {
    return v7_throwf(v7, "Error", "Invalid UART number");
  }
  *us = &sj_us[uart_no];
  return V7_OK;
}
Beispiel #10
0
SJ_PRIVATE enum v7_err Http_request_abort(struct v7 *v7, v7_val_t *res) {
  enum v7_err rcode = V7_OK;
  DECLARE_CONN();
  c->flags |= MG_F_CLOSE_IMMEDIATELY;
  *res = v7_get_this(v7);

clean:
  return rcode;
}
Beispiel #11
0
SJ_PRIVATE enum v7_err Http_request_write(struct v7 *v7, v7_val_t *res) {
  enum v7_err rcode = V7_OK;
  DECLARE_CONN();

  Http_write_data(v7, c);
  *res = v7_get_this(v7);

clean:
  return rcode;
}
Beispiel #12
0
/* JS signature: listen(addr, [options]) */
SJ_PRIVATE enum v7_err Http_Server_listen(struct v7 *v7, v7_val_t *res) {
  enum v7_err rcode = V7_OK;
  char buf[50], *p = buf;
  const char *ca_cert = NULL, *cert = NULL;
  v7_val_t this_obj = v7_get_this(v7);
  v7_val_t arg0 = v7_arg(v7, 0);
  v7_val_t opts = v7_arg(v7, 1);

  if (!v7_is_number(arg0) && !v7_is_string(arg0)) {
    rcode = v7_throwf(v7, "TypeError", "Function expected");
    goto clean;
  }

  if (!v7_is_undefined(opts) && !v7_is_object(opts)) {
    rcode = v7_throwf(v7, "TypeError", "Options must be an object");
    goto clean;
  }

  if (!v7_is_undefined(opts)) {
    v7_val_t ca_cert_v = v7_get(v7, opts, "ssl_ca_cert", ~0);
    v7_val_t cert_v = v7_get(v7, opts, "ssl_cert", ~0);
    if (!v7_is_undefined(ca_cert_v) && !v7_is_string(ca_cert_v)) {
      rcode = v7_throwf(v7, "TypeError", "ca_cert must be a string");
      goto clean;
    }

    if (!v7_is_undefined(cert_v) && !v7_is_string(cert_v)) {
      rcode = v7_throwf(v7, "TypeError", "cert must be a string");
      goto clean;
    }

    if (!v7_is_undefined(ca_cert_v)) {
      ca_cert = v7_to_cstring(v7, &ca_cert_v);
    }

    if (!v7_is_undefined(cert_v)) {
      cert = v7_to_cstring(v7, &cert_v);
    }
  }

  p = v7_stringify(v7, arg0, buf, sizeof(buf), 0);
  rcode = start_http_server(v7, p, this_obj, ca_cert, cert);
  if (rcode != V7_OK) {
    goto clean;
  }

  *res = this_obj;

clean:
  if (p != buf) {
    free(p);
  }
  return rcode;
}
Beispiel #13
0
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;
}
Beispiel #14
0
SJ_PRIVATE enum v7_err Http_request_set_timeout(struct v7 *v7, v7_val_t *res) {
  enum v7_err rcode = V7_OK;
  DECLARE_CONN();

  struct user_data *ud = (struct user_data *) c->user_data;
  mg_set_timer(c, time(NULL) + v7_to_number(v7_arg(v7, 0)) / 1000.0);
  ud->timeout_callback = v7_arg(v7, 1);
  v7_own(v7, &ud->timeout_callback);

  *res = v7_get_this(v7);

clean:
  return rcode;
}
Beispiel #15
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 #16
0
SJ_PRIVATE enum v7_err Http_response_end(struct v7 *v7, v7_val_t *res) {
  enum v7_err rcode = V7_OK;
  DECLARE_CONN();

  rcode = Http_response_write(v7, res);
  if (rcode != V7_OK) {
    goto clean;
  }

  mg_send_http_chunk(c, "", 0);
  *res = v7_get_this(v7);

clean:
  return rcode;
}
Beispiel #17
0
/*
 * Regiter a callback to be invoked when there is at least N bytes available.
 * N defaults to maxint if undefined
 */
static enum v7_err UART_recv(struct v7 *v7, v7_val_t *res) {
  v7_val_t this_obj = v7_get_this(v7);
  v7_val_t cb = v7_arg(v7, 0);
  v7_val_t wantv = v7_arg(v7, 1);
  v7_val_t udv = v7_get(v7, this_obj, "_ud", ~0);
  size_t want = v7_is_number(wantv) ? (size_t) v7_to_number(wantv) : ~0;

  struct user_data *ud = (struct user_data *) v7_to_foreign(udv);
  ud->cb = cb;
  v7_own(v7, &ud->cb);
  ud->want = want;
  /* TODO(mkm): trigger cb if there is already something in the buffer */

  return V7_OK;
}
Beispiel #18
0
SJ_PRIVATE enum v7_err Http_request_end(struct v7 *v7, v7_val_t *res) {
  enum v7_err rcode = V7_OK;
  DECLARE_CONN();

  rcode = Http_request_write(v7, res);
  if (rcode != V7_OK) {
    goto clean;
  }

  mg_send_http_chunk(c, "", 0);
  c->flags |= MG_F_CLOSE_CONNECTION_AFTER_RESPONSE;
  *res = v7_get_this(v7);

clean:
  return rcode;
}
Beispiel #19
0
static v7_val_t MyThing_myMethod(struct v7 *v7) {
  v7_val_t this_obj = v7_get_this(v7);
  return v7_get(v7, this_obj, "__arg", ~0);
}
Beispiel #20
0
static v7_val_t MyThing_ctor(struct v7 *v7) {
  v7_val_t this_obj = v7_get_this(v7);
  v7_val_t arg0 = v7_arg(v7, 0);
  v7_set(v7, this_obj, "__arg", ~0 /* = strlen */, V7_PROPERTY_DONT_ENUM, arg0);
  return this_obj;
}
Beispiel #21
0
/*
 * Same as `get_mgconn_obj()`, but uses `this` as an `obj`.
 */
static struct mg_connection *get_mgconn(struct v7 *v7) {
  return get_mgconn_obj(v7, v7_get_this(v7));
}
Beispiel #22
0
Datei: js_oop.c Projekt: QUSIR/v7
static enum v7_err MyThing_myMethod(struct v7 *v7, v7_val_t *res) {
    v7_val_t this_obj = v7_get_this(v7);
    *res = v7_get(v7, this_obj, "__arg", ~0);
    return V7_OK;
}