1515#include " eppp_link.h"
1616#include " wifi_remote_rpc_params.h"
1717#include " lwip/apps/snmp.h"
18+ #include " esp_vfs.h"
19+ #include " esp_vfs_eventfd.h"
1820
1921extern " C" esp_netif_t *wifi_remote_eppp_init (eppp_type_t role);
2022
@@ -32,7 +34,74 @@ const unsigned char key[] = "-----BEGIN PRIVATE KEY-----\n" CONFIG_ESP_WIFI_REMO
3234
3335using namespace server ;
3436
37+ struct Events {
38+ api_id type;
39+ int32_t id;
40+ esp_wifi_remote_eppp_ip_event *ip_data{nullptr };
41+ bool clean_ip_data{true };
42+ esp_err_t create_ip_data ()
43+ {
44+ ip_data = new (std::nothrow) esp_wifi_remote_eppp_ip_event;
45+ return ip_data ? ESP_OK : ESP_ERR_NO_MEM;
46+ }
47+ ~Events ()
48+ {
49+ if (clean_ip_data) {
50+ delete ip_data;
51+ }
52+ }
53+ };
54+
55+ class Sync {
56+ friend class RpcInstance ;
57+ public:
58+ esp_err_t put (Events &ev)
59+ {
60+ ESP_RETURN_ON_FALSE (xQueueSend (queue, &ev, pdMS_TO_TICKS (queue_timeout)), ESP_FAIL, TAG, " Failed to queue event %" PRIi32, ev.id );
61+ ev.clean_ip_data = false ; // IP data were successfully sent to the queue, will free manually after receiving from it
62+ uint64_t event_queued = 1 ;
63+ write (fd, &event_queued, sizeof (event_queued)); // trigger the wait loop that
64+ return ESP_OK;
65+ }
66+ Events get ()
67+ {
68+ Events ev{};
69+ if (!xQueueReceive (queue, &ev, 0 )) {
70+ ev.type = api_id::ERROR;
71+ }
72+ return ev;
73+ }
74+ esp_err_t init ()
75+ {
76+ queue = xQueueCreate (max_items, sizeof (Events));
77+ esp_vfs_eventfd_config_t config = ESP_VFS_EVENTD_CONFIG_DEFAULT ();
78+ esp_vfs_eventfd_register (&config);
79+ fd = eventfd (0 , EFD_SUPPORT_ISR);
80+ return queue == nullptr || fd < 0 ? ESP_ERR_NO_MEM : ESP_OK;
81+ }
82+ ~Sync ()
83+ {
84+ if (queue) {
85+ vQueueDelete (queue);
86+ }
87+ if (fd >= 0 ) {
88+ close (fd);
89+ }
90+ }
91+ int fd{-1 };
92+ // Used to trigger task by either an internal event or rpc command
93+ static const int NONE = 0 ;
94+ static const int ERROR = 1 ;
95+ static const int EVENT = 2 ;
96+ static const int RPC = 4 ;
97+ private:
98+ QueueHandle_t queue{nullptr };
99+ const int max_items = 15 ;
100+ const int queue_timeout = 200 ;
101+ };
102+
35103class RpcInstance {
104+ friend class Sync ;
36105public:
37106 RpcEngine rpc{role::SERVER};
38107 int sock{-1 };
@@ -43,11 +112,12 @@ class RpcInstance {
43112 ESP_RETURN_ON_ERROR (start_server (), TAG, " Failed to start RPC server" );
44113 ESP_RETURN_ON_ERROR (rpc.init (), TAG, " Failed to init RPC engine" );
45114 ESP_RETURN_ON_ERROR (esp_netif_napt_enable (netif), TAG, " Failed to enable NAPT" );
115+ ESP_RETURN_ON_ERROR (sync.init (), TAG, " Failed to init event queue" );
46116 ESP_RETURN_ON_ERROR (esp_event_handler_register (WIFI_EVENT, ESP_EVENT_ANY_ID, handler, this ), TAG, " Failed to register event" );
47117 ESP_RETURN_ON_ERROR (esp_event_handler_register (IP_EVENT, ESP_EVENT_ANY_ID, handler, this ), TAG, " Failed to register event" );
48118 return xTaskCreate (task, " server" , 8192 , this , 5 , nullptr ) == pdTRUE ? ESP_OK : ESP_FAIL;
49119 }
50-
120+ Sync sync;
51121private:
52122 esp_netif_t *netif{nullptr };
53123 static void task (void *ctx)
@@ -81,23 +151,24 @@ class RpcInstance {
81151 esp_err_t wifi_event (int32_t id)
82152 {
83153 ESP_LOGI (TAG, " Received WIFI event %" PRIi32, id);
84- ESP_RETURN_ON_ERROR (rpc.send (api_id::WIFI_EVENT, &id), TAG, " Failed to marshall WiFi event" );
154+ Events ev{api_id::WIFI_EVENT, id, nullptr };
155+ ESP_RETURN_ON_ERROR (sync.put (ev), TAG, " Failed to queue WiFi event" );
85156 return ESP_OK;
86157 }
87158 esp_err_t ip_event (int32_t id, ip_event_got_ip_t *ip_data)
88159 {
89160 ESP_LOGI (TAG, " Received IP event %" PRIi32, id);
90- esp_wifi_remote_eppp_ip_event ip_event{};
91- ip_event.id = id;
161+ Events ev{api_id::IP_EVENT, id, nullptr };
92162 if (ip_data->esp_netif ) {
93- // marshall additional data, only if netif available
94- ESP_RETURN_ON_ERROR (esp_netif_get_dns_info (ip_data->esp_netif , ESP_NETIF_DNS_MAIN, &ip_event.dns ), TAG, " Failed to get DNS info" );
95- ESP_LOGI (TAG, " Main DNS:" IPSTR, IP2STR (&ip_event.dns .ip .u_addr .ip4 ));
96- memcpy (&ip_event.wifi_ip , &ip_data->ip_info , sizeof (ip_event.wifi_ip ));
97- ESP_RETURN_ON_ERROR (esp_netif_get_ip_info (netif, &ip_event.ppp_ip ), TAG, " Failed to get IP info" );
163+ ESP_RETURN_ON_ERROR (ev.create_ip_data (), TAG, " Failed to allocate event data" );
164+ ev.ip_data ->id = id;
165+ ESP_RETURN_ON_ERROR (esp_netif_get_dns_info (ip_data->esp_netif , ESP_NETIF_DNS_MAIN, &ev.ip_data ->dns ), TAG, " Failed to get DNS info" );
166+ ESP_LOGI (TAG, " Main DNS:" IPSTR, IP2STR (&ev.ip_data ->dns .ip .u_addr .ip4 ));
167+ memcpy (&ev.ip_data ->wifi_ip , &ip_data->ip_info , sizeof (ev.ip_data ->wifi_ip ));
168+ ESP_RETURN_ON_ERROR (esp_netif_get_ip_info (netif, &ev.ip_data ->ppp_ip ), TAG, " Failed to get IP info" );
98169 ESP_LOGI (TAG, " IP address:" IPSTR, IP2STR (&ip_data->ip_info .ip ));
99170 }
100- ESP_RETURN_ON_ERROR (rpc. send (api_id::IP_EVENT, &ip_event ), TAG, " Failed to marshal IP event" );
171+ ESP_RETURN_ON_ERROR (sync. put (ev ), TAG, " Failed to queue IP event" );
101172 return ESP_OK;
102173 }
103174 static void handler (void *ctx, esp_event_base_t base, int32_t id, void *data)
@@ -110,11 +181,83 @@ class RpcInstance {
110181 instance->ip_event (id, ip_data);
111182 }
112183 }
184+ int select ()
185+ {
186+ struct timeval timeout = { .tv_sec = 1 , .tv_usec = 0 };
187+ int rpc_sock = rpc.get_socket_fd ();
188+
189+ ESP_RETURN_ON_FALSE (rpc_sock != -1 , Sync::ERROR, TAG, " failed ot get rpc socket" );
190+ fd_set readset;
191+ fd_set errset;
192+ FD_ZERO (&readset);
193+ FD_ZERO (&errset);
194+ FD_SET (rpc_sock, &readset);
195+ FD_SET (sync.fd , &readset);
196+ FD_SET (rpc_sock, &errset);
197+ int ret = ::select (std::max (rpc_sock, 5 ) + 1 , &readset, nullptr , &errset, &timeout);
198+ if (ret == 0 ) {
199+ ESP_LOGV (TAG, " poll_read: select - Timeout before any socket was ready!" );
200+ return Sync::NONE;
201+ }
202+ if (ret < 0 ) {
203+ ESP_LOGE (TAG, " select error: %d" , errno);
204+ return Sync::ERROR;
205+ }
206+ if (FD_ISSET (rpc_sock, &errset)) {
207+ int sock_errno = 0 ;
208+ uint32_t optlen = sizeof (sock_errno);
209+ getsockopt (rpc_sock, SOL_SOCKET, SO_ERROR, &sock_errno, &optlen);
210+ ESP_LOGE (TAG, " select failed, socket errno = %d" , sock_errno);
211+ return Sync::ERROR;
212+ }
213+ int result = Sync::NONE;
214+ if (FD_ISSET (rpc_sock, &readset)) {
215+ result |= Sync::RPC;
216+ }
217+ if (FD_ISSET (sync.fd , &readset)) {
218+ result |= Sync::EVENT;
219+ }
220+ return result;
221+ }
222+ esp_err_t marshall_events ()
223+ {
224+ api_id type;
225+ do {
226+ Events ev = sync.get ();
227+ type = ev.type ;
228+ if (ev.type == api_id::WIFI_EVENT) {
229+ ESP_RETURN_ON_ERROR (rpc.send (api_id::WIFI_EVENT, &ev.id ), TAG, " Failed to marshall WiFi event" );
230+ } else if (ev.type == api_id::IP_EVENT && ev.ip_data ) {
231+ ESP_RETURN_ON_ERROR (rpc.send (api_id::IP_EVENT, ev.ip_data ), TAG, " Failed to marshal IP event" );
232+ }
233+ } while (type != api_id::ERROR);
234+ return ESP_OK;
235+ }
113236 esp_err_t perform ()
237+ {
238+ auto res = select ();
239+ if (res == Sync::ERROR) {
240+ return ESP_FAIL;
241+ }
242+ if (res & Sync::EVENT) {
243+ uint64_t data;
244+ read (sync.fd , &data, sizeof (data));
245+ if (marshall_events () != ESP_OK) {
246+ return ESP_FAIL;
247+ }
248+ }
249+ if (res & Sync::RPC) {
250+ if (handle_commands () != ESP_OK) {
251+ return ESP_FAIL;
252+ }
253+ }
254+ return ESP_OK;
255+ }
256+
257+ esp_err_t handle_commands ()
114258 {
115259 auto header = rpc.get_header ();
116260 ESP_LOGI (TAG, " Received header id %d" , (int ) header.id );
117-
118261 switch (header.id ) {
119262 case api_id::SET_MODE: {
120263 auto req = rpc.get_payload <wifi_mode_t >(api_id::SET_MODE, header);
0 commit comments