Esempio n. 1
0
/*
 * Check if there is a new image available and
 * send it to the cloud endpoint if the send buffer is not too full.
 * The image is moved in a new file by the jpeg optimizer function;
 * this ensures that we will detect a new frame when raspistill writes
 * it's output file.
 */
static void send_mjpg_frame(struct mg_connection *nc, const char *file_path) {
  static int skipped_frames = 0;
  struct stat st;
  FILE *fp;

  /* Check file modification time. */
  if (stat(file_path, &st) == 0) {
    /* Skip the frame if there is too much unsent data. */
    if (nc->send_mbuf.len > 256) skipped_frames++;

    /* Read new mjpg frame into a buffer */
    fp = fopen(file_path, "rb");
    char buf[st.st_size];
    fread(buf, 1, sizeof(buf), fp);
    fclose(fp);

    /*
     * Delete the file so we can detect when raspistill creates a new one.
     * mtime granularity is only 1s.
     */
    unlink(file_path);

    /* Send those buffer through the websocket connection */
    mg_send_websocket_frame(nc, WEBSOCKET_OP_BINARY, buf, sizeof(buf));
    printf("Sent mjpg frame, %lu bytes after skippping %d frames\n",
           (unsigned long) sizeof(buf), skipped_frames);
    skipped_frames = 0;
  }
}
Esempio n. 2
0
void TestHttpClient::SendBinary(struct mg_connection * conn,
                                const std::vector<uint8_t> & bytes) {
  mg_send_websocket_frame(conn,
                          WEBSOCKET_OP_BINARY,
                          &bytes[0],
                          bytes.size());
}
Esempio n. 3
0
struct mg_connection * TestHttpClient::Connect(const std::string & address,
                                               const std::string & uri) {

  boost::mutex mutex;
  boost::condition_variable cond;

  struct mg_connection * conn;
  on_connected_ = [&](struct mg_connection * ws) {
      assert(conn == ws);
      boost::mutex::scoped_lock lock(mutex);
      cond.notify_one();
    };

  conn = mg_connect(&mgr_, address.c_str(), callback);
  mg_set_protocol_http_websocket(conn);
  mg_send_websocket_handshake(conn, uri.c_str(), nullptr);

  const boost::chrono::seconds d(10);
  boost::mutex::scoped_lock lock(mutex);
  const auto timeout = cond.wait_for(lock, d);
  if (boost::cv_status::timeout == timeout) {
    mg_send_websocket_frame(conn, WEBSOCKET_OP_CLOSE, nullptr, 0);
    return nullptr;
  }

  return conn;
}
Esempio n. 4
0
void TestHttpClient::SendText(struct mg_connection * conn,
                              const std::string & text) {
  mg_send_websocket_frame(conn,
                          WEBSOCKET_OP_TEXT,
                          text.c_str(),
                          text.length());
}
Esempio n. 5
0
/*
 * Sends and encoded chunk with a websocket fragment.
 * Mongoose WS API for sending fragmenting is quite low level, so we have to do
 * our own
 * bookkeeping. TODO(mkm): consider moving to Mongoose.
 */
