You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
243 lines
5.9 KiB
243 lines
5.9 KiB
/*
|
|
* libwebsockets - small server side websockets and web server implementation
|
|
*
|
|
* Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com>
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
* of this software and associated documentation files (the "Software"), to
|
|
* deal in the Software without restriction, including without limitation the
|
|
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
* sell copies of the Software, and to permit persons to whom the Software is
|
|
* furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in
|
|
* all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
* IN THE SOFTWARE.
|
|
*/
|
|
|
|
#include <string.h>
|
|
#include <nvs.h>
|
|
#include <esp_ota_ops.h>
|
|
|
|
typedef enum {
|
|
GROUP_STATE_NONE,
|
|
GROUP_STATE_INITIAL,
|
|
GROUP_STATE_MEMBERS,
|
|
GROUP_STATE_FINAL
|
|
} group_state;
|
|
|
|
struct per_session_data__lws_group {
|
|
struct per_session_data__lws_group *next;
|
|
group_state group_state;
|
|
|
|
struct lws_group_member *member;
|
|
|
|
unsigned char subsequent:1;
|
|
unsigned char changed_partway:1;
|
|
};
|
|
|
|
struct per_vhost_data__lws_group {
|
|
struct per_session_data__lws_group *live_pss_list;
|
|
struct lws_context *context;
|
|
struct lws_vhost *vhost;
|
|
const struct lws_protocols *protocol;
|
|
int count_live_pss;
|
|
};
|
|
|
|
static void render_ip4(char *dest, int len, uint8_t *ip)
|
|
{
|
|
snprintf(dest, len, "%u.%u.%u.%u", ip[0], ip[1], ip[2], ip[3]);
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
callback_lws_group(struct lws *wsi, enum lws_callback_reasons reason,
|
|
void *user, void *in, size_t len)
|
|
{
|
|
struct per_session_data__lws_group *pss =
|
|
(struct per_session_data__lws_group *)user;
|
|
struct per_vhost_data__lws_group *vhd =
|
|
(struct per_vhost_data__lws_group *)
|
|
lws_protocol_vh_priv_get(lws_get_vhost(wsi),
|
|
lws_get_protocol(wsi));
|
|
char buffer[1024 + LWS_PRE], ipv4[20];
|
|
char *start = buffer + LWS_PRE - 1, *p = start,
|
|
*end = buffer + sizeof(buffer) - 1;
|
|
struct lws_group_member *mbr;
|
|
int n, m;
|
|
|
|
switch (reason) {
|
|
|
|
case LWS_CALLBACK_PROTOCOL_INIT:
|
|
vhd = lws_protocol_vh_priv_zalloc(lws_get_vhost(wsi),
|
|
lws_get_protocol(wsi),
|
|
sizeof(struct per_vhost_data__lws_group));
|
|
vhd->context = lws_get_context(wsi);
|
|
vhd->protocol = lws_get_protocol(wsi);
|
|
vhd->vhost = lws_get_vhost(wsi);
|
|
break;
|
|
|
|
case LWS_CALLBACK_PROTOCOL_DESTROY:
|
|
if (!vhd)
|
|
break;
|
|
break;
|
|
|
|
case LWS_CALLBACK_ESTABLISHED:
|
|
lwsl_notice("%s: ESTABLISHED\n", __func__);
|
|
vhd->count_live_pss++;
|
|
pss->next = vhd->live_pss_list;
|
|
vhd->live_pss_list = pss;
|
|
pss->group_state = GROUP_STATE_INITIAL;
|
|
lws_callback_on_writable(wsi);
|
|
break;
|
|
|
|
case LWS_CALLBACK_SERVER_WRITEABLE:
|
|
|
|
switch (pss->group_state) {
|
|
|
|
case GROUP_STATE_NONE:
|
|
/* fallthru */
|
|
|
|
case GROUP_STATE_INITIAL:
|
|
|
|
p += snprintf((char *)p, end - p,
|
|
"{\n"
|
|
" \"group\":\"%s\","
|
|
" \"members\":[\n",
|
|
lws_esp32.group);
|
|
|
|
n = LWS_WRITE_TEXT | LWS_WRITE_NO_FIN;
|
|
pss->group_state = GROUP_STATE_MEMBERS;
|
|
pss->subsequent = 0;
|
|
pss->changed_partway = 0;
|
|
pss->member = lws_esp32.first;
|
|
break;
|
|
|
|
case GROUP_STATE_MEMBERS:
|
|
|
|
/* confirm pss->member is still in the list... */
|
|
|
|
mbr = lws_esp32.first;
|
|
while (mbr && mbr != pss->member)
|
|
mbr = mbr->next;
|
|
|
|
if (!mbr) { /* no longer exists... */
|
|
if (lws_esp32.first || pss->member)
|
|
pss->changed_partway = 1;
|
|
*p++ = ' ';
|
|
pss->member = NULL;
|
|
|
|
/*
|
|
* finish the list where we got to, then
|
|
* immediately reissue it
|
|
*/
|
|
}
|
|
|
|
while (end - p > 100 && pss->member) {
|
|
|
|
if (pss->subsequent)
|
|
*p++ = ',';
|
|
|
|
pss->subsequent = 1;
|
|
render_ip4(ipv4, sizeof(ipv4), (uint8_t *)&pss->member->addr);
|
|
|
|
p += snprintf((char *)p, end - p,
|
|
" {\n"
|
|
" \"mac\":\"%s\",\n"
|
|
" \"model\":\"%s\",\n"
|
|
" \"role\":\"%s\",\n"
|
|
" \"width\":\"%d\",\n"
|
|
" \"height\":\"%d\",\n"
|
|
" \"ipv4\":\"%s\"\n"
|
|
" }\n",
|
|
pss->member->mac,
|
|
pss->member->model,
|
|
pss->member->role,
|
|
pss->member->width,
|
|
pss->member->height,
|
|
ipv4
|
|
);
|
|
pss->member = pss->member->next;
|
|
}
|
|
|
|
lwsl_notice("%s\n", p);
|
|
|
|
n = LWS_WRITE_CONTINUATION | LWS_WRITE_NO_FIN;
|
|
if (!pss->member)
|
|
pss->group_state = GROUP_STATE_FINAL;
|
|
break;
|
|
|
|
case GROUP_STATE_FINAL:
|
|
n = LWS_WRITE_CONTINUATION;
|
|
p += sprintf((char *)p, "],\n \"discard\":\"%d\"}\n",
|
|
pss->changed_partway);
|
|
if (pss->changed_partway)
|
|
pss->group_state = GROUP_STATE_INITIAL;
|
|
else
|
|
pss->group_state = GROUP_STATE_NONE;
|
|
break;
|
|
default:
|
|
return 0;
|
|
}
|
|
// lwsl_notice("issue: %d (%d)\n", p - start, n);
|
|
m = lws_write(wsi, (unsigned char *)start, p - start, n);
|
|
if (m < 0) {
|
|
lwsl_err("ERROR %d writing to di socket\n", m);
|
|
return -1;
|
|
}
|
|
|
|
if (pss->group_state != GROUP_STATE_NONE)
|
|
lws_callback_on_writable(wsi);
|
|
|
|
break;
|
|
|
|
case LWS_CALLBACK_RECEIVE:
|
|
{
|
|
break;
|
|
}
|
|
|
|
case LWS_CALLBACK_CLOSED:
|
|
{
|
|
struct per_session_data__lws_group **p = &vhd->live_pss_list;
|
|
|
|
while (*p) {
|
|
if ((*p) == pss) {
|
|
*p = pss->next;
|
|
continue;
|
|
}
|
|
|
|
p = &((*p)->next);
|
|
}
|
|
|
|
vhd->count_live_pss--;
|
|
}
|
|
break;
|
|
|
|
case LWS_CALLBACK_HTTP_DROP_PROTOCOL:
|
|
/* called when our wsi user_space is going to be destroyed */
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
#define LWS_PLUGIN_PROTOCOL_LWS_GROUP \
|
|
{ \
|
|
"lws-group", \
|
|
callback_lws_group, \
|
|
sizeof(struct per_session_data__lws_group), \
|
|
1024, 0, NULL, 900 \
|
|
}
|
|
|