Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initialize SoftAP DhcpServer object on demand #8546

Merged
merged 21 commits into from
Jun 1, 2022
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 67 additions & 36 deletions cores/esp8266/LwipDhcpServer-NonOS.cpp
Original file line number Diff line number Diff line change
@@ -1,63 +1,94 @@
/*
lwIPDhcpServer-NonOS.cpp - DHCP server wrapper
NonOS DHCP server helpers

Copyright (c) 2020 esp8266 arduino. All rights reserved.
Copyright (c) 2020-2022 esp8266 arduino. All rights reserved.
This file is part of the esp8266 core for Arduino environment.

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; either
version 2.1 of the License, or (at your option) any later version.

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 St, Fifth Floor, Boston, MA 02110-1301 USA
*/

// STARTS/STOPS DHCP SERVER ON WIFI AP INTERFACE
// these functions must exists as-is with "C" interface,
// nonos-sdk calls them at boot time and later

#include <lwip/init.h> // LWIP_VERSION
#include "LwipDhcpServer-NonOS.h"

#include <lwip/init.h>
#include <lwip/netif.h>
#include "LwipDhcpServer.h"

extern netif netif_git[2];

// global DHCP instance for softAP interface
DhcpServer dhcpSoftAP(&netif_git[SOFTAP_IF]);
// Global static DHCP instance for softAP interface
// (since the netif object never goes away, even when AP is disabled)
// Initial version fully emulates nonos-sdk api in DhcpServer class,
// before trying to further change it and possibly break legacy behaviour
DhcpServer& getNonOSDhcpServer()
{
extern netif netif_git[2];
static DhcpServer server(&netif_git[SOFTAP_IF]);
return server;
}

extern "C"
{
void dhcps_start(struct ip_info* info, netif* apnetif)
// `ip_info` is useless, since we get the information from the netif directly
// `netif` would be netif_git[SOFTAP_IF], which we get from the lwip2 glue
void dhcps_start(ip_info*, netif*)
{
auto& server = getNonOSDhcpServer();
if (!server.isRunning())
{
server.begin();
}
}

void dhcps_stop() {
auto& server = getNonOSDhcpServer();
if (server.isRunning())
{
server.end();
}
}

// providing the rest of the nonos-sdk API, which was originally removed in 3.0.0

bool wifi_softap_set_dhcps_lease(dhcps_lease* please)
{
auto& server = getNonOSDhcpServer();
return server.set_dhcps_lease(please);
}

bool wifi_softap_get_dhcps_lease(dhcps_lease* please)
{
// apnetif is esp interface, replaced by lwip2's
// netif_git[SOFTAP_IF] interface in constructor
(void)apnetif;

#if 0
// can't use C++ now, global ctors are not initialized yet
dhcpSoftAP.begin(info);
#else
(void)info;
// initial version: emulate nonos-sdk in DhcpServer class before
// trying to change legacy behavor
// `fw_has_started_softap_dhcps` will be read in DhcpServer::DhcpServer
// which is called when c++ ctors are initialized, specifically
// dhcpSoftAP initialized with AP interface number above.
fw_has_started_softap_dhcps = 1;
#endif
}

void dhcps_stop()
auto& server = getNonOSDhcpServer();
return server.get_dhcps_lease(please);
}

uint32 wifi_softap_get_dhcps_lease_time()
{
auto& server = getNonOSDhcpServer();
return server.get_dhcps_lease_time();
}

bool wifi_softap_set_dhcps_lease_time(uint32 minutes)
{
auto& server = getNonOSDhcpServer();
return server.set_dhcps_lease_time(minutes);
}

bool wifi_softap_reset_dhcps_lease_time()
{
auto& server = getNonOSDhcpServer();
return server.reset_dhcps_lease_time();
}

bool wifi_softap_add_dhcps_lease(uint8* macaddr)
{
dhcpSoftAP.end();
auto& server = getNonOSDhcpServer();
return server.add_dhcps_lease(macaddr);
}

} // extern "C"
24 changes: 24 additions & 0 deletions cores/esp8266/LwipDhcpServer-NonOS.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
NonOS DHCP server helpers

Copyright (c) 2020-2022 esp8266 arduino. All rights reserved.
This file is part of the esp8266 core for Arduino environment.
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; either
version 2.1 of the License, or (at your option) any later version.
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 St, Fifth Floor, Boston, MA 02110-1301 USA
*/

#pragma once

#include "LwipDhcpServer.h"

// Global static DHCP instance for softAP interface
DhcpServer& getNonOSDhcpServer();
57 changes: 12 additions & 45 deletions cores/esp8266/LwipDhcpServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,6 @@