static void clubby_proto_ws_emit(char *d, size_t l, int end, void *user_data) {
  struct mg_connection *nc = (struct mg_connection *) user_data;

  if (!clubby_proto_is_connected(nc)) {
    /*
     * Not trying to reconect here,
     * It should be done before calling clubby_proto_ws_emit
     */
    LOG(LL_ERROR, ("Clubby is not connected"));
    return;
  }

  int flags = end ? 0 : WEBSOCKET_DONT_FIN;
  int op = nc->flags & MG_F_WS_FRAGMENTED ? WEBSOCKET_OP_CONTINUE
                                          : WEBSOCKET_OP_BINARY;
  if (!end) {
    nc->flags |= MG_F_WS_FRAGMENTED;
  } else {
    nc->flags &= ~MG_F_WS_FRAGMENTED;
  }

  LOG(LL_DEBUG, ("sending websocket frame flags=%x", op | flags));

  mg_send_websocket_frame(nc, op | flags, d, l);
}
Esempio n. 6
0
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);
}
Esempio n. 7
0
static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
  switch (ev) {
    case MG_EV_HTTP_REQUEST:
      mg_serve_http(nc, (struct http_message *)ev_data, s_http_server_opts);
      break;
    case MG_EV_WEBSOCKET_HANDSHAKE_DONE: {
      DEBUG("[Server] Client connected!\n");
      break;
    }
    case MG_EV_WEBSOCKET_FRAME: {
      struct websocket_message *wm = (struct websocket_message *)ev_data;
      memcpy(input, wm->data, wm->size);
      if (BUFFER_SIZE != fwrite(input, sizeof(float), BUFFER_SIZE, dsp_in)) {
        DEBUG("[Server] Terminated (fread).\n");
        s_signal_received = 9;
        break;
      }
      fflush(dsp_in);
      DEBUG("[Server] Samples sent.\n");
      if (BUFFER_SIZE != fread(output, sizeof(float), BUFFER_SIZE, dsp_out)) {
        printf("Server Terminated (fwrite).\n");
        s_signal_received = 9;
        break;
      }
      DEBUG("[Server] Samples received.\n");
      mg_send_websocket_frame(nc, WEBSOCKET_OP_BINARY, output, BUFFER_SIZE * sizeof(float));
      break;
    }
  }
}
Esempio n. 8
0
/*
 * Sends a Close websocket frame with the given data, and closes the underlying
 * connection. If `len` is ~0, strlen(data) is used.
 */
static void mg_ws_close(struct mg_connection *nc, const void *data,
                        size_t len) {
  if ((int) len == ~0) {
    len = strlen((const char *) data);
  }
  mg_send_websocket_frame(nc, WEBSOCKET_OP_CLOSE, data, len);
  nc->flags |= MG_F_SEND_AND_CLOSE;
}
Esempio n. 9
0
static bool mg_rpc_channel_ws_send_frame(struct mg_rpc_channel *ch,
                                         const struct mg_str f) {
  struct mg_rpc_channel_ws_data *chd =
      (struct mg_rpc_channel_ws_data *) ch->channel_data;
  if (chd->nc == NULL || chd->sending) return false;
  chd->sending = true;
  mg_send_websocket_frame(chd->nc, WEBSOCKET_OP_TEXT, f.p, f.len);
  return true;
}
Esempio n. 10
0
void RestServ::websocketBroadcast(mg_connection& nc, const char* msg, size_t len) 
{
    mg_connection* iter;

    for (iter = mg_next(nc.mgr, nullptr); iter != nullptr; iter = mg_next(nc.mgr, iter))
    {
      mg_send_websocket_frame(iter, WEBSOCKET_OP_TEXT, msg, len);
    }
}
Esempio n. 11
0
static void save_all( struct mg_connection* nc )
{
  s_source->pathCount = 0;

  printf("REMOVE ALL\n");
  snprintf( s_output_buffer, kOutputBufferSize, "{ \"cmd\" : \"SAVE-ALL\" }" );
  int len = strlen( s_output_buffer );
  mg_send_websocket_frame(nc, WEBSOCKET_OP_TEXT, s_output_buffer, len );
}
Esempio n. 12
0
/*
 * Forwards API payload to the device, by scanning through
 * all the connections to find those that are tagged as WebSocket.
 */
