15
15
#include " eppp_link.h"
16
16
#include " wifi_remote_rpc_params.h"
17
17
#include " lwip/apps/snmp.h"
18
+ #include " esp_vfs.h"
19
+ #include " esp_vfs_eventfd.h"
18
20
19
21
extern " C" esp_netif_t *wifi_remote_eppp_init (eppp_type_t role);
20
22
@@ -32,7 +34,74 @@ const unsigned char key[] = "-----BEGIN PRIVATE KEY-----\n" CONFIG_ESP_WIFI_REMO
32
34
33
35
using namespace server ;
34
36
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
+
35
103
class RpcInstance {
104
+ friend class Sync ;
36
105
public:
37
106
RpcEngine rpc{role::SERVER};
38
107
int sock{-1 };
@@ -43,11 +112,12 @@ class RpcInstance {
43
112
ESP_RETURN_ON_ERROR (start_server (), TAG, " Failed to start RPC server" );
44
113
ESP_RETURN_ON_ERROR (rpc.init (), TAG, " Failed to init RPC engine" );
45
114
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" );
46
116
ESP_RETURN_ON_ERROR (esp_event_handler_register (WIFI_EVENT, ESP_EVENT_ANY_ID, handler, this ), TAG, " Failed to register event" );
47
117
ESP_RETURN_ON_ERROR (esp_event_handler_register (IP_EVENT, ESP_EVENT_ANY_ID, handler, this ), TAG, " Failed to register event" );
48
118
return xTaskCreate (task, " server" , 8192 , this , 5 , nullptr ) == pdTRUE ? ESP_OK : ESP_FAIL;
49
119
}
50
-
120
+ Sync sync;
51
121
private:
52
122
esp_netif_t *netif{nullptr };
53
123
static void task (void *ctx)
@@ -81,23 +151,24 @@ class RpcInstance {
81
151
esp_err_t wifi_event (int32_t id)
82
152
{
83
153
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" );
85
156
return ESP_OK;
86
157
}
87
158
esp_err_t ip_event (int32_t id, ip_event_got_ip_t *ip_data)
88
159
{
89
160
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 };
92
162
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" );
98
169
ESP_LOGI (TAG, " IP address:" IPSTR, IP2STR (&ip_data->ip_info .ip ));
99
170
}
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" );
101
172
return ESP_OK;
102
173
}
103
174
static void handler (void *ctx, esp_event_base_t base, int32_t id, void *data)
@@ -110,11 +181,83 @@ class RpcInstance {
110
181
instance->ip_event (id, ip_data);
111
182
}
112
183
}
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
+ }
113
236
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 ()
114
258
{
115
259
auto header = rpc.get_header ();
116
260
ESP_LOGI (TAG, " Received header id %d" , (int ) header.id );
117
-
118
261
switch (header.id ) {
119
262
case api_id::SET_MODE: {
120
263
auto req = rpc.get_payload <wifi_mode_t >(api_id::SET_MODE, header);
0 commit comments