2 * ESP32 Group protocol handler
4 * Copyright (C) 2017 Andy Green <andy@warmcat.com>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation:
9 * version 2.1 of the License.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
24 #include <esp_ota_ops.h>
33 struct per_session_data__lws_group {
34 struct per_session_data__lws_group *next;
35 group_state group_state;
37 struct lws_group_member *member;
39 unsigned char subsequent:1;
40 unsigned char changed_partway:1;
43 struct per_vhost_data__lws_group {
44 struct per_session_data__lws_group *live_pss_list;
45 struct lws_context *context;
46 struct lws_vhost *vhost;
47 const struct lws_protocols *protocol;
51 static void render_ip4(char *dest, int len, uint8_t *ip)
53 snprintf(dest, len, "%u.%u.%u.%u", ip[0], ip[1], ip[2], ip[3]);
59 callback_lws_group(struct lws *wsi, enum lws_callback_reasons reason,
60 void *user, void *in, size_t len)
62 struct per_session_data__lws_group *pss =
63 (struct per_session_data__lws_group *)user;
64 struct per_vhost_data__lws_group *vhd =
65 (struct per_vhost_data__lws_group *)
66 lws_protocol_vh_priv_get(lws_get_vhost(wsi),
67 lws_get_protocol(wsi));
68 char buffer[1024 + LWS_PRE], ipv4[20];
69 char *start = buffer + LWS_PRE - 1, *p = start,
70 *end = buffer + sizeof(buffer) - 1;
71 struct lws_group_member *mbr;
76 case LWS_CALLBACK_PROTOCOL_INIT:
77 vhd = lws_protocol_vh_priv_zalloc(lws_get_vhost(wsi),
78 lws_get_protocol(wsi),
79 sizeof(struct per_vhost_data__lws_group));
80 vhd->context = lws_get_context(wsi);
81 vhd->protocol = lws_get_protocol(wsi);
82 vhd->vhost = lws_get_vhost(wsi);
85 case LWS_CALLBACK_PROTOCOL_DESTROY:
90 case LWS_CALLBACK_ESTABLISHED:
91 lwsl_notice("%s: ESTABLISHED\n", __func__);
92 vhd->count_live_pss++;
93 pss->next = vhd->live_pss_list;
94 vhd->live_pss_list = pss;
95 pss->group_state = GROUP_STATE_INITIAL;
96 lws_callback_on_writable(wsi);
99 case LWS_CALLBACK_SERVER_WRITEABLE:
101 switch (pss->group_state) {
103 case GROUP_STATE_NONE:
106 case GROUP_STATE_INITIAL:
108 p += snprintf((char *)p, end - p,
114 n = LWS_WRITE_TEXT | LWS_WRITE_NO_FIN;
115 pss->group_state = GROUP_STATE_MEMBERS;
117 pss->changed_partway = 0;
118 pss->member = lws_esp32.first;
121 case GROUP_STATE_MEMBERS:
123 /* confirm pss->member is still in the list... */
125 mbr = lws_esp32.first;
126 while (mbr && mbr != pss->member)
129 if (!mbr) { /* no longer exists... */
130 if (lws_esp32.first || pss->member)
131 pss->changed_partway = 1;
136 * finish the list where we got to, then
137 * immediately reissue it
141 while (end - p > 100 && pss->member) {
147 render_ip4(ipv4, sizeof(ipv4), (uint8_t *)&pss->member->addr);
149 p += snprintf((char *)p, end - p,
152 " \"model\":\"%s\",\n"
153 " \"role\":\"%s\",\n"
154 " \"width\":\"%d\",\n"
155 " \"height\":\"%d\",\n"
165 pss->member = pss->member->next;
168 lwsl_notice("%s\n", p);
170 n = LWS_WRITE_CONTINUATION | LWS_WRITE_NO_FIN;
172 pss->group_state = GROUP_STATE_FINAL;
175 case GROUP_STATE_FINAL:
176 n = LWS_WRITE_CONTINUATION;
177 p += sprintf((char *)p, "],\n \"discard\":\"%d\"}\n",
178 pss->changed_partway);
179 if (pss->changed_partway)
180 pss->group_state = GROUP_STATE_INITIAL;
182 pss->group_state = GROUP_STATE_NONE;
187 // lwsl_notice("issue: %d (%d)\n", p - start, n);
188 m = lws_write(wsi, (unsigned char *)start, p - start, n);
190 lwsl_err("ERROR %d writing to di socket\n", m);
194 if (pss->group_state != GROUP_STATE_NONE)
195 lws_callback_on_writable(wsi);
199 case LWS_CALLBACK_RECEIVE:
204 case LWS_CALLBACK_CLOSED:
206 struct per_session_data__lws_group **p = &vhd->live_pss_list;
217 vhd->count_live_pss--;
221 case LWS_CALLBACK_HTTP_DROP_PROTOCOL:
222 /* called when our wsi user_space is going to be destroyed */
232 #define LWS_PLUGIN_PROTOCOL_LWS_GROUP \
235 callback_lws_group, \
236 sizeof(struct per_session_data__lws_group), \