#include <lwip/init.h> // LWIP_VERSION

#define DHCPS_LEASE_TIME_DEF (120)

#define USE_DNS

#include "lwip/inet.h"
Expand Down Expand Up @@ -166,7 +164,7 @@ const char mem_debug_file[] ICACHE_RODATA_ATTR = __FILE__;
int ret = 1, errval = (err); \
if (errval != ERR_OK) \
{ \
os_printf("DHCPS ERROR: %s (lwip:%d)\n", what, errval); \
os_printf("DHCPS ERROR: %s (lwip:%s(%d))\n", what, lwip_strerr(errval), errval); \
ret = 0; \
} \
ret; \
Expand All @@ -175,36 +173,9 @@ const char mem_debug_file[] ICACHE_RODATA_ATTR = __FILE__;
#define LWIP_IS_OK(what, err) ((err) == ERR_OK)
#endif

const uint32 DhcpServer::magic_cookie = 0x63538263; // https://tools.ietf.org/html/rfc1497

int fw_has_started_softap_dhcps = 0;

////////////////////////////////////////////////////////////////////////////////////

DhcpServer::DhcpServer(netif* netif) : _netif(netif)
{
pcb_dhcps = nullptr;
dns_address.addr = 0;
plist = nullptr;
offer = 0xFF;
renew = false;
dhcps_lease_time = DHCPS_LEASE_TIME_DEF; // minute

if (netif->num == SOFTAP_IF && fw_has_started_softap_dhcps == 1)
{
// When nonos-sdk starts DHCPS at boot:
// 1. `fw_has_started_softap_dhcps` is already initialized to 1
// 2. global ctor DhcpServer's `dhcpSoftAP(&netif_git[SOFTAP_IF])` is called
// 3. (that's here) => begin(legacy-values) is called
ip_info ip = {
{ 0x0104a8c0 }, // IP 192.168.4.1
{ 0x00ffffff }, // netmask 255.255.255.0
{ 0 } // gateway 0.0.0.0
};
begin(&ip);
fw_has_started_softap_dhcps = 2; // not 1, ending initial boot sequence
}
};
DhcpServer::DhcpServer(netif* netif) : _netif(netif) { }

