1039 lines
31 KiB
C++
1039 lines
31 KiB
C++
|
/*
|
||
|
; Project: Open Vehicle Monitor System
|
||
|
; Date: 14th March 2017
|
||
|
;
|
||
|
; Changes:
|
||
|
; 1.0 Initial release
|
||
|
;
|
||
|
; (C) 2011 Michael Stegen / Stegen Electronics
|
||
|
; (C) 2011-2017 Mark Webb-Johnson
|
||
|
; (C) 2011 Sonny Chen @ EPRO/DX
|
||
|
;
|
||
|
; Permission is hereby granted, free of charge, to any person obtaining a copy
|
||
|
; of this software and associated documentation files (the "Software"), to deal
|
||
|
; in the Software without restriction, including without limitation the rights
|
||
|
; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||
|
; copies of the Software, and to permit persons to whom the Software is
|
||
|
; furnished to do so, subject to the following conditions:
|
||
|
;
|
||
|
; The above copyright notice and this permission notice shall be included in
|
||
|
; all copies or substantial portions of the Software.
|
||
|
;
|
||
|
; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||
|
; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||
|
; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||
|
; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||
|
; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||
|
; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||
|
; THE SOFTWARE.
|
||
|
*/
|
||
|
|
||
|
#include "ovms_log.h"
|
||
|
static const char *TAG = "netmanager";
|
||
|
|
||
|
#include <string.h>
|
||
|
#include <stdio.h>
|
||
|
#include <lwip/tcpip.h>
|
||
|
#include <lwip/ip_addr.h>
|
||
|
#include <lwip/netif.h>
|
||
|
#include <lwip/dns.h>
|
||
|
#include <netinet/in.h>
|
||
|
#include "metrics_standard.h"
|
||
|
#include "ovms_peripherals.h"
|
||
|
#include "ovms_netmanager.h"
|
||
|
#include "ovms_command.h"
|
||
|
#include "ovms_config.h"
|
||
|
#include "ovms_module.h"
|
||
|
|
||
|
#ifndef CONFIG_OVMS_NETMAN_TASK_PRIORITY
|
||
|
#define CONFIG_OVMS_NETMAN_TASK_PRIORITY 5
|
||
|
#endif
|
||
|
|
||
|
OvmsNetManager MyNetManager __attribute__ ((init_priority (8999)));
|
||
|
|
||
|
void network_status(int verbosity, OvmsWriter* writer, OvmsCommand* cmd, int argc, const char* const* argv)
|
||
|
{
|
||
|
struct netif *ni;
|
||
|
for (ni = netif_list; ni; ni = ni->next)
|
||
|
{
|
||
|
if (ni->name[0]=='l' && ni->name[1]=='o')
|
||
|
continue;
|
||
|
writer->printf("Interface#%d: %c%c%d (ifup=%d linkup=%d)\n",
|
||
|
ni->num,ni->name[0],ni->name[1],ni->num,
|
||
|
((ni->flags & NETIF_FLAG_UP) != 0),
|
||
|
((ni->flags & NETIF_FLAG_LINK_UP) != 0));
|
||
|
writer->printf(" IPv4: " IPSTR "/" IPSTR " gateway " IPSTR "\n",
|
||
|
IP2STR(&ni->ip_addr.u_addr.ip4), IP2STR(&ni->netmask.u_addr.ip4), IP2STR(&ni->gw.u_addr.ip4));
|
||
|
writer->puts("");
|
||
|
}
|
||
|
|
||
|
writer->printf("DNS:");
|
||
|
int dnsservers = 0;
|
||
|
for (int k=0;k<DNS_MAX_SERVERS;k++)
|
||
|
{
|
||
|
const ip_addr_t* srv = dns_getserver(k);
|
||
|
if (! ip_addr_isany(srv))
|
||
|
{
|
||
|
dnsservers++;
|
||
|
if (srv->type == IPADDR_TYPE_V4)
|
||
|
writer->printf(" " IPSTR, IP2STR(&srv->u_addr.ip4));
|
||
|
else if (srv->type == IPADDR_TYPE_V6)
|
||
|
writer->printf(" " IPSTR, IP2STR(&srv->u_addr.ip6));
|
||
|
}
|
||
|
}
|
||
|
if (dnsservers == 0)
|
||
|
writer->puts(" None");
|
||
|
else
|
||
|
writer->puts("");
|
||
|
|
||
|
if (netif_default)
|
||
|
{
|
||
|
writer->printf("\nDefault Interface: %c%c%d (" IPSTR "/" IPSTR " gateway " IPSTR ")\n",
|
||
|
netif_default->name[0], netif_default->name[1], netif_default->num,
|
||
|
IP2STR(&netif_default->ip_addr.u_addr.ip4),
|
||
|
IP2STR(&netif_default->netmask.u_addr.ip4),
|
||
|
IP2STR(&netif_default->gw.u_addr.ip4));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
writer->printf("\nDefault Interface: None\n");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void network_restart(int verbosity, OvmsWriter* writer, OvmsCommand* cmd, int argc, const char* const* argv)
|
||
|
{
|
||
|
writer->puts("Restarting network...");
|
||
|
vTaskDelay(pdMS_TO_TICKS(100));
|
||
|
MyNetManager.RestartNetwork();
|
||
|
}
|
||
|
|
||
|
#ifdef CONFIG_OVMS_SC_GPL_MONGOOSE
|
||
|
|
||
|
void network_connections(int verbosity, OvmsWriter* writer, OvmsCommand* cmd, int argc, const char* const* argv)
|
||
|
{
|
||
|
if (!MyNetManager.MongooseRunning())
|
||
|
{
|
||
|
writer->puts("ERROR: Mongoose task not running");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (xTaskGetCurrentTaskHandle() == MyNetManager.GetMongooseTaskHandle())
|
||
|
{
|
||
|
// inline execution in mongoose context:
|
||
|
if (strcmp(cmd->GetName(), "close") == 0)
|
||
|
{
|
||
|
uint32_t id = strtol(argv[0], NULL, 16);
|
||
|
int cnt = MyNetManager.CloseConnection(id);
|
||
|
if (cnt == 0)
|
||
|
writer->printf("ERROR: connection ID %08x not found\n", id);
|
||
|
else
|
||
|
writer->printf("Close signal sent to %d connection(s)\n", cnt);
|
||
|
}
|
||
|
else if (strcmp(cmd->GetName(), "cleanup") == 0)
|
||
|
{
|
||
|
int cnt = MyNetManager.CleanupConnections();
|
||
|
if (cnt == 0)
|
||
|
writer->puts("All connections OK");
|
||
|
else
|
||
|
writer->printf("Close signal sent to %d connection(s)\n", cnt);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
MyNetManager.ListConnections(verbosity, writer);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// remote execution from non-mongoose context:
|
||
|
static netman_job_t job;
|
||
|
memset(&job, 0, sizeof(job));
|
||
|
if (strcmp(cmd->GetName(), "close") == 0)
|
||
|
{
|
||
|
job.cmd = nmc_close;
|
||
|
job.close.id = strtol(argv[0], NULL, 16);
|
||
|
if (!MyNetManager.ExecuteJob(&job, pdMS_TO_TICKS(5000)))
|
||
|
writer->puts("ERROR: job failed");
|
||
|
else if (job.close.cnt == 0)
|
||
|
writer->printf("ERROR: connection ID %08x not found\n", job.close.id);
|
||
|
else
|
||
|
writer->printf("Close signal sent to %d connection(s)\n", job.close.cnt);
|
||
|
}
|
||
|
else if (strcmp(cmd->GetName(), "cleanup") == 0)
|
||
|
{
|
||
|
job.cmd = nmc_cleanup;
|
||
|
if (!MyNetManager.ExecuteJob(&job, pdMS_TO_TICKS(5000)))
|
||
|
writer->puts("ERROR: job failed");
|
||
|
else if (job.cleanup.cnt == 0)
|
||
|
writer->puts("All connections OK");
|
||
|
else
|
||
|
writer->printf("Close signal sent to %d connection(s)\n", job.cleanup.cnt);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Note: a timeout occurring after the job has begun processing will result in a crash
|
||
|
// here due to the StringWriter being deleted. This only applies to the list command.
|
||
|
// If this becomes a problem, we need to upgrade the job processing from send/notify
|
||
|
// to a full send/receive scheme.
|
||
|
job.cmd = nmc_list;
|
||
|
job.list.verbosity = verbosity;
|
||
|
job.list.buf = new StringWriter();
|
||
|
if (!MyNetManager.ExecuteJob(&job, pdMS_TO_TICKS(10000)))
|
||
|
writer->puts("ERROR: job failed");
|
||
|
else
|
||
|
writer->write(job.list.buf->data(), job.list.buf->size());
|
||
|
delete job.list.buf;
|
||
|
job.list.buf = NULL;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#endif // CONFIG_OVMS_SC_GPL_MONGOOSE
|
||
|
|
||
|
OvmsNetManager::OvmsNetManager()
|
||
|
{
|
||
|
ESP_LOGI(TAG, "Initialising NETMANAGER (8999)");
|
||
|
m_connected_wifi = false;
|
||
|
m_connected_modem = false;
|
||
|
m_connected_any = false;
|
||
|
m_wifi_sta = false;
|
||
|
m_wifi_good = false;
|
||
|
m_wifi_ap = false;
|
||
|
m_network_any = false;
|
||
|
m_cfg_wifi_sq_good = -87;
|
||
|
m_cfg_wifi_sq_bad = -89;
|
||
|
|
||
|
for (int i=0; i<DNS_MAX_SERVERS; i++)
|
||
|
{
|
||
|
m_dns_modem[i] = (ip_addr_t)ip_addr_any;
|
||
|
m_dns_wifi[i] = (ip_addr_t)ip_addr_any;
|
||
|
m_previous_dns[i] = (ip_addr_t)ip_addr_any;
|
||
|
}
|
||
|
m_previous_name[0] = m_previous_name[1] = 0;
|
||
|
|
||
|
#ifdef CONFIG_OVMS_SC_GPL_MONGOOSE
|
||
|
m_mongoose_task = 0;
|
||
|
m_mongoose_running = false;
|
||
|
m_jobqueue = xQueueCreate(CONFIG_OVMS_HW_NETMANAGER_QUEUE_SIZE, sizeof(netman_job_t*));
|
||
|
#endif //#ifdef CONFIG_OVMS_SC_GPL_MONGOOSE
|
||
|
|
||
|
// Register our commands
|
||
|
OvmsCommand* cmd_network = MyCommandApp.RegisterCommand("network","NETWORK framework",network_status, "", 0, 0, false);
|
||
|
cmd_network->RegisterCommand("status","Show network status",network_status, "", 0, 0, false);
|
||
|
cmd_network->RegisterCommand("restart","Restart network",network_restart, "", 0, 0, false);
|
||
|
#ifdef CONFIG_OVMS_SC_GPL_MONGOOSE
|
||
|
cmd_network->RegisterCommand("list", "List network connections", network_connections);
|
||
|
cmd_network->RegisterCommand("close", "Close network connection(s)", network_connections, "<id>\nUse ID from connection list / 0 to close all", 1, 1);
|
||
|
cmd_network->RegisterCommand("cleanup", "Close orphaned network connections", network_connections);
|
||
|
#endif // CONFIG_OVMS_SC_GPL_MONGOOSE
|
||
|
|
||
|
// Register our events
|
||
|
#undef bind // Kludgy, but works
|
||
|
using std::placeholders::_1;
|
||
|
using std::placeholders::_2;
|
||
|
|
||
|
#ifdef CONFIG_OVMS_COMP_WIFI
|
||
|
MyEvents.RegisterEvent(TAG,"system.wifi.sta.gotip", std::bind(&OvmsNetManager::WifiStaGotIP, this, _1, _2));
|
||
|
MyEvents.RegisterEvent(TAG,"system.wifi.sta.lostip", std::bind(&OvmsNetManager::WifiStaLostIP, this, _1, _2));
|
||
|
MyEvents.RegisterEvent(TAG,"network.wifi.sta.good", std::bind(&OvmsNetManager::WifiStaGood, this, _1, _2));
|
||
|
MyEvents.RegisterEvent(TAG,"network.wifi.sta.bad", std::bind(&OvmsNetManager::WifiStaBad, this, _1, _2));
|
||
|
MyEvents.RegisterEvent(TAG,"system.wifi.sta.stop", std::bind(&OvmsNetManager::WifiStaStop, this, _1, _2));
|
||
|
MyEvents.RegisterEvent(TAG,"system.wifi.sta.connected", std::bind(&OvmsNetManager::WifiStaConnected, this, _1, _2));
|
||
|
MyEvents.RegisterEvent(TAG,"system.wifi.sta.disconnected", std::bind(&OvmsNetManager::WifiStaStop, this, _1, _2));
|
||
|
MyEvents.RegisterEvent(TAG,"system.wifi.down", std::bind(&OvmsNetManager::WifiStaStop, this, _1, _2));
|
||
|
MyEvents.RegisterEvent(TAG,"system.wifi.ap.start", std::bind(&OvmsNetManager::WifiUpAP, this, _1, _2));
|
||
|
MyEvents.RegisterEvent(TAG,"system.wifi.ap.stop", std::bind(&OvmsNetManager::WifiDownAP, this, _1, _2));
|
||
|
MyEvents.RegisterEvent(TAG,"system.wifi.ap.sta.disconnected", std::bind(&OvmsNetManager::WifiApStaDisconnect, this, _1, _2));
|
||
|
#endif // #ifdef CONFIG_OVMS_COMP_WIFI
|
||
|
|
||
|
MyEvents.RegisterEvent(TAG,"system.modem.gotip", std::bind(&OvmsNetManager::ModemUp, this, _1, _2));
|
||
|
MyEvents.RegisterEvent(TAG,"system.modem.stop", std::bind(&OvmsNetManager::ModemDown, this, _1, _2));
|
||
|
MyEvents.RegisterEvent(TAG,"system.modem.down", std::bind(&OvmsNetManager::ModemDown, this, _1, _2));
|
||
|
|
||
|
MyEvents.RegisterEvent(TAG,"config.mounted", std::bind(&OvmsNetManager::ConfigChanged, this, _1, _2));
|
||
|
MyEvents.RegisterEvent(TAG,"config.changed", std::bind(&OvmsNetManager::ConfigChanged, this, _1, _2));
|
||
|
MyEvents.RegisterEvent(TAG,"system.shuttingdown", std::bind(&OvmsNetManager::EventSystemShuttingDown, this, _1, _2));
|
||
|
|
||
|
MyConfig.RegisterParam("network", "Network Configuration", true, true);
|
||
|
// Our instances:
|
||
|
// dns Space-separated list of DNS servers
|
||
|
// wifi.sq.good Threshold for usable wifi signal [dBm], default -87
|
||
|
// wifi.sq.bad Threshold for unusable wifi signal [dBm], default -89
|
||
|
|
||
|
#ifdef CONFIG_OVMS_COMP_WIFI
|
||
|
MyMetrics.RegisterListener(TAG, MS_N_WIFI_SQ, std::bind(&OvmsNetManager::WifiStaCheckSQ, this, _1));
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
OvmsNetManager::~OvmsNetManager()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
void OvmsNetManager::RestartNetwork()
|
||
|
{
|
||
|
#ifdef CONFIG_OVMS_COMP_WIFI
|
||
|
if (MyPeripherals && MyPeripherals->m_esp32wifi)
|
||
|
MyPeripherals->m_esp32wifi->Restart();
|
||
|
#endif // #ifdef CONFIG_OVMS_COMP_WIFI
|
||
|
|
||
|
#ifdef CONFIG_OVMS_COMP_CELLULAR
|
||
|
if (MyPeripherals && MyPeripherals->m_cellular_modem)
|
||
|
MyPeripherals->m_cellular_modem->Restart();
|
||
|
#endif // CONFIG_OVMS_COMP_CELLULAR
|
||
|
}
|
||
|
|
||
|
#ifdef CONFIG_OVMS_COMP_WIFI
|
||
|
|
||
|
void OvmsNetManager::WifiConnect()
|
||
|
{
|
||
|
if (m_wifi_sta && !m_connected_wifi)
|
||
|
{
|
||
|
m_connected_wifi = true;
|
||
|
PrioritiseAndIndicate();
|
||
|
|
||
|
MyEvents.SignalEvent("network.wifi.up",NULL);
|
||
|
|
||
|
if (m_connected_modem)
|
||
|
{
|
||
|
ESP_LOGI(TAG, "WIFI client up (with MODEM up): reconfigured for WIFI client priority");
|
||
|
MyEvents.SignalEvent("network.reconfigured",NULL);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ESP_LOGI(TAG, "WIFI client up (with MODEM down): starting network with WIFI client");
|
||
|
MyEvents.SignalEvent("network.up",NULL);
|
||
|
}
|
||
|
|
||
|
#ifdef CONFIG_OVMS_SC_GPL_MONGOOSE
|
||
|
StartMongooseTask();
|
||
|
#endif
|
||
|
|
||
|
MyEvents.SignalEvent("network.interface.change",NULL);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void OvmsNetManager::WifiDisconnect()
|
||
|
{
|
||
|
if (m_connected_wifi)
|
||
|
{
|
||
|
m_connected_wifi = false;
|
||
|
PrioritiseAndIndicate();
|
||
|
|
||
|
MyEvents.SignalEvent("network.wifi.down",NULL);
|
||
|
|
||
|
if (m_connected_any)
|
||
|
{
|
||
|
ESP_LOGI(TAG, "WIFI client down (with MODEM up): reconfigured for MODEM priority");
|
||
|
MyEvents.SignalEvent("network.reconfigured",NULL);
|
||
|
#ifdef CONFIG_OVMS_SC_GPL_MONGOOSE
|
||
|
ScheduleCleanup();
|
||
|
#endif
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ESP_LOGI(TAG, "WIFI client down (with MODEM down): network connectivity has been lost");
|
||
|
MyEvents.SignalEvent("network.down",NULL);
|
||
|
|
||
|
#ifdef CONFIG_OVMS_SC_GPL_MONGOOSE
|
||
|
StopMongooseTask();
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
MyEvents.SignalEvent("network.interface.change",NULL);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void OvmsNetManager::WifiStaGotIP(std::string event, void* data)
|
||
|
{
|
||
|
m_wifi_sta = true;
|
||
|
ESP_LOGI(TAG, "WIFI client got IP");
|
||
|
SaveDNSServer(m_dns_wifi);
|
||
|
|
||
|
// Re-prioritise, just in case, as Wifi stack seems to mess with this
|
||
|
// (in particular if an AP interface is up, and STA goes down, Wifi
|
||
|
// stack seems to switch default interface to AP)
|
||
|
PrioritiseAndIndicate();
|
||
|
#ifdef CONFIG_OVMS_SC_GPL_MONGOOSE
|
||
|
ScheduleCleanup();
|
||
|
#endif
|
||
|
|
||
|
WifiStaCheckSQ(StdMetrics.ms_m_net_wifi_sq);
|
||
|
}
|
||
|
|
||
|
void OvmsNetManager::WifiStaLostIP(std::string event, void* data)
|
||
|
{
|
||
|
// Re-prioritise, just in case, as Wifi stack seems to mess with this
|
||
|
// (in particular if an AP interface is up, and STA goes down, Wifi
|
||
|
// stack seems to switch default interface to AP)
|
||
|
PrioritiseAndIndicate();
|
||
|
#ifdef CONFIG_OVMS_SC_GPL_MONGOOSE
|
||
|
ScheduleCleanup();
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
void OvmsNetManager::WifiStaConnected(std::string event, void* data)
|
||
|
{
|
||
|
// Re-prioritise, just in case, as Wifi stack seems to mess with this
|
||
|
// (in particular if an AP interface is up, and STA goes down, Wifi
|
||
|
// stack seems to switch default interface to AP)
|
||
|
PrioritiseAndIndicate();
|
||
|
#ifdef CONFIG_OVMS_SC_GPL_MONGOOSE
|
||
|
ScheduleCleanup();
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
void OvmsNetManager::WifiStaStop(std::string event, void* data)
|
||
|
{
|
||
|
WifiStaSetSQ(false);
|
||
|
if (m_wifi_sta)
|
||
|
{
|
||
|
m_wifi_sta = false;
|
||
|
ESP_LOGI(TAG, "WIFI client stop");
|
||
|
if (m_connected_wifi)
|
||
|
{
|
||
|
WifiDisconnect();
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Re-prioritise, just in case, as Wifi stack seems to mess with this
|
||
|
// (in particular if an AP interface is up, and STA goes down, Wifi
|
||
|
// stack seems to switch default interface to AP)
|
||
|
PrioritiseAndIndicate();
|
||
|
#ifdef CONFIG_OVMS_SC_GPL_MONGOOSE
|
||
|
ScheduleCleanup();
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
void OvmsNetManager::WifiStaGood(std::string event, void* data)
|
||
|
{
|
||
|
if (m_wifi_sta && !m_connected_wifi)
|
||
|
{
|
||
|
ESP_LOGI(TAG, "WIFI client has good signal quality (%.1f dBm); connect",
|
||
|
StdMetrics.ms_m_net_wifi_sq->AsFloat());
|
||
|
WifiConnect();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void OvmsNetManager::WifiStaBad(std::string event, void* data)
|
||
|
{
|
||
|
if (m_wifi_sta && m_connected_wifi)
|
||
|
{
|
||
|
ESP_LOGI(TAG, "WIFI client has bad signal quality (%.1f dBm); disconnect",
|
||
|
StdMetrics.ms_m_net_wifi_sq->AsFloat());
|
||
|
// Stop using the Wifi network:
|
||
|
WifiDisconnect();
|
||
|
// If enabled, start reconnecting immediately (for fast transition to next best
|
||
|
// AP instead of trying to reassociate to current AP):
|
||
|
if (MyPeripherals && MyPeripherals->m_esp32wifi &&
|
||
|
MyConfig.GetParamValueBool("network", "wifi.bad.reconnect") == true)
|
||
|
{
|
||
|
MyPeripherals->m_esp32wifi->Reconnect(NULL);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void OvmsNetManager::WifiStaCheckSQ(OvmsMetric* metric)
|
||
|
{
|
||
|
if (m_wifi_sta)
|
||
|
{
|
||
|
float sq = StdMetrics.ms_m_net_wifi_sq->AsFloat();
|
||
|
if ((!metric || !m_wifi_good) && sq >= m_cfg_wifi_sq_good)
|
||
|
{
|
||
|
m_wifi_good = true;
|
||
|
MyEvents.SignalEvent("network.wifi.sta.good", NULL);
|
||
|
}
|
||
|
else if ((!metric || m_wifi_good) && sq <= m_cfg_wifi_sq_bad)
|
||
|
{
|
||
|
m_wifi_good = false;
|
||
|
MyEvents.SignalEvent("network.wifi.sta.bad", NULL);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void OvmsNetManager::WifiStaSetSQ(bool good)
|
||
|
{
|
||
|
if (m_wifi_sta && m_wifi_good != good)
|
||
|
{
|
||
|
m_wifi_good = good;
|
||
|
MyEvents.SignalEvent(good ? "network.wifi.sta.good" : "network.wifi.sta.bad", NULL);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void OvmsNetManager::WifiUpAP(std::string event, void* data)
|
||
|
{
|
||
|
m_wifi_ap = true;
|
||
|
PrioritiseAndIndicate();
|
||
|
|
||
|
ESP_LOGI(TAG, "WIFI access point is up");
|
||
|
|
||
|
#ifdef CONFIG_OVMS_SC_GPL_MONGOOSE
|
||
|
StartMongooseTask();
|
||
|
#endif //#ifdef CONFIG_OVMS_SC_GPL_MONGOOSE
|
||
|
|
||
|
MyEvents.SignalEvent("network.interface.change",NULL);
|
||
|
}
|
||
|
|
||
|
void OvmsNetManager::WifiDownAP(std::string event, void* data)
|
||
|
{
|
||
|
m_wifi_ap = false;
|
||
|
PrioritiseAndIndicate();
|
||
|
|
||
|
ESP_LOGI(TAG, "WIFI access point is down");
|
||
|
|
||
|
#ifdef CONFIG_OVMS_SC_GPL_MONGOOSE
|
||
|
StopMongooseTask();
|
||
|
#endif //#ifdef CONFIG_OVMS_SC_GPL_MONGOOSE
|
||
|
|
||
|
MyEvents.SignalEvent("network.interface.change",NULL);
|
||
|
}
|
||
|
|
||
|
void OvmsNetManager::WifiApStaDisconnect(std::string event, void* data)
|
||
|
{
|
||
|
ESP_LOGI(TAG, "WIFI access point station disconnected");
|
||
|
#ifdef CONFIG_OVMS_SC_GPL_MONGOOSE
|
||
|
ScheduleCleanup();
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
#endif // #ifdef CONFIG_OVMS_COMP_WIFI
|
||
|
|
||
|
|
||
|
void OvmsNetManager::ModemUp(std::string event, void* data)
|
||
|
{
|
||
|
m_connected_modem = true;
|
||
|
SaveDNSServer(m_dns_modem);
|
||
|
PrioritiseAndIndicate();
|
||
|
|
||
|
MyEvents.SignalEvent("network.modem.up",NULL);
|
||
|
|
||
|
if (!m_connected_wifi)
|
||
|
{
|
||
|
ESP_LOGI(TAG, "MODEM up (with WIFI client down): starting network with MODEM");
|
||
|
MyEvents.SignalEvent("network.up",NULL);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ESP_LOGI(TAG, "MODEM up (with WIFI client up): staying with WIFI client priority");
|
||
|
}
|
||
|
|
||
|
#ifdef CONFIG_OVMS_SC_GPL_MONGOOSE
|
||
|
StartMongooseTask();
|
||
|
#endif //#ifdef CONFIG_OVMS_SC_GPL_MONGOOSE
|
||
|
|
||
|
MyEvents.SignalEvent("network.interface.change",NULL);
|
||
|
}
|
||
|
|
||
|
void OvmsNetManager::ModemDown(std::string event, void* data)
|
||
|
{
|
||
|
if (m_connected_modem)
|
||
|
{
|
||
|
m_connected_modem = false;
|
||
|
PrioritiseAndIndicate();
|
||
|
|
||
|
MyEvents.SignalEvent("network.modem.down",NULL);
|
||
|
|
||
|
if (m_connected_any)
|
||
|
{
|
||
|
ESP_LOGI(TAG, "MODEM down (with WIFI client up): staying with WIFI client priority");
|
||
|
#ifdef CONFIG_OVMS_SC_GPL_MONGOOSE
|
||
|
ScheduleCleanup();
|
||
|
#endif
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ESP_LOGI(TAG, "MODEM down (with WIFI client down): network connectivity has been lost");
|
||
|
MyEvents.SignalEvent("network.down",NULL);
|
||
|
|
||
|
#ifdef CONFIG_OVMS_SC_GPL_MONGOOSE
|
||
|
StopMongooseTask();
|
||
|
#endif //#ifdef CONFIG_OVMS_SC_GPL_MONGOOSE
|
||
|
}
|
||
|
|
||
|
MyEvents.SignalEvent("network.interface.change",NULL);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Re-prioritise, just in case, as Wifi stack seems to mess with this
|
||
|
// (in particular if an AP interface is up, and STA goes down, Wifi
|
||
|
// stack seems to switch default interface to AP)
|
||
|
PrioritiseAndIndicate();
|
||
|
#ifdef CONFIG_OVMS_SC_GPL_MONGOOSE
|
||
|
ScheduleCleanup();
|
||
|
#endif
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void OvmsNetManager::ConfigChanged(std::string event, void* data)
|
||
|
{
|
||
|
OvmsConfigParam* param = (OvmsConfigParam*)data;
|
||
|
if (!param || param->GetName() == "network")
|
||
|
{
|
||
|
// Network config has been changed, apply:
|
||
|
m_cfg_wifi_sq_good = MyConfig.GetParamValueFloat("network", "wifi.sq.good", -87);
|
||
|
m_cfg_wifi_sq_bad = MyConfig.GetParamValueFloat("network", "wifi.sq.bad", -89);
|
||
|
if (m_cfg_wifi_sq_good < m_cfg_wifi_sq_bad)
|
||
|
{
|
||
|
float x = m_cfg_wifi_sq_good;
|
||
|
m_cfg_wifi_sq_good = m_cfg_wifi_sq_bad;
|
||
|
m_cfg_wifi_sq_bad = x;
|
||
|
}
|
||
|
#ifdef CONFIG_OVMS_COMP_WIFI
|
||
|
WifiStaCheckSQ(NULL);
|
||
|
#endif
|
||
|
if (param && m_network_any)
|
||
|
PrioritiseAndIndicate();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void OvmsNetManager::EventSystemShuttingDown(std::string event, void* data)
|
||
|
{
|
||
|
#ifdef CONFIG_OVMS_SC_GPL_MONGOOSE
|
||
|
StopMongooseTask();
|
||
|
#endif //#ifdef CONFIG_OVMS_SC_GPL_MONGOOSE
|
||
|
}
|
||
|
|
||
|
void OvmsNetManager::SaveDNSServer(ip_addr_t* dnsstore)
|
||
|
{
|
||
|
for (int i=0; i<DNS_MAX_SERVERS; i++)
|
||
|
{
|
||
|
dnsstore[i] = *dns_getserver(i);
|
||
|
ESP_LOGD(TAG, "Saved DNS#%d %s", i, inet_ntoa(dnsstore[i]));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void OvmsNetManager::SetDNSServer(ip_addr_t* dnsstore)
|
||
|
{
|
||
|
// Read DNS configuration:
|
||
|
std::string servers = MyConfig.GetParamValue("network", "dns");
|
||
|
if (!servers.empty())
|
||
|
{
|
||
|
int spos = 0;
|
||
|
size_t sep = 0;
|
||
|
while ((spos<DNS_MAX_SERVERS)&&(sep != string::npos))
|
||
|
{
|
||
|
// Set the specified DNS servers
|
||
|
size_t next = servers.find(' ',sep);
|
||
|
std::string cserver;
|
||
|
ip_addr_t serverip;
|
||
|
if (next == std::string::npos)
|
||
|
{
|
||
|
// The last one
|
||
|
cserver = std::string(servers,sep,string::npos);
|
||
|
sep = string::npos;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// One of many
|
||
|
cserver = std::string(servers,sep,next-sep);
|
||
|
sep = next+1;
|
||
|
}
|
||
|
ip4_addr_set_u32(ip_2_ip4(&serverip), ipaddr_addr(cserver.c_str()));
|
||
|
serverip.type = IPADDR_TYPE_V4;
|
||
|
if (!ip_addr_cmp(&serverip, &m_previous_dns[spos]))
|
||
|
{
|
||
|
m_previous_dns[spos] = serverip;
|
||
|
ESP_LOGI(TAG, "Set DNS#%d %s",spos,cserver.c_str());
|
||
|
}
|
||
|
dns_setserver(spos++, &serverip);
|
||
|
}
|
||
|
for (;spos<DNS_MAX_SERVERS;spos++)
|
||
|
{
|
||
|
dns_setserver(spos, IP_ADDR_ANY);
|
||
|
}
|
||
|
}
|
||
|
else if (dnsstore)
|
||
|
{
|
||
|
// Set stored DNS servers:
|
||
|
for (int i=0; i<DNS_MAX_SERVERS; i++)
|
||
|
{
|
||
|
if (ip_addr_cmp(&dnsstore[i], &m_previous_dns[i]))
|
||
|
{
|
||
|
m_previous_dns[i] = dnsstore[i];
|
||
|
ESP_LOGI(TAG, "Set DNS#%d %s", i, inet_ntoa(dnsstore[i]));
|
||
|
}
|
||
|
dns_setserver(i, &dnsstore[i]);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void OvmsNetManager::SetNetType(std::string type)
|
||
|
{
|
||
|
if (type == "wifi")
|
||
|
{
|
||
|
StdMetrics.ms_m_net_type->SetValue(type);
|
||
|
#ifdef CONFIG_OVMS_COMP_WIFI
|
||
|
if (MyPeripherals && MyPeripherals->m_esp32wifi)
|
||
|
MyPeripherals->m_esp32wifi->UpdateNetMetrics();
|
||
|
#endif // CONFIG_OVMS_COMP_WIFI
|
||
|
}
|
||
|
else if (type == "modem")
|
||
|
{
|
||
|
StdMetrics.ms_m_net_type->SetValue(type);
|
||
|
#ifdef CONFIG_OVMS_COMP_CELLULAR
|
||
|
if (MyPeripherals && MyPeripherals->m_cellular_modem)
|
||
|
MyPeripherals->m_cellular_modem->UpdateNetMetrics();
|
||
|
#endif // CONFIG_OVMS_COMP_CELLULAR
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
StdMetrics.ms_m_net_type->SetValue("none");
|
||
|
StdMetrics.ms_m_net_provider->SetValue("");
|
||
|
StdMetrics.ms_m_net_sq->SetValue(0, dbm);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void SafePrioritiseAndIndicate(void* ctx)
|
||
|
{
|
||
|
MyNetManager.DoSafePrioritiseAndIndicate();
|
||
|
}
|
||
|
|
||
|
void OvmsNetManager::PrioritiseAndIndicate()
|
||
|
{
|
||
|
tcpip_callback_with_block(SafePrioritiseAndIndicate, NULL, 1);
|
||
|
}
|
||
|
|
||
|
void OvmsNetManager::DoSafePrioritiseAndIndicate()
|
||
|
{
|
||
|
const char *search = NULL;
|
||
|
ip_addr_t* dns = NULL;
|
||
|
|
||
|
// A convenient place to keep track of connectivity in general
|
||
|
m_connected_any = m_connected_wifi || m_connected_modem;
|
||
|
m_network_any = m_connected_wifi || m_connected_modem || m_wifi_ap;
|
||
|
|
||
|
// Priority order...
|
||
|
if (m_connected_wifi)
|
||
|
{
|
||
|
// Wifi is up
|
||
|
SetNetType("wifi");
|
||
|
search = "st";
|
||
|
dns = m_dns_wifi;
|
||
|
}
|
||
|
else if (m_connected_modem)
|
||
|
{
|
||
|
// Modem is up
|
||
|
SetNetType("modem");
|
||
|
search = "pp";
|
||
|
dns = m_dns_modem;
|
||
|
}
|
||
|
|
||
|
if (search == NULL)
|
||
|
{
|
||
|
SetNetType("none");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
for (struct netif *pri = netif_list; pri != NULL; pri=pri->next)
|
||
|
{
|
||
|
if ((pri->name[0]==search[0])&&
|
||
|
(pri->name[1]==search[1]))
|
||
|
{
|
||
|
if (search[0] != m_previous_name[0] || search[1] != m_previous_name[1])
|
||
|
{
|
||
|
ESP_LOGI(TAG, "Interface priority is %c%c%d (" IPSTR "/" IPSTR " gateway " IPSTR ")",
|
||
|
pri->name[0], pri->name[1], pri->num,
|
||
|
IP2STR(&pri->ip_addr.u_addr.ip4), IP2STR(&pri->netmask.u_addr.ip4), IP2STR(&pri->gw.u_addr.ip4));
|
||
|
m_previous_name[0] = search[0];
|
||
|
m_previous_name[1] = search[1];
|
||
|
for (int i=0; i<DNS_MAX_SERVERS; i++)
|
||
|
m_previous_dns[i] = (ip_addr_t)ip_addr_any;
|
||
|
}
|
||
|
netif_set_default(pri);
|
||
|
SetDNSServer(dns);
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
ESP_LOGE(TAG, "Inconsistent state: no interface of type '%s' found", search);
|
||
|
}
|
||
|
|
||
|
#ifdef CONFIG_OVMS_SC_GPL_MONGOOSE
|
||
|
|
||
|
static void MongooseRawTask(void *pvParameters)
|
||
|
{
|
||
|
OvmsNetManager* me = (OvmsNetManager*)pvParameters;
|
||
|
me->MongooseTask();
|
||
|
}
|
||
|
|
||
|
void OvmsNetManager::MongooseTask()
|
||
|
{
|
||
|
int pri, lastpri = CONFIG_OVMS_NETMAN_TASK_PRIORITY;
|
||
|
|
||
|
// Initialise the mongoose manager
|
||
|
ESP_LOGD(TAG, "MongooseTask starting");
|
||
|
mg_mgr_init(&m_mongoose_mgr, NULL);
|
||
|
MyEvents.SignalEvent("network.mgr.init",NULL);
|
||
|
|
||
|
m_mongoose_running = true;
|
||
|
|
||
|
// Main event loop
|
||
|
while (m_mongoose_running)
|
||
|
{
|
||
|
// poll interfaces:
|
||
|
if (mg_mgr_poll(&m_mongoose_mgr, 250) == 0)
|
||
|
{
|
||
|
ESP_LOGD(TAG, "MongooseTask: no interfaces available => exit");
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// check for netmanager control jobs:
|
||
|
ProcessJobs();
|
||
|
|
||
|
// Detect broken mutex priority inheritance:
|
||
|
// (may be removed if solved by esp-idf commit 22d636b7b0d6006e06b5b3cfddfbf6e2cf69b4b8)
|
||
|
if ((pri = uxTaskPriorityGet(NULL)) != lastpri)
|
||
|
{
|
||
|
ESP_LOGD(TAG, "MongooseTask: priority changed from %d to %d", lastpri, pri);
|
||
|
lastpri = pri;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
m_mongoose_running = false;
|
||
|
|
||
|
// Shutdown cleanly
|
||
|
ESP_LOGD(TAG, "MongooseTask stopping");
|
||
|
MyEvents.SignalEvent("network.mgr.stop",NULL);
|
||
|
mg_mgr_free(&m_mongoose_mgr);
|
||
|
m_mongoose_task = NULL;
|
||
|
vTaskDelete(NULL);
|
||
|
}
|
||
|
|
||
|
struct mg_mgr* OvmsNetManager::GetMongooseMgr()
|
||
|
{
|
||
|
return &m_mongoose_mgr;
|
||
|
}
|
||
|
|
||
|
bool OvmsNetManager::MongooseRunning()
|
||
|
{
|
||
|
return m_mongoose_running;
|
||
|
}
|
||
|
|
||
|
void OvmsNetManager::StartMongooseTask()
|
||
|
{
|
||
|
if (!m_mongoose_running)
|
||
|
{
|
||
|
if (m_network_any)
|
||
|
{
|
||
|
// wait for previous task to finish shutting down:
|
||
|
while (m_mongoose_task)
|
||
|
vTaskDelay(pdMS_TO_TICKS(50));
|
||
|
// start new task:
|
||
|
xTaskCreatePinnedToCore(MongooseRawTask, "OVMS NetMan",10*1024, (void*)this,
|
||
|
CONFIG_OVMS_NETMAN_TASK_PRIORITY, &m_mongoose_task, CORE(1));
|
||
|
AddTaskToMap(m_mongoose_task);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void OvmsNetManager::StopMongooseTask()
|
||
|
{
|
||
|
if (!m_network_any)
|
||
|
m_mongoose_running = false;
|
||
|
}
|
||
|
|
||
|
void OvmsNetManager::ProcessJobs()
|
||
|
{
|
||
|
netman_job_t* job;
|
||
|
while (xQueueReceive(m_jobqueue, &job, 0) == pdTRUE)
|
||
|
{
|
||
|
ESP_LOGD(TAG, "MongooseTask: got cmd %d from %p", job->cmd, job->caller);
|
||
|
switch (job->cmd)
|
||
|
{
|
||
|
case nmc_none:
|
||
|
break;
|
||
|
case nmc_list:
|
||
|
job->list.cnt = ListConnections(job->list.verbosity, job->list.buf);
|
||
|
break;
|
||
|
case nmc_close:
|
||
|
job->close.cnt = CloseConnection(job->close.id);
|
||
|
break;
|
||
|
case nmc_cleanup:
|
||
|
job->cleanup.cnt = CleanupConnections();
|
||
|
break;
|
||
|
default:
|
||
|
ESP_LOGW(TAG, "MongooseTask: got unknown cmd %d from %p", job->cmd, job->caller);
|
||
|
}
|
||
|
if (job->caller)
|
||
|
xTaskNotifyGive(job->caller);
|
||
|
ESP_LOGD(TAG, "MongooseTask: done cmd %d from %p", job->cmd, job->caller);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bool OvmsNetManager::ExecuteJob(netman_job_t* job, TickType_t timeout /*=portMAX_DELAY*/)
|
||
|
{
|
||
|
if (!m_mongoose_running)
|
||
|
return false;
|
||
|
if (timeout)
|
||
|
{
|
||
|
job->caller = xTaskGetCurrentTaskHandle();
|
||
|
xTaskNotifyWait(ULONG_MAX, ULONG_MAX, NULL, 0); // clear state
|
||
|
}
|
||
|
else
|
||
|
job->caller = 0;
|
||
|
ESP_LOGD(TAG, "send cmd %d from %p", job->cmd, job->caller);
|
||
|
if (xQueueSend(m_jobqueue, &job, timeout) != pdTRUE)
|
||
|
{
|
||
|
ESP_LOGW(TAG, "ExecuteJob: cmd %d: queue overflow", job->cmd);
|
||
|
return false;
|
||
|
}
|
||
|
if (timeout && ulTaskNotifyTake(pdTRUE, timeout) == 0)
|
||
|
{
|
||
|
// try to prevent delayed processing (cannot stop if already started):
|
||
|
netman_cmd_t cmd = job->cmd;
|
||
|
job->cmd = nmc_none;
|
||
|
job->caller = 0;
|
||
|
ESP_LOGW(TAG, "ExecuteJob: cmd %d: timeout", cmd);
|
||
|
return false;
|
||
|
}
|
||
|
ESP_LOGD(TAG, "done cmd %d from %p", job->cmd, job->caller);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
void OvmsNetManager::ScheduleCleanup()
|
||
|
{
|
||
|
static netman_job_t job;
|
||
|
memset(&job, 0, sizeof(job));
|
||
|
job.cmd = nmc_cleanup;
|
||
|
ExecuteJob(&job, 0);
|
||
|
}
|
||
|
|
||
|
int OvmsNetManager::ListConnections(int verbosity, OvmsWriter* writer)
|
||
|
{
|
||
|
if (!m_mongoose_running)
|
||
|
return 0;
|
||
|
mg_connection *c;
|
||
|
int cnt = 0;
|
||
|
char local[48], remote[48];
|
||
|
writer->printf("ID Flags Handler Local Remote\n");
|
||
|
for (c = mg_next(&m_mongoose_mgr, NULL); c; c = mg_next(&m_mongoose_mgr, c))
|
||
|
{
|
||
|
if (c->flags & MG_F_LISTENING)
|
||
|
continue;
|
||
|
mg_conn_addr_to_str(c, local, sizeof(local), MG_SOCK_STRINGIFY_IP|MG_SOCK_STRINGIFY_PORT);
|
||
|
mg_conn_addr_to_str(c, remote, sizeof(remote), MG_SOCK_STRINGIFY_IP|MG_SOCK_STRINGIFY_PORT|MG_SOCK_STRINGIFY_REMOTE);
|
||
|
writer->printf("%08x %08x %08x %-21s %s\n", (uint32_t)c, (uint32_t)c->flags, (uint32_t)c->user_data, local, remote);
|
||
|
cnt++;
|
||
|
}
|
||
|
return cnt;
|
||
|
}
|
||
|
|
||
|
int OvmsNetManager::CloseConnection(uint32_t id)
|
||
|
{
|
||
|
if (!m_mongoose_running)
|
||
|
return 0;
|
||
|
mg_connection *c;
|
||
|
int cnt = 0;
|
||
|
for (c = mg_next(&m_mongoose_mgr, NULL); c; c = mg_next(&m_mongoose_mgr, c))
|
||
|
{
|
||
|
if (c->flags & MG_F_LISTENING)
|
||
|
continue;
|
||
|
if (id == 0 || c == (mg_connection*)id)
|
||
|
{
|
||
|
c->flags |= MG_F_CLOSE_IMMEDIATELY;
|
||
|
cnt++;
|
||
|
}
|
||
|
}
|
||
|
return cnt;
|
||
|
}
|
||
|
|
||
|
int OvmsNetManager::CleanupConnections()
|
||
|
{
|
||
|
if (!m_mongoose_running)
|
||
|
return 0;
|
||
|
|
||
|
struct netif *ni;
|
||
|
mg_connection *c;
|
||
|
tcpip_adapter_sta_list_t ap_ip_list;
|
||
|
union socket_address sa;
|
||
|
socklen_t slen = sizeof(sa);
|
||
|
int cnt = 0;
|
||
|
|
||
|
// get IP addresses of stations connected to our wifi AP:
|
||
|
ap_ip_list.num = 0;
|
||
|
#ifdef CONFIG_OVMS_COMP_WIFI
|
||
|
if (m_wifi_ap)
|
||
|
{
|
||
|
wifi_sta_list_t sta_list;
|
||
|
if (esp_wifi_ap_get_sta_list(&sta_list) != ESP_OK)
|
||
|
ESP_LOGW(TAG, "CleanupConnections: can't get AP station list");
|
||
|
else if (tcpip_adapter_get_sta_list(&sta_list, &ap_ip_list) != ESP_OK)
|
||
|
ESP_LOGW(TAG, "CleanupConnections: can't get AP station IP list");
|
||
|
}
|
||
|
#endif // #ifdef CONFIG_OVMS_COMP_WIFI
|
||
|
|
||
|
for (c = mg_next(&m_mongoose_mgr, NULL); c; c = mg_next(&m_mongoose_mgr, c))
|
||
|
{
|
||
|
if (c->flags & MG_F_LISTENING)
|
||
|
continue;
|
||
|
|
||
|
// get local address:
|
||
|
memset(&sa, 0, sizeof(sa));
|
||
|
if (getsockname(c->sock, &sa.sa, &slen) != 0)
|
||
|
{
|
||
|
ESP_LOGW(TAG, "CleanupConnections: conn %08x: getsockname failed", (uint32_t)c);
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if (sa.sa.sa_family != AF_INET || sa.sin.sin_addr.s_addr == IPADDR_ANY || sa.sin.sin_addr.s_addr == IPADDR_NONE)
|
||
|
continue;
|
||
|
|
||
|
// find interface:
|
||
|
for (ni = netif_list; ni; ni = ni->next)
|
||
|
{
|
||
|
if (sa.sin.sin_addr.s_addr == ip4_addr_get_u32(netif_ip4_addr(ni)))
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (ni)
|
||
|
ESP_LOGD(TAG, "CleanupConnections: conn %08x -> iface %c%c%d", (uint32_t)c, ni->name[0], ni->name[1], ni->num);
|
||
|
else
|
||
|
ESP_LOGD(TAG, "CleanupConnections: conn %08x -> no iface", (uint32_t)c);
|
||
|
|
||
|
if (!ni || !(ni->flags & NETIF_FLAG_UP) || !(ni->flags & NETIF_FLAG_LINK_UP))
|
||
|
{
|
||
|
ESP_LOGI(TAG, "CleanupConnections: closing conn %08x: interface/link down", (uint32_t)c);
|
||
|
c->flags |= MG_F_CLOSE_IMMEDIATELY;
|
||
|
cnt++;
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
// check remote address on wifi AP:
|
||
|
if (ni->name[0] == 'a' && ni->name[1] == 'p')
|
||
|
{
|
||
|
memset(&sa, 0, sizeof(sa));
|
||
|
if (getpeername(c->sock, &sa.sa, &slen) != 0)
|
||
|
{
|
||
|
ESP_LOGW(TAG, "CleanupConnections: conn %08x: getpeername failed", (uint32_t)c);
|
||
|
continue;
|
||
|
}
|
||
|
int i;
|
||
|
for (i = 0; i < ap_ip_list.num; i++)
|
||
|
{
|
||
|
if (sa.sin.sin_addr.s_addr == ap_ip_list.sta[i].ip.addr)
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (i < ap_ip_list.num)
|
||
|
{
|
||
|
ESP_LOGD(TAG, "CleanupConnections: conn %08x -> AP IP " IPSTR, (uint32_t)c, IP2STR(&ap_ip_list.sta[i].ip));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ESP_LOGI(TAG, "CleanupConnections: closing conn %08x: AP peer disconnected", (uint32_t)c);
|
||
|
c->flags |= MG_F_CLOSE_IMMEDIATELY;
|
||
|
cnt++;
|
||
|
}
|
||
|
} // AP remotes
|
||
|
} // connection loop
|
||
|
return cnt;
|
||
|
}
|
||
|
|
||
|
bool OvmsNetManager::IsNetManagerTask()
|
||
|
{
|
||
|
// Return TRUE if the currently running task is the Net Manager task
|
||
|
extern void *pxCurrentTCB[portNUM_PROCESSORS];
|
||
|
|
||
|
return (m_mongoose_task == pxCurrentTCB[xPortGetCoreID()]);
|
||
|
}
|
||
|
|
||
|
#endif //#ifdef CONFIG_OVMS_SC_GPL_MONGOOSE
|