static void send_command_to_the_device(struct mg_mgr *mgr,
                                       const struct mg_str *cmd) {
  struct mg_connection *nc;
  for (nc = mg_next(mgr, NULL); nc != NULL; nc = mg_next(mgr, nc)) {
    if (!(nc->flags & MG_F_IS_WEBSOCKET))
      continue;  // Ignore non-websocket requests

    mg_send_websocket_frame(nc, WEBSOCKET_OP_TEXT, cmd->p, cmd->len);
    printf("Sent API command [%.*s] to %p\n", (int) cmd->len, cmd->p, nc);
  }
}
Esempio n. 13
0
static void broadcast_callback(struct mg_connection *nc, int ev, void *ev_data)
{
	char *buf = (char *) ev_data;

	if (ev != MG_EV_POLL)
		return;

	if (!(nc->flags & MG_F_IS_WEBSOCKET))
		return;

	mg_send_websocket_frame(nc, WEBSOCKET_OP_TEXT, buf, strlen(buf));
}
Esempio n. 14
0
static void broadcast(struct mg_connection *nc, const struct mg_str msg) {
  struct mg_connection *c;
  char buf[500];
  char addr[32];
  mg_sock_addr_to_str(&nc->sa, addr, sizeof(addr),
                      MG_SOCK_STRINGIFY_IP | MG_SOCK_STRINGIFY_PORT);

  snprintf(buf, sizeof(buf), "%s %.*s", addr, (int) msg.len, msg.p);
  printf("%s\n", buf); /* Local echo. */
  for (c = mg_next(nc->mgr, NULL); c != NULL; c = mg_next(nc->mgr, c)) {
    if (c == nc) continue; /* Don't send to the sender. */
    mg_send_websocket_frame(c, WEBSOCKET_OP_TEXT, buf, strlen(buf));
  }
}
Esempio n. 15
0
static void send_sources( struct mg_connection* nc )
{
  for (int i=0; i<s_source->pathCount; i++)
  {
    int path_len = strlen( s_source->paths[i] );
    if (path_len)
    {
      printf("SEND %s\n",s_source->paths[i]);
      snprintf( s_output_buffer, kOutputBufferSize, "{ \"cmd\" : \"LOAD\", \"path\" : \"%s\", \"text\" : \"%s\" }", s_source->paths[i],s_source->text[i]);
      int len = strlen( s_output_buffer );
      mg_send_websocket_frame(nc, WEBSOCKET_OP_TEXT, s_output_buffer, len );
    }
  }
}
Esempio n. 16
0
void TestHttpClient::Close(struct mg_connection * conn) {

  boost::mutex mutex;
  boost::condition_variable cond;

  on_closed_ = [&](struct mg_connection * ws) {
      assert(conn == ws);
      boost::mutex::scoped_lock lock(mutex);
      cond.notify_one();
    };

  mg_send_websocket_frame(conn, WEBSOCKET_OP_CLOSE, nullptr, 0);
  boost::mutex::scoped_lock lock(mutex);
  cond.wait(lock);
}
Esempio n. 17
0
void mg_printf_websocket_frame(struct mg_connection *nc, int op,
                               const char *fmt, ...) {
  char mem[MG_VPRINTF_BUFFER_SIZE], *buf = mem;
  va_list ap;
  int len;

  va_start(ap, fmt);
  if ((len = mg_avprintf(&buf, sizeof(mem), fmt, ap)) > 0) {
    mg_send_websocket_frame(nc, op, buf, len);
  }
  va_end(ap);

  if (buf != mem && buf != NULL) {
    MG_FREE(buf);
  }
}
Esempio n. 18
0
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);
    }
  }
}
Esempio n. 19
0
void RestServ::websocketSend(mg_connection* nc, const char* msg, size_t len) 
{
    mg_send_websocket_frame(nc, WEBSOCKET_OP_TEXT, msg, len);
}
Esempio n. 20
0
static int mg_deliver_websocket_data(struct mg_connection *nc) {
  /* Using unsigned char *, cause of integer arithmetic below */
  uint64_t i, data_len = 0, frame_len = 0, new_data_len = nc->recv_mbuf.len,
              len, mask_len = 0, header_len = 0;
  struct mg_ws_proto_data *wsd = mg_ws_get_proto_data(nc);
  unsigned char *new_data = (unsigned char *) nc->recv_mbuf.buf,
                *e = (unsigned char *) nc->recv_mbuf.buf + nc->recv_mbuf.len;
  uint8_t flags;
  int ok, reass;

  if (wsd->reass_len > 0) {
    /*
     * We already have some previously received data which we need to
     * reassemble and deliver to the client code when we get the final
     * fragment.
     *
     * NOTE: it doesn't mean that the current message must be a continuation:
     * it might be a control frame (Close, Ping or Pong), which should be
     * handled without breaking the fragmented message.
     */

    size_t existing_len = wsd->reass_len;
    assert(new_data_len >= existing_len);

    new_data += existing_len;
    new_data_len -= existing_len;
  }

  flags = new_data[0];

  reass = new_data_len > 0 && mg_is_ws_fragment(flags) &&
          !(nc->flags & MG_F_WEBSOCKET_NO_DEFRAG);

  if (reass && mg_is_ws_control_frame(flags)) {
    /*
     * Control frames can't be fragmented, so if we encounter fragmented
     * control frame, close connection immediately.
     */
    mg_ws_close(nc, "fragmented control frames are illegal", ~0);
    return 0;
  } else if (new_data_len > 0 && !reass && !mg_is_ws_control_frame(flags) &&
             wsd->reass_len > 0) {
    /*
     * When in the middle of a fragmented message, only the continuations
     * and control frames are allowed.
     */
    mg_ws_close(nc, "non-continuation in the middle of a fragmented message",
                ~0);
    return 0;
  }

  if (new_data_len >= 2) {
    len = new_data[1] & 0x7f;
    mask_len = new_data[1] & FLAGS_MASK_FIN ? 4 : 0;
    if (len < 126 && new_data_len >= mask_len) {
      data_len = len;
      header_len = 2 + mask_len;
    } else if (len == 126 && new_data_len >= 4 + mask_len) {
      header_len = 4 + mask_len;
      data_len = ntohs(*(uint16_t *) &new_data[2]);
    } else if (new_data_len >= 10 + mask_len) {
      header_len = 10 + mask_len;
      data_len = (((uint64_t) ntohl(*(uint32_t *) &new_data[2])) << 32) +
                 ntohl(*(uint32_t *) &new_data[6]);
    }
  }

  frame_len = header_len + data_len;
  ok = (frame_len > 0 && frame_len <= new_data_len);

  /* Check for overflow */
  if (frame_len < header_len || frame_len < data_len) {
    ok = 0;
    mg_ws_close(nc, "overflowed message", ~0);
  }

  if (ok) {
    size_t cleanup_len = 0;
    struct websocket_message wsm;

    wsm.size = (size_t) data_len;
    wsm.data = new_data + header_len;
    wsm.flags = flags;

    /* Apply mask if necessary */
    if (mask_len > 0) {
      for (i = 0; i < data_len; i++) {
        new_data[i + header_len] ^= (new_data + header_len - mask_len)[i % 4];
      }
    }

    if (reass) {
      /* This is a message fragment */

      if (mg_is_ws_first_fragment(flags)) {
        /*
         * On the first fragmented frame, skip the first byte (op) and also
         * reset size to 1 (op), it'll be incremented with the data len below.
         */
        new_data += 1;
        wsd->reass_len = 1 /* op */;
      }

      /* Append this frame to the reassembled buffer */
      memmove(new_data, wsm.data, e - wsm.data);
      wsd->reass_len += wsm.size;
      nc->recv_mbuf.len -= wsm.data - new_data;

      if (flags & FLAGS_MASK_FIN) {
        /* On last fragmented frame - call user handler and remove data */
        wsm.flags = FLAGS_MASK_FIN | nc->recv_mbuf.buf[0];
        wsm.data = (unsigned char *) nc->recv_mbuf.buf + 1 /* op */;
        wsm.size = wsd->reass_len - 1 /* op */;
        cleanup_len = wsd->reass_len;
        wsd->reass_len = 0;

        /* Pass reassembled message to the client code. */
        mg_handle_incoming_websocket_frame(nc, &wsm);
        mbuf_remove(&nc->recv_mbuf, cleanup_len); /* Cleanup frame */
      }
    } else {
      /*
       * This is a complete message, not a fragment. It might happen in between
       * of a fragmented message (in this case, WebSocket protocol requires
       * current message to be a control frame).
       */
      cleanup_len = (size_t) frame_len;

      /* First of all, check if we need to react on a control frame. */
      switch (flags & FLAGS_MASK_OP) {
        case WEBSOCKET_OP_PING:
          mg_send_websocket_frame(nc, WEBSOCKET_OP_PONG, wsm.data, wsm.size);
          break;

        case WEBSOCKET_OP_CLOSE:
          mg_ws_close(nc, wsm.data, wsm.size);
          break;
      }

      /* Pass received message to the client code. */
      mg_handle_incoming_websocket_frame(nc, &wsm);

      /* Cleanup frame */
      memmove(nc->recv_mbuf.buf + wsd->reass_len,
              nc->recv_mbuf.buf + wsd->reass_len + cleanup_len,
              nc->recv_mbuf.len - wsd->reass_len - cleanup_len);
      nc->recv_mbuf.len -= cleanup_len;
    }
  }

  return ok;
}
Esempio n. 21
0
static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
  struct websocket_message *wm = (struct websocket_message *) ev_data;
  (void) nc;

  switch (ev) {
    case MG_EV_CONNECT: {
      int status = *((int *) ev_data);
      if (status != 0) {
        printf("-- Connection error: %d\n", status);
      }
      break;
    }
    case MG_EV_WEBSOCKET_HANDSHAKE_DONE: {
      printf("-- Connected\n");
      s_is_connected = 1;
      break;
    }
    case MG_EV_POLL: {
      char msg[500];
      int n = 0;
#ifdef _WIN32 /* Windows console input is special. */
      INPUT_RECORD inp[100];
      HANDLE h = GetStdHandle(STD_INPUT_HANDLE);
      DWORD i, num;
      if (!PeekConsoleInput(h, inp, sizeof(inp) / sizeof(*inp), &num)) break;
      for (i = 0; i < num; i++) {
        if (inp[i].EventType == KEY_EVENT &&
            inp[i].Event.KeyEvent.wVirtualKeyCode == VK_RETURN) {
          break;
        }
      }
      if (i == num) break;
      if (!ReadConsole(h, msg, sizeof(msg), &num, NULL)) break;
      /* Un-unicode. This is totally not the right way to do it. */
      for (i = 0; i < num * 2; i += 2) msg[i / 2] = msg[i];
      n = (int) num;
#else /* For everybody else, we just read() stdin. */
      fd_set read_set, write_set, err_set;
      struct timeval timeout = {0, 0};
      FD_ZERO(&read_set);
      FD_ZERO(&write_set);
      FD_ZERO(&err_set);
      FD_SET(0 /* stdin */, &read_set);
      if (select(1, &read_set, &write_set, &err_set, &timeout) == 1) {
        n = read(0, msg, sizeof(msg));
      }
#endif
      if (n <= 0) break;
      while (msg[n - 1] == '\r' || msg[n - 1] == '\n') n--;
      mg_send_websocket_frame(nc, WEBSOCKET_OP_TEXT, msg, n);
      break;
    }
    case MG_EV_WEBSOCKET_FRAME: {
      printf("%.*s\n", (int) wm->size, wm->data);
      break;
    }
    case MG_EV_CLOSE: {
      if (s_is_connected) printf("-- Disconnected\n");
      s_done = 1;
      break;
    }
  }
}
Esempio n. 22
0
/**
 * @brief Close the WebSocket from the web server end.
 * Previously a client has connected to us and created a WebSocket.  By making this call we are
 * declaring that the socket should be closed from the server end.
 * @return N/A.
 */
void WebServer::WebSocketHandler::close() {
	mg_send_websocket_frame(m_mgConnection, WEBSOCKET_OP_CLOSE, nullptr, 0);
} // close
Esempio n. 23
0
/**
 * @brief Send data down the WebSocket
 * @param [in] data The message to send down the socket.
 * @param [in] size The size of the message
 * @return N/A.
 */
void WebServer::WebSocketHandler::sendData(uint8_t *data, uint32_t size) {
	mg_send_websocket_frame(m_mgConnection,
	   WEBSOCKET_OP_BINARY | WEBSOCKET_OP_CONTINUE,
	   data, size);
} // sendData
Esempio n. 24
0
/**
 * @brief Send data down the WebSocket
 * @param [in] message The message to send down the socket.
 * @return N/A.
 */
void WebServer::WebSocketHandler::sendData(std::string message) {
	ESP_LOGD(tag, "WebSocketHandler::sendData(length=%d)", message.length());
	mg_send_websocket_frame(m_mgConnection,
	   WEBSOCKET_OP_BINARY | WEBSOCKET_OP_CONTINUE,
	   message.data(), message.length());
} // sendData