// wifi_softap_set_station_info is missing in user_interface.h:
extern "C" void wifi_softap_set_station_info(uint8_t* mac, struct ipv4_addr*);
Expand Down Expand Up @@ -516,7 +487,7 @@ void DhcpServer::create_msg(struct dhcps_msg* m)
memset((char*)m->sname, 0, sizeof(m->sname));
memset((char*)m->file, 0, sizeof(m->file));
memset((char*)m->options, 0, sizeof(m->options));
memcpy((char*)m->options, &magic_cookie, sizeof(magic_cookie));
memcpy((char*)m->options, &MagicCookie, sizeof(MagicCookie));
}
///////////////////////////////////////////////////////////////////////////////////
/*
Expand Down Expand Up @@ -821,7 +792,7 @@ uint8_t DhcpServer::parse_options(uint8_t* optptr, sint16_t len)
///////////////////////////////////////////////////////////////////////////////////
sint16_t DhcpServer::parse_msg(struct dhcps_msg* m, u16_t len)
{
if (memcmp((char*)m->options, &magic_cookie, sizeof(magic_cookie)) == 0)
if (memcmp((char*)m->options, &MagicCookie, sizeof(MagicCookie)) == 0)
{
struct ipv4_addr ip;
memcpy(&ip.addr, m->ciaddr, sizeof(ip.addr));
Expand Down Expand Up @@ -1008,17 +979,19 @@ void DhcpServer::init_dhcps_lease(uint32 ip)
}
///////////////////////////////////////////////////////////////////////////////////

bool DhcpServer::begin(struct ip_info* info)
bool DhcpServer::begin()
{
if (pcb_dhcps != nullptr)
{
udp_remove(pcb_dhcps);
}

pcb_dhcps = udp_new();
if (pcb_dhcps == nullptr || info == nullptr)
if (pcb_dhcps == nullptr)
{
#if DHCPS_DEBUG
os_printf("dhcps_start(): could not obtain pcb\n");
#endif
return false;
}

Expand All @@ -1030,7 +1003,7 @@ bool DhcpServer::begin(struct ip_info* info)
ip_2_ip4(&broadcast_dhcps)->addr |= ~ip_2_ip4(&_netif->netmask)->addr;
// XXXFIXMEIPV6 broadcast address?

server_address = info->ip;
server_address = *ip_2_ip4(&_netif->ip_addr);
init_dhcps_lease(server_address.addr);

udp_bind(pcb_dhcps, IP_ADDR_ANY, DHCPS_SERVER_PORT);
Expand All @@ -1040,12 +1013,6 @@ bool DhcpServer::begin(struct ip_info* info)
"pcb_dhcps\n");
#endif

if (_netif->num == SOFTAP_IF)
{
wifi_set_ip_info(SOFTAP_IF, info); // added for lwip-git, not sure whether useful
}
_netif->flags |= NETIF_FLAG_UP | NETIF_FLAG_LINK_UP; // added for lwip-git

return true;
}

Expand Down Expand Up @@ -1091,9 +1058,9 @@ void DhcpServer::end()
}
}

bool DhcpServer::isRunning()
bool DhcpServer::isRunning() const
{
return !!_netif->state;
return pcb_dhcps != nullptr;
}

/******************************************************************************
Expand Down Expand Up @@ -1342,7 +1309,7 @@ bool DhcpServer::reset_dhcps_lease_time(void)
{
return false;
}
dhcps_lease_time = DHCPS_LEASE_TIME_DEF;
dhcps_lease_time = DefaultLeaseTime;
return true;
}

Expand Down
34 changes: 14 additions & 20 deletions cores/esp8266/LwipDhcpServer.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,22 +28,24 @@
// nearly as-is. This is an initial version to guaranty legacy behavior
// with same default values.

#ifndef __DHCPS_H__
#define __DHCPS_H__
#pragma once

#include <lwip/init.h> // LWIP_VERSION

class DhcpServer
{
public:
DhcpServer(netif* netif);
static constexpr int DefaultLeaseTime = 720; // minutes
static constexpr uint32 MagicCookie = 0x63538263; // https://tools.ietf.org/html/rfc1497

DhcpServer(netif*);
~DhcpServer();

void setDns(int num, const ipv4_addr_t* dns);

bool begin(ip_info* info);
bool begin();
void end();
bool isRunning();
bool isRunning() const;

// this is the C interface encapsulated in a class
// (originally dhcpserver.c in lwIP-v1.4 in NonOS-SDK)
Expand Down Expand Up @@ -91,25 +93,17 @@ class DhcpServer
void dhcps_client_leave(u8* bssid, struct ipv4_addr* ip, bool force);
uint32 dhcps_client_update(u8* bssid, struct ipv4_addr* ip);

netif* _netif;
netif* _netif = nullptr;

struct udp_pcb* pcb_dhcps;
ip_addr_t broadcast_dhcps;
struct ipv4_addr server_address;
struct ipv4_addr client_address;
struct ipv4_addr dns_address;
uint32 dhcps_lease_time;
udp_pcb* pcb_dhcps = nullptr;
ip_addr_t broadcast_dhcps {};
ipv4_addr server_address {};
ipv4_addr client_address {};
ipv4_addr dns_address {};
uint32 dhcps_lease_time = DefaultLeaseTime;

struct dhcps_lease dhcps_lease;
list_node* plist;
uint8 offer;
bool renew;

static const uint32 magic_cookie;
};

// SoftAP DHCP server always exists and is started on boot
extern DhcpServer dhcpSoftAP;
extern "C" int fw_has_started_softap_dhcps;

#endif // __DHCPS_H__
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,6 @@
#include <ESP8266WiFi.h>
#include <lwip/napt.h>
#include <lwip/dns.h>
#include <dhcpserver.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <DNSServer.h>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
#include <ESP8266WiFi.h>
#include <lwip/napt.h>
#include <lwip/dns.h>
#include <LwipDhcpServer.h>

#define NAPT 1000
#define NAPT_PORT 10
Expand Down Expand Up @@ -54,8 +53,9 @@ void setup() {
Serial.printf("\nSTA: %s (dns: %s / %s)\n", WiFi.localIP().toString().c_str(), WiFi.dnsIP(0).toString().c_str(), WiFi.dnsIP(1).toString().c_str());

// give DNS servers to AP side
dhcpSoftAP.dhcps_set_dns(0, WiFi.dnsIP(0));
dhcpSoftAP.dhcps_set_dns(1, WiFi.dnsIP(1));
auto& server = WiFi.softAPDhcpServer();
server.dhcps_set_dns(0, WiFi.dnsIP(0));
server.dhcps_set_dns(1, WiFi.dnsIP(1));

WiFi.softAPConfig( // enable AP, with android-compatible google domain
IPAddress(172, 217, 28, 254), IPAddress(172, 217, 28, 254), IPAddress(255, 255, 255, 0));
Expand Down
Loading