plugins: group
This commit is contained in:
parent
3cf570ec52
commit
8f16f92cac
1 changed files with 239 additions and 0 deletions
239
plugins/protocol_esp32_lws_group.c
Normal file
239
plugins/protocol_esp32_lws_group.c
Normal file
|
@ -0,0 +1,239 @@
|
|||
/*
|
||||
* ESP32 Group protocol handler
|
||||
*
|
||||
* Copyright (C) 2017 Andy Green <andy@warmcat.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation:
|
||||
* version 2.1 of the License.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
* MA 02110-1301 USA*
|
||||
*
|
||||
*/
|
||||
#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 \
|
||||
}
|
||||
|
Loading…
Add table
Reference in a new issue