TinyPPP
PPP networking over any Arduino Stream
Loading...
Searching...
No Matches
TinyPPP_ESP32.h
Go to the documentation of this file.
1#pragma once
15#include <Arduino.h>
16#include <Network.h>
17
18#include "esp_event.h"
19#include "esp_netif.h"
20#include "esp_netif_ppp.h"
21#include "freertos/FreeRTOS.h"
22#include "freertos/task.h"
23
24#ifndef TINYPPP_RX_BUFFER
25#define TINYPPP_RX_BUFFER 512
26#endif
27
28namespace tinyppp {
29
34
39class TinyPPP_ESP32 : public NetworkInterface {
40 public:
41 TinyPPP_ESP32() = default;
42 TinyPPP_ESP32(const TinyPPP_ESP32 &) = delete;
45
53 if (_esp_netif != nullptr) end();
54 _io = &io;
55
56 Network.begin();
57
59 &pppEventCb, this,
61 log_e("register NETIF_PPP_STATUS failed");
62 return false;
63 }
64
67 if (_esp_netif == nullptr) {
68 log_e("esp_netif_new failed");
69 end();
70 return false;
71 }
72 // receive the IP events of the Network library
74
75 _driver.base.post_attach = postAttach;
76 _driver.self = this;
78 log_e("esp_netif_attach failed");
79 end();
80 return false;
81 }
82
83 if (_user.length() > 0) {
85 _password.c_str());
86 }
87
88 _running = true;
89 _stopping = false;
90 _restartAt = 0;
91 if (xTaskCreatePinnedToCore(rxTask, "TinyPPP", 4096, this, taskPriority,
92 &_task, core) != pdPASS) {
93 log_e("task creation failed");
94 end();
95 return false;
96 }
97
100 esp_netif_action_start(_esp_netif, nullptr, 0, nullptr);
101 return true;
102 }
103
105 void end() {
106 if (_esp_netif != nullptr && _running) {
107 _stopping = true;
109 esp_netif_action_stop(_esp_netif, nullptr, 0, nullptr);
110 // the reader task must run to receive the Terminate-Ack
112 pdMS_TO_TICKS(5000));
113 }
114 if (_task != nullptr) {
115 _running = false;
116 for (int i = 0; i < 100 && _task != nullptr; i++) delay(10);
117 }
119 if (_esp_netif != nullptr) {
124 destroyNetif();
125 }
126 if (_pppEventInstance != nullptr) {
129 _pppEventInstance = nullptr;
130 }
131 }
132
134 void setCredentials(const char *user, const char *password) {
135 _user = user ? user : "";
136 _password = password ? password : "";
137 }
138
140 void setLogger(Print &out) { _log = &out; }
141
144 if (_esp_netif == nullptr) return false;
147 }
148
150 bool connected() const { return _esp_netif != nullptr && hasIP(); }
151
152 protected:
153 static constexpr EventBits_t DEAD_BIT = BIT0;
154
155 struct Driver {
156 esp_netif_driver_base_t base; // must be the first member
158 };
159
161 Stream *_io = nullptr;
162 Print *_log = nullptr;
166 volatile bool _running = false;
167 volatile bool _stopping = false;
168 volatile uint32_t _restartAt = 0;
171
173 if (_eventGroup == nullptr) _eventGroup = xEventGroupCreate();
174 return _eventGroup;
175 }
176
177 size_t printDriverInfo(Print &out) const override {
178 return out.print(",TinyPPP");
179 }
180
183 event.event_id = id;
184 Network.postEvent(&event);
185 }
186
187 // esp_netif driver: called by esp_netif_attach()
190 driver->base.netif = netif;
192 ifconfig.handle = handle;
193 ifconfig.transmit = transmit;
195 if (rc != ESP_OK) return rc;
198 pppConfig.ppp_phase_event_enabled = true;
199 pppConfig.ppp_error_event_enabled = true;
201 }
202
203 // esp_netif driver: output of the PPP stack (called from the lwIP task)
204 static esp_err_t transmit(void *handle, void *buffer, size_t len) {
205 TinyPPP_ESP32 *self = ((Driver *)handle)->self;
206 if (self->_io == nullptr) return ESP_FAIL;
207 const uint8_t *data = (const uint8_t *)buffer;
208 size_t done = 0;
209 for (int retry = 0; retry < 100 && done < len; retry++) {
210 size_t n = self->_io->write(data + done, len - done);
211 done += n;
212 if (n == 0) vTaskDelay(1);
213 }
214 return done == len ? ESP_OK : ESP_FAIL;
215 }
216
217 // reads the stream and feeds the PPP stack
218 static void rxTask(void *arg) {
221 while (self->_running) {
222 int avail = self->_io->available();
223 if (avail > 0) {
224 size_t n = self->_io->readBytes(
225 buffer, (size_t)avail < sizeof(buffer) ? (size_t)avail : sizeof(buffer));
226 if (n > 0) esp_netif_receive(self->_esp_netif, buffer, n, nullptr);
227 } else {
228 vTaskDelay(1);
229 }
230 // restart the negotiation after the link was lost
232 if (restart != 0 && !self->_stopping &&
233 (int32_t)(millis() - restart) >= 0) {
234 self->_restartAt = 0;
235 self->log("restarting");
236 esp_netif_action_start(self->_esp_netif, nullptr, 0, nullptr);
237 }
238 }
239 self->_task = nullptr;
240 vTaskDelete(nullptr);
241 }
242
243 void log(const char *msg, int32_t id = -1) {
244 log_d("TinyPPP: %s (%d)", msg, (int)id);
245 if (_log == nullptr) return;
246 _log->print("PPP: ");
247 _log->print(msg);
248 if (id >= 0) {
249 _log->print(" (");
250 _log->print(id);
251 _log->print(")");
252 }
253 _log->println();
254 }
255
256 static void pppEventCb(void *arg, esp_event_base_t base, int32_t id,
257 void *data) {
259 // event data is a esp_netif_t** (except for NETIF_PPP_CONNECT_FAILED where
260 // ESP-IDF posts the netif struct itself: there is only one PPP slot anyway)
261 if (id != NETIF_PPP_CONNECT_FAILED) {
262 esp_netif_t *netif = data ? *(esp_netif_t **)data : nullptr;
263 if (netif != self->_esp_netif) return;
264 }
265 self->onPppEvent(id);
266 }
267
269 if (id == NETIF_PPP_ERRORNONE) {
270 log("connected");
274 }
275 } else if (id < NETIF_PP_PHASE_OFFSET) {
276 // error: the link is down
277 log("link down, error", id);
281 }
282 if (_stopping) {
284 } else {
285 _restartAt = millis() + 1000;
286 }
287 } else if (id == NETIF_PPP_PHASE_DEAD) {
288 log("phase dead");
290 } else if (id == NETIF_PPP_PHASE_RUNNING) {
291 log("phase running");
292 } else if (id == NETIF_PPP_PHASE_ESTABLISH) {
293 log("phase establish");
294 } else if (id == NETIF_PPP_PHASE_NETWORK) {
295 log("phase network");
296 } else if (id == NETIF_PPP_CONNECT_FAILED) {
297 log("connect failed");
298 if (!_stopping) _restartAt = millis() + 2000;
299 }
300 }
301};
302
305
306} // namespace tinyppp
#define TINYPPP_RX_BUFFER
Definition TinyPPP_ESP32.h:25
TCP client over PPP: used like WiFiClient or EthernetClient.
Definition PPPSockets.h:25
TCP server over PPP: used like WiFiServer or EthernetServer.
Definition PPPSockets.h:144
UDP socket over PPP: used like WiFiUDP or EthernetUDP.
Definition PPPSockets.h:206
Byte ring buffer with a fixed capacity of N bytes.
Definition IPStack.h:76
size_t available() const
Number of stored bytes.
Definition IPStack.h:79
size_t write(const uint8_t *data, size_t len)
Appends data: returns the number of bytes stored.
Definition IPStack.h:88
PPP network interface for ESP32 (arduino-esp32 3.x): ESP-IDF lwIP PPP via esp_netif,...
Definition TinyPPP_ESP32.h:39
static void rxTask(void *arg)
Definition TinyPPP_ESP32.h:218
volatile bool _stopping
Definition TinyPPP_ESP32.h:167
static void postEvent(arduino_event_id_t id)
Definition TinyPPP_ESP32.h:181
volatile uint32_t _restartAt
Definition TinyPPP_ESP32.h:168
String _user
Definition TinyPPP_ESP32.h:169
EventGroupHandle_t _events()
Definition TinyPPP_ESP32.h:172
esp_event_handler_instance_t _pppEventInstance
Definition TinyPPP_ESP32.h:164
static esp_err_t transmit(void *handle, void *buffer, size_t len)
Definition TinyPPP_ESP32.h:204
bool waitConnected(uint32_t timeoutMs=30000)
Waits until we have got an IP address.
Definition TinyPPP_ESP32.h:143
static void pppEventCb(void *arg, esp_event_base_t base, int32_t id, void *data)
Definition TinyPPP_ESP32.h:256
Driver _driver
Definition TinyPPP_ESP32.h:160
void log(const char *msg, int32_t id=-1)
Definition TinyPPP_ESP32.h:243
volatile bool _running
Definition TinyPPP_ESP32.h:166
void onPppEvent(int32_t id)
Definition TinyPPP_ESP32.h:268
void setCredentials(const char *user, const char *password)
PAP credentials, if the peer requires authentication (before begin())
Definition TinyPPP_ESP32.h:134
bool connected() const
true when the link is up and we have an IP address
Definition TinyPPP_ESP32.h:150
static constexpr EventBits_t DEAD_BIT
Definition TinyPPP_ESP32.h:153
Stream * _io
Definition TinyPPP_ESP32.h:161
TinyPPP_ESP32(const TinyPPP_ESP32 &)=delete
bool begin(Stream &io, UBaseType_t taskPriority=5, BaseType_t core=tskNO_AFFINITY)
Definition TinyPPP_ESP32.h:51
void end()
Terminates the link and removes the interface.
Definition TinyPPP_ESP32.h:105
size_t printDriverInfo(Print &out) const override
Definition TinyPPP_ESP32.h:177
void setLogger(Print &out)
Debug output of the PPP state changes, e.g. setLogger(Serial1)
Definition TinyPPP_ESP32.h:140
TinyPPP_ESP32 & operator=(const TinyPPP_ESP32 &)=delete
String _password
Definition TinyPPP_ESP32.h:170
EventGroupHandle_t _eventGroup
Definition TinyPPP_ESP32.h:165
~TinyPPP_ESP32()
Definition TinyPPP_ESP32.h:44
TaskHandle_t _task
Definition TinyPPP_ESP32.h:163
Print * _log
Definition TinyPPP_ESP32.h:162
static esp_err_t postAttach(esp_netif_t *netif, void *handle)
Definition TinyPPP_ESP32.h:188
TinyPPP internals: PPP engine, HDLC framing and the IP stack.
Definition HDLC.h:11
Definition TinyPPP_ESP32.h:155
TinyPPP_ESP32 * self
Definition TinyPPP_ESP32.h:157
esp_netif_driver_base_t base
Definition TinyPPP_ESP32.h:156