Added Software
This commit is contained in:
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* HTTP over TLS (HTTPS) example sketch
|
||||
*
|
||||
* This example demonstrates how to use
|
||||
* WiFiClientSecure class to access HTTPS API.
|
||||
* We fetch and display the status of
|
||||
* esp8266/Arduino project continuous integration
|
||||
* build.
|
||||
*
|
||||
* Created by Ivan Grokhotkov, 2015.
|
||||
* This example is in public domain.
|
||||
*/
|
||||
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <WiFiClientSecure.h>
|
||||
|
||||
const char* ssid = "........";
|
||||
const char* password = "........";
|
||||
|
||||
const char* host = "api.github.com";
|
||||
const int httpsPort = 443;
|
||||
|
||||
// Use web browser to view and copy
|
||||
// SHA1 fingerprint of the certificate
|
||||
const char* fingerprint = "CF 05 98 89 CA FF 8E D8 5E 5C E0 C2 E4 F7 E6 C3 C7 50 DD 5C";
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
Serial.println();
|
||||
Serial.print("connecting to ");
|
||||
Serial.println(ssid);
|
||||
WiFi.begin(ssid, password);
|
||||
while (WiFi.status() != WL_CONNECTED) {
|
||||
delay(500);
|
||||
Serial.print(".");
|
||||
}
|
||||
Serial.println("");
|
||||
Serial.println("WiFi connected");
|
||||
Serial.println("IP address: ");
|
||||
Serial.println(WiFi.localIP());
|
||||
|
||||
// Use WiFiClientSecure class to create TLS connection
|
||||
WiFiClientSecure client;
|
||||
Serial.print("connecting to ");
|
||||
Serial.println(host);
|
||||
if (!client.connect(host, httpsPort)) {
|
||||
Serial.println("connection failed");
|
||||
return;
|
||||
}
|
||||
|
||||
if (client.verify(fingerprint, host)) {
|
||||
Serial.println("certificate matches");
|
||||
} else {
|
||||
Serial.println("certificate doesn't match");
|
||||
}
|
||||
|
||||
String url = "/repos/esp8266/Arduino/commits/master/status";
|
||||
Serial.print("requesting URL: ");
|
||||
Serial.println(url);
|
||||
|
||||
client.print(String("GET ") + url + " HTTP/1.1\r\n" +
|
||||
"Host: " + host + "\r\n" +
|
||||
"User-Agent: BuildFailureDetectorESP8266\r\n" +
|
||||
"Connection: close\r\n\r\n");
|
||||
|
||||
Serial.println("request sent");
|
||||
while (client.connected()) {
|
||||
String line = client.readStringUntil('\n');
|
||||
if (line == "\r") {
|
||||
Serial.println("headers received");
|
||||
break;
|
||||
}
|
||||
}
|
||||
String line = client.readStringUntil('\n');
|
||||
if (line.startsWith("{\"state\":\"success\"")) {
|
||||
Serial.println("esp8266/Arduino CI successfull!");
|
||||
} else {
|
||||
Serial.println("esp8266/Arduino CI has failed");
|
||||
}
|
||||
Serial.println("reply was:");
|
||||
Serial.println("==========");
|
||||
Serial.println(line);
|
||||
Serial.println("==========");
|
||||
Serial.println("closing connection");
|
||||
}
|
||||
|
||||
void loop() {
|
||||
}
|
@ -0,0 +1,86 @@
|
||||
|
||||
const unsigned char caCert[] PROGMEM = {
|
||||
0x30, 0x82, 0x03, 0xc5, 0x30, 0x82, 0x02, 0xad, 0xa0, 0x03, 0x02, 0x01,
|
||||
0x02, 0x02, 0x10, 0x02, 0xac, 0x5c, 0x26, 0x6a, 0x0b, 0x40, 0x9b, 0x8f,
|
||||
0x0b, 0x79, 0xf2, 0xae, 0x46, 0x25, 0x77, 0x30, 0x0d, 0x06, 0x09, 0x2a,
|
||||
0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x6c,
|
||||
0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55,
|
||||
0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0c,
|
||||
0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, 0x6e, 0x63,
|
||||
0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x10, 0x77,
|
||||
0x77, 0x77, 0x2e, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, 0x74, 0x2e,
|
||||
0x63, 0x6f, 0x6d, 0x31, 0x2b, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, 0x03,
|
||||
0x13, 0x22, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x48,
|
||||
0x69, 0x67, 0x68, 0x20, 0x41, 0x73, 0x73, 0x75, 0x72, 0x61, 0x6e, 0x63,
|
||||
0x65, 0x20, 0x45, 0x56, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41,
|
||||
0x30, 0x1e, 0x17, 0x0d, 0x30, 0x36, 0x31, 0x31, 0x31, 0x30, 0x30, 0x30,
|
||||
0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x33, 0x31, 0x31, 0x31, 0x31,
|
||||
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x6c, 0x31, 0x0b,
|
||||
0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31,
|
||||
0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0c, 0x44, 0x69,
|
||||
0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, 0x6e, 0x63, 0x31, 0x19,
|
||||
0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x10, 0x77, 0x77, 0x77,
|
||||
0x2e, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, 0x74, 0x2e, 0x63, 0x6f,
|
||||
0x6d, 0x31, 0x2b, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x22,
|
||||
0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x48, 0x69, 0x67,
|
||||
0x68, 0x20, 0x41, 0x73, 0x73, 0x75, 0x72, 0x61, 0x6e, 0x63, 0x65, 0x20,
|
||||
0x45, 0x56, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x30, 0x82,
|
||||
0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
|
||||
0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82,
|
||||
0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xc6, 0xcc, 0xe5, 0x73, 0xe6,
|
||||
0xfb, 0xd4, 0xbb, 0xe5, 0x2d, 0x2d, 0x32, 0xa6, 0xdf, 0xe5, 0x81, 0x3f,
|
||||
0xc9, 0xcd, 0x25, 0x49, 0xb6, 0x71, 0x2a, 0xc3, 0xd5, 0x94, 0x34, 0x67,
|
||||
0xa2, 0x0a, 0x1c, 0xb0, 0x5f, 0x69, 0xa6, 0x40, 0xb1, 0xc4, 0xb7, 0xb2,
|
||||
0x8f, 0xd0, 0x98, 0xa4, 0xa9, 0x41, 0x59, 0x3a, 0xd3, 0xdc, 0x94, 0xd6,
|
||||
0x3c, 0xdb, 0x74, 0x38, 0xa4, 0x4a, 0xcc, 0x4d, 0x25, 0x82, 0xf7, 0x4a,
|
||||
0xa5, 0x53, 0x12, 0x38, 0xee, 0xf3, 0x49, 0x6d, 0x71, 0x91, 0x7e, 0x63,
|
||||
0xb6, 0xab, 0xa6, 0x5f, 0xc3, 0xa4, 0x84, 0xf8, 0x4f, 0x62, 0x51, 0xbe,
|
||||
0xf8, 0xc5, 0xec, 0xdb, 0x38, 0x92, 0xe3, 0x06, 0xe5, 0x08, 0x91, 0x0c,
|
||||
0xc4, 0x28, 0x41, 0x55, 0xfb, 0xcb, 0x5a, 0x89, 0x15, 0x7e, 0x71, 0xe8,
|
||||
0x35, 0xbf, 0x4d, 0x72, 0x09, 0x3d, 0xbe, 0x3a, 0x38, 0x50, 0x5b, 0x77,
|
||||
0x31, 0x1b, 0x8d, 0xb3, 0xc7, 0x24, 0x45, 0x9a, 0xa7, 0xac, 0x6d, 0x00,
|
||||
0x14, 0x5a, 0x04, 0xb7, 0xba, 0x13, 0xeb, 0x51, 0x0a, 0x98, 0x41, 0x41,
|
||||
0x22, 0x4e, 0x65, 0x61, 0x87, 0x81, 0x41, 0x50, 0xa6, 0x79, 0x5c, 0x89,
|
||||
0xde, 0x19, 0x4a, 0x57, 0xd5, 0x2e, 0xe6, 0x5d, 0x1c, 0x53, 0x2c, 0x7e,
|
||||
0x98, 0xcd, 0x1a, 0x06, 0x16, 0xa4, 0x68, 0x73, 0xd0, 0x34, 0x04, 0x13,
|
||||
0x5c, 0xa1, 0x71, 0xd3, 0x5a, 0x7c, 0x55, 0xdb, 0x5e, 0x64, 0xe1, 0x37,
|
||||
0x87, 0x30, 0x56, 0x04, 0xe5, 0x11, 0xb4, 0x29, 0x80, 0x12, 0xf1, 0x79,
|
||||
0x39, 0x88, 0xa2, 0x02, 0x11, 0x7c, 0x27, 0x66, 0xb7, 0x88, 0xb7, 0x78,
|
||||
0xf2, 0xca, 0x0a, 0xa8, 0x38, 0xab, 0x0a, 0x64, 0xc2, 0xbf, 0x66, 0x5d,
|
||||
0x95, 0x84, 0xc1, 0xa1, 0x25, 0x1e, 0x87, 0x5d, 0x1a, 0x50, 0x0b, 0x20,
|
||||
0x12, 0xcc, 0x41, 0xbb, 0x6e, 0x0b, 0x51, 0x38, 0xb8, 0x4b, 0xcb, 0x02,
|
||||
0x03, 0x01, 0x00, 0x01, 0xa3, 0x63, 0x30, 0x61, 0x30, 0x0e, 0x06, 0x03,
|
||||
0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x86,
|
||||
0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05,
|
||||
0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e,
|
||||
0x04, 0x16, 0x04, 0x14, 0xb1, 0x3e, 0xc3, 0x69, 0x03, 0xf8, 0xbf, 0x47,
|
||||
0x01, 0xd4, 0x98, 0x26, 0x1a, 0x08, 0x02, 0xef, 0x63, 0x64, 0x2b, 0xc3,
|
||||
0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80,
|
||||
0x14, 0xb1, 0x3e, 0xc3, 0x69, 0x03, 0xf8, 0xbf, 0x47, 0x01, 0xd4, 0x98,
|
||||
0x26, 0x1a, 0x08, 0x02, 0xef, 0x63, 0x64, 0x2b, 0xc3, 0x30, 0x0d, 0x06,
|
||||
0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00,
|
||||
0x03, 0x82, 0x01, 0x01, 0x00, 0x1c, 0x1a, 0x06, 0x97, 0xdc, 0xd7, 0x9c,
|
||||
0x9f, 0x3c, 0x88, 0x66, 0x06, 0x08, 0x57, 0x21, 0xdb, 0x21, 0x47, 0xf8,
|
||||
0x2a, 0x67, 0xaa, 0xbf, 0x18, 0x32, 0x76, 0x40, 0x10, 0x57, 0xc1, 0x8a,
|
||||
0xf3, 0x7a, 0xd9, 0x11, 0x65, 0x8e, 0x35, 0xfa, 0x9e, 0xfc, 0x45, 0xb5,
|
||||
0x9e, 0xd9, 0x4c, 0x31, 0x4b, 0xb8, 0x91, 0xe8, 0x43, 0x2c, 0x8e, 0xb3,
|
||||
0x78, 0xce, 0xdb, 0xe3, 0x53, 0x79, 0x71, 0xd6, 0xe5, 0x21, 0x94, 0x01,
|
||||
0xda, 0x55, 0x87, 0x9a, 0x24, 0x64, 0xf6, 0x8a, 0x66, 0xcc, 0xde, 0x9c,
|
||||
0x37, 0xcd, 0xa8, 0x34, 0xb1, 0x69, 0x9b, 0x23, 0xc8, 0x9e, 0x78, 0x22,
|
||||
0x2b, 0x70, 0x43, 0xe3, 0x55, 0x47, 0x31, 0x61, 0x19, 0xef, 0x58, 0xc5,
|
||||
0x85, 0x2f, 0x4e, 0x30, 0xf6, 0xa0, 0x31, 0x16, 0x23, 0xc8, 0xe7, 0xe2,
|
||||
0x65, 0x16, 0x33, 0xcb, 0xbf, 0x1a, 0x1b, 0xa0, 0x3d, 0xf8, 0xca, 0x5e,
|
||||
0x8b, 0x31, 0x8b, 0x60, 0x08, 0x89, 0x2d, 0x0c, 0x06, 0x5c, 0x52, 0xb7,
|
||||
0xc4, 0xf9, 0x0a, 0x98, 0xd1, 0x15, 0x5f, 0x9f, 0x12, 0xbe, 0x7c, 0x36,
|
||||
0x63, 0x38, 0xbd, 0x44, 0xa4, 0x7f, 0xe4, 0x26, 0x2b, 0x0a, 0xc4, 0x97,
|
||||
0x69, 0x0d, 0xe9, 0x8c, 0xe2, 0xc0, 0x10, 0x57, 0xb8, 0xc8, 0x76, 0x12,
|
||||
0x91, 0x55, 0xf2, 0x48, 0x69, 0xd8, 0xbc, 0x2a, 0x02, 0x5b, 0x0f, 0x44,
|
||||
0xd4, 0x20, 0x31, 0xdb, 0xf4, 0xba, 0x70, 0x26, 0x5d, 0x90, 0x60, 0x9e,
|
||||
0xbc, 0x4b, 0x17, 0x09, 0x2f, 0xb4, 0xcb, 0x1e, 0x43, 0x68, 0xc9, 0x07,
|
||||
0x27, 0xc1, 0xd2, 0x5c, 0xf7, 0xea, 0x21, 0xb9, 0x68, 0x12, 0x9c, 0x3c,
|
||||
0x9c, 0xbf, 0x9e, 0xfc, 0x80, 0x5c, 0x9b, 0x63, 0xcd, 0xec, 0x47, 0xaa,
|
||||
0x25, 0x27, 0x67, 0xa0, 0x37, 0xf3, 0x00, 0x82, 0x7d, 0x54, 0xd7, 0xa9,
|
||||
0xf8, 0xe9, 0x2e, 0x13, 0xa3, 0x77, 0xe8, 0x1f, 0x4a
|
||||
};
|
||||
const unsigned int caCertLen = 969;
|
||||
|
@ -0,0 +1,132 @@
|
||||
/*
|
||||
HTTP over TLS (HTTPS) example sketch
|
||||
|
||||
This example demonstrates how to use
|
||||
WiFiClientSecure class to connect to a TLS server.
|
||||
|
||||
This example verifies server certificate using the
|
||||
root CA certificate.
|
||||
|
||||
We fetch and display the status of
|
||||
esp8266/Arduino project continuous integration
|
||||
build.
|
||||
|
||||
Created by Ivan Grokhotkov, 2017.
|
||||
This example is in public domain.
|
||||
*/
|
||||
|
||||
#include <time.h>
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <WiFiClientSecure.h>
|
||||
|
||||
const char* ssid = "........";
|
||||
const char* password = "........";
|
||||
|
||||
const char* host = "api.github.com";
|
||||
const int httpsPort = 443;
|
||||
|
||||
// Root certificate used by api.github.com.
|
||||
// Defined in "CACert" tab.
|
||||
extern const unsigned char caCert[] PROGMEM;
|
||||
extern const unsigned int caCertLen;
|
||||
|
||||
WiFiClientSecure client;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
Serial.println();
|
||||
Serial.print("connecting to ");
|
||||
Serial.println(ssid);
|
||||
WiFi.begin(ssid, password);
|
||||
while (WiFi.status() != WL_CONNECTED) {
|
||||
delay(500);
|
||||
Serial.print(".");
|
||||
}
|
||||
Serial.println("");
|
||||
Serial.println("WiFi connected");
|
||||
Serial.println("IP address: ");
|
||||
Serial.println(WiFi.localIP());
|
||||
|
||||
// Synchronize time useing SNTP. This is necessary to verify that
|
||||
// the TLS certificates offered by the server are currently valid.
|
||||
Serial.print("Setting time using SNTP");
|
||||
configTime(8 * 3600, 0, "pool.ntp.org", "time.nist.gov");
|
||||
time_t now = time(nullptr);
|
||||
while (now < 1000) {
|
||||
delay(500);
|
||||
Serial.print(".");
|
||||
now = time(nullptr);
|
||||
}
|
||||
Serial.println("");
|
||||
struct tm timeinfo;
|
||||
gmtime_r(&now, &timeinfo);
|
||||
Serial.print("Current time: ");
|
||||
Serial.print(asctime(&timeinfo));
|
||||
|
||||
// Load root certificate in DER format into WiFiClientSecure object
|
||||
bool res = client.setCACert_P(caCert, caCertLen);
|
||||
if (!res) {
|
||||
Serial.println("Failed to load root CA certificate!");
|
||||
while (true) {
|
||||
yield();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// Connect to remote server
|
||||
Serial.print("connecting to ");
|
||||
Serial.println(host);
|
||||
if (!client.connect(host, httpsPort)) {
|
||||
Serial.println("connection failed");
|
||||
return;
|
||||
}
|
||||
|
||||
// Verify validity of server's certificate
|
||||
if (client.verifyCertChain(host)) {
|
||||
Serial.println("Server certificate verified");
|
||||
} else {
|
||||
Serial.println("ERROR: certificate verification failed!");
|
||||
return;
|
||||
}
|
||||
|
||||
String url = "/repos/esp8266/Arduino/commits/master/status";
|
||||
Serial.print("requesting URL: ");
|
||||
Serial.println(url);
|
||||
|
||||
client.print(String("GET ") + url + " HTTP/1.1\r\n" +
|
||||
"Host: " + host + "\r\n" +
|
||||
"User-Agent: BuildFailureDetectorESP8266\r\n" +
|
||||
"Connection: close\r\n\r\n");
|
||||
|
||||
Serial.println("request sent");
|
||||
while (client.connected()) {
|
||||
String line = client.readStringUntil('\n');
|
||||
if (line == "\r") {
|
||||
Serial.println("headers received");
|
||||
break;
|
||||
}
|
||||
}
|
||||
String line = client.readStringUntil('\n');
|
||||
if (line.startsWith("{\"state\":\"success\"")) {
|
||||
Serial.println("esp8266/Arduino CI successfull!");
|
||||
} else {
|
||||
Serial.println("esp8266/Arduino CI has failed");
|
||||
}
|
||||
Serial.println("reply was:");
|
||||
Serial.println("==========");
|
||||
Serial.println(line);
|
||||
Serial.println("==========");
|
||||
Serial.println();
|
||||
|
||||
static int repeat = 0;
|
||||
if (++repeat == 3) {
|
||||
Serial.println("Done");
|
||||
while (true) {
|
||||
delay(1000);
|
||||
}
|
||||
}
|
||||
delay(10000);
|
||||
}
|
||||
|
||||
|
153
Software/libraries/ESP8266WiFi/examples/NTPClient/NTPClient.ino
Normal file
153
Software/libraries/ESP8266WiFi/examples/NTPClient/NTPClient.ino
Normal file
@ -0,0 +1,153 @@
|
||||
/*
|
||||
|
||||
Udp NTP Client
|
||||
|
||||
Get the time from a Network Time Protocol (NTP) time server
|
||||
Demonstrates use of UDP sendPacket and ReceivePacket
|
||||
For more on NTP time servers and the messages needed to communicate with them,
|
||||
see http://en.wikipedia.org/wiki/Network_Time_Protocol
|
||||
|
||||
created 4 Sep 2010
|
||||
by Michael Margolis
|
||||
modified 9 Apr 2012
|
||||
by Tom Igoe
|
||||
updated for the ESP8266 12 Apr 2015
|
||||
by Ivan Grokhotkov
|
||||
|
||||
This code is in the public domain.
|
||||
|
||||
*/
|
||||
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <WiFiUdp.h>
|
||||
|
||||
char ssid[] = "*************"; // your network SSID (name)
|
||||
char pass[] = "********"; // your network password
|
||||
|
||||
|
||||
unsigned int localPort = 2390; // local port to listen for UDP packets
|
||||
|
||||
/* Don't hardwire the IP address or we won't get the benefits of the pool.
|
||||
* Lookup the IP address for the host name instead */
|
||||
//IPAddress timeServer(129, 6, 15, 28); // time.nist.gov NTP server
|
||||
IPAddress timeServerIP; // time.nist.gov NTP server address
|
||||
const char* ntpServerName = "time.nist.gov";
|
||||
|
||||
const int NTP_PACKET_SIZE = 48; // NTP time stamp is in the first 48 bytes of the message
|
||||
|
||||
byte packetBuffer[ NTP_PACKET_SIZE]; //buffer to hold incoming and outgoing packets
|
||||
|
||||
// A UDP instance to let us send and receive packets over UDP
|
||||
WiFiUDP udp;
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.println();
|
||||
Serial.println();
|
||||
|
||||
// We start by connecting to a WiFi network
|
||||
Serial.print("Connecting to ");
|
||||
Serial.println(ssid);
|
||||
WiFi.begin(ssid, pass);
|
||||
|
||||
while (WiFi.status() != WL_CONNECTED) {
|
||||
delay(500);
|
||||
Serial.print(".");
|
||||
}
|
||||
Serial.println("");
|
||||
|
||||
Serial.println("WiFi connected");
|
||||
Serial.println("IP address: ");
|
||||
Serial.println(WiFi.localIP());
|
||||
|
||||
Serial.println("Starting UDP");
|
||||
udp.begin(localPort);
|
||||
Serial.print("Local port: ");
|
||||
Serial.println(udp.localPort());
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
//get a random server from the pool
|
||||
WiFi.hostByName(ntpServerName, timeServerIP);
|
||||
|
||||
sendNTPpacket(timeServerIP); // send an NTP packet to a time server
|
||||
// wait to see if a reply is available
|
||||
delay(1000);
|
||||
|
||||
int cb = udp.parsePacket();
|
||||
if (!cb) {
|
||||
Serial.println("no packet yet");
|
||||
}
|
||||
else {
|
||||
Serial.print("packet received, length=");
|
||||
Serial.println(cb);
|
||||
// We've received a packet, read the data from it
|
||||
udp.read(packetBuffer, NTP_PACKET_SIZE); // read the packet into the buffer
|
||||
|
||||
//the timestamp starts at byte 40 of the received packet and is four bytes,
|
||||
// or two words, long. First, esxtract the two words:
|
||||
|
||||
unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
|
||||
unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);
|
||||
// combine the four bytes (two words) into a long integer
|
||||
// this is NTP time (seconds since Jan 1 1900):
|
||||
unsigned long secsSince1900 = highWord << 16 | lowWord;
|
||||
Serial.print("Seconds since Jan 1 1900 = " );
|
||||
Serial.println(secsSince1900);
|
||||
|
||||
// now convert NTP time into everyday time:
|
||||
Serial.print("Unix time = ");
|
||||
// Unix time starts on Jan 1 1970. In seconds, that's 2208988800:
|
||||
const unsigned long seventyYears = 2208988800UL;
|
||||
// subtract seventy years:
|
||||
unsigned long epoch = secsSince1900 - seventyYears;
|
||||
// print Unix time:
|
||||
Serial.println(epoch);
|
||||
|
||||
|
||||
// print the hour, minute and second:
|
||||
Serial.print("The UTC time is "); // UTC is the time at Greenwich Meridian (GMT)
|
||||
Serial.print((epoch % 86400L) / 3600); // print the hour (86400 equals secs per day)
|
||||
Serial.print(':');
|
||||
if ( ((epoch % 3600) / 60) < 10 ) {
|
||||
// In the first 10 minutes of each hour, we'll want a leading '0'
|
||||
Serial.print('0');
|
||||
}
|
||||
Serial.print((epoch % 3600) / 60); // print the minute (3600 equals secs per minute)
|
||||
Serial.print(':');
|
||||
if ( (epoch % 60) < 10 ) {
|
||||
// In the first 10 seconds of each minute, we'll want a leading '0'
|
||||
Serial.print('0');
|
||||
}
|
||||
Serial.println(epoch % 60); // print the second
|
||||
}
|
||||
// wait ten seconds before asking for the time again
|
||||
delay(10000);
|
||||
}
|
||||
|
||||
// send an NTP request to the time server at the given address
|
||||
unsigned long sendNTPpacket(IPAddress& address)
|
||||
{
|
||||
Serial.println("sending NTP packet...");
|
||||
// set all bytes in the buffer to 0
|
||||
memset(packetBuffer, 0, NTP_PACKET_SIZE);
|
||||
// Initialize values needed to form NTP request
|
||||
// (see URL above for details on the packets)
|
||||
packetBuffer[0] = 0b11100011; // LI, Version, Mode
|
||||
packetBuffer[1] = 0; // Stratum, or type of clock
|
||||
packetBuffer[2] = 6; // Polling Interval
|
||||
packetBuffer[3] = 0xEC; // Peer Clock Precision
|
||||
// 8 bytes of zero for Root Delay & Root Dispersion
|
||||
packetBuffer[12] = 49;
|
||||
packetBuffer[13] = 0x4E;
|
||||
packetBuffer[14] = 49;
|
||||
packetBuffer[15] = 52;
|
||||
|
||||
// all NTP fields have been given values, now
|
||||
// you can send a packet requesting a timestamp:
|
||||
udp.beginPacket(address, 123); //NTP requests are to port 123
|
||||
udp.write(packetBuffer, NTP_PACKET_SIZE);
|
||||
udp.endPacket();
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Majenko Technologies
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or
|
||||
* other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of Majenko Technologies nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* Create a WiFi access point and provide a web server on it. */
|
||||
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <WiFiClient.h>
|
||||
#include <ESP8266WebServer.h>
|
||||
|
||||
/* Set these to your desired credentials. */
|
||||
const char *ssid = "ESPap";
|
||||
const char *password = "thereisnospoon";
|
||||
|
||||
ESP8266WebServer server(80);
|
||||
|
||||
/* Just a little test message. Go to http://192.168.4.1 in a web browser
|
||||
* connected to this access point to see it.
|
||||
*/
|
||||
void handleRoot() {
|
||||
server.send(200, "text/html", "<h1>You are connected</h1>");
|
||||
}
|
||||
|
||||
void setup() {
|
||||
delay(1000);
|
||||
Serial.begin(115200);
|
||||
Serial.println();
|
||||
Serial.print("Configuring access point...");
|
||||
/* You can remove the password parameter if you want the AP to be open. */
|
||||
WiFi.softAP(ssid, password);
|
||||
|
||||
IPAddress myIP = WiFi.softAPIP();
|
||||
Serial.print("AP IP address: ");
|
||||
Serial.println(myIP);
|
||||
server.on("/", handleRoot);
|
||||
server.begin();
|
||||
Serial.println("HTTP server started");
|
||||
}
|
||||
|
||||
void loop() {
|
||||
server.handleClient();
|
||||
}
|
@ -0,0 +1,96 @@
|
||||
/*
|
||||
* This sketch sends data via HTTP GET requests to data.sparkfun.com service.
|
||||
*
|
||||
* You need to get streamId and privateKey at data.sparkfun.com and paste them
|
||||
* below. Or just customize this script to talk to other HTTP servers.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <ESP8266WiFi.h>
|
||||
|
||||
const char* ssid = "your-ssid";
|
||||
const char* password = "your-password";
|
||||
|
||||
const char* host = "data.sparkfun.com";
|
||||
const char* streamId = "....................";
|
||||
const char* privateKey = "....................";
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
delay(10);
|
||||
|
||||
// We start by connecting to a WiFi network
|
||||
|
||||
Serial.println();
|
||||
Serial.println();
|
||||
Serial.print("Connecting to ");
|
||||
Serial.println(ssid);
|
||||
|
||||
/* Explicitly set the ESP8266 to be a WiFi-client, otherwise, it by default,
|
||||
would try to act as both a client and an access-point and could cause
|
||||
network-issues with your other WiFi-devices on your WiFi-network. */
|
||||
WiFi.mode(WIFI_STA);
|
||||
WiFi.begin(ssid, password);
|
||||
|
||||
while (WiFi.status() != WL_CONNECTED) {
|
||||
delay(500);
|
||||
Serial.print(".");
|
||||
}
|
||||
|
||||
Serial.println("");
|
||||
Serial.println("WiFi connected");
|
||||
Serial.println("IP address: ");
|
||||
Serial.println(WiFi.localIP());
|
||||
}
|
||||
|
||||
int value = 0;
|
||||
|
||||
void loop() {
|
||||
delay(5000);
|
||||
++value;
|
||||
|
||||
Serial.print("connecting to ");
|
||||
Serial.println(host);
|
||||
|
||||
// Use WiFiClient class to create TCP connections
|
||||
WiFiClient client;
|
||||
const int httpPort = 80;
|
||||
if (!client.connect(host, httpPort)) {
|
||||
Serial.println("connection failed");
|
||||
return;
|
||||
}
|
||||
|
||||
// We now create a URI for the request
|
||||
String url = "/input/";
|
||||
url += streamId;
|
||||
url += "?private_key=";
|
||||
url += privateKey;
|
||||
url += "&value=";
|
||||
url += value;
|
||||
|
||||
Serial.print("Requesting URL: ");
|
||||
Serial.println(url);
|
||||
|
||||
// This will send the request to the server
|
||||
client.print(String("GET ") + url + " HTTP/1.1\r\n" +
|
||||
"Host: " + host + "\r\n" +
|
||||
"Connection: close\r\n\r\n");
|
||||
unsigned long timeout = millis();
|
||||
while (client.available() == 0) {
|
||||
if (millis() - timeout > 5000) {
|
||||
Serial.println(">>> Client Timeout !");
|
||||
client.stop();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Read all the lines of the reply from server and print them to Serial
|
||||
while(client.available()){
|
||||
String line = client.readStringUntil('\r');
|
||||
Serial.print(line);
|
||||
}
|
||||
|
||||
Serial.println();
|
||||
Serial.println("closing connection");
|
||||
}
|
||||
|
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* This sketch sends a message to a TCP server
|
||||
*
|
||||
*/
|
||||
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <ESP8266WiFiMulti.h>
|
||||
|
||||
ESP8266WiFiMulti WiFiMulti;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
delay(10);
|
||||
|
||||
// We start by connecting to a WiFi network
|
||||
WiFiMulti.addAP("SSID", "passpasspass");
|
||||
|
||||
Serial.println();
|
||||
Serial.println();
|
||||
Serial.print("Wait for WiFi... ");
|
||||
|
||||
while(WiFiMulti.run() != WL_CONNECTED) {
|
||||
Serial.print(".");
|
||||
delay(500);
|
||||
}
|
||||
|
||||
Serial.println("");
|
||||
Serial.println("WiFi connected");
|
||||
Serial.println("IP address: ");
|
||||
Serial.println(WiFi.localIP());
|
||||
|
||||
delay(500);
|
||||
}
|
||||
|
||||
|
||||
void loop() {
|
||||
const uint16_t port = 80;
|
||||
const char * host = "192.168.1.1"; // ip or dns
|
||||
|
||||
|
||||
|
||||
Serial.print("connecting to ");
|
||||
Serial.println(host);
|
||||
|
||||
// Use WiFiClient class to create TCP connections
|
||||
WiFiClient client;
|
||||
|
||||
if (!client.connect(host, port)) {
|
||||
Serial.println("connection failed");
|
||||
Serial.println("wait 5 sec...");
|
||||
delay(5000);
|
||||
return;
|
||||
}
|
||||
|
||||
// This will send the request to the server
|
||||
client.print("Send this data to server");
|
||||
|
||||
//read back one line from server
|
||||
String line = client.readStringUntil('\r');
|
||||
client.println(line);
|
||||
|
||||
Serial.println("closing connection");
|
||||
client.stop();
|
||||
|
||||
Serial.println("wait 5 sec...");
|
||||
delay(5000);
|
||||
}
|
||||
|
@ -0,0 +1,99 @@
|
||||
/*
|
||||
This sketch shows how to use WiFi event handlers.
|
||||
|
||||
In this example, ESP8266 works in AP mode.
|
||||
Three event handlers are demonstrated:
|
||||
- station connects to the ESP8266 AP
|
||||
- station disconnects from the ESP8266 AP
|
||||
- ESP8266 AP receives a probe request from a station
|
||||
|
||||
Written by Markus Sattler, 2015-12-29.
|
||||
Updated for new event handlers by Ivan Grokhotkov, 2017-02-02.
|
||||
This example is released into public domain,
|
||||
or, at your option, CC0 licensed.
|
||||
*/
|
||||
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <stdio.h>
|
||||
|
||||
const char* ssid = "ap-ssid";
|
||||
const char* password = "ap-password";
|
||||
|
||||
WiFiEventHandler stationConnectedHandler;
|
||||
WiFiEventHandler stationDisconnectedHandler;
|
||||
WiFiEventHandler probeRequestPrintHandler;
|
||||
WiFiEventHandler probeRequestBlinkHandler;
|
||||
|
||||
bool blinkFlag;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
pinMode(LED_BUILTIN, OUTPUT);
|
||||
digitalWrite(LED_BUILTIN, HIGH);
|
||||
|
||||
// Don't save WiFi configuration in flash - optional
|
||||
WiFi.persistent(false);
|
||||
|
||||
// Set up an access point
|
||||
WiFi.mode(WIFI_AP);
|
||||
WiFi.softAP(ssid, password);
|
||||
|
||||
// Register event handlers.
|
||||
// Callback functions will be called as long as these handler objects exist.
|
||||
// Call "onStationConnected" each time a station connects
|
||||
stationConnectedHandler = WiFi.onSoftAPModeStationConnected(&onStationConnected);
|
||||
// Call "onStationDisconnected" each time a station disconnects
|
||||
stationDisconnectedHandler = WiFi.onSoftAPModeStationDisconnected(&onStationDisconnected);
|
||||
// Call "onProbeRequestPrint" and "onProbeRequestBlink" each time
|
||||
// a probe request is received.
|
||||
// Former will print MAC address of the station and RSSI to Serial,
|
||||
// latter will blink an LED.
|
||||
probeRequestPrintHandler = WiFi.onSoftAPModeProbeRequestReceived(&onProbeRequestPrint);
|
||||
probeRequestBlinkHandler = WiFi.onSoftAPModeProbeRequestReceived(&onProbeRequestBlink);
|
||||
}
|
||||
|
||||
void onStationConnected(const WiFiEventSoftAPModeStationConnected& evt) {
|
||||
Serial.print("Station connected: ");
|
||||
Serial.println(macToString(evt.mac));
|
||||
}
|
||||
|
||||
void onStationDisconnected(const WiFiEventSoftAPModeStationDisconnected& evt) {
|
||||
Serial.print("Station disconnected: ");
|
||||
Serial.println(macToString(evt.mac));
|
||||
}
|
||||
|
||||
void onProbeRequestPrint(const WiFiEventSoftAPModeProbeRequestReceived& evt) {
|
||||
Serial.print("Probe request from: ");
|
||||
Serial.print(macToString(evt.mac));
|
||||
Serial.print(" RSSI: ");
|
||||
Serial.println(evt.rssi);
|
||||
}
|
||||
|
||||
void onProbeRequestBlink(const WiFiEventSoftAPModeProbeRequestReceived&) {
|
||||
// We can't use "delay" or other blocking functions in the event handler.
|
||||
// Therefore we set a flag here and then check it inside "loop" function.
|
||||
blinkFlag = true;
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (millis() > 10000 && probeRequestPrintHandler) {
|
||||
// After 10 seconds, disable the probe request event handler which prints.
|
||||
// Other three event handlers remain active.
|
||||
Serial.println("Not printing probe requests any more (LED should still blink)");
|
||||
probeRequestPrintHandler = WiFiEventHandler();
|
||||
}
|
||||
if (blinkFlag) {
|
||||
blinkFlag = false;
|
||||
digitalWrite(LED_BUILTIN, LOW);
|
||||
delay(100);
|
||||
digitalWrite(LED_BUILTIN, HIGH);
|
||||
}
|
||||
delay(10);
|
||||
}
|
||||
|
||||
String macToString(const unsigned char* mac) {
|
||||
char buf[20];
|
||||
snprintf(buf, sizeof(buf), "%02x:%02x:%02x:%02x:%02x:%02x",
|
||||
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
||||
return String(buf);
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* This sketch trys to Connect to the best AP based on a given list
|
||||
*
|
||||
*/
|
||||
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <ESP8266WiFiMulti.h>
|
||||
|
||||
ESP8266WiFiMulti wifiMulti;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
delay(10);
|
||||
|
||||
wifiMulti.addAP("ssid_from_AP_1", "your_password_for_AP_1");
|
||||
wifiMulti.addAP("ssid_from_AP_2", "your_password_for_AP_2");
|
||||
wifiMulti.addAP("ssid_from_AP_3", "your_password_for_AP_3");
|
||||
|
||||
Serial.println("Connecting Wifi...");
|
||||
if(wifiMulti.run() == WL_CONNECTED) {
|
||||
Serial.println("");
|
||||
Serial.println("WiFi connected");
|
||||
Serial.println("IP address: ");
|
||||
Serial.println(WiFi.localIP());
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if(wifiMulti.run() != WL_CONNECTED) {
|
||||
Serial.println("WiFi not connected!");
|
||||
delay(1000);
|
||||
}
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* This sketch demonstrates how to scan WiFi networks.
|
||||
* The API is almost the same as with the WiFi Shield library,
|
||||
* the most obvious difference being the different file you need to include:
|
||||
*/
|
||||
#include "ESP8266WiFi.h"
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
|
||||
// Set WiFi to station mode and disconnect from an AP if it was previously connected
|
||||
WiFi.mode(WIFI_STA);
|
||||
WiFi.disconnect();
|
||||
delay(100);
|
||||
|
||||
Serial.println("Setup done");
|
||||
}
|
||||
|
||||
void loop() {
|
||||
Serial.println("scan start");
|
||||
|
||||
// WiFi.scanNetworks will return the number of networks found
|
||||
int n = WiFi.scanNetworks();
|
||||
Serial.println("scan done");
|
||||
if (n == 0)
|
||||
Serial.println("no networks found");
|
||||
else
|
||||
{
|
||||
Serial.print(n);
|
||||
Serial.println(" networks found");
|
||||
for (int i = 0; i < n; ++i)
|
||||
{
|
||||
// Print SSID and RSSI for each network found
|
||||
Serial.print(i + 1);
|
||||
Serial.print(": ");
|
||||
Serial.print(WiFi.SSID(i));
|
||||
Serial.print(" (");
|
||||
Serial.print(WiFi.RSSI(i));
|
||||
Serial.print(")");
|
||||
Serial.println((WiFi.encryptionType(i) == ENC_TYPE_NONE)?" ":"*");
|
||||
delay(10);
|
||||
}
|
||||
}
|
||||
Serial.println("");
|
||||
|
||||
// Wait a bit before scanning again
|
||||
delay(5000);
|
||||
}
|
@ -0,0 +1,90 @@
|
||||
/*
|
||||
WiFiTelnetToSerial - Example Transparent UART to Telnet Server for esp8266
|
||||
|
||||
Copyright (c) 2015 Hristo Gochkov. All rights reserved.
|
||||
This file is part of the ESP8266WiFi library 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
|
||||
*/
|
||||
#include <ESP8266WiFi.h>
|
||||
|
||||
//how many clients should be able to telnet to this ESP8266
|
||||
#define MAX_SRV_CLIENTS 1
|
||||
const char* ssid = "**********";
|
||||
const char* password = "**********";
|
||||
|
||||
WiFiServer server(23);
|
||||
WiFiClient serverClients[MAX_SRV_CLIENTS];
|
||||
|
||||
void setup() {
|
||||
Serial1.begin(115200);
|
||||
WiFi.begin(ssid, password);
|
||||
Serial1.print("\nConnecting to "); Serial1.println(ssid);
|
||||
uint8_t i = 0;
|
||||
while (WiFi.status() != WL_CONNECTED && i++ < 20) delay(500);
|
||||
if(i == 21){
|
||||
Serial1.print("Could not connect to"); Serial1.println(ssid);
|
||||
while(1) delay(500);
|
||||
}
|
||||
//start UART and the server
|
||||
Serial.begin(115200);
|
||||
server.begin();
|
||||
server.setNoDelay(true);
|
||||
|
||||
Serial1.print("Ready! Use 'telnet ");
|
||||
Serial1.print(WiFi.localIP());
|
||||
Serial1.println(" 23' to connect");
|
||||
}
|
||||
|
||||
void loop() {
|
||||
uint8_t i;
|
||||
//check if there are any new clients
|
||||
if (server.hasClient()){
|
||||
for(i = 0; i < MAX_SRV_CLIENTS; i++){
|
||||
//find free/disconnected spot
|
||||
if (!serverClients[i] || !serverClients[i].connected()){
|
||||
if(serverClients[i]) serverClients[i].stop();
|
||||
serverClients[i] = server.available();
|
||||
Serial1.print("New client: "); Serial1.print(i);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
//no free/disconnected spot so reject
|
||||
WiFiClient serverClient = server.available();
|
||||
serverClient.stop();
|
||||
}
|
||||
//check clients for data
|
||||
for(i = 0; i < MAX_SRV_CLIENTS; i++){
|
||||
if (serverClients[i] && serverClients[i].connected()){
|
||||
if(serverClients[i].available()){
|
||||
//get data from the telnet client and push it to the UART
|
||||
while(serverClients[i].available()) Serial.write(serverClients[i].read());
|
||||
}
|
||||
}
|
||||
}
|
||||
//check UART for data
|
||||
if(Serial.available()){
|
||||
size_t len = Serial.available();
|
||||
uint8_t sbuf[len];
|
||||
Serial.readBytes(sbuf, len);
|
||||
//push UART data to all connected telnet clients
|
||||
for(i = 0; i < MAX_SRV_CLIENTS; i++){
|
||||
if (serverClients[i] && serverClients[i].connected()){
|
||||
serverClients[i].write(sbuf, len);
|
||||
delay(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,98 @@
|
||||
/*
|
||||
* This sketch demonstrates how to set up a simple HTTP-like server.
|
||||
* The server will set a GPIO pin depending on the request
|
||||
* http://server_ip/gpio/0 will set the GPIO2 low,
|
||||
* http://server_ip/gpio/1 will set the GPIO2 high
|
||||
* server_ip is the IP address of the ESP8266 module, will be
|
||||
* printed to Serial when the module is connected.
|
||||
*/
|
||||
|
||||
#include <ESP8266WiFi.h>
|
||||
|
||||
const char* ssid = "your-ssid";
|
||||
const char* password = "your-password";
|
||||
|
||||
// Create an instance of the server
|
||||
// specify the port to listen on as an argument
|
||||
WiFiServer server(80);
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
delay(10);
|
||||
|
||||
// prepare GPIO2
|
||||
pinMode(2, OUTPUT);
|
||||
digitalWrite(2, 0);
|
||||
|
||||
// Connect to WiFi network
|
||||
Serial.println();
|
||||
Serial.println();
|
||||
Serial.print("Connecting to ");
|
||||
Serial.println(ssid);
|
||||
|
||||
WiFi.begin(ssid, password);
|
||||
|
||||
while (WiFi.status() != WL_CONNECTED) {
|
||||
delay(500);
|
||||
Serial.print(".");
|
||||
}
|
||||
Serial.println("");
|
||||
Serial.println("WiFi connected");
|
||||
|
||||
// Start the server
|
||||
server.begin();
|
||||
Serial.println("Server started");
|
||||
|
||||
// Print the IP address
|
||||
Serial.println(WiFi.localIP());
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// Check if a client has connected
|
||||
WiFiClient client = server.available();
|
||||
if (!client) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Wait until the client sends some data
|
||||
Serial.println("new client");
|
||||
while(!client.available()){
|
||||
delay(1);
|
||||
}
|
||||
|
||||
// Read the first line of the request
|
||||
String req = client.readStringUntil('\r');
|
||||
Serial.println(req);
|
||||
client.flush();
|
||||
|
||||
// Match the request
|
||||
int val;
|
||||
if (req.indexOf("/gpio/0") != -1)
|
||||
val = 0;
|
||||
else if (req.indexOf("/gpio/1") != -1)
|
||||
val = 1;
|
||||
else {
|
||||
Serial.println("invalid request");
|
||||
client.stop();
|
||||
return;
|
||||
}
|
||||
|
||||
// Set GPIO2 according to the request
|
||||
digitalWrite(2, val);
|
||||
|
||||
client.flush();
|
||||
|
||||
// Prepare the response
|
||||
String s = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n<!DOCTYPE HTML>\r\n<html>\r\nGPIO is now ";
|
||||
s += (val)?"high":"low";
|
||||
s += "</html>\n";
|
||||
|
||||
// Send the response to the client
|
||||
client.print(s);
|
||||
delay(1);
|
||||
Serial.println("Client disonnected");
|
||||
|
||||
// The client will actually be disconnected
|
||||
// when the function returns and 'client' object is detroyed
|
||||
}
|
||||
|
174
Software/libraries/ESP8266WiFi/keywords.txt
Normal file
174
Software/libraries/ESP8266WiFi/keywords.txt
Normal file
@ -0,0 +1,174 @@
|
||||
#######################################
|
||||
# Syntax Coloring Map For ESP8266WiFi
|
||||
#######################################
|
||||
|
||||
#######################################
|
||||
# Library (KEYWORD3)
|
||||
#######################################
|
||||
|
||||
ESP8266WiFi KEYWORD3
|
||||
|
||||
#######################################
|
||||
# Datatypes (KEYWORD1)
|
||||
#######################################
|
||||
|
||||
WiFi KEYWORD1
|
||||
WiFiClient KEYWORD1
|
||||
WiFiServer KEYWORD1
|
||||
WiFiUDP KEYWORD1
|
||||
WiFiClientSecure KEYWORD1
|
||||
ESP8266WiFiMulti KEYWORD1
|
||||
#######################################
|
||||
# Methods and Functions (KEYWORD2)
|
||||
#######################################
|
||||
|
||||
#ESP8266WiFiGenericClass
|
||||
onEvent KEYWORD2
|
||||
onStationModeConnected KEYWORD2
|
||||
onStationModeDisconnected KEYWORD2
|
||||
onStationModeAuthModeChanged KEYWORD2
|
||||
onStationModeGotIP KEYWORD2
|
||||
onStationModeDHCPTimeout KEYWORD2
|
||||
onSoftAPModeStationConnected KEYWORD2
|
||||
onSoftAPModeStationDisconnected KEYWORD2
|
||||
onWiFiModeChange KEYWORD2
|
||||
channel KEYWORD2
|
||||
setSleepMode KEYWORD2
|
||||
getSleepMode KEYWORD2
|
||||
setPhyMode KEYWORD2
|
||||
getPhyMode KEYWORD2
|
||||
setOutputPower KEYWORD2
|
||||
persistent KEYWORD2
|
||||
mode KEYWORD2
|
||||
getMode KEYWORD2
|
||||
enableSTA KEYWORD2
|
||||
enableAP KEYWORD2
|
||||
forceSleepBegin KEYWORD2
|
||||
forceSleepWake KEYWORD2
|
||||
|
||||
#ESP8266WiFi
|
||||
printDiag KEYWORD2
|
||||
|
||||
#ESP8266WiFiAP
|
||||
softAP KEYWORD2
|
||||
softAPIP KEYWORD2
|
||||
softAPmacAddress KEYWORD2
|
||||
softAPConfig KEYWORD2
|
||||
softAPdisconnect KEYWORD2
|
||||
softAPgetStationNum KEYWORD2
|
||||
|
||||
#ESP8266WiFiMulti
|
||||
addAP KEYWORD2
|
||||
run KEYWORD2
|
||||
|
||||
#ESP8266WiFiScan
|
||||
scanNetworks KEYWORD2
|
||||
scanNetworksAsync KEYWORD2
|
||||
scanComplete KEYWORD2
|
||||
scanDelete KEYWORD2
|
||||
getNetworkInfo KEYWORD2
|
||||
SSID KEYWORD2
|
||||
encryptionType KEYWORD2
|
||||
RSSI KEYWORD2
|
||||
BSSID KEYWORD2
|
||||
BSSIDstr KEYWORD2
|
||||
channel KEYWORD2
|
||||
isHidden KEYWORD2
|
||||
|
||||
#ESP8266WiFiSTA
|
||||
begin KEYWORD2
|
||||
config KEYWORD2
|
||||
reconnect KEYWORD2
|
||||
disconnect KEYWORD2
|
||||
isConnected KEYWORD2
|
||||
setAutoConnect KEYWORD2
|
||||
getAutoConnect KEYWORD2
|
||||
setAutoReconnect KEYWORD2
|
||||
waitForConnectResult KEYWORD2
|
||||
localIP KEYWORD2
|
||||
macAddress KEYWORD2
|
||||
subnetMask KEYWORD2
|
||||
gatewayIP KEYWORD2
|
||||
dnsIP KEYWORD2
|
||||
hostname KEYWORD2
|
||||
status KEYWORD2
|
||||
SSID KEYWORD2
|
||||
psk KEYWORD2
|
||||
BSSID KEYWORD2
|
||||
BSSIDstr KEYWORD2
|
||||
RSSI KEYWORD2
|
||||
beginWPSConfig KEYWORD2
|
||||
beginSmartConfig KEYWORD2
|
||||
stopSmartConfig KEYWORD2
|
||||
smartConfigDone KEYWORD2
|
||||
|
||||
#WiFiClient
|
||||
status KEYWORD2
|
||||
connect KEYWORD2
|
||||
write KEYWORD2
|
||||
write_P KEYWORD2
|
||||
available KEYWORD2
|
||||
read KEYWORD2
|
||||
peek KEYWORD2
|
||||
peekBytes KEYWORD2
|
||||
flush KEYWORD2
|
||||
stop KEYWORD2
|
||||
connected KEYWORD2
|
||||
bool KEYWORD2
|
||||
remoteIP KEYWORD2
|
||||
remotePort KEYWORD2
|
||||
localIP KEYWORD2
|
||||
localPort KEYWORD2
|
||||
getNoDelay KEYWORD2
|
||||
setNoDelay KEYWORD2
|
||||
setLocalPortStart KEYWORD2
|
||||
stopAll KEYWORD2
|
||||
stopAllExcept KEYWORD2
|
||||
|
||||
#WiFiClientSecure
|
||||
verify KEYWORD2
|
||||
verifyCertChain KEYWORD2
|
||||
setCertificate KEYWORD2
|
||||
setPrivateKey KEYWORD2
|
||||
setCACert KEYWORD2
|
||||
setCertificate_P KEYWORD2
|
||||
setPrivateKey_P KEYWORD2
|
||||
setCACert_P KEYWORD2
|
||||
loadCertificate KEYWORD2
|
||||
loadPrivateKey KEYWORD2
|
||||
loadCACert KEYWORD2
|
||||
allowSelfSignedCerts KEYWORD2
|
||||
|
||||
#WiFiServer
|
||||
hasClient KEYWORD2
|
||||
close KEYWORD2
|
||||
|
||||
#WiFiUdp
|
||||
beginMulticast KEYWORD2
|
||||
beginPacket KEYWORD2
|
||||
beginPacketMulticast KEYWORD2
|
||||
endPacket KEYWORD2
|
||||
parsePacket KEYWORD2
|
||||
remoteIP KEYWORD2
|
||||
remotePort KEYWORD2
|
||||
destinationIP KEYWORD2
|
||||
localPort KEYWORD2
|
||||
stopAll KEYWORD2
|
||||
stopAllExcept KEYWORD2
|
||||
|
||||
#######################################
|
||||
# Constants (LITERAL1)
|
||||
#######################################
|
||||
WIFI_OFF LITERAL1
|
||||
WIFI_AP LITERAL1
|
||||
WIFI_STA LITERAL1
|
||||
WIFI_AP_STA LITERAL1
|
||||
WIFI_PHY_MODE_11B LITERAL1
|
||||
WIFI_PHY_MODE_11G LITERAL1
|
||||
WIFI_PHY_MODE_11N LITERAL1
|
||||
WIFI_NONE_SLEEP LITERAL1
|
||||
WIFI_LIGHT_SLEEP LITERAL1
|
||||
WIFI_MODEM_SLEEP LITERAL1
|
||||
WIFICLIENT_MAX_PACKET_SIZE LITERAL1
|
||||
UDP_TX_PACKET_MAX_SIZE LITERAL1
|
||||
DEBUG_ESP_WIFI LITERAL1
|
9
Software/libraries/ESP8266WiFi/library.properties
Normal file
9
Software/libraries/ESP8266WiFi/library.properties
Normal file
@ -0,0 +1,9 @@
|
||||
name=ESP8266WiFi
|
||||
version=1.0
|
||||
author=Ivan Grokhotkov
|
||||
maintainer=Ivan Grokhtkov <ivan@esp8266.com>
|
||||
sentence=Enables network connection (local and Internet) using the ESP8266 built-in WiFi.
|
||||
paragraph=With this library you can instantiate Servers, Clients and send/receive UDP packets through WiFi. The shield can connect either to open or encrypted networks (WEP, WPA). The IP address can be assigned statically or through a DHCP. The library can also manage DNS.
|
||||
category=Communication
|
||||
url=
|
||||
architectures=esp8266
|
92
Software/libraries/ESP8266WiFi/src/ESP8266WiFi.cpp
Normal file
92
Software/libraries/ESP8266WiFi/src/ESP8266WiFi.cpp
Normal file
@ -0,0 +1,92 @@
|
||||
/*
|
||||
ESP8266WiFi.cpp - WiFi library for esp8266
|
||||
|
||||
Copyright (c) 2014 Ivan Grokhotkov. 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
|
||||
|
||||
Reworked on 28 Dec 2015 by Markus Sattler
|
||||
|
||||
*/
|
||||
|
||||
#include "ESP8266WiFi.h"
|
||||
|
||||
extern "C" {
|
||||
#include "c_types.h"
|
||||
#include "ets_sys.h"
|
||||
#include "os_type.h"
|
||||
#include "osapi.h"
|
||||
#include "mem.h"
|
||||
#include "user_interface.h"
|
||||
#include "smartconfig.h"
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/err.h"
|
||||
#include "lwip/dns.h"
|
||||
}
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------------------------
|
||||
// ---------------------------------------------------------- Debug ------------------------------------------------------
|
||||
// -----------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
/**
|
||||
* Output WiFi settings to an object derived from Print interface (like Serial).
|
||||
* @param p Print interface
|
||||
*/
|
||||
void ESP8266WiFiClass::printDiag(Print& p) {
|
||||
const char* modes[] = { "NULL", "STA", "AP", "STA+AP" };
|
||||
p.print("Mode: ");
|
||||
p.println(modes[wifi_get_opmode()]);
|
||||
|
||||
const char* phymodes[] = { "", "B", "G", "N" };
|
||||
p.print("PHY mode: ");
|
||||
p.println(phymodes[(int) wifi_get_phy_mode()]);
|
||||
|
||||
p.print("Channel: ");
|
||||
p.println(wifi_get_channel());
|
||||
|
||||
p.print("AP id: ");
|
||||
p.println(wifi_station_get_current_ap_id());
|
||||
|
||||
p.print("Status: ");
|
||||
p.println(wifi_station_get_connect_status());
|
||||
|
||||
p.print("Auto connect: ");
|
||||
p.println(wifi_station_get_auto_connect());
|
||||
|
||||
struct station_config conf;
|
||||
wifi_station_get_config(&conf);
|
||||
|
||||
const char* ssid = reinterpret_cast<const char*>(conf.ssid);
|
||||
p.print("SSID (");
|
||||
p.print(strlen(ssid));
|
||||
p.print("): ");
|
||||
p.println(ssid);
|
||||
|
||||
const char* passphrase = reinterpret_cast<const char*>(conf.password);
|
||||
p.print("Passphrase (");
|
||||
p.print(strlen(passphrase));
|
||||
p.print("): ");
|
||||
p.println(passphrase);
|
||||
|
||||
p.print("BSSID set: ");
|
||||
p.println(conf.bssid_set);
|
||||
|
||||
}
|
||||
|
||||
ESP8266WiFiClass WiFi;
|
88
Software/libraries/ESP8266WiFi/src/ESP8266WiFi.h
Normal file
88
Software/libraries/ESP8266WiFi/src/ESP8266WiFi.h
Normal file
@ -0,0 +1,88 @@
|
||||
/*
|
||||
ESP8266WiFi.h - esp8266 Wifi support.
|
||||
Based on WiFi.h from Arduino WiFi shield library.
|
||||
Copyright (c) 2011-2014 Arduino. All right reserved.
|
||||
Modified by Ivan Grokhotkov, December 2014
|
||||
|
||||
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
|
||||
*/
|
||||
|
||||
#ifndef WiFi_h
|
||||
#define WiFi_h
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
extern "C" {
|
||||
#include "include/wl_definitions.h"
|
||||
}
|
||||
|
||||
#include "IPAddress.h"
|
||||
|
||||
#include "ESP8266WiFiType.h"
|
||||
#include "ESP8266WiFiSTA.h"
|
||||
#include "ESP8266WiFiAP.h"
|
||||
#include "ESP8266WiFiScan.h"
|
||||
#include "ESP8266WiFiGeneric.h"
|
||||
|
||||
#include "WiFiClient.h"
|
||||
#include "WiFiServer.h"
|
||||
#include "WiFiClientSecure.h"
|
||||
|
||||
#ifdef DEBUG_ESP_WIFI
|
||||
#ifdef DEBUG_ESP_PORT
|
||||
#define DEBUG_WIFI(...) DEBUG_ESP_PORT.printf( __VA_ARGS__ )
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef DEBUG_WIFI
|
||||
#define DEBUG_WIFI(...)
|
||||
#endif
|
||||
|
||||
|
||||
class ESP8266WiFiClass : public ESP8266WiFiGenericClass, public ESP8266WiFiSTAClass, public ESP8266WiFiScanClass, public ESP8266WiFiAPClass {
|
||||
public:
|
||||
|
||||
// workaround same function name with different signature
|
||||
using ESP8266WiFiGenericClass::channel;
|
||||
|
||||
using ESP8266WiFiSTAClass::SSID;
|
||||
using ESP8266WiFiSTAClass::RSSI;
|
||||
using ESP8266WiFiSTAClass::BSSID;
|
||||
using ESP8266WiFiSTAClass::BSSIDstr;
|
||||
|
||||
using ESP8266WiFiScanClass::SSID;
|
||||
using ESP8266WiFiScanClass::encryptionType;
|
||||
using ESP8266WiFiScanClass::RSSI;
|
||||
using ESP8266WiFiScanClass::BSSID;
|
||||
using ESP8266WiFiScanClass::BSSIDstr;
|
||||
using ESP8266WiFiScanClass::channel;
|
||||
using ESP8266WiFiScanClass::isHidden;
|
||||
|
||||
// ----------------------------------------------------------------------------------------------
|
||||
// ------------------------------------------- Debug --------------------------------------------
|
||||
// ----------------------------------------------------------------------------------------------
|
||||
|
||||
public:
|
||||
|
||||
void printDiag(Print& dest);
|
||||
|
||||
friend class WiFiClient;
|
||||
friend class WiFiServer;
|
||||
|
||||
};
|
||||
|
||||
extern ESP8266WiFiClass WiFi;
|
||||
|
||||
#endif
|
328
Software/libraries/ESP8266WiFi/src/ESP8266WiFiAP.cpp
Normal file
328
Software/libraries/ESP8266WiFi/src/ESP8266WiFiAP.cpp
Normal file
@ -0,0 +1,328 @@
|
||||
/*
|
||||
ESP8266WiFiSTA.cpp - WiFi library for esp8266
|
||||
|
||||
Copyright (c) 2014 Ivan Grokhotkov. 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
|
||||
|
||||
Reworked on 28 Dec 2015 by Markus Sattler
|
||||
|
||||
*/
|
||||
|
||||
#include "ESP8266WiFi.h"
|
||||
#include "ESP8266WiFiGeneric.h"
|
||||
#include "ESP8266WiFiAP.h"
|
||||
|
||||
extern "C" {
|
||||
#include "c_types.h"
|
||||
#include "ets_sys.h"
|
||||
#include "os_type.h"
|
||||
#include "osapi.h"
|
||||
#include "mem.h"
|
||||
#include "user_interface.h"
|
||||
}
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------------------------
|
||||
// ---------------------------------------------------- Private functions ------------------------------------------------
|
||||
// -----------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
static bool softap_config_equal(const softap_config& lhs, const softap_config& rhs);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* compare two AP configurations
|
||||
* @param lhs softap_config
|
||||
* @param rhs softap_config
|
||||
* @return equal
|
||||
*/
|
||||
static bool softap_config_equal(const softap_config& lhs, const softap_config& rhs) {
|
||||
if(strcmp(reinterpret_cast<const char*>(lhs.ssid), reinterpret_cast<const char*>(rhs.ssid)) != 0) {
|
||||
return false;
|
||||
}
|
||||
if(strcmp(reinterpret_cast<const char*>(lhs.password), reinterpret_cast<const char*>(rhs.password)) != 0) {
|
||||
return false;
|
||||
}
|
||||
if(lhs.channel != rhs.channel) {
|
||||
return false;
|
||||
}
|
||||
if(lhs.ssid_hidden != rhs.ssid_hidden) {
|
||||
return false;
|
||||
}
|
||||
if(lhs.max_connection != rhs.max_connection) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------------------------
|
||||
// ----------------------------------------------------- AP function -----------------------------------------------------
|
||||
// -----------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
/**
|
||||
* Set up an access point
|
||||
* @param ssid Pointer to the SSID (max 63 char).
|
||||
* @param passphrase (for WPA2 min 8 char, for open use NULL)
|
||||
* @param channel WiFi channel number, 1 - 13.
|
||||
* @param ssid_hidden Network cloaking (0 = broadcast SSID, 1 = hide SSID)
|
||||
* @param max_connection Max simultaneous connected clients, 1 - 4.
|
||||
*/
|
||||
bool ESP8266WiFiAPClass::softAP(const char* ssid, const char* passphrase, int channel, int ssid_hidden, int max_connection) {
|
||||
|
||||
if(!WiFi.enableAP(true)) {
|
||||
// enable AP failed
|
||||
DEBUG_WIFI("[AP] enableAP failed!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!ssid || strlen(ssid) == 0 || strlen(ssid) > 31) {
|
||||
// fail SSID too long or missing!
|
||||
DEBUG_WIFI("[AP] SSID too long or missing!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(passphrase && strlen(passphrase) > 0 && (strlen(passphrase) > 63 || strlen(passphrase) < 8)) {
|
||||
// fail passphrase to long or short!
|
||||
DEBUG_WIFI("[AP] fail passphrase to long or short!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ret = true;
|
||||
|
||||
struct softap_config conf;
|
||||
strcpy(reinterpret_cast<char*>(conf.ssid), ssid);
|
||||
conf.channel = channel;
|
||||
conf.ssid_len = strlen(ssid);
|
||||
conf.ssid_hidden = ssid_hidden;
|
||||
conf.max_connection = max_connection;
|
||||
conf.beacon_interval = 100;
|
||||
|
||||
if(!passphrase || strlen(passphrase) == 0) {
|
||||
conf.authmode = AUTH_OPEN;
|
||||
*conf.password = 0;
|
||||
} else {
|
||||
conf.authmode = AUTH_WPA2_PSK;
|
||||
strcpy(reinterpret_cast<char*>(conf.password), passphrase);
|
||||
}
|
||||
|
||||
struct softap_config conf_current;
|
||||
wifi_softap_get_config(&conf_current);
|
||||
if(!softap_config_equal(conf, conf_current)) {
|
||||
|
||||
ETS_UART_INTR_DISABLE();
|
||||
if(WiFi._persistent) {
|
||||
ret = wifi_softap_set_config(&conf);
|
||||
} else {
|
||||
ret = wifi_softap_set_config_current(&conf);
|
||||
}
|
||||
ETS_UART_INTR_ENABLE();
|
||||
|
||||
if(!ret) {
|
||||
DEBUG_WIFI("[AP] set_config failed!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
} else {
|
||||
DEBUG_WIFI("[AP] softap config unchanged\n");
|
||||
}
|
||||
|
||||
if(wifi_softap_dhcps_status() != DHCP_STARTED) {
|
||||
DEBUG_WIFI("[AP] DHCP not started, starting...\n");
|
||||
if(!wifi_softap_dhcps_start()) {
|
||||
DEBUG_WIFI("[AP] wifi_softap_dhcps_start failed!\n");
|
||||
ret = false;
|
||||
}
|
||||
}
|
||||
|
||||
// check IP config
|
||||
struct ip_info ip;
|
||||
if(wifi_get_ip_info(SOFTAP_IF, &ip)) {
|
||||
if(ip.ip.addr == 0x00000000) {
|
||||
// Invalid config
|
||||
DEBUG_WIFI("[AP] IP config Invalid resetting...\n");
|
||||
//192.168.244.1 , 192.168.244.1 , 255.255.255.0
|
||||
ret = softAPConfig(0x01F4A8C0, 0x01F4A8C0, 0x00FFFFFF);
|
||||
if(!ret) {
|
||||
DEBUG_WIFI("[AP] softAPConfig failed!\n");
|
||||
ret = false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
DEBUG_WIFI("[AP] wifi_get_ip_info failed!\n");
|
||||
ret = false;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Configure access point
|
||||
* @param local_ip access point IP
|
||||
* @param gateway gateway IP
|
||||
* @param subnet subnet mask
|
||||
*/
|
||||
bool ESP8266WiFiAPClass::softAPConfig(IPAddress local_ip, IPAddress gateway, IPAddress subnet) {
|
||||
DEBUG_WIFI("[APConfig] local_ip: %s gateway: %s subnet: %s\n", local_ip.toString().c_str(), gateway.toString().c_str(), subnet.toString().c_str());
|
||||
if(!WiFi.enableAP(true)) {
|
||||
// enable AP failed
|
||||
DEBUG_WIFI("[APConfig] enableAP failed!\n");
|
||||
return false;
|
||||
}
|
||||
bool ret = true;
|
||||
|
||||
struct ip_info info;
|
||||
info.ip.addr = static_cast<uint32_t>(local_ip);
|
||||
info.gw.addr = static_cast<uint32_t>(gateway);
|
||||
info.netmask.addr = static_cast<uint32_t>(subnet);
|
||||
|
||||
if(!wifi_softap_dhcps_stop()) {
|
||||
DEBUG_WIFI("[APConfig] wifi_softap_dhcps_stop failed!\n");
|
||||
}
|
||||
|
||||
if(!wifi_set_ip_info(SOFTAP_IF, &info)) {
|
||||
DEBUG_WIFI("[APConfig] wifi_set_ip_info failed!\n");
|
||||
ret = false;
|
||||
}
|
||||
|
||||
struct dhcps_lease dhcp_lease;
|
||||
IPAddress ip = local_ip;
|
||||
ip[3] += 99;
|
||||
dhcp_lease.start_ip.addr = static_cast<uint32_t>(ip);
|
||||
DEBUG_WIFI("[APConfig] DHCP IP start: %s\n", ip.toString().c_str());
|
||||
|
||||
ip[3] += 100;
|
||||
dhcp_lease.end_ip.addr = static_cast<uint32_t>(ip);
|
||||
DEBUG_WIFI("[APConfig] DHCP IP end: %s\n", ip.toString().c_str());
|
||||
|
||||
if(!wifi_softap_set_dhcps_lease(&dhcp_lease)) {
|
||||
DEBUG_WIFI("[APConfig] wifi_set_ip_info failed!\n");
|
||||
ret = false;
|
||||
}
|
||||
|
||||
// set lease time to 720min --> 12h
|
||||
if(!wifi_softap_set_dhcps_lease_time(720)) {
|
||||
DEBUG_WIFI("[APConfig] wifi_softap_set_dhcps_lease_time failed!\n");
|
||||
ret = false;
|
||||
}
|
||||
|
||||
uint8 mode = 1;
|
||||
if(!wifi_softap_set_dhcps_offer_option(OFFER_ROUTER, &mode)) {
|
||||
DEBUG_WIFI("[APConfig] wifi_softap_set_dhcps_offer_option failed!\n");
|
||||
ret = false;
|
||||
}
|
||||
|
||||
if(!wifi_softap_dhcps_start()) {
|
||||
DEBUG_WIFI("[APConfig] wifi_softap_dhcps_start failed!\n");
|
||||
ret = false;
|
||||
}
|
||||
|
||||
// check config
|
||||
if(wifi_get_ip_info(SOFTAP_IF, &info)) {
|
||||
if(info.ip.addr == 0x00000000) {
|
||||
DEBUG_WIFI("[APConfig] IP config Invalid?!\n");
|
||||
ret = false;
|
||||
} else if(local_ip != info.ip.addr) {
|
||||
ip = info.ip.addr;
|
||||
DEBUG_WIFI("[APConfig] IP config not set correct?! new IP: %s\n", ip.toString().c_str());
|
||||
ret = false;
|
||||
}
|
||||
} else {
|
||||
DEBUG_WIFI("[APConfig] wifi_get_ip_info failed!\n");
|
||||
ret = false;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Disconnect from the network (close AP)
|
||||
* @param wifioff disable mode?
|
||||
* @return one value of wl_status_t enum
|
||||
*/
|
||||
bool ESP8266WiFiAPClass::softAPdisconnect(bool wifioff) {
|
||||
bool ret;
|
||||
struct softap_config conf;
|
||||
*conf.ssid = 0;
|
||||
*conf.password = 0;
|
||||
ETS_UART_INTR_DISABLE();
|
||||
if(WiFi._persistent) {
|
||||
ret = wifi_softap_set_config(&conf);
|
||||
} else {
|
||||
ret = wifi_softap_set_config_current(&conf);
|
||||
}
|
||||
ETS_UART_INTR_ENABLE();
|
||||
|
||||
if(!ret) {
|
||||
DEBUG_WIFI("[APdisconnect] set_config failed!\n");
|
||||
}
|
||||
|
||||
if(wifioff) {
|
||||
ret = WiFi.enableAP(false);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the count of the Station / client that are connected to the softAP interface
|
||||
* @return Stations count
|
||||
*/
|
||||
uint8_t ESP8266WiFiAPClass::softAPgetStationNum() {
|
||||
return wifi_softap_get_station_num();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the softAP interface IP address.
|
||||
* @return IPAddress softAP IP
|
||||
*/
|
||||
IPAddress ESP8266WiFiAPClass::softAPIP() {
|
||||
struct ip_info ip;
|
||||
wifi_get_ip_info(SOFTAP_IF, &ip);
|
||||
return IPAddress(ip.ip.addr);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the softAP interface MAC address.
|
||||
* @param mac pointer to uint8_t array with length WL_MAC_ADDR_LENGTH
|
||||
* @return pointer to uint8_t*
|
||||
*/
|
||||
uint8_t* ESP8266WiFiAPClass::softAPmacAddress(uint8_t* mac) {
|
||||
wifi_get_macaddr(SOFTAP_IF, mac);
|
||||
return mac;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the softAP interface MAC address.
|
||||
* @return String mac
|
||||
*/
|
||||
String ESP8266WiFiAPClass::softAPmacAddress(void) {
|
||||
uint8_t mac[6];
|
||||
char macStr[18] = { 0 };
|
||||
wifi_get_macaddr(SOFTAP_IF, mac);
|
||||
|
||||
sprintf(macStr, "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
||||
return String(macStr);
|
||||
}
|
54
Software/libraries/ESP8266WiFi/src/ESP8266WiFiAP.h
Normal file
54
Software/libraries/ESP8266WiFi/src/ESP8266WiFiAP.h
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
ESP8266WiFiAP.h - esp8266 Wifi support.
|
||||
Based on WiFi.h from Arduino WiFi shield library.
|
||||
Copyright (c) 2011-2014 Arduino. All right reserved.
|
||||
Modified by Ivan Grokhotkov, December 2014
|
||||
Reworked by Markus Sattler, December 2015
|
||||
|
||||
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
|
||||
*/
|
||||
|
||||
#ifndef ESP8266WIFIAP_H_
|
||||
#define ESP8266WIFIAP_H_
|
||||
|
||||
|
||||
#include "ESP8266WiFiType.h"
|
||||
#include "ESP8266WiFiGeneric.h"
|
||||
|
||||
|
||||
class ESP8266WiFiAPClass {
|
||||
|
||||
// ----------------------------------------------------------------------------------------------
|
||||
// ----------------------------------------- AP function ----------------------------------------
|
||||
// ----------------------------------------------------------------------------------------------
|
||||
|
||||
public:
|
||||
|
||||
bool softAP(const char* ssid, const char* passphrase = NULL, int channel = 1, int ssid_hidden = 0, int max_connection = 4);
|
||||
bool softAPConfig(IPAddress local_ip, IPAddress gateway, IPAddress subnet);
|
||||
bool softAPdisconnect(bool wifioff = false);
|
||||
|
||||
uint8_t softAPgetStationNum();
|
||||
|
||||
IPAddress softAPIP();
|
||||
|
||||
uint8_t* softAPmacAddress(uint8_t* mac);
|
||||
String softAPmacAddress(void);
|
||||
|
||||
protected:
|
||||
|
||||
};
|
||||
|
||||
#endif /* ESP8266WIFIAP_H_*/
|
500
Software/libraries/ESP8266WiFi/src/ESP8266WiFiGeneric.cpp
Normal file
500
Software/libraries/ESP8266WiFi/src/ESP8266WiFiGeneric.cpp
Normal file
@ -0,0 +1,500 @@
|
||||
/*
|
||||
ESP8266WiFiGeneric.cpp - WiFi library for esp8266
|
||||
|
||||
Copyright (c) 2014 Ivan Grokhotkov. 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
|
||||
|
||||
Reworked on 28 Dec 2015 by Markus Sattler
|
||||
|
||||
*/
|
||||
|
||||
#include <list>
|
||||
#include <string.h>
|
||||
#include "ESP8266WiFi.h"
|
||||
#include "ESP8266WiFiGeneric.h"
|
||||
|
||||
extern "C" {
|
||||
#include "c_types.h"
|
||||
#include "ets_sys.h"
|
||||
#include "os_type.h"
|
||||
#include "osapi.h"
|
||||
#include "mem.h"
|
||||
#include "user_interface.h"
|
||||
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/err.h"
|
||||
#include "lwip/dns.h"
|
||||
#include "lwip/init.h" // LWIP_VERSION_
|
||||
}
|
||||
|
||||
#include "WiFiClient.h"
|
||||
#include "WiFiUdp.h"
|
||||
#include "debug.h"
|
||||
|
||||
extern "C" void esp_schedule();
|
||||
extern "C" void esp_yield();
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------------------------
|
||||
// ------------------------------------------------- Generic WiFi function -----------------------------------------------
|
||||
// -----------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
struct WiFiEventHandlerOpaque
|
||||
{
|
||||
WiFiEventHandlerOpaque(WiFiEvent_t event, std::function<void(System_Event_t*)> handler)
|
||||
: mEvent(event), mHandler(handler)
|
||||
{
|
||||
}
|
||||
|
||||
void operator()(System_Event_t* e)
|
||||
{
|
||||
if (static_cast<WiFiEvent>(e->event) == mEvent || mEvent == WIFI_EVENT_ANY) {
|
||||
mHandler(e);
|
||||
}
|
||||
}
|
||||
|
||||
bool canExpire()
|
||||
{
|
||||
return mCanExpire;
|
||||
}
|
||||
|
||||
WiFiEvent_t mEvent;
|
||||
std::function<void(System_Event_t*)> mHandler;
|
||||
bool mCanExpire = true; /* stopgap solution to handle deprecated void onEvent(cb, evt) case */
|
||||
};
|
||||
|
||||
static std::list<WiFiEventHandler> sCbEventList;
|
||||
|
||||
bool ESP8266WiFiGenericClass::_persistent = true;
|
||||
WiFiMode_t ESP8266WiFiGenericClass::_forceSleepLastMode = WIFI_OFF;
|
||||
|
||||
ESP8266WiFiGenericClass::ESP8266WiFiGenericClass()
|
||||
{
|
||||
wifi_set_event_handler_cb((wifi_event_handler_cb_t) &ESP8266WiFiGenericClass::_eventCallback);
|
||||
}
|
||||
|
||||
void ESP8266WiFiGenericClass::onEvent(WiFiEventCb f, WiFiEvent_t event)
|
||||
{
|
||||
WiFiEventHandler handler = std::make_shared<WiFiEventHandlerOpaque>(event, [f](System_Event_t* e) {
|
||||
(*f)(static_cast<WiFiEvent>(e->event));
|
||||
});
|
||||
handler->mCanExpire = false;
|
||||
sCbEventList.push_back(handler);
|
||||
}
|
||||
|
||||
WiFiEventHandler ESP8266WiFiGenericClass::onStationModeConnected(std::function<void(const WiFiEventStationModeConnected&)> f)
|
||||
{
|
||||
WiFiEventHandler handler = std::make_shared<WiFiEventHandlerOpaque>(WIFI_EVENT_STAMODE_CONNECTED, [f](System_Event_t* e) {
|
||||
auto& src = e->event_info.connected;
|
||||
WiFiEventStationModeConnected dst;
|
||||
dst.ssid = String(reinterpret_cast<char*>(src.ssid));
|
||||
memcpy(dst.bssid, src.bssid, 6);
|
||||
dst.channel = src.channel;
|
||||
f(dst);
|
||||
});
|
||||
sCbEventList.push_back(handler);
|
||||
return handler;
|
||||
}
|
||||
|
||||
WiFiEventHandler ESP8266WiFiGenericClass::onStationModeDisconnected(std::function<void(const WiFiEventStationModeDisconnected&)> f)
|
||||
{
|
||||
WiFiEventHandler handler = std::make_shared<WiFiEventHandlerOpaque>(WIFI_EVENT_STAMODE_DISCONNECTED, [f](System_Event_t* e){
|
||||
auto& src = e->event_info.disconnected;
|
||||
WiFiEventStationModeDisconnected dst;
|
||||
dst.ssid = String(reinterpret_cast<char*>(src.ssid));
|
||||
memcpy(dst.bssid, src.bssid, 6);
|
||||
dst.reason = static_cast<WiFiDisconnectReason>(src.reason);
|
||||
f(dst);
|
||||
});
|
||||
sCbEventList.push_back(handler);
|
||||
return handler;
|
||||
}
|
||||
|
||||
WiFiEventHandler ESP8266WiFiGenericClass::onStationModeAuthModeChanged(std::function<void(const WiFiEventStationModeAuthModeChanged&)> f)
|
||||
{
|
||||
WiFiEventHandler handler = std::make_shared<WiFiEventHandlerOpaque>(WIFI_EVENT_STAMODE_AUTHMODE_CHANGE, [f](System_Event_t* e){
|
||||
auto& src = e->event_info.auth_change;
|
||||
WiFiEventStationModeAuthModeChanged dst;
|
||||
dst.oldMode = src.old_mode;
|
||||
dst.newMode = src.new_mode;
|
||||
f(dst);
|
||||
});
|
||||
sCbEventList.push_back(handler);
|
||||
return handler;
|
||||
}
|
||||
|
||||
WiFiEventHandler ESP8266WiFiGenericClass::onStationModeGotIP(std::function<void(const WiFiEventStationModeGotIP&)> f)
|
||||
{
|
||||
WiFiEventHandler handler = std::make_shared<WiFiEventHandlerOpaque>(WIFI_EVENT_STAMODE_GOT_IP, [f](System_Event_t* e){
|
||||
auto& src = e->event_info.got_ip;
|
||||
WiFiEventStationModeGotIP dst;
|
||||
dst.ip = src.ip.addr;
|
||||
dst.mask = src.mask.addr;
|
||||
dst.gw = src.gw.addr;
|
||||
f(dst);
|
||||
});
|
||||
sCbEventList.push_back(handler);
|
||||
return handler;
|
||||
}
|
||||
|
||||
WiFiEventHandler ESP8266WiFiGenericClass::onStationModeDHCPTimeout(std::function<void(void)> f)
|
||||
{
|
||||
WiFiEventHandler handler = std::make_shared<WiFiEventHandlerOpaque>(WIFI_EVENT_STAMODE_DHCP_TIMEOUT, [f](System_Event_t* e){
|
||||
(void) e;
|
||||
f();
|
||||
});
|
||||
sCbEventList.push_back(handler);
|
||||
return handler;
|
||||
}
|
||||
|
||||
WiFiEventHandler ESP8266WiFiGenericClass::onSoftAPModeStationConnected(std::function<void(const WiFiEventSoftAPModeStationConnected&)> f)
|
||||
{
|
||||
WiFiEventHandler handler = std::make_shared<WiFiEventHandlerOpaque>(WIFI_EVENT_SOFTAPMODE_STACONNECTED, [f](System_Event_t* e){
|
||||
auto& src = e->event_info.sta_connected;
|
||||
WiFiEventSoftAPModeStationConnected dst;
|
||||
memcpy(dst.mac, src.mac, 6);
|
||||
dst.aid = src.aid;
|
||||
f(dst);
|
||||
});
|
||||
sCbEventList.push_back(handler);
|
||||
return handler;
|
||||
}
|
||||
|
||||
WiFiEventHandler ESP8266WiFiGenericClass::onSoftAPModeStationDisconnected(std::function<void(const WiFiEventSoftAPModeStationDisconnected&)> f)
|
||||
{
|
||||
WiFiEventHandler handler = std::make_shared<WiFiEventHandlerOpaque>(WIFI_EVENT_SOFTAPMODE_STADISCONNECTED, [f](System_Event_t* e){
|
||||
auto& src = e->event_info.sta_disconnected;
|
||||
WiFiEventSoftAPModeStationDisconnected dst;
|
||||
memcpy(dst.mac, src.mac, 6);
|
||||
dst.aid = src.aid;
|
||||
f(dst);
|
||||
});
|
||||
sCbEventList.push_back(handler);
|
||||
return handler;
|
||||
}
|
||||
|
||||
WiFiEventHandler ESP8266WiFiGenericClass::onSoftAPModeProbeRequestReceived(std::function<void(const WiFiEventSoftAPModeProbeRequestReceived&)> f)
|
||||
{
|
||||
WiFiEventHandler handler = std::make_shared<WiFiEventHandlerOpaque>(WIFI_EVENT_SOFTAPMODE_PROBEREQRECVED, [f](System_Event_t* e){
|
||||
auto& src = e->event_info.ap_probereqrecved;
|
||||
WiFiEventSoftAPModeProbeRequestReceived dst;
|
||||
memcpy(dst.mac, src.mac, 6);
|
||||
dst.rssi = src.rssi;
|
||||
f(dst);
|
||||
});
|
||||
sCbEventList.push_back(handler);
|
||||
return handler;
|
||||
}
|
||||
|
||||
// WiFiEventHandler ESP8266WiFiGenericClass::onWiFiModeChange(std::function<void(const WiFiEventModeChange&)> f)
|
||||
// {
|
||||
// WiFiEventHandler handler = std::make_shared<WiFiEventHandlerOpaque>(WIFI_EVENT_MODE_CHANGE, [f](System_Event_t* e){
|
||||
// WiFiEventModeChange& dst = *reinterpret_cast<WiFiEventModeChange*>(&e->event_info);
|
||||
// f(dst);
|
||||
// });
|
||||
// sCbEventList.push_back(handler);
|
||||
// return handler;
|
||||
// }
|
||||
|
||||
/**
|
||||
* callback for WiFi events
|
||||
* @param arg
|
||||
*/
|
||||
void ESP8266WiFiGenericClass::_eventCallback(void* arg)
|
||||
{
|
||||
System_Event_t* event = reinterpret_cast<System_Event_t*>(arg);
|
||||
DEBUG_WIFI("wifi evt: %d\n", event->event);
|
||||
|
||||
if(event->event == EVENT_STAMODE_DISCONNECTED) {
|
||||
DEBUG_WIFI("STA disconnect: %d\n", event->event_info.disconnected.reason);
|
||||
WiFiClient::stopAll();
|
||||
}
|
||||
|
||||
for(auto it = std::begin(sCbEventList); it != std::end(sCbEventList); ) {
|
||||
WiFiEventHandler &handler = *it;
|
||||
if (handler->canExpire() && handler.unique()) {
|
||||
it = sCbEventList.erase(it);
|
||||
}
|
||||
else {
|
||||
(*handler)(event);
|
||||
++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the current channel associated with the network
|
||||
* @return channel (1-13)
|
||||
*/
|
||||
int32_t ESP8266WiFiGenericClass::channel(void) {
|
||||
return wifi_get_channel();
|
||||
}
|
||||
|
||||
/**
|
||||
* set Sleep mode
|
||||
* @param type sleep_type_t
|
||||
* @return bool
|
||||
*/
|
||||
bool ESP8266WiFiGenericClass::setSleepMode(WiFiSleepType_t type) {
|
||||
return wifi_set_sleep_type((sleep_type_t) type);
|
||||
}
|
||||
|
||||
/**
|
||||
* get Sleep mode
|
||||
* @return sleep_type_t
|
||||
*/
|
||||
WiFiSleepType_t ESP8266WiFiGenericClass::getSleepMode() {
|
||||
return (WiFiSleepType_t) wifi_get_sleep_type();
|
||||
}
|
||||
|
||||
/**
|
||||
* set phy Mode
|
||||
* @param mode phy_mode_t
|
||||
* @return bool
|
||||
*/
|
||||
bool ESP8266WiFiGenericClass::setPhyMode(WiFiPhyMode_t mode) {
|
||||
return wifi_set_phy_mode((phy_mode_t) mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* get phy Mode
|
||||
* @return phy_mode_t
|
||||
*/
|
||||
WiFiPhyMode_t ESP8266WiFiGenericClass::getPhyMode() {
|
||||
return (WiFiPhyMode_t) wifi_get_phy_mode();
|
||||
}
|
||||
|
||||
/**
|
||||
* set the output power of WiFi
|
||||
* @param dBm max: +20.5dBm min: 0dBm
|
||||
*/
|
||||
void ESP8266WiFiGenericClass::setOutputPower(float dBm) {
|
||||
|
||||
if(dBm > 20.5) {
|
||||
dBm = 20.5;
|
||||
} else if(dBm < 0) {
|
||||
dBm = 0;
|
||||
}
|
||||
|
||||
uint8_t val = (dBm*4.0f);
|
||||
system_phy_set_max_tpw(val);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* store WiFi config in SDK flash area
|
||||
* @param persistent
|
||||
*/
|
||||
void ESP8266WiFiGenericClass::persistent(bool persistent) {
|
||||
_persistent = persistent;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* set new mode
|
||||
* @param m WiFiMode_t
|
||||
*/
|
||||
bool ESP8266WiFiGenericClass::mode(WiFiMode_t m) {
|
||||
if(wifi_get_opmode() == (uint8) m) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ret = false;
|
||||
|
||||
ETS_UART_INTR_DISABLE();
|
||||
if(_persistent) {
|
||||
ret = wifi_set_opmode(m);
|
||||
} else {
|
||||
ret = wifi_set_opmode_current(m);
|
||||
}
|
||||
ETS_UART_INTR_ENABLE();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* get WiFi mode
|
||||
* @return WiFiMode
|
||||
*/
|
||||
WiFiMode_t ESP8266WiFiGenericClass::getMode() {
|
||||
return (WiFiMode_t) wifi_get_opmode();
|
||||
}
|
||||
|
||||
/**
|
||||
* control STA mode
|
||||
* @param enable bool
|
||||
* @return ok
|
||||
*/
|
||||
bool ESP8266WiFiGenericClass::enableSTA(bool enable) {
|
||||
|
||||
WiFiMode_t currentMode = getMode();
|
||||
bool isEnabled = ((currentMode & WIFI_STA) != 0);
|
||||
|
||||
if(isEnabled != enable) {
|
||||
if(enable) {
|
||||
return mode((WiFiMode_t)(currentMode | WIFI_STA));
|
||||
} else {
|
||||
return mode((WiFiMode_t)(currentMode & (~WIFI_STA)));
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* control AP mode
|
||||
* @param enable bool
|
||||
* @return ok
|
||||
*/
|
||||
bool ESP8266WiFiGenericClass::enableAP(bool enable){
|
||||
|
||||
WiFiMode_t currentMode = getMode();
|
||||
bool isEnabled = ((currentMode & WIFI_AP) != 0);
|
||||
|
||||
if(isEnabled != enable) {
|
||||
if(enable) {
|
||||
return mode((WiFiMode_t)(currentMode | WIFI_AP));
|
||||
} else {
|
||||
return mode((WiFiMode_t)(currentMode & (~WIFI_AP)));
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Disable WiFi for x us when value is not 0
|
||||
* @param sleep_time_in_us
|
||||
* @return ok
|
||||
*/
|
||||
bool ESP8266WiFiGenericClass::forceSleepBegin(uint32 sleepUs) {
|
||||
_forceSleepLastMode = getMode();
|
||||
if(!mode(WIFI_OFF)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(sleepUs == 0) {
|
||||
sleepUs = 0xFFFFFFF;
|
||||
}
|
||||
|
||||
wifi_fpm_set_sleep_type(MODEM_SLEEP_T);
|
||||
wifi_fpm_open();
|
||||
return (wifi_fpm_do_sleep(sleepUs) == 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* wake up WiFi Modem
|
||||
* @return ok
|
||||
*/
|
||||
bool ESP8266WiFiGenericClass::forceSleepWake() {
|
||||
wifi_fpm_do_wakeup();
|
||||
wifi_fpm_close();
|
||||
|
||||
// restore last mode
|
||||
if(mode(_forceSleepLastMode)) {
|
||||
if((_forceSleepLastMode & WIFI_STA) != 0){
|
||||
wifi_station_connect();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------------------------
|
||||
// ------------------------------------------------ Generic Network function ---------------------------------------------
|
||||
// -----------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
#if LWIP_VERSION_MAJOR == 1
|
||||
void wifi_dns_found_callback(const char *name, ip_addr_t *ipaddr, void *callback_arg);
|
||||
#else
|
||||
void wifi_dns_found_callback(const char *name, const ip_addr_t *ipaddr, void *callback_arg);
|
||||
#endif
|
||||
|
||||
static bool _dns_lookup_pending = false;
|
||||
|
||||
/**
|
||||
* Resolve the given hostname to an IP address.
|
||||
* @param aHostname Name to be resolved
|
||||
* @param aResult IPAddress structure to store the returned IP address
|
||||
* @return 1 if aIPAddrString was successfully converted to an IP address,
|
||||
* else error code
|
||||
*/
|
||||
int ESP8266WiFiGenericClass::hostByName(const char* aHostname, IPAddress& aResult)
|
||||
{
|
||||
return hostByName(aHostname, aResult, 10000);
|
||||
}
|
||||
|
||||
|
||||
int ESP8266WiFiGenericClass::hostByName(const char* aHostname, IPAddress& aResult, uint32_t timeout_ms)
|
||||
{
|
||||
ip_addr_t addr;
|
||||
aResult = static_cast<uint32_t>(0);
|
||||
|
||||
if(aResult.fromString(aHostname)) {
|
||||
// Host name is a IP address use it!
|
||||
DEBUG_WIFI_GENERIC("[hostByName] Host: %s is a IP!\n", aHostname);
|
||||
return 1;
|
||||
}
|
||||
|
||||
DEBUG_WIFI_GENERIC("[hostByName] request IP for: %s\n", aHostname);
|
||||
err_t err = dns_gethostbyname(aHostname, &addr, &wifi_dns_found_callback, &aResult);
|
||||
if(err == ERR_OK) {
|
||||
aResult = addr.addr;
|
||||
} else if(err == ERR_INPROGRESS) {
|
||||
_dns_lookup_pending = true;
|
||||
delay(timeout_ms);
|
||||
_dns_lookup_pending = false;
|
||||
// will return here when dns_found_callback fires
|
||||
if(aResult != 0) {
|
||||
err = ERR_OK;
|
||||
}
|
||||
}
|
||||
|
||||
if(err != 0) {
|
||||
DEBUG_WIFI_GENERIC("[hostByName] Host: %s lookup error: %d!\n", aHostname, err);
|
||||
} else {
|
||||
DEBUG_WIFI_GENERIC("[hostByName] Host: %s IP: %s\n", aHostname, aResult.toString().c_str());
|
||||
}
|
||||
|
||||
return (err == ERR_OK) ? 1 : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* DNS callback
|
||||
* @param name
|
||||
* @param ipaddr
|
||||
* @param callback_arg
|
||||
*/
|
||||
#if LWIP_VERSION_MAJOR == 1
|
||||
void wifi_dns_found_callback(const char *name, ip_addr_t *ipaddr, void *callback_arg)
|
||||
#else
|
||||
void wifi_dns_found_callback(const char *name, const ip_addr_t *ipaddr, void *callback_arg)
|
||||
#endif
|
||||
{
|
||||
(void) name;
|
||||
if (!_dns_lookup_pending) {
|
||||
return;
|
||||
}
|
||||
if(ipaddr) {
|
||||
(*reinterpret_cast<IPAddress*>(callback_arg)) = ipaddr->addr;
|
||||
}
|
||||
esp_schedule(); // resume the hostByName function
|
||||
}
|
||||
|
||||
|
110
Software/libraries/ESP8266WiFi/src/ESP8266WiFiGeneric.h
Normal file
110
Software/libraries/ESP8266WiFi/src/ESP8266WiFiGeneric.h
Normal file
@ -0,0 +1,110 @@
|
||||
/*
|
||||
ESP8266WiFiGeneric.h - esp8266 Wifi support.
|
||||
Based on WiFi.h from Ardiono WiFi shield library.
|
||||
Copyright (c) 2011-2014 Arduino. All right reserved.
|
||||
Modified by Ivan Grokhotkov, December 2014
|
||||
Reworked by Markus Sattler, December 2015
|
||||
|
||||
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
|
||||
*/
|
||||
|
||||
#ifndef ESP8266WIFIGENERIC_H_
|
||||
#define ESP8266WIFIGENERIC_H_
|
||||
|
||||
#include "ESP8266WiFiType.h"
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
|
||||
#ifdef DEBUG_ESP_WIFI
|
||||
#ifdef DEBUG_ESP_PORT
|
||||
#define DEBUG_WIFI_GENERIC(...) DEBUG_ESP_PORT.printf( __VA_ARGS__ )
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef DEBUG_WIFI_GENERIC
|
||||
#define DEBUG_WIFI_GENERIC(...)
|
||||
#endif
|
||||
|
||||
struct WiFiEventHandlerOpaque;
|
||||
typedef std::shared_ptr<WiFiEventHandlerOpaque> WiFiEventHandler;
|
||||
|
||||
typedef void (*WiFiEventCb)(WiFiEvent_t);
|
||||
|
||||
class ESP8266WiFiGenericClass {
|
||||
// ----------------------------------------------------------------------------------------------
|
||||
// -------------------------------------- Generic WiFi function ---------------------------------
|
||||
// ----------------------------------------------------------------------------------------------
|
||||
|
||||
public:
|
||||
ESP8266WiFiGenericClass();
|
||||
|
||||
// Note: this function is deprecated. Use one of the functions below instead.
|
||||
void onEvent(WiFiEventCb cb, WiFiEvent_t event = WIFI_EVENT_ANY) __attribute__((deprecated));
|
||||
|
||||
// Subscribe to specific event and get event information as an argument to the callback
|
||||
WiFiEventHandler onStationModeConnected(std::function<void(const WiFiEventStationModeConnected&)>);
|
||||
WiFiEventHandler onStationModeDisconnected(std::function<void(const WiFiEventStationModeDisconnected&)>);
|
||||
WiFiEventHandler onStationModeAuthModeChanged(std::function<void(const WiFiEventStationModeAuthModeChanged&)>);
|
||||
WiFiEventHandler onStationModeGotIP(std::function<void(const WiFiEventStationModeGotIP&)>);
|
||||
WiFiEventHandler onStationModeDHCPTimeout(std::function<void(void)>);
|
||||
WiFiEventHandler onSoftAPModeStationConnected(std::function<void(const WiFiEventSoftAPModeStationConnected&)>);
|
||||
WiFiEventHandler onSoftAPModeStationDisconnected(std::function<void(const WiFiEventSoftAPModeStationDisconnected&)>);
|
||||
WiFiEventHandler onSoftAPModeProbeRequestReceived(std::function<void(const WiFiEventSoftAPModeProbeRequestReceived&)>);
|
||||
// WiFiEventHandler onWiFiModeChange(std::function<void(const WiFiEventModeChange&)>);
|
||||
|
||||
int32_t channel(void);
|
||||
|
||||
bool setSleepMode(WiFiSleepType_t type);
|
||||
WiFiSleepType_t getSleepMode();
|
||||
|
||||
bool setPhyMode(WiFiPhyMode_t mode);
|
||||
WiFiPhyMode_t getPhyMode();
|
||||
|
||||
void setOutputPower(float dBm);
|
||||
|
||||
void persistent(bool persistent);
|
||||
|
||||
bool mode(WiFiMode_t);
|
||||
WiFiMode_t getMode();
|
||||
|
||||
bool enableSTA(bool enable);
|
||||
bool enableAP(bool enable);
|
||||
|
||||
bool forceSleepBegin(uint32 sleepUs = 0);
|
||||
bool forceSleepWake();
|
||||
|
||||
protected:
|
||||
static bool _persistent;
|
||||
static WiFiMode_t _forceSleepLastMode;
|
||||
|
||||
static void _eventCallback(void *event);
|
||||
|
||||
// ----------------------------------------------------------------------------------------------
|
||||
// ------------------------------------ Generic Network function --------------------------------
|
||||
// ----------------------------------------------------------------------------------------------
|
||||
|
||||
public:
|
||||
|
||||
int hostByName(const char* aHostname, IPAddress& aResult);
|
||||
int hostByName(const char* aHostname, IPAddress& aResult, uint32_t timeout_ms);
|
||||
|
||||
protected:
|
||||
|
||||
friend class ESP8266WiFiSTAClass;
|
||||
friend class ESP8266WiFiScanClass;
|
||||
friend class ESP8266WiFiAPClass;
|
||||
};
|
||||
|
||||
#endif /* ESP8266WIFIGENERIC_H_ */
|
216
Software/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.cpp
Normal file
216
Software/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.cpp
Normal file
@ -0,0 +1,216 @@
|
||||
/**
|
||||
*
|
||||
* @file ESP8266WiFiMulti.cpp
|
||||
* @date 16.05.2015
|
||||
* @author Markus Sattler
|
||||
*
|
||||
* Copyright (c) 2015 Markus Sattler. 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
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ESP8266WiFiMulti.h"
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
|
||||
ESP8266WiFiMulti::ESP8266WiFiMulti() {
|
||||
}
|
||||
|
||||
ESP8266WiFiMulti::~ESP8266WiFiMulti() {
|
||||
APlistClean();
|
||||
}
|
||||
|
||||
bool ESP8266WiFiMulti::addAP(const char* ssid, const char *passphrase) {
|
||||
return APlistAdd(ssid, passphrase);
|
||||
}
|
||||
|
||||
wl_status_t ESP8266WiFiMulti::run(void) {
|
||||
|
||||
int8_t scanResult;
|
||||
wl_status_t status = WiFi.status();
|
||||
if(status == WL_DISCONNECTED || status == WL_NO_SSID_AVAIL || status == WL_IDLE_STATUS || status == WL_CONNECT_FAILED) {
|
||||
|
||||
scanResult = WiFi.scanComplete();
|
||||
if(scanResult == WIFI_SCAN_RUNNING) {
|
||||
// scan is running
|
||||
return WL_NO_SSID_AVAIL;
|
||||
} else if(scanResult > 0) {
|
||||
// scan done analyze
|
||||
WifiAPlist_t bestNetwork { NULL, NULL };
|
||||
int bestNetworkDb = INT_MIN;
|
||||
uint8 bestBSSID[6];
|
||||
int32_t bestChannel;
|
||||
|
||||
DEBUG_WIFI_MULTI("[WIFI] scan done\n");
|
||||
delay(0);
|
||||
|
||||
if(scanResult <= 0) {
|
||||
DEBUG_WIFI_MULTI("[WIFI] no networks found\n");
|
||||
} else {
|
||||
DEBUG_WIFI_MULTI("[WIFI] %d networks found\n", scanResult);
|
||||
for(int8_t i = 0; i < scanResult; ++i) {
|
||||
|
||||
String ssid_scan;
|
||||
int32_t rssi_scan;
|
||||
uint8_t sec_scan;
|
||||
uint8_t* BSSID_scan;
|
||||
int32_t chan_scan;
|
||||
bool hidden_scan;
|
||||
|
||||
WiFi.getNetworkInfo(i, ssid_scan, sec_scan, rssi_scan, BSSID_scan, chan_scan, hidden_scan);
|
||||
|
||||
bool known = false;
|
||||
for(uint32_t x = 0; x < APlist.size(); x++) {
|
||||
WifiAPlist_t entry = APlist[x];
|
||||
|
||||
if(ssid_scan == entry.ssid) { // SSID match
|
||||
known = true;
|
||||
if(rssi_scan > bestNetworkDb) { // best network
|
||||
if(sec_scan == ENC_TYPE_NONE || entry.passphrase) { // check for passphrase if not open wlan
|
||||
bestNetworkDb = rssi_scan;
|
||||
bestChannel = chan_scan;
|
||||
memcpy((void*) &bestNetwork, (void*) &entry, sizeof(bestNetwork));
|
||||
memcpy((void*) &bestBSSID, (void*) BSSID_scan, sizeof(bestBSSID));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(known) {
|
||||
DEBUG_WIFI_MULTI(" ---> ");
|
||||
} else {
|
||||
DEBUG_WIFI_MULTI(" ");
|
||||
}
|
||||
|
||||
DEBUG_WIFI_MULTI(" %d: [%d][%02X:%02X:%02X:%02X:%02X:%02X] %s (%d) %c\n", i, chan_scan, BSSID_scan[0], BSSID_scan[1], BSSID_scan[2], BSSID_scan[3], BSSID_scan[4], BSSID_scan[5], ssid_scan.c_str(), rssi_scan, (sec_scan == ENC_TYPE_NONE) ? ' ' : '*');
|
||||
delay(0);
|
||||
}
|
||||
}
|
||||
|
||||
// clean up ram
|
||||
WiFi.scanDelete();
|
||||
|
||||
DEBUG_WIFI_MULTI("\n\n");
|
||||
delay(0);
|
||||
|
||||
if(bestNetwork.ssid) {
|
||||
DEBUG_WIFI_MULTI("[WIFI] Connecting BSSID: %02X:%02X:%02X:%02X:%02X:%02X SSID: %s Channal: %d (%d)\n", bestBSSID[0], bestBSSID[1], bestBSSID[2], bestBSSID[3], bestBSSID[4], bestBSSID[5], bestNetwork.ssid, bestChannel, bestNetworkDb);
|
||||
|
||||
WiFi.begin(bestNetwork.ssid, bestNetwork.passphrase, bestChannel, bestBSSID);
|
||||
status = WiFi.status();
|
||||
|
||||
// wait for connection or fail
|
||||
while(status != WL_CONNECTED && status != WL_NO_SSID_AVAIL && status != WL_CONNECT_FAILED) {
|
||||
delay(10);
|
||||
status = WiFi.status();
|
||||
}
|
||||
#ifdef DEBUG_ESP_WIFI
|
||||
IPAddress ip;
|
||||
uint8_t * mac;
|
||||
switch(status) {
|
||||
case WL_CONNECTED:
|
||||
ip = WiFi.localIP();
|
||||
mac = WiFi.BSSID();
|
||||
DEBUG_WIFI_MULTI("[WIFI] Connecting done.\n");
|
||||
DEBUG_WIFI_MULTI("[WIFI] SSID: %s\n", WiFi.SSID().c_str());
|
||||
DEBUG_WIFI_MULTI("[WIFI] IP: %d.%d.%d.%d\n", ip[0], ip[1], ip[2], ip[3]);
|
||||
DEBUG_WIFI_MULTI("[WIFI] MAC: %02X:%02X:%02X:%02X:%02X:%02X\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
||||
DEBUG_WIFI_MULTI("[WIFI] Channel: %d\n", WiFi.channel());
|
||||
break;
|
||||
case WL_NO_SSID_AVAIL:
|
||||
DEBUG_WIFI_MULTI("[WIFI] Connecting Failed AP not found.\n");
|
||||
break;
|
||||
case WL_CONNECT_FAILED:
|
||||
DEBUG_WIFI_MULTI("[WIFI] Connecting Failed.\n");
|
||||
break;
|
||||
default:
|
||||
DEBUG_WIFI_MULTI("[WIFI] Connecting Failed (%d).\n", status);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
DEBUG_WIFI_MULTI("[WIFI] no matching wifi found!\n");
|
||||
}
|
||||
} else {
|
||||
// start scan
|
||||
DEBUG_WIFI_MULTI("[WIFI] delete old wifi config...\n");
|
||||
WiFi.disconnect();
|
||||
|
||||
DEBUG_WIFI_MULTI("[WIFI] start scan\n");
|
||||
// scan wifi async mode
|
||||
WiFi.scanNetworks(true);
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
// ##################################################################################
|
||||
|
||||
bool ESP8266WiFiMulti::APlistAdd(const char* ssid, const char *passphrase) {
|
||||
|
||||
WifiAPlist_t newAP;
|
||||
|
||||
if(!ssid || *ssid == 0x00 || strlen(ssid) > 31) {
|
||||
// fail SSID to long or missing!
|
||||
DEBUG_WIFI_MULTI("[WIFI][APlistAdd] no ssid or ssid to long\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(passphrase && strlen(passphrase) > 63) {
|
||||
// fail passphrase to long!
|
||||
DEBUG_WIFI_MULTI("[WIFI][APlistAdd] passphrase to long\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
newAP.ssid = strdup(ssid);
|
||||
|
||||
if(!newAP.ssid) {
|
||||
DEBUG_WIFI_MULTI("[WIFI][APlistAdd] fail newAP.ssid == 0\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(passphrase) {
|
||||
newAP.passphrase = strdup(passphrase);
|
||||
} else {
|
||||
newAP.passphrase = strdup("");
|
||||
}
|
||||
|
||||
if(!newAP.passphrase) {
|
||||
DEBUG_WIFI_MULTI("[WIFI][APlistAdd] fail newAP.passphrase == 0\n");
|
||||
free(newAP.ssid);
|
||||
return false;
|
||||
}
|
||||
|
||||
APlist.push_back(newAP);
|
||||
DEBUG_WIFI_MULTI("[WIFI][APlistAdd] add SSID: %s\n", newAP.ssid);
|
||||
return true;
|
||||
}
|
||||
|
||||
void ESP8266WiFiMulti::APlistClean(void) {
|
||||
for(uint32_t i = 0; i < APlist.size(); i++) {
|
||||
WifiAPlist_t entry = APlist[i];
|
||||
if(entry.ssid) {
|
||||
free(entry.ssid);
|
||||
}
|
||||
if(entry.passphrase) {
|
||||
free(entry.passphrase);
|
||||
}
|
||||
}
|
||||
APlist.clear();
|
||||
}
|
||||
|
66
Software/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.h
Normal file
66
Software/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.h
Normal file
@ -0,0 +1,66 @@
|
||||
/**
|
||||
*
|
||||
* @file ESP8266WiFiMulti.h
|
||||
* @date 16.05.2015
|
||||
* @author Markus Sattler
|
||||
*
|
||||
* Copyright (c) 2015 Markus Sattler. 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
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef WIFICLIENTMULTI_H_
|
||||
#define WIFICLIENTMULTI_H_
|
||||
|
||||
#include "ESP8266WiFi.h"
|
||||
#undef min
|
||||
#undef max
|
||||
#include <vector>
|
||||
|
||||
#ifdef DEBUG_ESP_WIFI
|
||||
#ifdef DEBUG_ESP_PORT
|
||||
#define DEBUG_WIFI_MULTI(...) DEBUG_ESP_PORT.printf( __VA_ARGS__ )
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef DEBUG_WIFI_MULTI
|
||||
#define DEBUG_WIFI_MULTI(...)
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
char * ssid;
|
||||
char * passphrase;
|
||||
} WifiAPlist_t;
|
||||
|
||||
class ESP8266WiFiMulti {
|
||||
public:
|
||||
ESP8266WiFiMulti();
|
||||
~ESP8266WiFiMulti();
|
||||
|
||||
bool addAP(const char* ssid, const char *passphrase = NULL);
|
||||
|
||||
wl_status_t run(void);
|
||||
|
||||
private:
|
||||
std::vector<WifiAPlist_t> APlist;
|
||||
bool APlistAdd(const char* ssid, const char *passphrase = NULL);
|
||||
void APlistClean(void);
|
||||
|
||||
};
|
||||
|
||||
#endif /* WIFICLIENTMULTI_H_ */
|
684
Software/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.cpp
Normal file
684
Software/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.cpp
Normal file
@ -0,0 +1,684 @@
|
||||
/*
|
||||
ESP8266WiFiSTA.cpp - WiFi library for esp8266
|
||||
|
||||
Copyright (c) 2014 Ivan Grokhotkov. 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
|
||||
|
||||
Reworked on 28 Dec 2015 by Markus Sattler
|
||||
|
||||
*/
|
||||
|
||||
#include "ESP8266WiFi.h"
|
||||
#include "ESP8266WiFiGeneric.h"
|
||||
#include "ESP8266WiFiSTA.h"
|
||||
|
||||
extern "C" {
|
||||
#include "c_types.h"
|
||||
#include "ets_sys.h"
|
||||
#include "os_type.h"
|
||||
#include "osapi.h"
|
||||
#include "mem.h"
|
||||
#include "user_interface.h"
|
||||
#include "smartconfig.h"
|
||||
#include "lwip/err.h"
|
||||
#include "lwip/dns.h"
|
||||
#include "lwip/init.h" // LWIP_VERSION_
|
||||
}
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
extern "C" void esp_schedule();
|
||||
extern "C" void esp_yield();
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------------------------
|
||||
// ---------------------------------------------------- Private functions ------------------------------------------------
|
||||
// -----------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
static bool sta_config_equal(const station_config& lhs, const station_config& rhs);
|
||||
|
||||
|
||||
/**
|
||||
* compare two STA configurations
|
||||
* @param lhs station_config
|
||||
* @param rhs station_config
|
||||
* @return equal
|
||||
*/
|
||||
static bool sta_config_equal(const station_config& lhs, const station_config& rhs) {
|
||||
if(strcmp(reinterpret_cast<const char*>(lhs.ssid), reinterpret_cast<const char*>(rhs.ssid)) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(strcmp(reinterpret_cast<const char*>(lhs.password), reinterpret_cast<const char*>(rhs.password)) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(lhs.bssid_set != rhs.bssid_set) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(lhs.bssid_set) {
|
||||
if(memcmp(lhs.bssid, rhs.bssid, 6) != 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------------------------
|
||||
// ---------------------------------------------------- STA function -----------------------------------------------------
|
||||
// -----------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
bool ESP8266WiFiSTAClass::_useStaticIp = false;
|
||||
|
||||
/**
|
||||
* Start Wifi connection
|
||||
* if passphrase is set the most secure supported mode will be automatically selected
|
||||
* @param ssid const char* Pointer to the SSID string.
|
||||
* @param passphrase const char * Optional. Passphrase. Valid characters in a passphrase must be between ASCII 32-126 (decimal).
|
||||
* @param bssid uint8_t[6] Optional. BSSID / MAC of AP
|
||||
* @param channel Optional. Channel of AP
|
||||
* @param connect Optional. call connect
|
||||
* @return
|
||||
*/
|
||||
wl_status_t ESP8266WiFiSTAClass::begin(const char* ssid, const char *passphrase, int32_t channel, const uint8_t* bssid, bool connect) {
|
||||
|
||||
if(!WiFi.enableSTA(true)) {
|
||||
// enable STA failed
|
||||
return WL_CONNECT_FAILED;
|
||||
}
|
||||
|
||||
if(!ssid || *ssid == 0x00 || strlen(ssid) > 31) {
|
||||
// fail SSID too long or missing!
|
||||
return WL_CONNECT_FAILED;
|
||||
}
|
||||
|
||||
if(passphrase && strlen(passphrase) > 64) {
|
||||
// fail passphrase too long!
|
||||
return WL_CONNECT_FAILED;
|
||||
}
|
||||
|
||||
struct station_config conf;
|
||||
strcpy(reinterpret_cast<char*>(conf.ssid), ssid);
|
||||
|
||||
if(passphrase) {
|
||||
if (strlen(passphrase) == 64) // it's not a passphrase, is the PSK
|
||||
memcpy(reinterpret_cast<char*>(conf.password), passphrase, 64);
|
||||
else
|
||||
strcpy(reinterpret_cast<char*>(conf.password), passphrase);
|
||||
} else {
|
||||
*conf.password = 0;
|
||||
}
|
||||
|
||||
if(bssid) {
|
||||
conf.bssid_set = 1;
|
||||
memcpy((void *) &conf.bssid[0], (void *) bssid, 6);
|
||||
} else {
|
||||
conf.bssid_set = 0;
|
||||
}
|
||||
|
||||
struct station_config current_conf;
|
||||
wifi_station_get_config(¤t_conf);
|
||||
if(sta_config_equal(current_conf, conf)) {
|
||||
DEBUGV("sta config unchanged");
|
||||
}
|
||||
else {
|
||||
ETS_UART_INTR_DISABLE();
|
||||
|
||||
if(WiFi._persistent) {
|
||||
// workaround for #1997: make sure the value of ap_number is updated and written to flash
|
||||
// to be removed after SDK update
|
||||
wifi_station_ap_number_set(2);
|
||||
wifi_station_ap_number_set(1);
|
||||
|
||||
wifi_station_set_config(&conf);
|
||||
} else {
|
||||
wifi_station_set_config_current(&conf);
|
||||
}
|
||||
|
||||
ETS_UART_INTR_ENABLE();
|
||||
}
|
||||
|
||||
ETS_UART_INTR_DISABLE();
|
||||
if(connect) {
|
||||
wifi_station_connect();
|
||||
}
|
||||
ETS_UART_INTR_ENABLE();
|
||||
|
||||
if(channel > 0 && channel <= 13) {
|
||||
wifi_set_channel(channel);
|
||||
}
|
||||
|
||||
if(!_useStaticIp) {
|
||||
wifi_station_dhcpc_start();
|
||||
}
|
||||
|
||||
return status();
|
||||
}
|
||||
|
||||
wl_status_t ESP8266WiFiSTAClass::begin(char* ssid, char *passphrase, int32_t channel, const uint8_t* bssid, bool connect) {
|
||||
return begin((const char*) ssid, (const char*) passphrase, channel, bssid, connect);
|
||||
}
|
||||
|
||||
/**
|
||||
* Use to connect to SDK config.
|
||||
* @return wl_status_t
|
||||
*/
|
||||
wl_status_t ESP8266WiFiSTAClass::begin() {
|
||||
|
||||
if(!WiFi.enableSTA(true)) {
|
||||
// enable STA failed
|
||||
return WL_CONNECT_FAILED;
|
||||
}
|
||||
|
||||
ETS_UART_INTR_DISABLE();
|
||||
wifi_station_connect();
|
||||
ETS_UART_INTR_ENABLE();
|
||||
|
||||
if(!_useStaticIp) {
|
||||
wifi_station_dhcpc_start();
|
||||
}
|
||||
return status();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Change IP configuration settings disabling the dhcp client
|
||||
* @param local_ip Static ip configuration
|
||||
* @param gateway Static gateway configuration
|
||||
* @param subnet Static Subnet mask
|
||||
* @param dns1 Static DNS server 1
|
||||
* @param dns2 Static DNS server 2
|
||||
*/
|
||||
bool ESP8266WiFiSTAClass::config(IPAddress local_ip, IPAddress gateway, IPAddress subnet, IPAddress dns1, IPAddress dns2) {
|
||||
|
||||
if(!WiFi.enableSTA(true)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
struct ip_info info;
|
||||
info.ip.addr = static_cast<uint32_t>(local_ip);
|
||||
info.gw.addr = static_cast<uint32_t>(gateway);
|
||||
info.netmask.addr = static_cast<uint32_t>(subnet);
|
||||
|
||||
if (local_ip == 0U && gateway == 0U && subnet == 0U) {
|
||||
_useStaticIp = false;
|
||||
wifi_station_dhcpc_start();
|
||||
return true;
|
||||
}
|
||||
|
||||
wifi_station_dhcpc_stop();
|
||||
if(wifi_set_ip_info(STATION_IF, &info)) {
|
||||
_useStaticIp = true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
ip_addr_t d;
|
||||
|
||||
if(dns1 != (uint32_t)0x00000000) {
|
||||
// Set DNS1-Server
|
||||
d.addr = static_cast<uint32_t>(dns1);
|
||||
dns_setserver(0, &d);
|
||||
}
|
||||
|
||||
if(dns2 != (uint32_t)0x00000000) {
|
||||
// Set DNS2-Server
|
||||
d.addr = static_cast<uint32_t>(dns2);
|
||||
dns_setserver(1, &d);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* will force a disconnect an then start reconnecting to AP
|
||||
* @return ok
|
||||
*/
|
||||
bool ESP8266WiFiSTAClass::reconnect() {
|
||||
if((WiFi.getMode() & WIFI_STA) != 0) {
|
||||
if(wifi_station_disconnect()) {
|
||||
return wifi_station_connect();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disconnect from the network
|
||||
* @param wifioff
|
||||
* @return one value of wl_status_t enum
|
||||
*/
|
||||
bool ESP8266WiFiSTAClass::disconnect(bool wifioff) {
|
||||
bool ret;
|
||||
struct station_config conf;
|
||||
*conf.ssid = 0;
|
||||
*conf.password = 0;
|
||||
|
||||
ETS_UART_INTR_DISABLE();
|
||||
if(WiFi._persistent) {
|
||||
wifi_station_set_config(&conf);
|
||||
} else {
|
||||
wifi_station_set_config_current(&conf);
|
||||
}
|
||||
ret = wifi_station_disconnect();
|
||||
ETS_UART_INTR_ENABLE();
|
||||
|
||||
if(wifioff) {
|
||||
WiFi.enableSTA(false);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* is STA interface connected?
|
||||
* @return true if STA is connected to an AD
|
||||
*/
|
||||
bool ESP8266WiFiSTAClass::isConnected() {
|
||||
return (status() == WL_CONNECTED);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Setting the ESP8266 station to connect to the AP (which is recorded)
|
||||
* automatically or not when powered on. Enable auto-connect by default.
|
||||
* @param autoConnect bool
|
||||
* @return if saved
|
||||
*/
|
||||
bool ESP8266WiFiSTAClass::setAutoConnect(bool autoConnect) {
|
||||
bool ret;
|
||||
ETS_UART_INTR_DISABLE();
|
||||
ret = wifi_station_set_auto_connect(autoConnect);
|
||||
ETS_UART_INTR_ENABLE();
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if ESP8266 station mode will connect to AP
|
||||
* automatically or not when it is powered on.
|
||||
* @return auto connect
|
||||
*/
|
||||
bool ESP8266WiFiSTAClass::getAutoConnect() {
|
||||
return (wifi_station_get_auto_connect() != 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether reconnect or not when the ESP8266 station is disconnected from AP.
|
||||
* @param autoReconnect
|
||||
* @return
|
||||
*/
|
||||
bool ESP8266WiFiSTAClass::setAutoReconnect(bool autoReconnect) {
|
||||
return wifi_station_set_reconnect_policy(autoReconnect);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for WiFi connection to reach a result
|
||||
* returns the status reached or disconnect if STA is off
|
||||
* @return wl_status_t
|
||||
*/
|
||||
uint8_t ESP8266WiFiSTAClass::waitForConnectResult() {
|
||||
//1 and 3 have STA enabled
|
||||
if((wifi_get_opmode() & 1) == 0) {
|
||||
return WL_DISCONNECTED;
|
||||
}
|
||||
while(status() == WL_DISCONNECTED) {
|
||||
delay(100);
|
||||
}
|
||||
return status();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the station interface IP address.
|
||||
* @return IPAddress station IP
|
||||
*/
|
||||
IPAddress ESP8266WiFiSTAClass::localIP() {
|
||||
struct ip_info ip;
|
||||
wifi_get_ip_info(STATION_IF, &ip);
|
||||
return IPAddress(ip.ip.addr);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the station interface MAC address.
|
||||
* @param mac pointer to uint8_t array with length WL_MAC_ADDR_LENGTH
|
||||
* @return pointer to uint8_t *
|
||||
*/
|
||||
uint8_t* ESP8266WiFiSTAClass::macAddress(uint8_t* mac) {
|
||||
wifi_get_macaddr(STATION_IF, mac);
|
||||
return mac;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the station interface MAC address.
|
||||
* @return String mac
|
||||
*/
|
||||
String ESP8266WiFiSTAClass::macAddress(void) {
|
||||
uint8_t mac[6];
|
||||
char macStr[18] = { 0 };
|
||||
wifi_get_macaddr(STATION_IF, mac);
|
||||
|
||||
sprintf(macStr, "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
||||
return String(macStr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the interface subnet mask address.
|
||||
* @return IPAddress subnetMask
|
||||
*/
|
||||
IPAddress ESP8266WiFiSTAClass::subnetMask() {
|
||||
struct ip_info ip;
|
||||
wifi_get_ip_info(STATION_IF, &ip);
|
||||
return IPAddress(ip.netmask.addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the gateway ip address.
|
||||
* @return IPAddress gatewayIP
|
||||
*/
|
||||
IPAddress ESP8266WiFiSTAClass::gatewayIP() {
|
||||
struct ip_info ip;
|
||||
wifi_get_ip_info(STATION_IF, &ip);
|
||||
return IPAddress(ip.gw.addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the DNS ip address.
|
||||
* @param dns_no
|
||||
* @return IPAddress DNS Server IP
|
||||
*/
|
||||
IPAddress ESP8266WiFiSTAClass::dnsIP(uint8_t dns_no) {
|
||||
#if LWIP_VERSION_MAJOR == 1
|
||||
ip_addr_t dns_ip = dns_getserver(dns_no);
|
||||
return IPAddress(dns_ip.addr);
|
||||
#else
|
||||
const ip_addr_t* dns_ip = dns_getserver(dns_no);
|
||||
return IPAddress(dns_ip->addr);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get ESP8266 station DHCP hostname
|
||||
* @return hostname
|
||||
*/
|
||||
String ESP8266WiFiSTAClass::hostname(void) {
|
||||
return String(wifi_station_get_hostname());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set ESP8266 station DHCP hostname
|
||||
* @param aHostname max length:32
|
||||
* @return ok
|
||||
*/
|
||||
bool ESP8266WiFiSTAClass::hostname(char* aHostname) {
|
||||
if(strlen(aHostname) > 32) {
|
||||
return false;
|
||||
}
|
||||
return wifi_station_set_hostname(aHostname);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set ESP8266 station DHCP hostname
|
||||
* @param aHostname max length:32
|
||||
* @return ok
|
||||
*/
|
||||
bool ESP8266WiFiSTAClass::hostname(const char* aHostname) {
|
||||
return hostname((char*) aHostname);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set ESP8266 station DHCP hostname
|
||||
* @param aHostname max length:32
|
||||
* @return ok
|
||||
*/
|
||||
bool ESP8266WiFiSTAClass::hostname(String aHostname) {
|
||||
return hostname((char*) aHostname.c_str());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return Connection status.
|
||||
* @return one of the value defined in wl_status_t
|
||||
*
|
||||
*/
|
||||
wl_status_t ESP8266WiFiSTAClass::status() {
|
||||
station_status_t status = wifi_station_get_connect_status();
|
||||
|
||||
switch(status) {
|
||||
case STATION_GOT_IP:
|
||||
return WL_CONNECTED;
|
||||
case STATION_NO_AP_FOUND:
|
||||
return WL_NO_SSID_AVAIL;
|
||||
case STATION_CONNECT_FAIL:
|
||||
case STATION_WRONG_PASSWORD:
|
||||
return WL_CONNECT_FAILED;
|
||||
case STATION_IDLE:
|
||||
return WL_IDLE_STATUS;
|
||||
default:
|
||||
return WL_DISCONNECTED;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the current SSID associated with the network
|
||||
* @return SSID
|
||||
*/
|
||||
String ESP8266WiFiSTAClass::SSID() const {
|
||||
struct station_config conf;
|
||||
wifi_station_get_config(&conf);
|
||||
return String(reinterpret_cast<char*>(conf.ssid));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the current pre shared key associated with the network
|
||||
* @return psk string
|
||||
*/
|
||||
String ESP8266WiFiSTAClass::psk() const {
|
||||
struct station_config conf;
|
||||
wifi_station_get_config(&conf);
|
||||
return String(reinterpret_cast<char*>(conf.password));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the current bssid / mac associated with the network if configured
|
||||
* @return bssid uint8_t *
|
||||
*/
|
||||
uint8_t* ESP8266WiFiSTAClass::BSSID(void) {
|
||||
static struct station_config conf;
|
||||
wifi_station_get_config(&conf);
|
||||
return reinterpret_cast<uint8_t*>(conf.bssid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the current bssid / mac associated with the network if configured
|
||||
* @return String bssid mac
|
||||
*/
|
||||
String ESP8266WiFiSTAClass::BSSIDstr(void) {
|
||||
struct station_config conf;
|
||||
char mac[18] = { 0 };
|
||||
wifi_station_get_config(&conf);
|
||||
sprintf(mac, "%02X:%02X:%02X:%02X:%02X:%02X", conf.bssid[0], conf.bssid[1], conf.bssid[2], conf.bssid[3], conf.bssid[4], conf.bssid[5]);
|
||||
return String(mac);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the current network RSSI.
|
||||
* @return RSSI value
|
||||
*/
|
||||
int32_t ESP8266WiFiSTAClass::RSSI(void) {
|
||||
return wifi_station_get_rssi();
|
||||
}
|
||||
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------------------------
|
||||
// -------------------------------------------------- STA remote configure -----------------------------------------------
|
||||
// -----------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
void wifi_wps_status_cb(wps_cb_status status);
|
||||
|
||||
/**
|
||||
* WPS config
|
||||
* so far only WPS_TYPE_PBC is supported (SDK 1.2.0)
|
||||
* @return ok
|
||||
*/
|
||||
bool ESP8266WiFiSTAClass::beginWPSConfig(void) {
|
||||
|
||||
if(!WiFi.enableSTA(true)) {
|
||||
// enable STA failed
|
||||
return false;
|
||||
}
|
||||
|
||||
disconnect();
|
||||
|
||||
DEBUGV("wps begin\n");
|
||||
|
||||
if(!wifi_wps_disable()) {
|
||||
DEBUGV("wps disable failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// so far only WPS_TYPE_PBC is supported (SDK 1.2.0)
|
||||
if(!wifi_wps_enable(WPS_TYPE_PBC)) {
|
||||
DEBUGV("wps enable failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!wifi_set_wps_cb((wps_st_cb_t) &wifi_wps_status_cb)) {
|
||||
DEBUGV("wps cb failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!wifi_wps_start()) {
|
||||
DEBUGV("wps start failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
esp_yield();
|
||||
// will return here when wifi_wps_status_cb fires
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* WPS callback
|
||||
* @param status wps_cb_status
|
||||
*/
|
||||
void wifi_wps_status_cb(wps_cb_status status) {
|
||||
DEBUGV("wps cb status: %d\r\n", status);
|
||||
switch(status) {
|
||||
case WPS_CB_ST_SUCCESS:
|
||||
if(!wifi_wps_disable()) {
|
||||
DEBUGV("wps disable failed\n");
|
||||
}
|
||||
wifi_station_connect();
|
||||
break;
|
||||
case WPS_CB_ST_FAILED:
|
||||
DEBUGV("wps FAILED\n");
|
||||
break;
|
||||
case WPS_CB_ST_TIMEOUT:
|
||||
DEBUGV("wps TIMEOUT\n");
|
||||
break;
|
||||
case WPS_CB_ST_WEP:
|
||||
DEBUGV("wps WEP\n");
|
||||
break;
|
||||
case WPS_CB_ST_UNK:
|
||||
DEBUGV("wps UNKNOWN\n");
|
||||
if(!wifi_wps_disable()) {
|
||||
DEBUGV("wps disable failed\n");
|
||||
}
|
||||
break;
|
||||
}
|
||||
// TODO user function to get status
|
||||
|
||||
esp_schedule(); // resume the beginWPSConfig function
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool ESP8266WiFiSTAClass::_smartConfigStarted = false;
|
||||
bool ESP8266WiFiSTAClass::_smartConfigDone = false;
|
||||
|
||||
/**
|
||||
* Start SmartConfig
|
||||
*/
|
||||
bool ESP8266WiFiSTAClass::beginSmartConfig() {
|
||||
if(_smartConfigStarted) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!WiFi.enableSTA(true)) {
|
||||
// enable STA failed
|
||||
return false;
|
||||
}
|
||||
|
||||
if(smartconfig_start(reinterpret_cast<sc_callback_t>(&ESP8266WiFiSTAClass::_smartConfigCallback), 1)) {
|
||||
_smartConfigStarted = true;
|
||||
_smartConfigDone = false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Stop SmartConfig
|
||||
*/
|
||||
bool ESP8266WiFiSTAClass::stopSmartConfig() {
|
||||
if(!_smartConfigStarted) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if(smartconfig_stop()) {
|
||||
_smartConfigStarted = false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Query SmartConfig status, to decide when stop config
|
||||
* @return smartConfig Done
|
||||
*/
|
||||
bool ESP8266WiFiSTAClass::smartConfigDone() {
|
||||
if(!_smartConfigStarted) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return _smartConfigDone;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* _smartConfigCallback
|
||||
* @param st
|
||||
* @param result
|
||||
*/
|
||||
void ESP8266WiFiSTAClass::_smartConfigCallback(uint32_t st, void* result) {
|
||||
sc_status status = (sc_status) st;
|
||||
if(status == SC_STATUS_LINK) {
|
||||
station_config* sta_conf = reinterpret_cast<station_config*>(result);
|
||||
|
||||
wifi_station_set_config(sta_conf);
|
||||
wifi_station_disconnect();
|
||||
wifi_station_connect();
|
||||
|
||||
_smartConfigDone = true;
|
||||
} else if(status == SC_STATUS_LINK_OVER) {
|
||||
WiFi.stopSmartConfig();
|
||||
}
|
||||
}
|
107
Software/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.h
Normal file
107
Software/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.h
Normal file
@ -0,0 +1,107 @@
|
||||
/*
|
||||
ESP8266WiFiSTA.h - esp8266 Wifi support.
|
||||
Based on WiFi.h from Ardiono WiFi shield library.
|
||||
Copyright (c) 2011-2014 Arduino. All right reserved.
|
||||
Modified by Ivan Grokhotkov, December 2014
|
||||
Reworked by Markus Sattler, December 2015
|
||||
|
||||
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
|
||||
*/
|
||||
|
||||
#ifndef ESP8266WIFISTA_H_
|
||||
#define ESP8266WIFISTA_H_
|
||||
|
||||
|
||||
#include "ESP8266WiFiType.h"
|
||||
#include "ESP8266WiFiGeneric.h"
|
||||
|
||||
|
||||
class ESP8266WiFiSTAClass {
|
||||
// ----------------------------------------------------------------------------------------------
|
||||
// ---------------------------------------- STA function ----------------------------------------
|
||||
// ----------------------------------------------------------------------------------------------
|
||||
|
||||
public:
|
||||
|
||||
wl_status_t begin(const char* ssid, const char *passphrase = NULL, int32_t channel = 0, const uint8_t* bssid = NULL, bool connect = true);
|
||||
wl_status_t begin(char* ssid, char *passphrase = NULL, int32_t channel = 0, const uint8_t* bssid = NULL, bool connect = true);
|
||||
wl_status_t begin();
|
||||
|
||||
bool config(IPAddress local_ip, IPAddress gateway, IPAddress subnet, IPAddress dns1 = (uint32_t)0x00000000, IPAddress dns2 = (uint32_t)0x00000000);
|
||||
|
||||
bool reconnect();
|
||||
bool disconnect(bool wifioff = false);
|
||||
|
||||
bool isConnected();
|
||||
|
||||
bool setAutoConnect(bool autoConnect);
|
||||
bool getAutoConnect();
|
||||
|
||||
bool setAutoReconnect(bool autoReconnect);
|
||||
|
||||
uint8_t waitForConnectResult();
|
||||
|
||||
// STA network info
|
||||
IPAddress localIP();
|
||||
|
||||
uint8_t * macAddress(uint8_t* mac);
|
||||
String macAddress();
|
||||
|
||||
IPAddress subnetMask();
|
||||
IPAddress gatewayIP();
|
||||
IPAddress dnsIP(uint8_t dns_no = 0);
|
||||
|
||||
String hostname();
|
||||
bool hostname(char* aHostname);
|
||||
bool hostname(const char* aHostname);
|
||||
bool hostname(String aHostname);
|
||||
|
||||
// STA WiFi info
|
||||
wl_status_t status();
|
||||
String SSID() const;
|
||||
String psk() const;
|
||||
|
||||
uint8_t * BSSID();
|
||||
String BSSIDstr();
|
||||
|
||||
int32_t RSSI();
|
||||
|
||||
protected:
|
||||
|
||||
static bool _useStaticIp;
|
||||
|
||||
// ----------------------------------------------------------------------------------------------
|
||||
// ------------------------------------ STA remote configure -----------------------------------
|
||||
// ----------------------------------------------------------------------------------------------
|
||||
|
||||
public:
|
||||
|
||||
bool beginWPSConfig(void);
|
||||
|
||||
bool beginSmartConfig();
|
||||
bool stopSmartConfig();
|
||||
bool smartConfigDone();
|
||||
|
||||
protected:
|
||||
|
||||
static bool _smartConfigStarted;
|
||||
static bool _smartConfigDone;
|
||||
|
||||
static void _smartConfigCallback(uint32_t status, void* result);
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif /* ESP8266WIFISTA_H_ */
|
335
Software/libraries/ESP8266WiFi/src/ESP8266WiFiScan.cpp
Normal file
335
Software/libraries/ESP8266WiFi/src/ESP8266WiFiScan.cpp
Normal file
@ -0,0 +1,335 @@
|
||||
/*
|
||||
ESP8266WiFiScan.cpp - WiFi library for esp8266
|
||||
|
||||
Copyright (c) 2014 Ivan Grokhotkov. 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
|
||||
|
||||
Reworked on 28 Dec 2015 by Markus Sattler
|
||||
|
||||
*/
|
||||
|
||||
#include "ESP8266WiFi.h"
|
||||
#include "ESP8266WiFiGeneric.h"
|
||||
#include "ESP8266WiFiScan.h"
|
||||
|
||||
extern "C" {
|
||||
#include "c_types.h"
|
||||
#include "ets_sys.h"
|
||||
#include "os_type.h"
|
||||
#include "osapi.h"
|
||||
#include "mem.h"
|
||||
#include "user_interface.h"
|
||||
}
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
extern "C" void esp_schedule();
|
||||
extern "C" void esp_yield();
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------------------------
|
||||
// ---------------------------------------------------- Private functions ------------------------------------------------
|
||||
// -----------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------------------------
|
||||
// ----------------------------------------------------- scan function ---------------------------------------------------
|
||||
// -----------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
bool ESP8266WiFiScanClass::_scanAsync = false;
|
||||
bool ESP8266WiFiScanClass::_scanStarted = false;
|
||||
bool ESP8266WiFiScanClass::_scanComplete = false;
|
||||
|
||||
size_t ESP8266WiFiScanClass::_scanCount = 0;
|
||||
void* ESP8266WiFiScanClass::_scanResult = 0;
|
||||
|
||||
std::function<void(int)> ESP8266WiFiScanClass::_onComplete;
|
||||
|
||||
/**
|
||||
* Start scan WiFi networks available
|
||||
* @param async run in async mode
|
||||
* @param show_hidden show hidden networks
|
||||
* @return Number of discovered networks
|
||||
*/
|
||||
int8_t ESP8266WiFiScanClass::scanNetworks(bool async, bool show_hidden) {
|
||||
if(ESP8266WiFiScanClass::_scanStarted) {
|
||||
return WIFI_SCAN_RUNNING;
|
||||
}
|
||||
|
||||
ESP8266WiFiScanClass::_scanAsync = async;
|
||||
|
||||
WiFi.enableSTA(true);
|
||||
|
||||
int status = wifi_station_get_connect_status();
|
||||
if(status != STATION_GOT_IP && status != STATION_IDLE) {
|
||||
wifi_station_disconnect();
|
||||
}
|
||||
|
||||
scanDelete();
|
||||
|
||||
struct scan_config config;
|
||||
config.ssid = 0;
|
||||
config.bssid = 0;
|
||||
config.channel = 0;
|
||||
config.show_hidden = show_hidden;
|
||||
if(wifi_station_scan(&config, reinterpret_cast<scan_done_cb_t>(&ESP8266WiFiScanClass::_scanDone))) {
|
||||
ESP8266WiFiScanClass::_scanComplete = false;
|
||||
ESP8266WiFiScanClass::_scanStarted = true;
|
||||
|
||||
if(ESP8266WiFiScanClass::_scanAsync) {
|
||||
delay(0); // time for the OS to trigger the scan
|
||||
return WIFI_SCAN_RUNNING;
|
||||
}
|
||||
|
||||
esp_yield();
|
||||
return ESP8266WiFiScanClass::_scanCount;
|
||||
} else {
|
||||
return WIFI_SCAN_FAILED;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts scanning WiFi networks available in async mode
|
||||
* @param onComplete the event handler executed when the scan is done
|
||||
* @param show_hidden show hidden networks
|
||||
*/
|
||||
void ESP8266WiFiScanClass::scanNetworksAsync(std::function<void(int)> onComplete, bool show_hidden) {
|
||||
_onComplete = onComplete;
|
||||
scanNetworks(true, show_hidden);
|
||||
}
|
||||
|
||||
/**
|
||||
* called to get the scan state in Async mode
|
||||
* @return scan result or status
|
||||
* -1 if scan not fin
|
||||
* -2 if scan not triggered
|
||||
*/
|
||||
int8_t ESP8266WiFiScanClass::scanComplete() {
|
||||
|
||||
if(_scanStarted) {
|
||||
return WIFI_SCAN_RUNNING;
|
||||
}
|
||||
|
||||
if(_scanComplete) {
|
||||
return ESP8266WiFiScanClass::_scanCount;
|
||||
}
|
||||
|
||||
return WIFI_SCAN_FAILED;
|
||||
}
|
||||
|
||||
/**
|
||||
* delete last scan result from RAM
|
||||
*/
|
||||
void ESP8266WiFiScanClass::scanDelete() {
|
||||
if(ESP8266WiFiScanClass::_scanResult) {
|
||||
delete[] reinterpret_cast<bss_info*>(ESP8266WiFiScanClass::_scanResult);
|
||||
ESP8266WiFiScanClass::_scanResult = 0;
|
||||
ESP8266WiFiScanClass::_scanCount = 0;
|
||||
}
|
||||
_scanComplete = false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* loads all infos from a scanned wifi in to the ptr parameters
|
||||
* @param networkItem uint8_t
|
||||
* @param ssid const char**
|
||||
* @param encryptionType uint8_t *
|
||||
* @param RSSI int32_t *
|
||||
* @param BSSID uint8_t **
|
||||
* @param channel int32_t *
|
||||
* @param isHidden bool *
|
||||
* @return (true if ok)
|
||||
*/
|
||||
bool ESP8266WiFiScanClass::getNetworkInfo(uint8_t i, String &ssid, uint8_t &encType, int32_t &rssi, uint8_t* &bssid, int32_t &channel, bool &isHidden) {
|
||||
struct bss_info* it = reinterpret_cast<struct bss_info*>(_getScanInfoByIndex(i));
|
||||
if(!it) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ssid = (const char*) it->ssid;
|
||||
encType = encryptionType(i);
|
||||
rssi = it->rssi;
|
||||
bssid = it->bssid; // move ptr
|
||||
channel = it->channel;
|
||||
isHidden = (it->is_hidden != 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the SSID discovered during the network scan.
|
||||
* @param i specify from which network item want to get the information
|
||||
* @return ssid string of the specified item on the networks scanned list
|
||||
*/
|
||||
String ESP8266WiFiScanClass::SSID(uint8_t i) {
|
||||
struct bss_info* it = reinterpret_cast<struct bss_info*>(_getScanInfoByIndex(i));
|
||||
if(!it) {
|
||||
return "";
|
||||
}
|
||||
|
||||
return String(reinterpret_cast<const char*>(it->ssid));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the encryption type of the networks discovered during the scanNetworks
|
||||
* @param i specify from which network item want to get the information
|
||||
* @return encryption type (enum wl_enc_type) of the specified item on the networks scanned list
|
||||
*/
|
||||
uint8_t ESP8266WiFiScanClass::encryptionType(uint8_t i) {
|
||||
struct bss_info* it = reinterpret_cast<struct bss_info*>(_getScanInfoByIndex(i));
|
||||
if(!it) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch(it->authmode) {
|
||||
case AUTH_OPEN:
|
||||
return ENC_TYPE_NONE;
|
||||
case AUTH_WEP:
|
||||
return ENC_TYPE_WEP;
|
||||
case AUTH_WPA_PSK:
|
||||
return ENC_TYPE_TKIP;
|
||||
case AUTH_WPA2_PSK:
|
||||
return ENC_TYPE_CCMP;
|
||||
case AUTH_WPA_WPA2_PSK:
|
||||
return ENC_TYPE_AUTO;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the RSSI of the networks discovered during the scanNetworks
|
||||
* @param i specify from which network item want to get the information
|
||||
* @return signed value of RSSI of the specified item on the networks scanned list
|
||||
*/
|
||||
int32_t ESP8266WiFiScanClass::RSSI(uint8_t i) {
|
||||
struct bss_info* it = reinterpret_cast<struct bss_info*>(_getScanInfoByIndex(i));
|
||||
if(!it) {
|
||||
return 0;
|
||||
}
|
||||
return it->rssi;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* return MAC / BSSID of scanned wifi
|
||||
* @param i specify from which network item want to get the information
|
||||
* @return uint8_t * MAC / BSSID of scanned wifi
|
||||
*/
|
||||
uint8_t * ESP8266WiFiScanClass::BSSID(uint8_t i) {
|
||||
struct bss_info* it = reinterpret_cast<struct bss_info*>(_getScanInfoByIndex(i));
|
||||
if(!it) {
|
||||
return 0;
|
||||
}
|
||||
return it->bssid;
|
||||
}
|
||||
|
||||
/**
|
||||
* return MAC / BSSID of scanned wifi
|
||||
* @param i specify from which network item want to get the information
|
||||
* @return String MAC / BSSID of scanned wifi
|
||||
*/
|
||||
String ESP8266WiFiScanClass::BSSIDstr(uint8_t i) {
|
||||
char mac[18] = { 0 };
|
||||
struct bss_info* it = reinterpret_cast<struct bss_info*>(_getScanInfoByIndex(i));
|
||||
if(!it) {
|
||||
return String("");
|
||||
}
|
||||
sprintf(mac, "%02X:%02X:%02X:%02X:%02X:%02X", it->bssid[0], it->bssid[1], it->bssid[2], it->bssid[3], it->bssid[4], it->bssid[5]);
|
||||
return String(mac);
|
||||
}
|
||||
|
||||
int32_t ESP8266WiFiScanClass::channel(uint8_t i) {
|
||||
struct bss_info* it = reinterpret_cast<struct bss_info*>(_getScanInfoByIndex(i));
|
||||
if(!it) {
|
||||
return 0;
|
||||
}
|
||||
return it->channel;
|
||||
}
|
||||
|
||||
/**
|
||||
* return if the scanned wifi is Hidden (no SSID)
|
||||
* @param networkItem specify from which network item want to get the information
|
||||
* @return bool (true == hidden)
|
||||
*/
|
||||
bool ESP8266WiFiScanClass::isHidden(uint8_t i) {
|
||||
struct bss_info* it = reinterpret_cast<struct bss_info*>(_getScanInfoByIndex(i));
|
||||
if(!it) {
|
||||
return false;
|
||||
}
|
||||
return (it->is_hidden != 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* private
|
||||
* scan callback
|
||||
* @param result void *arg
|
||||
* @param status STATUS
|
||||
*/
|
||||
void ESP8266WiFiScanClass::_scanDone(void* result, int status) {
|
||||
if(status != OK) {
|
||||
ESP8266WiFiScanClass::_scanCount = 0;
|
||||
ESP8266WiFiScanClass::_scanResult = 0;
|
||||
} else {
|
||||
|
||||
int i = 0;
|
||||
bss_info* head = reinterpret_cast<bss_info*>(result);
|
||||
|
||||
for(bss_info* it = head; it; it = STAILQ_NEXT(it, next), ++i)
|
||||
;
|
||||
ESP8266WiFiScanClass::_scanCount = i;
|
||||
if(i == 0) {
|
||||
ESP8266WiFiScanClass::_scanResult = 0;
|
||||
} else {
|
||||
bss_info* copied_info = new bss_info[i];
|
||||
i = 0;
|
||||
for(bss_info* it = head; it; it = STAILQ_NEXT(it, next), ++i) {
|
||||
memcpy(copied_info + i, it, sizeof(bss_info));
|
||||
}
|
||||
|
||||
ESP8266WiFiScanClass::_scanResult = copied_info;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ESP8266WiFiScanClass::_scanStarted = false;
|
||||
ESP8266WiFiScanClass::_scanComplete = true;
|
||||
|
||||
if(!ESP8266WiFiScanClass::_scanAsync) {
|
||||
esp_schedule();
|
||||
} else if (ESP8266WiFiScanClass::_onComplete) {
|
||||
ESP8266WiFiScanClass::_onComplete(ESP8266WiFiScanClass::_scanCount);
|
||||
ESP8266WiFiScanClass::_onComplete = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param i specify from which network item want to get the information
|
||||
* @return bss_info *
|
||||
*/
|
||||
void * ESP8266WiFiScanClass::_getScanInfoByIndex(int i) {
|
||||
if(!ESP8266WiFiScanClass::_scanResult || (size_t) i > ESP8266WiFiScanClass::_scanCount) {
|
||||
return 0;
|
||||
}
|
||||
return reinterpret_cast<bss_info*>(ESP8266WiFiScanClass::_scanResult) + i;
|
||||
}
|
71
Software/libraries/ESP8266WiFi/src/ESP8266WiFiScan.h
Normal file
71
Software/libraries/ESP8266WiFi/src/ESP8266WiFiScan.h
Normal file
@ -0,0 +1,71 @@
|
||||
/*
|
||||
ESP8266WiFiScan.h - esp8266 Wifi support.
|
||||
Based on WiFi.h from Ardiono WiFi shield library.
|
||||
Copyright (c) 2011-2014 Arduino. All right reserved.
|
||||
Modified by Ivan Grokhotkov, December 2014
|
||||
Reworked by Markus Sattler, December 2015
|
||||
|
||||
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
|
||||
*/
|
||||
|
||||
#ifndef ESP8266WIFISCAN_H_
|
||||
#define ESP8266WIFISCAN_H_
|
||||
|
||||
#include "ESP8266WiFiType.h"
|
||||
#include "ESP8266WiFiGeneric.h"
|
||||
|
||||
class ESP8266WiFiScanClass {
|
||||
|
||||
// ----------------------------------------------------------------------------------------------
|
||||
// ----------------------------------------- scan function --------------------------------------
|
||||
// ----------------------------------------------------------------------------------------------
|
||||
|
||||
public:
|
||||
|
||||
int8_t scanNetworks(bool async = false, bool show_hidden = false);
|
||||
void scanNetworksAsync(std::function<void(int)> onComplete, bool show_hidden = false);
|
||||
|
||||
int8_t scanComplete();
|
||||
void scanDelete();
|
||||
|
||||
// scan result
|
||||
bool getNetworkInfo(uint8_t networkItem, String &ssid, uint8_t &encryptionType, int32_t &RSSI, uint8_t* &BSSID, int32_t &channel, bool &isHidden);
|
||||
|
||||
String SSID(uint8_t networkItem);
|
||||
uint8_t encryptionType(uint8_t networkItem);
|
||||
int32_t RSSI(uint8_t networkItem);
|
||||
uint8_t * BSSID(uint8_t networkItem);
|
||||
String BSSIDstr(uint8_t networkItem);
|
||||
int32_t channel(uint8_t networkItem);
|
||||
bool isHidden(uint8_t networkItem);
|
||||
|
||||
protected:
|
||||
|
||||
static bool _scanAsync;
|
||||
static bool _scanStarted;
|
||||
static bool _scanComplete;
|
||||
|
||||
static size_t _scanCount;
|
||||
static void* _scanResult;
|
||||
|
||||
static std::function<void(int)> _onComplete;
|
||||
|
||||
static void _scanDone(void* result, int status);
|
||||
static void * _getScanInfoByIndex(int i);
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif /* ESP8266WIFISCAN_H_ */
|
151
Software/libraries/ESP8266WiFi/src/ESP8266WiFiType.h
Normal file
151
Software/libraries/ESP8266WiFi/src/ESP8266WiFiType.h
Normal file
@ -0,0 +1,151 @@
|
||||
/*
|
||||
ESP8266WiFiType.h - esp8266 Wifi support.
|
||||
Copyright (c) 2011-2014 Arduino. All right reserved.
|
||||
Modified by Ivan Grokhotkov, December 2014
|
||||
Reworked by Markus Sattler, December 2015
|
||||
|
||||
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
|
||||
*/
|
||||
|
||||
|
||||
#ifndef ESP8266WIFITYPE_H_
|
||||
#define ESP8266WIFITYPE_H_
|
||||
|
||||
#include <queue.h>
|
||||
|
||||
#define WIFI_SCAN_RUNNING (-1)
|
||||
#define WIFI_SCAN_FAILED (-2)
|
||||
|
||||
// Note: these enums need to be in sync with the SDK!
|
||||
|
||||
// TODO: replace/deprecate/remove enum typedefs ending with _t below
|
||||
|
||||
typedef enum WiFiMode
|
||||
{
|
||||
WIFI_OFF = 0, WIFI_STA = 1, WIFI_AP = 2, WIFI_AP_STA = 3
|
||||
} WiFiMode_t;
|
||||
|
||||
typedef enum WiFiPhyMode
|
||||
{
|
||||
WIFI_PHY_MODE_11B = 1, WIFI_PHY_MODE_11G = 2, WIFI_PHY_MODE_11N = 3
|
||||
} WiFiPhyMode_t;
|
||||
|
||||
typedef enum WiFiSleepType
|
||||
{
|
||||
WIFI_NONE_SLEEP = 0, WIFI_LIGHT_SLEEP = 1, WIFI_MODEM_SLEEP = 2
|
||||
} WiFiSleepType_t;
|
||||
|
||||
|
||||
typedef enum WiFiEvent
|
||||
{
|
||||
WIFI_EVENT_STAMODE_CONNECTED = 0,
|
||||
WIFI_EVENT_STAMODE_DISCONNECTED,
|
||||
WIFI_EVENT_STAMODE_AUTHMODE_CHANGE,
|
||||
WIFI_EVENT_STAMODE_GOT_IP,
|
||||
WIFI_EVENT_STAMODE_DHCP_TIMEOUT,
|
||||
WIFI_EVENT_SOFTAPMODE_STACONNECTED,
|
||||
WIFI_EVENT_SOFTAPMODE_STADISCONNECTED,
|
||||
WIFI_EVENT_SOFTAPMODE_PROBEREQRECVED,
|
||||
WIFI_EVENT_MAX,
|
||||
WIFI_EVENT_ANY = WIFI_EVENT_MAX,
|
||||
WIFI_EVENT_MODE_CHANGE
|
||||
} WiFiEvent_t;
|
||||
|
||||
enum WiFiDisconnectReason
|
||||
{
|
||||
WIFI_DISCONNECT_REASON_UNSPECIFIED = 1,
|
||||
WIFI_DISCONNECT_REASON_AUTH_EXPIRE = 2,
|
||||
WIFI_DISCONNECT_REASON_AUTH_LEAVE = 3,
|
||||
WIFI_DISCONNECT_REASON_ASSOC_EXPIRE = 4,
|
||||
WIFI_DISCONNECT_REASON_ASSOC_TOOMANY = 5,
|
||||
WIFI_DISCONNECT_REASON_NOT_AUTHED = 6,
|
||||
WIFI_DISCONNECT_REASON_NOT_ASSOCED = 7,
|
||||
WIFI_DISCONNECT_REASON_ASSOC_LEAVE = 8,
|
||||
WIFI_DISCONNECT_REASON_ASSOC_NOT_AUTHED = 9,
|
||||
WIFI_DISCONNECT_REASON_DISASSOC_PWRCAP_BAD = 10, /* 11h */
|
||||
WIFI_DISCONNECT_REASON_DISASSOC_SUPCHAN_BAD = 11, /* 11h */
|
||||
WIFI_DISCONNECT_REASON_IE_INVALID = 13, /* 11i */
|
||||
WIFI_DISCONNECT_REASON_MIC_FAILURE = 14, /* 11i */
|
||||
WIFI_DISCONNECT_REASON_4WAY_HANDSHAKE_TIMEOUT = 15, /* 11i */
|
||||
WIFI_DISCONNECT_REASON_GROUP_KEY_UPDATE_TIMEOUT = 16, /* 11i */
|
||||
WIFI_DISCONNECT_REASON_IE_IN_4WAY_DIFFERS = 17, /* 11i */
|
||||
WIFI_DISCONNECT_REASON_GROUP_CIPHER_INVALID = 18, /* 11i */
|
||||
WIFI_DISCONNECT_REASON_PAIRWISE_CIPHER_INVALID = 19, /* 11i */
|
||||
WIFI_DISCONNECT_REASON_AKMP_INVALID = 20, /* 11i */
|
||||
WIFI_DISCONNECT_REASON_UNSUPP_RSN_IE_VERSION = 21, /* 11i */
|
||||
WIFI_DISCONNECT_REASON_INVALID_RSN_IE_CAP = 22, /* 11i */
|
||||
WIFI_DISCONNECT_REASON_802_1X_AUTH_FAILED = 23, /* 11i */
|
||||
WIFI_DISCONNECT_REASON_CIPHER_SUITE_REJECTED = 24, /* 11i */
|
||||
|
||||
WIFI_DISCONNECT_REASON_BEACON_TIMEOUT = 200,
|
||||
WIFI_DISCONNECT_REASON_NO_AP_FOUND = 201,
|
||||
WIFI_DISCONNECT_REASON_AUTH_FAIL = 202,
|
||||
WIFI_DISCONNECT_REASON_ASSOC_FAIL = 203,
|
||||
WIFI_DISCONNECT_REASON_HANDSHAKE_TIMEOUT = 204,
|
||||
};
|
||||
|
||||
struct WiFiEventModeChange
|
||||
{
|
||||
WiFiMode oldMode;
|
||||
WiFiMode newMode;
|
||||
};
|
||||
|
||||
struct WiFiEventStationModeConnected
|
||||
{
|
||||
String ssid;
|
||||
uint8 bssid[6];
|
||||
uint8 channel;
|
||||
};
|
||||
|
||||
struct WiFiEventStationModeDisconnected
|
||||
{
|
||||
String ssid;
|
||||
uint8 bssid[6];
|
||||
WiFiDisconnectReason reason;
|
||||
};
|
||||
|
||||
struct WiFiEventStationModeAuthModeChanged
|
||||
{
|
||||
uint8 oldMode;
|
||||
uint8 newMode;
|
||||
};
|
||||
|
||||
struct WiFiEventStationModeGotIP
|
||||
{
|
||||
IPAddress ip;
|
||||
IPAddress mask;
|
||||
IPAddress gw;
|
||||
};
|
||||
|
||||
struct WiFiEventSoftAPModeStationConnected
|
||||
{
|
||||
uint8 mac[6];
|
||||
uint8 aid;
|
||||
};
|
||||
|
||||
struct WiFiEventSoftAPModeStationDisconnected
|
||||
{
|
||||
uint8 mac[6];
|
||||
uint8 aid;
|
||||
};
|
||||
|
||||
struct WiFiEventSoftAPModeProbeRequestReceived
|
||||
{
|
||||
int rssi;
|
||||
uint8 mac[6];
|
||||
};
|
||||
|
||||
|
||||
#endif /* ESP8266WIFITYPE_H_ */
|
341
Software/libraries/ESP8266WiFi/src/WiFiClient.cpp
Normal file
341
Software/libraries/ESP8266WiFi/src/WiFiClient.cpp
Normal file
@ -0,0 +1,341 @@
|
||||
/*
|
||||
WiFiClient.cpp - TCP/IP client for esp8266, mostly compatible
|
||||
with Arduino WiFi shield library
|
||||
|
||||
Copyright (c) 2014 Ivan Grokhotkov. 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
|
||||
*/
|
||||
|
||||
#define LWIP_INTERNAL
|
||||
|
||||
extern "C"
|
||||
{
|
||||
#include "include/wl_definitions.h"
|
||||
#include "osapi.h"
|
||||
#include "ets_sys.h"
|
||||
}
|
||||
|
||||
#include "debug.h"
|
||||
#include "ESP8266WiFi.h"
|
||||
#include "WiFiClient.h"
|
||||
#include "WiFiServer.h"
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/ip.h"
|
||||
#include "lwip/tcp.h"
|
||||
#include "lwip/inet.h"
|
||||
#include "lwip/netif.h"
|
||||
#include "include/ClientContext.h"
|
||||
#include "c_types.h"
|
||||
|
||||
uint16_t WiFiClient::_localPort = 0;
|
||||
|
||||
template<>
|
||||
WiFiClient* SList<WiFiClient>::_s_first = 0;
|
||||
|
||||
|
||||
WiFiClient::WiFiClient()
|
||||
: _client(0)
|
||||
{
|
||||
_timeout = 5000;
|
||||
WiFiClient::_add(this);
|
||||
}
|
||||
|
||||
WiFiClient::WiFiClient(ClientContext* client)
|
||||
: _client(client)
|
||||
{
|
||||
_timeout = 5000;
|
||||
_client->ref();
|
||||
WiFiClient::_add(this);
|
||||
}
|
||||
|
||||
WiFiClient::~WiFiClient()
|
||||
{
|
||||
WiFiClient::_remove(this);
|
||||
if (_client)
|
||||
_client->unref();
|
||||
}
|
||||
|
||||
WiFiClient::WiFiClient(const WiFiClient& other)
|
||||
{
|
||||
_client = other._client;
|
||||
_timeout = other._timeout;
|
||||
_localPort = other._localPort;
|
||||
if (_client)
|
||||
_client->ref();
|
||||
WiFiClient::_add(this);
|
||||
}
|
||||
|
||||
WiFiClient& WiFiClient::operator=(const WiFiClient& other)
|
||||
{
|
||||
if (_client)
|
||||
_client->unref();
|
||||
_client = other._client;
|
||||
_timeout = other._timeout;
|
||||
_localPort = other._localPort;
|
||||
if (_client)
|
||||
_client->ref();
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
int WiFiClient::connect(const char* host, uint16_t port)
|
||||
{
|
||||
IPAddress remote_addr;
|
||||
if (WiFi.hostByName(host, remote_addr, _timeout))
|
||||
{
|
||||
return connect(remote_addr, port);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int WiFiClient::connect(IPAddress ip, uint16_t port)
|
||||
{
|
||||
ip_addr_t addr;
|
||||
addr.addr = ip;
|
||||
|
||||
if (_client)
|
||||
stop();
|
||||
|
||||
// if the default interface is down, tcp_connect exits early without
|
||||
// ever calling tcp_err
|
||||
// http://lists.gnu.org/archive/html/lwip-devel/2010-05/msg00001.html
|
||||
#if LWIP_VERSION_MAJOR == 1
|
||||
netif* interface = ip_route(&addr);
|
||||
if (!interface) {
|
||||
DEBUGV("no route to host\r\n");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
tcp_pcb* pcb = tcp_new();
|
||||
if (!pcb)
|
||||
return 0;
|
||||
|
||||
if (_localPort > 0) {
|
||||
pcb->local_port = _localPort++;
|
||||
}
|
||||
|
||||
_client = new ClientContext(pcb, nullptr, nullptr);
|
||||
_client->ref();
|
||||
_client->setTimeout(_timeout);
|
||||
int res = _client->connect(&addr, port);
|
||||
if (res == 0) {
|
||||
_client->unref();
|
||||
_client = nullptr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void WiFiClient::setNoDelay(bool nodelay) {
|
||||
if (!_client)
|
||||
return;
|
||||
_client->setNoDelay(nodelay);
|
||||
}
|
||||
|
||||
bool WiFiClient::getNoDelay() {
|
||||
if (!_client)
|
||||
return false;
|
||||
return _client->getNoDelay();
|
||||
}
|
||||
|
||||
size_t WiFiClient::availableForWrite ()
|
||||
{
|
||||
return _client->availableForWrite();
|
||||
}
|
||||
|
||||
size_t WiFiClient::write(uint8_t b)
|
||||
{
|
||||
return write(&b, 1);
|
||||
}
|
||||
|
||||
size_t WiFiClient::write(const uint8_t *buf, size_t size)
|
||||
{
|
||||
if (!_client || !size)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
_client->setTimeout(_timeout);
|
||||
return _client->write(buf, size);
|
||||
}
|
||||
|
||||
size_t WiFiClient::write(Stream& stream, size_t unused)
|
||||
{
|
||||
(void) unused;
|
||||
return WiFiClient::write(stream);
|
||||
}
|
||||
|
||||
size_t WiFiClient::write(Stream& stream)
|
||||
{
|
||||
if (!_client || !stream.available())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
_client->setTimeout(_timeout);
|
||||
return _client->write(stream);
|
||||
}
|
||||
|
||||
size_t WiFiClient::write_P(PGM_P buf, size_t size)
|
||||
{
|
||||
if (!_client || !size)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
_client->setTimeout(_timeout);
|
||||
return _client->write_P(buf, size);
|
||||
}
|
||||
|
||||
int WiFiClient::available()
|
||||
{
|
||||
if (!_client)
|
||||
return false;
|
||||
|
||||
int result = _client->getSize();
|
||||
|
||||
if (!result) {
|
||||
optimistic_yield(100);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int WiFiClient::read()
|
||||
{
|
||||
if (!available())
|
||||
return -1;
|
||||
|
||||
return _client->read();
|
||||
}
|
||||
|
||||
|
||||
int WiFiClient::read(uint8_t* buf, size_t size)
|
||||
{
|
||||
return (int) _client->read(reinterpret_cast<char*>(buf), size);
|
||||
}
|
||||
|
||||
int WiFiClient::peek()
|
||||
{
|
||||
if (!available())
|
||||
return -1;
|
||||
|
||||
return _client->peek();
|
||||
}
|
||||
|
||||
size_t WiFiClient::peekBytes(uint8_t *buffer, size_t length) {
|
||||
size_t count = 0;
|
||||
|
||||
if(!_client) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
_startMillis = millis();
|
||||
while((available() < (int) length) && ((millis() - _startMillis) < _timeout)) {
|
||||
yield();
|
||||
}
|
||||
|
||||
if(available() < (int) length) {
|
||||
count = available();
|
||||
} else {
|
||||
count = length;
|
||||
}
|
||||
|
||||
return _client->peekBytes((char *)buffer, count);
|
||||
}
|
||||
|
||||
void WiFiClient::flush()
|
||||
{
|
||||
if (_client)
|
||||
_client->flush();
|
||||
}
|
||||
|
||||
void WiFiClient::stop()
|
||||
{
|
||||
if (!_client)
|
||||
return;
|
||||
|
||||
_client->unref();
|
||||
_client = 0;
|
||||
}
|
||||
|
||||
uint8_t WiFiClient::connected()
|
||||
{
|
||||
if (!_client)
|
||||
return 0;
|
||||
|
||||
return _client->state() == ESTABLISHED || available();
|
||||
}
|
||||
|
||||
uint8_t WiFiClient::status()
|
||||
{
|
||||
if (!_client)
|
||||
return CLOSED;
|
||||
return _client->state();
|
||||
}
|
||||
|
||||
WiFiClient::operator bool()
|
||||
{
|
||||
return _client != 0;
|
||||
}
|
||||
|
||||
IPAddress WiFiClient::remoteIP()
|
||||
{
|
||||
if (!_client)
|
||||
return IPAddress(0U);
|
||||
|
||||
return IPAddress(_client->getRemoteAddress());
|
||||
}
|
||||
|
||||
uint16_t WiFiClient::remotePort()
|
||||
{
|
||||
if (!_client)
|
||||
return 0;
|
||||
|
||||
return _client->getRemotePort();
|
||||
}
|
||||
|
||||
IPAddress WiFiClient::localIP()
|
||||
{
|
||||
if (!_client)
|
||||
return IPAddress(0U);
|
||||
|
||||
return IPAddress(_client->getLocalAddress());
|
||||
}
|
||||
|
||||
uint16_t WiFiClient::localPort()
|
||||
{
|
||||
if (!_client)
|
||||
return 0;
|
||||
|
||||
return _client->getLocalPort();
|
||||
}
|
||||
|
||||
void WiFiClient::stopAll()
|
||||
{
|
||||
for (WiFiClient* it = _s_first; it; it = it->_next) {
|
||||
it->stop();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void WiFiClient::stopAllExcept(WiFiClient* except)
|
||||
{
|
||||
for (WiFiClient* it = _s_first; it; it = it->_next) {
|
||||
if (it != except) {
|
||||
it->stop();
|
||||
}
|
||||
}
|
||||
}
|
99
Software/libraries/ESP8266WiFi/src/WiFiClient.h
Normal file
99
Software/libraries/ESP8266WiFi/src/WiFiClient.h
Normal file
@ -0,0 +1,99 @@
|
||||
/*
|
||||
WiFiClient.h - Library for Arduino Wifi shield.
|
||||
Copyright (c) 2011-2014 Arduino. All right reserved.
|
||||
|
||||
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
|
||||
|
||||
Modified by Ivan Grokhotkov, December 2014 - esp8266 support
|
||||
*/
|
||||
|
||||
#ifndef wificlient_h
|
||||
#define wificlient_h
|
||||
#include <memory>
|
||||
#include "Arduino.h"
|
||||
#include "Print.h"
|
||||
#include "Client.h"
|
||||
#include "IPAddress.h"
|
||||
#include "include/slist.h"
|
||||
|
||||
#define WIFICLIENT_MAX_PACKET_SIZE 1460
|
||||
|
||||
class ClientContext;
|
||||
class WiFiServer;
|
||||
|
||||
class WiFiClient : public Client, public SList<WiFiClient> {
|
||||
protected:
|
||||
WiFiClient(ClientContext* client);
|
||||
|
||||
public:
|
||||
WiFiClient();
|
||||
virtual ~WiFiClient();
|
||||
WiFiClient(const WiFiClient&);
|
||||
WiFiClient& operator=(const WiFiClient&);
|
||||
|
||||
uint8_t status();
|
||||
virtual int connect(IPAddress ip, uint16_t port);
|
||||
virtual int connect(const char *host, uint16_t port);
|
||||
virtual size_t write(uint8_t);
|
||||
virtual size_t write(const uint8_t *buf, size_t size);
|
||||
size_t write_P(PGM_P buf, size_t size);
|
||||
size_t write(Stream& stream);
|
||||
|
||||
// This one is deprecated, use write(Stream& instead)
|
||||
size_t write(Stream& stream, size_t unitSize) __attribute__ ((deprecated));
|
||||
|
||||
virtual int available();
|
||||
virtual int read();
|
||||
virtual int read(uint8_t *buf, size_t size);
|
||||
virtual int peek();
|
||||
virtual size_t peekBytes(uint8_t *buffer, size_t length);
|
||||
size_t peekBytes(char *buffer, size_t length) {
|
||||
return peekBytes((uint8_t *) buffer, length);
|
||||
}
|
||||
virtual void flush();
|
||||
virtual void stop();
|
||||
virtual uint8_t connected();
|
||||
virtual operator bool();
|
||||
|
||||
IPAddress remoteIP();
|
||||
uint16_t remotePort();
|
||||
IPAddress localIP();
|
||||
uint16_t localPort();
|
||||
bool getNoDelay();
|
||||
void setNoDelay(bool nodelay);
|
||||
static void setLocalPortStart(uint16_t port) { _localPort = port; }
|
||||
|
||||
size_t availableForWrite();
|
||||
|
||||
friend class WiFiServer;
|
||||
|
||||
using Print::write;
|
||||
|
||||
static void stopAll();
|
||||
static void stopAllExcept(WiFiClient * c);
|
||||
|
||||
protected:
|
||||
|
||||
static int8_t _s_connected(void* arg, void* tpcb, int8_t err);
|
||||
static void _s_err(void* arg, int8_t err);
|
||||
|
||||
int8_t _connected(void* tpcb, int8_t err);
|
||||
void _err(int8_t err);
|
||||
|
||||
ClientContext* _client;
|
||||
static uint16_t _localPort;
|
||||
};
|
||||
|
||||
#endif
|
704
Software/libraries/ESP8266WiFi/src/WiFiClientSecure.cpp
Normal file
704
Software/libraries/ESP8266WiFi/src/WiFiClientSecure.cpp
Normal file
@ -0,0 +1,704 @@
|
||||
/*
|
||||
WiFiClientSecure.cpp - Variant of WiFiClient with TLS support
|
||||
Copyright (c) 2015 Ivan Grokhotkov. 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
|
||||
|
||||
*/
|
||||
|
||||
#define LWIP_INTERNAL
|
||||
|
||||
extern "C"
|
||||
{
|
||||
#include "osapi.h"
|
||||
#include "ets_sys.h"
|
||||
}
|
||||
#include <errno.h>
|
||||
#include "debug.h"
|
||||
#include "ESP8266WiFi.h"
|
||||
#include "WiFiClientSecure.h"
|
||||
#include "WiFiClient.h"
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/ip.h"
|
||||
#include "lwip/tcp.h"
|
||||
#include "lwip/inet.h"
|
||||
#include "lwip/netif.h"
|
||||
#include "include/ClientContext.h"
|
||||
#include "c_types.h"
|
||||
|
||||
#ifdef DEBUG_ESP_SSL
|
||||
#define DEBUG_SSL
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_SSL
|
||||
#define SSL_DEBUG_OPTS (SSL_DISPLAY_STATES | SSL_DISPLAY_CERTS)
|
||||
#else
|
||||
#define SSL_DEBUG_OPTS 0
|
||||
#endif
|
||||
|
||||
class SSLContext
|
||||
{
|
||||
public:
|
||||
SSLContext()
|
||||
{
|
||||
if (_ssl_ctx_refcnt == 0) {
|
||||
_ssl_ctx = ssl_ctx_new(SSL_SERVER_VERIFY_LATER | SSL_DEBUG_OPTS | SSL_CONNECT_IN_PARTS | SSL_READ_BLOCKING | SSL_NO_DEFAULT_KEY, 0);
|
||||
}
|
||||
++_ssl_ctx_refcnt;
|
||||
}
|
||||
|
||||
~SSLContext()
|
||||
{
|
||||
if (_ssl) {
|
||||
ssl_free(_ssl);
|
||||
_ssl = nullptr;
|
||||
}
|
||||
|
||||
--_ssl_ctx_refcnt;
|
||||
if (_ssl_ctx_refcnt == 0) {
|
||||
ssl_ctx_free(_ssl_ctx);
|
||||
}
|
||||
|
||||
s_io_ctx = nullptr;
|
||||
}
|
||||
|
||||
void ref()
|
||||
{
|
||||
++_refcnt;
|
||||
}
|
||||
|
||||
void unref()
|
||||
{
|
||||
if (--_refcnt == 0) {
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
|
||||
void connect(ClientContext* ctx, const char* hostName, uint32_t timeout_ms)
|
||||
{
|
||||
SSL_EXTENSIONS* ext = ssl_ext_new();
|
||||
ssl_ext_set_host_name(ext, hostName);
|
||||
ssl_ext_set_max_fragment_size(ext, 4096);
|
||||
if (_ssl) {
|
||||
/* Creating a new TLS session on top of a new TCP connection.
|
||||
ssl_free will want to send a close notify alert, but the old TCP connection
|
||||
is already gone at this point, so reset s_io_ctx. */
|
||||
s_io_ctx = nullptr;
|
||||
ssl_free(_ssl);
|
||||
_available = 0;
|
||||
_read_ptr = nullptr;
|
||||
}
|
||||
s_io_ctx = ctx;
|
||||
_ssl = ssl_client_new(_ssl_ctx, 0, nullptr, 0, ext);
|
||||
uint32_t t = millis();
|
||||
|
||||
while (millis() - t < timeout_ms && ssl_handshake_status(_ssl) != SSL_OK) {
|
||||
uint8_t* data;
|
||||
int rc = ssl_read(_ssl, &data);
|
||||
if (rc < SSL_OK) {
|
||||
ssl_display_error(rc);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void stop()
|
||||
{
|
||||
s_io_ctx = nullptr;
|
||||
}
|
||||
|
||||
bool connected()
|
||||
{
|
||||
return _ssl != nullptr && ssl_handshake_status(_ssl) == SSL_OK;
|
||||
}
|
||||
|
||||
int read(uint8_t* dst, size_t size)
|
||||
{
|
||||
if (!_available) {
|
||||
if (!_readAll()) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
size_t will_copy = (_available < size) ? _available : size;
|
||||
memcpy(dst, _read_ptr, will_copy);
|
||||
_read_ptr += will_copy;
|
||||
_available -= will_copy;
|
||||
if (_available == 0) {
|
||||
_read_ptr = nullptr;
|
||||
}
|
||||
return will_copy;
|
||||
}
|
||||
|
||||
int read()
|
||||
{
|
||||
if (!_available) {
|
||||
if (!_readAll()) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
int result = _read_ptr[0];
|
||||
++_read_ptr;
|
||||
--_available;
|
||||
if (_available == 0) {
|
||||
_read_ptr = nullptr;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int peek()
|
||||
{
|
||||
if (!_available) {
|
||||
if (!_readAll()) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return _read_ptr[0];
|
||||
}
|
||||
|
||||
size_t peekBytes(char *dst, size_t size)
|
||||
{
|
||||
if (!_available) {
|
||||
if (!_readAll()) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
size_t will_copy = (_available < size) ? _available : size;
|
||||
memcpy(dst, _read_ptr, will_copy);
|
||||
return will_copy;
|
||||
}
|
||||
|
||||
int available()
|
||||
{
|
||||
auto cb = _available;
|
||||
if (cb == 0) {
|
||||
cb = _readAll();
|
||||
} else {
|
||||
optimistic_yield(100);
|
||||
}
|
||||
return cb;
|
||||
}
|
||||
|
||||
bool loadObject(int type, Stream& stream, size_t size)
|
||||
{
|
||||
std::unique_ptr<uint8_t[]> buf(new uint8_t[size]);
|
||||
if (!buf.get()) {
|
||||
DEBUGV("loadObject: failed to allocate memory\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t cb = stream.readBytes(buf.get(), size);
|
||||
if (cb != size) {
|
||||
DEBUGV("loadObject: reading %u bytes, got %u\n", size, cb);
|
||||
return false;
|
||||
}
|
||||
|
||||
return loadObject(type, buf.get(), size);
|
||||
}
|
||||
|
||||
bool loadObject_P(int type, PGM_VOID_P data, size_t size)
|
||||
{
|
||||
std::unique_ptr<uint8_t[]> buf(new uint8_t[size]);
|
||||
memcpy_P(buf.get(),data, size);
|
||||
return loadObject(type, buf.get(), size);
|
||||
}
|
||||
|
||||
|
||||
bool loadObject(int type, const uint8_t* data, size_t size)
|
||||
{
|
||||
int rc = ssl_obj_memory_load(_ssl_ctx, type, data, static_cast<int>(size), nullptr);
|
||||
if (rc != SSL_OK) {
|
||||
DEBUGV("loadObject: ssl_obj_memory_load returned %d\n", rc);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool verifyCert()
|
||||
{
|
||||
int rc = ssl_verify_cert(_ssl);
|
||||
if (_allowSelfSignedCerts && rc == SSL_X509_ERROR(X509_VFY_ERROR_SELF_SIGNED)) {
|
||||
DEBUGV("Allowing self-signed certificate\n");
|
||||
return true;
|
||||
} else if (rc != SSL_OK) {
|
||||
DEBUGV("ssl_verify_cert returned %d\n", rc);
|
||||
ssl_display_error(rc);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void allowSelfSignedCerts()
|
||||
{
|
||||
_allowSelfSignedCerts = true;
|
||||
}
|
||||
|
||||
operator SSL*()
|
||||
{
|
||||
return _ssl;
|
||||
}
|
||||
|
||||
static ClientContext* getIOContext(int fd)
|
||||
{
|
||||
(void) fd;
|
||||
return s_io_ctx;
|
||||
}
|
||||
|
||||
protected:
|
||||
int _readAll()
|
||||
{
|
||||
if (!_ssl) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
optimistic_yield(100);
|
||||
|
||||
uint8_t* data;
|
||||
int rc = ssl_read(_ssl, &data);
|
||||
if (rc <= 0) {
|
||||
if (rc < SSL_OK && rc != SSL_CLOSE_NOTIFY && rc != SSL_ERROR_CONN_LOST) {
|
||||
ssl_free(_ssl);
|
||||
_ssl = nullptr;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
DEBUGV(":wcs ra %d\r\n", rc);
|
||||
_read_ptr = data;
|
||||
_available = rc;
|
||||
return _available;
|
||||
}
|
||||
|
||||
static SSL_CTX* _ssl_ctx;
|
||||
static int _ssl_ctx_refcnt;
|
||||
SSL* _ssl = nullptr;
|
||||
int _refcnt = 0;
|
||||
const uint8_t* _read_ptr = nullptr;
|
||||
size_t _available = 0;
|
||||
bool _allowSelfSignedCerts = false;
|
||||
static ClientContext* s_io_ctx;
|
||||
};
|
||||
|
||||
SSL_CTX* SSLContext::_ssl_ctx = nullptr;
|
||||
int SSLContext::_ssl_ctx_refcnt = 0;
|
||||
ClientContext* SSLContext::s_io_ctx = nullptr;
|
||||
|
||||
WiFiClientSecure::WiFiClientSecure()
|
||||
{
|
||||
}
|
||||
|
||||
WiFiClientSecure::~WiFiClientSecure()
|
||||
{
|
||||
if (_ssl) {
|
||||
_ssl->unref();
|
||||
}
|
||||
}
|
||||
|
||||
WiFiClientSecure::WiFiClientSecure(const WiFiClientSecure& other)
|
||||
: WiFiClient(static_cast<const WiFiClient&>(other))
|
||||
{
|
||||
_ssl = other._ssl;
|
||||
if (_ssl) {
|
||||
_ssl->ref();
|
||||
}
|
||||
}
|
||||
|
||||
WiFiClientSecure& WiFiClientSecure::operator=(const WiFiClientSecure& rhs)
|
||||
{
|
||||
(WiFiClient&) *this = rhs;
|
||||
_ssl = rhs._ssl;
|
||||
if (_ssl) {
|
||||
_ssl->ref();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
int WiFiClientSecure::connect(IPAddress ip, uint16_t port)
|
||||
{
|
||||
if (!WiFiClient::connect(ip, port)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return _connectSSL(nullptr);
|
||||
}
|
||||
|
||||
int WiFiClientSecure::connect(const char* name, uint16_t port)
|
||||
{
|
||||
IPAddress remote_addr;
|
||||
if (!WiFi.hostByName(name, remote_addr)) {
|
||||
return 0;
|
||||
}
|
||||
if (!WiFiClient::connect(remote_addr, port)) {
|
||||
return 0;
|
||||
}
|
||||
return _connectSSL(name);
|
||||
}
|
||||
|
||||
int WiFiClientSecure::_connectSSL(const char* hostName)
|
||||
{
|
||||
if (!_ssl) {
|
||||
_ssl = new SSLContext;
|
||||
_ssl->ref();
|
||||
}
|
||||
_ssl->connect(_client, hostName, 5000);
|
||||
|
||||
auto status = ssl_handshake_status(*_ssl);
|
||||
if (status != SSL_OK) {
|
||||
_ssl->unref();
|
||||
_ssl = nullptr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_t WiFiClientSecure::write(const uint8_t *buf, size_t size)
|
||||
{
|
||||
if (!_ssl) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rc = ssl_write(*_ssl, buf, size);
|
||||
if (rc >= 0) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (rc != SSL_CLOSE_NOTIFY) {
|
||||
_ssl->unref();
|
||||
_ssl = nullptr;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int WiFiClientSecure::read(uint8_t *buf, size_t size)
|
||||
{
|
||||
if (!_ssl) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return _ssl->read(buf, size);
|
||||
}
|
||||
|
||||
int WiFiClientSecure::read()
|
||||
{
|
||||
if (!_ssl) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return _ssl->read();
|
||||
}
|
||||
|
||||
int WiFiClientSecure::peek()
|
||||
{
|
||||
if (!_ssl) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return _ssl->peek();
|
||||
}
|
||||
|
||||
size_t WiFiClientSecure::peekBytes(uint8_t *buffer, size_t length)
|
||||
{
|
||||
size_t count = 0;
|
||||
|
||||
if (!_ssl) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
_startMillis = millis();
|
||||
while ((available() < (int) length) && ((millis() - _startMillis) < _timeout)) {
|
||||
yield();
|
||||
}
|
||||
|
||||
if (!_ssl) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (available() < (int) length) {
|
||||
count = available();
|
||||
} else {
|
||||
count = length;
|
||||
}
|
||||
|
||||
return _ssl->peekBytes((char *)buffer, count);
|
||||
}
|
||||
|
||||
int WiFiClientSecure::available()
|
||||
{
|
||||
if (!_ssl) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return _ssl->available();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
SSL TCP RX data connected
|
||||
null x x N
|
||||
!null x Y Y
|
||||
Y Y x Y
|
||||
x N N N
|
||||
err x N N
|
||||
*/
|
||||
uint8_t WiFiClientSecure::connected()
|
||||
{
|
||||
if (_ssl) {
|
||||
if (_ssl->available()) {
|
||||
return true;
|
||||
}
|
||||
if (_client && _client->state() == ESTABLISHED && _ssl->connected()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void WiFiClientSecure::stop()
|
||||
{
|
||||
if (_ssl) {
|
||||
_ssl->stop();
|
||||
}
|
||||
WiFiClient::stop();
|
||||
}
|
||||
|
||||
static bool parseHexNibble(char pb, uint8_t* res)
|
||||
{
|
||||
if (pb >= '0' && pb <= '9') {
|
||||
*res = (uint8_t) (pb - '0'); return true;
|
||||
} else if (pb >= 'a' && pb <= 'f') {
|
||||
*res = (uint8_t) (pb - 'a' + 10); return true;
|
||||
} else if (pb >= 'A' && pb <= 'F') {
|
||||
*res = (uint8_t) (pb - 'A' + 10); return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Compare a name from certificate and domain name, return true if they match
|
||||
static bool matchName(const String& name, const String& domainName)
|
||||
{
|
||||
int wildcardPos = name.indexOf('*');
|
||||
if (wildcardPos == -1) {
|
||||
// Not a wildcard, expect an exact match
|
||||
return name == domainName;
|
||||
}
|
||||
int firstDotPos = name.indexOf('.');
|
||||
if (wildcardPos > firstDotPos) {
|
||||
// Wildcard is not part of leftmost component of domain name
|
||||
// Do not attempt to match (rfc6125 6.4.3.1)
|
||||
return false;
|
||||
}
|
||||
if (wildcardPos != 0 || firstDotPos != 1) {
|
||||
// Matching of wildcards such as baz*.example.com and b*z.example.com
|
||||
// is optional. Maybe implement this in the future?
|
||||
return false;
|
||||
}
|
||||
int domainNameFirstDotPos = domainName.indexOf('.');
|
||||
if (domainNameFirstDotPos < 0) {
|
||||
return false;
|
||||
}
|
||||
return domainName.substring(domainNameFirstDotPos) == name.substring(firstDotPos);
|
||||
}
|
||||
|
||||
bool WiFiClientSecure::verify(const char* fp, const char* domain_name)
|
||||
{
|
||||
if (!_ssl) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t sha1[20];
|
||||
int len = strlen(fp);
|
||||
int pos = 0;
|
||||
for (size_t i = 0; i < sizeof(sha1); ++i) {
|
||||
while (pos < len && ((fp[pos] == ' ') || (fp[pos] == ':'))) {
|
||||
++pos;
|
||||
}
|
||||
if (pos > len - 2) {
|
||||
DEBUGV("pos:%d len:%d fingerprint too short\r\n", pos, len);
|
||||
return false;
|
||||
}
|
||||
uint8_t high, low;
|
||||
if (!parseHexNibble(fp[pos], &high) || !parseHexNibble(fp[pos+1], &low)) {
|
||||
DEBUGV("pos:%d len:%d invalid hex sequence: %c%c\r\n", pos, len, fp[pos], fp[pos+1]);
|
||||
return false;
|
||||
}
|
||||
pos += 2;
|
||||
sha1[i] = low | (high << 4);
|
||||
}
|
||||
if (ssl_match_fingerprint(*_ssl, sha1) != 0) {
|
||||
DEBUGV("fingerprint doesn't match\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return _verifyDN(domain_name);
|
||||
}
|
||||
|
||||
bool WiFiClientSecure::_verifyDN(const char* domain_name)
|
||||
{
|
||||
DEBUGV("domain name: '%s'\r\n", (domain_name)?domain_name:"(null)");
|
||||
String domain_name_str(domain_name);
|
||||
domain_name_str.toLowerCase();
|
||||
|
||||
const char* san = NULL;
|
||||
int i = 0;
|
||||
while ((san = ssl_get_cert_subject_alt_dnsname(*_ssl, i)) != NULL) {
|
||||
String san_str(san);
|
||||
san_str.toLowerCase();
|
||||
if (matchName(san_str, domain_name_str)) {
|
||||
return true;
|
||||
}
|
||||
DEBUGV("SAN %d: '%s', no match\r\n", i, san);
|
||||
++i;
|
||||
}
|
||||
const char* common_name = ssl_get_cert_dn(*_ssl, SSL_X509_CERT_COMMON_NAME);
|
||||
String common_name_str(common_name);
|
||||
common_name_str.toLowerCase();
|
||||
if (common_name && matchName(common_name_str, domain_name_str)) {
|
||||
return true;
|
||||
}
|
||||
DEBUGV("CN: '%s', no match\r\n", (common_name)?common_name:"(null)");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool WiFiClientSecure::verifyCertChain(const char* domain_name)
|
||||
{
|
||||
if (!_ssl) {
|
||||
return false;
|
||||
}
|
||||
if (!_ssl->verifyCert()) {
|
||||
return false;
|
||||
}
|
||||
return _verifyDN(domain_name);
|
||||
}
|
||||
|
||||
void WiFiClientSecure::_initSSLContext()
|
||||
{
|
||||
if (!_ssl) {
|
||||
_ssl = new SSLContext;
|
||||
_ssl->ref();
|
||||
}
|
||||
}
|
||||
|
||||
bool WiFiClientSecure::setCACert(const uint8_t* pk, size_t size)
|
||||
{
|
||||
_initSSLContext();
|
||||
return _ssl->loadObject(SSL_OBJ_X509_CACERT, pk, size);
|
||||
}
|
||||
|
||||
bool WiFiClientSecure::setCertificate(const uint8_t* pk, size_t size)
|
||||
{
|
||||
_initSSLContext();
|
||||
return _ssl->loadObject(SSL_OBJ_X509_CERT, pk, size);
|
||||
}
|
||||
|
||||
bool WiFiClientSecure::setPrivateKey(const uint8_t* pk, size_t size)
|
||||
{
|
||||
_initSSLContext();
|
||||
return _ssl->loadObject(SSL_OBJ_RSA_KEY, pk, size);
|
||||
}
|
||||
|
||||
bool WiFiClientSecure::setCACert_P(PGM_VOID_P pk, size_t size)
|
||||
{
|
||||
_initSSLContext();
|
||||
return _ssl->loadObject_P(SSL_OBJ_X509_CACERT, pk, size);
|
||||
}
|
||||
|
||||
bool WiFiClientSecure::setCertificate_P(PGM_VOID_P pk, size_t size)
|
||||
{
|
||||
_initSSLContext();
|
||||
return _ssl->loadObject_P(SSL_OBJ_X509_CERT, pk, size);
|
||||
}
|
||||
|
||||
bool WiFiClientSecure::setPrivateKey_P(PGM_VOID_P pk, size_t size)
|
||||
{
|
||||
_initSSLContext();
|
||||
return _ssl->loadObject_P(SSL_OBJ_RSA_KEY, pk, size);
|
||||
}
|
||||
|
||||
bool WiFiClientSecure::loadCACert(Stream& stream, size_t size)
|
||||
{
|
||||
_initSSLContext();
|
||||
return _ssl->loadObject(SSL_OBJ_X509_CACERT, stream, size);
|
||||
}
|
||||
|
||||
bool WiFiClientSecure::loadCertificate(Stream& stream, size_t size)
|
||||
{
|
||||
_initSSLContext();
|
||||
return _ssl->loadObject(SSL_OBJ_X509_CERT, stream, size);
|
||||
}
|
||||
|
||||
bool WiFiClientSecure::loadPrivateKey(Stream& stream, size_t size)
|
||||
{
|
||||
_initSSLContext();
|
||||
return _ssl->loadObject(SSL_OBJ_RSA_KEY, stream, size);
|
||||
}
|
||||
|
||||
void WiFiClientSecure::allowSelfSignedCerts()
|
||||
{
|
||||
_initSSLContext();
|
||||
_ssl->allowSelfSignedCerts();
|
||||
}
|
||||
|
||||
extern "C" int __ax_port_read(int fd, uint8_t* buffer, size_t count)
|
||||
{
|
||||
ClientContext* _client = SSLContext::getIOContext(fd);
|
||||
if (!_client || (_client->state() != ESTABLISHED && !_client->getSize())) {
|
||||
errno = EIO;
|
||||
return -1;
|
||||
}
|
||||
size_t cb = _client->read((char*) buffer, count);
|
||||
if (cb != count) {
|
||||
errno = EAGAIN;
|
||||
}
|
||||
if (cb == 0) {
|
||||
optimistic_yield(100);
|
||||
return -1;
|
||||
}
|
||||
return cb;
|
||||
}
|
||||
extern "C" void ax_port_read() __attribute__ ((weak, alias("__ax_port_read")));
|
||||
|
||||
extern "C" int __ax_port_write(int fd, uint8_t* buffer, size_t count)
|
||||
{
|
||||
ClientContext* _client = SSLContext::getIOContext(fd);
|
||||
if (!_client || _client->state() != ESTABLISHED) {
|
||||
errno = EIO;
|
||||
return -1;
|
||||
}
|
||||
|
||||
size_t cb = _client->write(buffer, count);
|
||||
if (cb != count) {
|
||||
errno = EAGAIN;
|
||||
}
|
||||
return cb;
|
||||
}
|
||||
extern "C" void ax_port_write() __attribute__ ((weak, alias("__ax_port_write")));
|
||||
|
||||
extern "C" int __ax_get_file(const char *filename, uint8_t **buf)
|
||||
{
|
||||
(void) filename;
|
||||
*buf = 0;
|
||||
return 0;
|
||||
}
|
||||
extern "C" void ax_get_file() __attribute__ ((weak, alias("__ax_get_file")));
|
||||
|
||||
extern "C" void __ax_wdt_feed()
|
||||
{
|
||||
optimistic_yield(10000);
|
||||
}
|
||||
extern "C" void ax_wdt_feed() __attribute__ ((weak, alias("__ax_wdt_feed")));
|
91
Software/libraries/ESP8266WiFi/src/WiFiClientSecure.h
Normal file
91
Software/libraries/ESP8266WiFi/src/WiFiClientSecure.h
Normal file
@ -0,0 +1,91 @@
|
||||
/*
|
||||
WiFiClientSecure.h - Variant of WiFiClient with TLS support
|
||||
Copyright (c) 2015 Ivan Grokhotkov. 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
|
||||
|
||||
*/
|
||||
|
||||
#ifndef wificlientsecure_h
|
||||
#define wificlientsecure_h
|
||||
#include "WiFiClient.h"
|
||||
#include "include/ssl.h"
|
||||
|
||||
|
||||
class SSLContext;
|
||||
|
||||
class WiFiClientSecure : public WiFiClient {
|
||||
public:
|
||||
WiFiClientSecure();
|
||||
~WiFiClientSecure() override;
|
||||
WiFiClientSecure(const WiFiClientSecure&);
|
||||
WiFiClientSecure& operator=(const WiFiClientSecure&);
|
||||
|
||||
int connect(IPAddress ip, uint16_t port) override;
|
||||
int connect(const char* name, uint16_t port) override;
|
||||
|
||||
bool verify(const char* fingerprint, const char* domain_name);
|
||||
bool verifyCertChain(const char* domain_name);
|
||||
|
||||
uint8_t connected() override;
|
||||
size_t write(const uint8_t *buf, size_t size) override;
|
||||
int read(uint8_t *buf, size_t size) override;
|
||||
int available() override;
|
||||
int read() override;
|
||||
int peek() override;
|
||||
size_t peekBytes(uint8_t *buffer, size_t length) override;
|
||||
void stop() override;
|
||||
|
||||
bool setCACert(const uint8_t* pk, size_t size);
|
||||
bool setCertificate(const uint8_t* pk, size_t size);
|
||||
bool setPrivateKey(const uint8_t* pk, size_t size);
|
||||
|
||||
bool setCACert_P(PGM_VOID_P pk, size_t size);
|
||||
bool setCertificate_P(PGM_VOID_P pk, size_t size);
|
||||
bool setPrivateKey_P(PGM_VOID_P pk, size_t size);
|
||||
|
||||
bool loadCACert(Stream& stream, size_t size);
|
||||
bool loadCertificate(Stream& stream, size_t size);
|
||||
bool loadPrivateKey(Stream& stream, size_t size);
|
||||
|
||||
void allowSelfSignedCerts();
|
||||
|
||||
template<typename TFile>
|
||||
bool loadCertificate(TFile& file) {
|
||||
return loadCertificate(file, file.size());
|
||||
}
|
||||
|
||||
template<typename TFile>
|
||||
bool loadPrivateKey(TFile& file) {
|
||||
return loadPrivateKey(file, file.size());
|
||||
}
|
||||
|
||||
template<typename TFile>
|
||||
bool loadCACert(TFile& file) {
|
||||
return loadCACert(file, file.size());
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
void _initSSLContext();
|
||||
int _connectSSL(const char* hostName);
|
||||
bool _verifyDN(const char* name);
|
||||
|
||||
SSLContext* _ssl = nullptr;
|
||||
};
|
||||
|
||||
#endif //wificlientsecure_h
|
175
Software/libraries/ESP8266WiFi/src/WiFiServer.cpp
Normal file
175
Software/libraries/ESP8266WiFi/src/WiFiServer.cpp
Normal file
@ -0,0 +1,175 @@
|
||||
/*
|
||||
WiFiServer.cpp - TCP/IP server for esp8266, mostly compatible
|
||||
with Arduino WiFi shield library
|
||||
|
||||
Copyright (c) 2014 Ivan Grokhotkov. 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
|
||||
*/
|
||||
|
||||
|
||||
#define LWIP_INTERNAL
|
||||
|
||||
extern "C" {
|
||||
#include "osapi.h"
|
||||
#include "ets_sys.h"
|
||||
}
|
||||
|
||||
#include "debug.h"
|
||||
#include "ESP8266WiFi.h"
|
||||
#include "WiFiClient.h"
|
||||
#include "WiFiServer.h"
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/tcp.h"
|
||||
#include "lwip/inet.h"
|
||||
#include "include/ClientContext.h"
|
||||
|
||||
WiFiServer::WiFiServer(IPAddress addr, uint16_t port)
|
||||
: _port(port)
|
||||
, _addr(addr)
|
||||
, _pcb(nullptr)
|
||||
, _unclaimed(nullptr)
|
||||
, _discarded(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
WiFiServer::WiFiServer(uint16_t port)
|
||||
: _port(port)
|
||||
, _addr((uint32_t) IPADDR_ANY)
|
||||
, _pcb(nullptr)
|
||||
, _unclaimed(nullptr)
|
||||
, _discarded(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
void WiFiServer::begin() {
|
||||
close();
|
||||
err_t err;
|
||||
tcp_pcb* pcb = tcp_new();
|
||||
if (!pcb)
|
||||
return;
|
||||
|
||||
ip_addr_t local_addr;
|
||||
local_addr.addr = (uint32_t) _addr;
|
||||
pcb->so_options |= SOF_REUSEADDR;
|
||||
err = tcp_bind(pcb, &local_addr, _port);
|
||||
|
||||
if (err != ERR_OK) {
|
||||
tcp_close(pcb);
|
||||
return;
|
||||
}
|
||||
|
||||
tcp_pcb* listen_pcb = tcp_listen(pcb);
|
||||
if (!listen_pcb) {
|
||||
tcp_close(pcb);
|
||||
return;
|
||||
}
|
||||
_pcb = listen_pcb;
|
||||
tcp_accept(listen_pcb, &WiFiServer::_s_accept);
|
||||
tcp_arg(listen_pcb, (void*) this);
|
||||
}
|
||||
|
||||
void WiFiServer::setNoDelay(bool nodelay) {
|
||||
_noDelay = nodelay;
|
||||
}
|
||||
|
||||
bool WiFiServer::getNoDelay() {
|
||||
return _noDelay;
|
||||
}
|
||||
|
||||
bool WiFiServer::hasClient() {
|
||||
if (_unclaimed)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
WiFiClient WiFiServer::available(byte* status) {
|
||||
(void) status;
|
||||
if (_unclaimed) {
|
||||
WiFiClient result(_unclaimed);
|
||||
_unclaimed = _unclaimed->next();
|
||||
result.setNoDelay(_noDelay);
|
||||
DEBUGV("WS:av\r\n");
|
||||
return result;
|
||||
}
|
||||
|
||||
optimistic_yield(1000);
|
||||
return WiFiClient();
|
||||
}
|
||||
|
||||
uint8_t WiFiServer::status() {
|
||||
if (!_pcb)
|
||||
return CLOSED;
|
||||
return _pcb->state;
|
||||
}
|
||||
|
||||
void WiFiServer::close() {
|
||||
if (!_pcb) {
|
||||
return;
|
||||
}
|
||||
tcp_close(_pcb);
|
||||
_pcb = nullptr;
|
||||
}
|
||||
|
||||
void WiFiServer::stop() {
|
||||
close();
|
||||
}
|
||||
|
||||
size_t WiFiServer::write(uint8_t b) {
|
||||
return write(&b, 1);
|
||||
}
|
||||
|
||||
size_t WiFiServer::write(const uint8_t *buffer, size_t size) {
|
||||
// write to all clients
|
||||
// not implemented
|
||||
(void) buffer;
|
||||
(void) size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T* slist_append_tail(T* head, T* item) {
|
||||
if (!head)
|
||||
return item;
|
||||
T* last = head;
|
||||
while(last->next())
|
||||
last = last->next();
|
||||
last->next(item);
|
||||
return head;
|
||||
}
|
||||
|
||||
long WiFiServer::_accept(tcp_pcb* apcb, long err) {
|
||||
(void) err;
|
||||
DEBUGV("WS:ac\r\n");
|
||||
ClientContext* client = new ClientContext(apcb, &WiFiServer::_s_discard, this);
|
||||
_unclaimed = slist_append_tail(_unclaimed, client);
|
||||
tcp_accepted(_pcb);
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
void WiFiServer::_discard(ClientContext* client) {
|
||||
(void) client;
|
||||
// _discarded = slist_append_tail(_discarded, client);
|
||||
DEBUGV("WS:dis\r\n");
|
||||
}
|
||||
|
||||
long WiFiServer::_s_accept(void *arg, tcp_pcb* newpcb, long err) {
|
||||
return reinterpret_cast<WiFiServer*>(arg)->_accept(newpcb, err);
|
||||
}
|
||||
|
||||
void WiFiServer::_s_discard(void* server, ClientContext* ctx) {
|
||||
reinterpret_cast<WiFiServer*>(server)->_discard(ctx);
|
||||
}
|
72
Software/libraries/ESP8266WiFi/src/WiFiServer.h
Normal file
72
Software/libraries/ESP8266WiFi/src/WiFiServer.h
Normal file
@ -0,0 +1,72 @@
|
||||
/*
|
||||
WiFiServer.h - Library for Arduino Wifi shield.
|
||||
Copyright (c) 2011-2014 Arduino LLC. All right reserved.
|
||||
|
||||
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
|
||||
|
||||
Modified by Ivan Grokhotkov, December 2014 - esp8266 support
|
||||
*/
|
||||
|
||||
#ifndef wifiserver_h
|
||||
#define wifiserver_h
|
||||
|
||||
extern "C" {
|
||||
#include "include/wl_definitions.h"
|
||||
|
||||
struct tcp_pcb;
|
||||
}
|
||||
|
||||
#include "Server.h"
|
||||
#include "IPAddress.h"
|
||||
|
||||
class ClientContext;
|
||||
class WiFiClient;
|
||||
|
||||
class WiFiServer : public Server {
|
||||
private:
|
||||
uint16_t _port;
|
||||
IPAddress _addr;
|
||||
tcp_pcb* _pcb;
|
||||
|
||||
ClientContext* _unclaimed;
|
||||
ClientContext* _discarded;
|
||||
bool _noDelay = false;
|
||||
|
||||
public:
|
||||
WiFiServer(IPAddress addr, uint16_t port);
|
||||
WiFiServer(uint16_t port);
|
||||
virtual ~WiFiServer() {}
|
||||
WiFiClient available(uint8_t* status = NULL);
|
||||
bool hasClient();
|
||||
void begin();
|
||||
void setNoDelay(bool nodelay);
|
||||
bool getNoDelay();
|
||||
virtual size_t write(uint8_t);
|
||||
virtual size_t write(const uint8_t *buf, size_t size);
|
||||
uint8_t status();
|
||||
void close();
|
||||
void stop();
|
||||
|
||||
using Print::write;
|
||||
|
||||
protected:
|
||||
long _accept(tcp_pcb* newpcb, long err);
|
||||
void _discard(ClientContext* client);
|
||||
|
||||
static long _s_accept(void *arg, tcp_pcb* newpcb, long err);
|
||||
static void _s_discard(void* server, ClientContext* ctx);
|
||||
};
|
||||
|
||||
#endif
|
300
Software/libraries/ESP8266WiFi/src/WiFiUdp.cpp
Normal file
300
Software/libraries/ESP8266WiFi/src/WiFiUdp.cpp
Normal file
@ -0,0 +1,300 @@
|
||||
/*
|
||||
WiFiUdp.cpp - UDP client/server for esp8266, mostly compatible
|
||||
with Arduino WiFi shield library
|
||||
|
||||
Copyright (c) 2015 Ivan Grokhotkov. 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
|
||||
*/
|
||||
|
||||
#define LWIP_INTERNAL
|
||||
#include <functional>
|
||||
|
||||
extern "C"
|
||||
{
|
||||
#include "include/wl_definitions.h"
|
||||
#include "osapi.h"
|
||||
#include "ets_sys.h"
|
||||
}
|
||||
|
||||
#include "debug.h"
|
||||
#include "ESP8266WiFi.h"
|
||||
#include "WiFiUdp.h"
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/udp.h"
|
||||
#include "lwip/inet.h"
|
||||
#include "lwip/igmp.h"
|
||||
#include "lwip/mem.h"
|
||||
#include "include/UdpContext.h"
|
||||
|
||||
|
||||
template<>
|
||||
WiFiUDP* SList<WiFiUDP>::_s_first = 0;
|
||||
|
||||
/* Constructor */
|
||||
WiFiUDP::WiFiUDP() : _ctx(0)
|
||||
{
|
||||
WiFiUDP::_add(this);
|
||||
}
|
||||
|
||||
WiFiUDP::WiFiUDP(const WiFiUDP& other)
|
||||
{
|
||||
_ctx = other._ctx;
|
||||
if (_ctx)
|
||||
_ctx->ref();
|
||||
WiFiUDP::_add(this);
|
||||
}
|
||||
|
||||
WiFiUDP& WiFiUDP::operator=(const WiFiUDP& rhs)
|
||||
{
|
||||
_ctx = rhs._ctx;
|
||||
if (_ctx)
|
||||
_ctx->ref();
|
||||
return *this;
|
||||
}
|
||||
|
||||
WiFiUDP::~WiFiUDP()
|
||||
{
|
||||
WiFiUDP::_remove(this);
|
||||
if (_ctx)
|
||||
_ctx->unref();
|
||||
}
|
||||
|
||||
/* Start WiFiUDP socket, listening at local port */
|
||||
uint8_t WiFiUDP::begin(uint16_t port)
|
||||
{
|
||||
if (_ctx) {
|
||||
_ctx->unref();
|
||||
_ctx = 0;
|
||||
}
|
||||
|
||||
_ctx = new UdpContext;
|
||||
_ctx->ref();
|
||||
ip_addr_t addr;
|
||||
addr.addr = INADDR_ANY;
|
||||
return (_ctx->listen(addr, port)) ? 1 : 0;
|
||||
}
|
||||
|
||||
uint8_t WiFiUDP::beginMulticast(IPAddress interfaceAddr, IPAddress multicast, uint16_t port)
|
||||
{
|
||||
if (_ctx) {
|
||||
_ctx->unref();
|
||||
_ctx = 0;
|
||||
}
|
||||
|
||||
ip_addr_t ifaddr;
|
||||
ifaddr.addr = (uint32_t) interfaceAddr;
|
||||
ip_addr_t multicast_addr;
|
||||
multicast_addr.addr = (uint32_t) multicast;
|
||||
|
||||
if (igmp_joingroup(&ifaddr, &multicast_addr)!= ERR_OK) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
_ctx = new UdpContext;
|
||||
_ctx->ref();
|
||||
if (!_ctx->listen(*IP_ADDR_ANY, port)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* return number of bytes available in the current packet,
|
||||
will return zero if parsePacket hasn't been called yet */
|
||||
int WiFiUDP::available() {
|
||||
int result = 0;
|
||||
|
||||
if (_ctx) {
|
||||
result = static_cast<int>(_ctx->getSize());
|
||||
}
|
||||
|
||||
if (!result) {
|
||||
// yielding here will not make more data "available",
|
||||
// but it will prevent the system from going into WDT reset
|
||||
optimistic_yield(1000);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Release any resources being used by this WiFiUDP instance */
|
||||
void WiFiUDP::stop()
|
||||
{
|
||||
if (_ctx) {
|
||||
_ctx->disconnect();
|
||||
_ctx->unref();
|
||||
}
|
||||
_ctx = 0;
|
||||
}
|
||||
|
||||
int WiFiUDP::beginPacket(const char *host, uint16_t port)
|
||||
{
|
||||
IPAddress remote_addr;
|
||||
if (WiFi.hostByName(host, remote_addr))
|
||||
{
|
||||
return beginPacket(remote_addr, port);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int WiFiUDP::beginPacket(IPAddress ip, uint16_t port)
|
||||
{
|
||||
ip_addr_t addr;
|
||||
addr.addr = ip;
|
||||
|
||||
if (!_ctx) {
|
||||
_ctx = new UdpContext;
|
||||
_ctx->ref();
|
||||
}
|
||||
return (_ctx->connect(addr, port)) ? 1 : 0;
|
||||
}
|
||||
|
||||
int WiFiUDP::beginPacketMulticast(IPAddress multicastAddress, uint16_t port,
|
||||
IPAddress interfaceAddress, int ttl)
|
||||
{
|
||||
ip_addr_t mcastAddr;
|
||||
mcastAddr.addr = multicastAddress;
|
||||
ip_addr_t ifaceAddr;
|
||||
ifaceAddr.addr = interfaceAddress;
|
||||
|
||||
if (!_ctx) {
|
||||
_ctx = new UdpContext;
|
||||
_ctx->ref();
|
||||
}
|
||||
if (!_ctx->connect(mcastAddr, port)) {
|
||||
return 0;
|
||||
}
|
||||
_ctx->setMulticastInterface(ifaceAddr);
|
||||
_ctx->setMulticastTTL(ttl);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int WiFiUDP::endPacket()
|
||||
{
|
||||
if (!_ctx)
|
||||
return 0;
|
||||
|
||||
return (_ctx->send()) ? 1 : 0;
|
||||
}
|
||||
|
||||
size_t WiFiUDP::write(uint8_t byte)
|
||||
{
|
||||
return write(&byte, 1);
|
||||
}
|
||||
|
||||
size_t WiFiUDP::write(const uint8_t *buffer, size_t size)
|
||||
{
|
||||
if (!_ctx)
|
||||
return 0;
|
||||
|
||||
return _ctx->append(reinterpret_cast<const char*>(buffer), size);
|
||||
}
|
||||
|
||||
int WiFiUDP::parsePacket()
|
||||
{
|
||||
if (!_ctx)
|
||||
return 0;
|
||||
|
||||
if (!_ctx->next()) {
|
||||
optimistic_yield(100);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return _ctx->getSize();
|
||||
}
|
||||
|
||||
int WiFiUDP::read()
|
||||
{
|
||||
if (!_ctx)
|
||||
return -1;
|
||||
|
||||
return _ctx->read();
|
||||
}
|
||||
|
||||
int WiFiUDP::read(unsigned char* buffer, size_t len)
|
||||
{
|
||||
if (!_ctx)
|
||||
return 0;
|
||||
|
||||
return _ctx->read(reinterpret_cast<char*>(buffer), len);
|
||||
}
|
||||
|
||||
int WiFiUDP::peek()
|
||||
{
|
||||
if (!_ctx)
|
||||
return -1;
|
||||
|
||||
return _ctx->peek();
|
||||
}
|
||||
|
||||
void WiFiUDP::flush()
|
||||
{
|
||||
if (_ctx)
|
||||
_ctx->flush();
|
||||
}
|
||||
|
||||
IPAddress WiFiUDP::remoteIP()
|
||||
{
|
||||
if (!_ctx)
|
||||
return IPAddress(0U);
|
||||
|
||||
return IPAddress(_ctx->getRemoteAddress());
|
||||
}
|
||||
|
||||
uint16_t WiFiUDP::remotePort()
|
||||
{
|
||||
if (!_ctx)
|
||||
return 0;
|
||||
|
||||
return _ctx->getRemotePort();
|
||||
}
|
||||
|
||||
IPAddress WiFiUDP::destinationIP()
|
||||
{
|
||||
IPAddress addr;
|
||||
|
||||
if (!_ctx)
|
||||
return addr;
|
||||
|
||||
addr = _ctx->getDestAddress();
|
||||
return addr;
|
||||
}
|
||||
|
||||
uint16_t WiFiUDP::localPort()
|
||||
{
|
||||
if (!_ctx)
|
||||
return 0;
|
||||
|
||||
return _ctx->getLocalPort();
|
||||
}
|
||||
|
||||
void WiFiUDP::stopAll()
|
||||
{
|
||||
for (WiFiUDP* it = _s_first; it; it = it->_next) {
|
||||
DEBUGV("%s %08x %08x\n", __func__, (uint32_t) it, (uint32_t) _s_first);
|
||||
it->stop();
|
||||
}
|
||||
}
|
||||
|
||||
void WiFiUDP::stopAllExcept(WiFiUDP * exC) {
|
||||
for (WiFiUDP* it = _s_first; it; it = it->_next) {
|
||||
if (it->_ctx != exC->_ctx) {
|
||||
DEBUGV("%s %08x %08x\n", __func__, (uint32_t) it, (uint32_t) _s_first);
|
||||
it->stop();
|
||||
}
|
||||
}
|
||||
}
|
113
Software/libraries/ESP8266WiFi/src/WiFiUdp.h
Normal file
113
Software/libraries/ESP8266WiFi/src/WiFiUdp.h
Normal file
@ -0,0 +1,113 @@
|
||||
/*
|
||||
WiFiUdp.h - Library for Arduino Wifi shield.
|
||||
Copyright (c) 2011-2014 Arduino LLC. All right reserved.
|
||||
|
||||
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
|
||||
|
||||
Modified by Ivan Grokhotkov, January 2015 - esp8266 support
|
||||
*/
|
||||
|
||||
#ifndef WIFIUDP_H
|
||||
#define WIFIUDP_H
|
||||
|
||||
#include <Udp.h>
|
||||
#include <include/slist.h>
|
||||
|
||||
#define UDP_TX_PACKET_MAX_SIZE 8192
|
||||
|
||||
class UdpContext;
|
||||
|
||||
class WiFiUDP : public UDP, public SList<WiFiUDP> {
|
||||
private:
|
||||
UdpContext* _ctx;
|
||||
|
||||
public:
|
||||
WiFiUDP(); // Constructor
|
||||
WiFiUDP(const WiFiUDP& other);
|
||||
WiFiUDP& operator=(const WiFiUDP& rhs);
|
||||
~WiFiUDP();
|
||||
|
||||
operator bool() const { return _ctx != 0; }
|
||||
|
||||
// initialize, start listening on specified port.
|
||||
// Returns 1 if successful, 0 if there are no sockets available to use
|
||||
virtual uint8_t begin(uint16_t port);
|
||||
// Finish with the UDP connetion
|
||||
virtual void stop();
|
||||
// join a multicast group and listen on the given port
|
||||
uint8_t beginMulticast(IPAddress interfaceAddr, IPAddress multicast, uint16_t port);
|
||||
|
||||
// Sending UDP packets
|
||||
|
||||
// Start building up a packet to send to the remote host specific in ip and port
|
||||
// Returns 1 if successful, 0 if there was a problem with the supplied IP address or port
|
||||
virtual int beginPacket(IPAddress ip, uint16_t port);
|
||||
// Start building up a packet to send to the remote host specific in host and port
|
||||
// Returns 1 if successful, 0 if there was a problem resolving the hostname or port
|
||||
virtual int beginPacket(const char *host, uint16_t port);
|
||||
// Start building up a packet to send to the multicast address
|
||||
// multicastAddress - muticast address to send to
|
||||
// interfaceAddress - the local IP address of the interface that should be used
|
||||
// use WiFi.localIP() or WiFi.softAPIP() depending on the interface you need
|
||||
// ttl - multicast packet TTL (default is 1)
|
||||
// Returns 1 if successful, 0 if there was a problem with the supplied IP address or port
|
||||
virtual int beginPacketMulticast(IPAddress multicastAddress,
|
||||
uint16_t port,
|
||||
IPAddress interfaceAddress,
|
||||
int ttl = 1);
|
||||
// Finish off this packet and send it
|
||||
// Returns 1 if the packet was sent successfully, 0 if there was an error
|
||||
virtual int endPacket();
|
||||
// Write a single byte into the packet
|
||||
virtual size_t write(uint8_t);
|
||||
// Write size bytes from buffer into the packet
|
||||
virtual size_t write(const uint8_t *buffer, size_t size);
|
||||
|
||||
using Print::write;
|
||||
|
||||
// Start processing the next available incoming packet
|
||||
// Returns the size of the packet in bytes, or 0 if no packets are available
|
||||
virtual int parsePacket();
|
||||
// Number of bytes remaining in the current packet
|
||||
virtual int available();
|
||||
// Read a single byte from the current packet
|
||||
virtual int read();
|
||||
// Read up to len bytes from the current packet and place them into buffer
|
||||
// Returns the number of bytes read, or 0 if none are available
|
||||
virtual int read(unsigned char* buffer, size_t len);
|
||||
// Read up to len characters from the current packet and place them into buffer
|
||||
// Returns the number of characters read, or 0 if none are available
|
||||
virtual int read(char* buffer, size_t len) { return read((unsigned char*)buffer, len); };
|
||||
// Return the next byte from the current packet without moving on to the next byte
|
||||
virtual int peek();
|
||||
virtual void flush(); // Finish reading the current packet
|
||||
|
||||
// Return the IP address of the host who sent the current incoming packet
|
||||
virtual IPAddress remoteIP();
|
||||
// Return the port of the host who sent the current incoming packet
|
||||
virtual uint16_t remotePort();
|
||||
// Return the destination address for incoming packets,
|
||||
// useful to distinguish multicast and ordinary packets
|
||||
IPAddress destinationIP();
|
||||
// Return the local port for outgoing packets
|
||||
uint16_t localPort();
|
||||
|
||||
static void stopAll();
|
||||
static void stopAllExcept(WiFiUDP * exC);
|
||||
|
||||
};
|
||||
|
||||
#endif //WIFIUDP_H
|
||||
|
BIN
Software/libraries/ESP8266WiFi/src/include/._ClientContext.h
Normal file
BIN
Software/libraries/ESP8266WiFi/src/include/._ClientContext.h
Normal file
Binary file not shown.
BIN
Software/libraries/ESP8266WiFi/src/include/._DataSource.h
Normal file
BIN
Software/libraries/ESP8266WiFi/src/include/._DataSource.h
Normal file
Binary file not shown.
BIN
Software/libraries/ESP8266WiFi/src/include/._UdpContext.h
Normal file
BIN
Software/libraries/ESP8266WiFi/src/include/._UdpContext.h
Normal file
Binary file not shown.
BIN
Software/libraries/ESP8266WiFi/src/include/._slist.h
Normal file
BIN
Software/libraries/ESP8266WiFi/src/include/._slist.h
Normal file
Binary file not shown.
BIN
Software/libraries/ESP8266WiFi/src/include/._ssl.h
Normal file
BIN
Software/libraries/ESP8266WiFi/src/include/._ssl.h
Normal file
Binary file not shown.
BIN
Software/libraries/ESP8266WiFi/src/include/._wl_definitions.h
Normal file
BIN
Software/libraries/ESP8266WiFi/src/include/._wl_definitions.h
Normal file
Binary file not shown.
548
Software/libraries/ESP8266WiFi/src/include/ClientContext.h
Normal file
548
Software/libraries/ESP8266WiFi/src/include/ClientContext.h
Normal file
@ -0,0 +1,548 @@
|
||||
/*
|
||||
ClientContext.h - TCP connection handling on top of lwIP
|
||||
|
||||
Copyright (c) 2014 Ivan Grokhotkov. 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
|
||||
*/
|
||||
#ifndef CLIENTCONTEXT_H
|
||||
#define CLIENTCONTEXT_H
|
||||
|
||||
class ClientContext;
|
||||
class WiFiClient;
|
||||
|
||||
typedef void (*discard_cb_t)(void*, ClientContext*);
|
||||
|
||||
extern "C" void esp_yield();
|
||||
extern "C" void esp_schedule();
|
||||
|
||||
#include "DataSource.h"
|
||||
|
||||
class ClientContext
|
||||
{
|
||||
public:
|
||||
ClientContext(tcp_pcb* pcb, discard_cb_t discard_cb, void* discard_cb_arg) :
|
||||
_pcb(pcb), _rx_buf(0), _rx_buf_offset(0), _discard_cb(discard_cb), _discard_cb_arg(discard_cb_arg), _refcnt(0), _next(0)
|
||||
{
|
||||
tcp_setprio(pcb, TCP_PRIO_MIN);
|
||||
tcp_arg(pcb, this);
|
||||
tcp_recv(pcb, &_s_recv);
|
||||
tcp_sent(pcb, &_s_sent);
|
||||
tcp_err(pcb, &_s_error);
|
||||
tcp_poll(pcb, &_s_poll, 1);
|
||||
}
|
||||
|
||||
err_t abort()
|
||||
{
|
||||
if(_pcb) {
|
||||
DEBUGV(":abort\r\n");
|
||||
tcp_arg(_pcb, NULL);
|
||||
tcp_sent(_pcb, NULL);
|
||||
tcp_recv(_pcb, NULL);
|
||||
tcp_err(_pcb, NULL);
|
||||
tcp_poll(_pcb, NULL, 0);
|
||||
tcp_abort(_pcb);
|
||||
_pcb = 0;
|
||||
}
|
||||
return ERR_ABRT;
|
||||
}
|
||||
|
||||
err_t close()
|
||||
{
|
||||
err_t err = ERR_OK;
|
||||
if(_pcb) {
|
||||
DEBUGV(":close\r\n");
|
||||
tcp_arg(_pcb, NULL);
|
||||
tcp_sent(_pcb, NULL);
|
||||
tcp_recv(_pcb, NULL);
|
||||
tcp_err(_pcb, NULL);
|
||||
tcp_poll(_pcb, NULL, 0);
|
||||
err = tcp_close(_pcb);
|
||||
if(err != ERR_OK) {
|
||||
DEBUGV(":tc err %d\r\n", (int) err);
|
||||
tcp_abort(_pcb);
|
||||
err = ERR_ABRT;
|
||||
}
|
||||
_pcb = 0;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
~ClientContext()
|
||||
{
|
||||
}
|
||||
|
||||
ClientContext* next() const
|
||||
{
|
||||
return _next;
|
||||
}
|
||||
|
||||
ClientContext* next(ClientContext* new_next)
|
||||
{
|
||||
_next = new_next;
|
||||
return _next;
|
||||
}
|
||||
|
||||
void ref()
|
||||
{
|
||||
++_refcnt;
|
||||
DEBUGV(":ref %d\r\n", _refcnt);
|
||||
}
|
||||
|
||||
void unref()
|
||||
{
|
||||
if(this != 0) {
|
||||
DEBUGV(":ur %d\r\n", _refcnt);
|
||||
if(--_refcnt == 0) {
|
||||
flush();
|
||||
close();
|
||||
if(_discard_cb) {
|
||||
_discard_cb(_discard_cb_arg, this);
|
||||
}
|
||||
DEBUGV(":del\r\n");
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int connect(ip_addr_t* addr, uint16_t port)
|
||||
{
|
||||
err_t err = tcp_connect(_pcb, addr, port, &ClientContext::_s_connected);
|
||||
if (err != ERR_OK) {
|
||||
return 0;
|
||||
}
|
||||
_connect_pending = 1;
|
||||
_op_start_time = millis();
|
||||
// This delay will be interrupted by esp_schedule in the connect callback
|
||||
delay(_timeout_ms);
|
||||
_connect_pending = 0;
|
||||
if (state() != ESTABLISHED) {
|
||||
abort();
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_t availableForWrite()
|
||||
{
|
||||
return _pcb? tcp_sndbuf(_pcb): 0;
|
||||
}
|
||||
|
||||
void setNoDelay(bool nodelay)
|
||||
{
|
||||
if(!_pcb) {
|
||||
return;
|
||||
}
|
||||
if(nodelay) {
|
||||
tcp_nagle_disable(_pcb);
|
||||
} else {
|
||||
tcp_nagle_enable(_pcb);
|
||||
}
|
||||
}
|
||||
|
||||
bool getNoDelay()
|
||||
{
|
||||
if(!_pcb) {
|
||||
return false;
|
||||
}
|
||||
return tcp_nagle_disabled(_pcb);
|
||||
}
|
||||
|
||||
void setTimeout(int timeout_ms)
|
||||
{
|
||||
_timeout_ms = timeout_ms;
|
||||
}
|
||||
|
||||
int getTimeout()
|
||||
{
|
||||
return _timeout_ms;
|
||||
}
|
||||
|
||||
uint32_t getRemoteAddress()
|
||||
{
|
||||
if(!_pcb) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return _pcb->remote_ip.addr;
|
||||
}
|
||||
|
||||
uint16_t getRemotePort()
|
||||
{
|
||||
if(!_pcb) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return _pcb->remote_port;
|
||||
}
|
||||
|
||||
uint32_t getLocalAddress()
|
||||
{
|
||||
if(!_pcb) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return _pcb->local_ip.addr;
|
||||
}
|
||||
|
||||
uint16_t getLocalPort()
|
||||
{
|
||||
if(!_pcb) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return _pcb->local_port;
|
||||
}
|
||||
|
||||
size_t getSize() const
|
||||
{
|
||||
if(!_rx_buf) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return _rx_buf->tot_len - _rx_buf_offset;
|
||||
}
|
||||
|
||||
char read()
|
||||
{
|
||||
if(!_rx_buf) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
char c = reinterpret_cast<char*>(_rx_buf->payload)[_rx_buf_offset];
|
||||
_consume(1);
|
||||
return c;
|
||||
}
|
||||
|
||||
size_t read(char* dst, size_t size)
|
||||
{
|
||||
if(!_rx_buf) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t max_size = _rx_buf->tot_len - _rx_buf_offset;
|
||||
size = (size < max_size) ? size : max_size;
|
||||
|
||||
DEBUGV(":rd %d, %d, %d\r\n", size, _rx_buf->tot_len, _rx_buf_offset);
|
||||
size_t size_read = 0;
|
||||
while(size) {
|
||||
size_t buf_size = _rx_buf->len - _rx_buf_offset;
|
||||
size_t copy_size = (size < buf_size) ? size : buf_size;
|
||||
DEBUGV(":rdi %d, %d\r\n", buf_size, copy_size);
|
||||
os_memcpy(dst, reinterpret_cast<char*>(_rx_buf->payload) + _rx_buf_offset, copy_size);
|
||||
dst += copy_size;
|
||||
_consume(copy_size);
|
||||
size -= copy_size;
|
||||
size_read += copy_size;
|
||||
}
|
||||
return size_read;
|
||||
}
|
||||
|
||||
char peek()
|
||||
{
|
||||
if(!_rx_buf) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return reinterpret_cast<char*>(_rx_buf->payload)[_rx_buf_offset];
|
||||
}
|
||||
|
||||
size_t peekBytes(char *dst, size_t size)
|
||||
{
|
||||
if(!_rx_buf) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t max_size = _rx_buf->tot_len - _rx_buf_offset;
|
||||
size = (size < max_size) ? size : max_size;
|
||||
|
||||
DEBUGV(":pd %d, %d, %d\r\n", size, _rx_buf->tot_len, _rx_buf_offset);
|
||||
size_t buf_size = _rx_buf->len - _rx_buf_offset;
|
||||
size_t copy_size = (size < buf_size) ? size : buf_size;
|
||||
DEBUGV(":rpi %d, %d\r\n", buf_size, copy_size);
|
||||
os_memcpy(dst, reinterpret_cast<char*>(_rx_buf->payload) + _rx_buf_offset, copy_size);
|
||||
return copy_size;
|
||||
}
|
||||
|
||||
void flush()
|
||||
{
|
||||
if(!_rx_buf) {
|
||||
return;
|
||||
}
|
||||
if(_pcb) {
|
||||
tcp_recved(_pcb, (size_t) _rx_buf->tot_len);
|
||||
}
|
||||
pbuf_free(_rx_buf);
|
||||
_rx_buf = 0;
|
||||
_rx_buf_offset = 0;
|
||||
}
|
||||
|
||||
uint8_t state() const
|
||||
{
|
||||
if(!_pcb) {
|
||||
return CLOSED;
|
||||
}
|
||||
|
||||
return _pcb->state;
|
||||
}
|
||||
|
||||
|
||||
size_t write(const uint8_t* data, size_t size)
|
||||
{
|
||||
if (!_pcb) {
|
||||
return 0;
|
||||
}
|
||||
return _write_from_source(new BufferDataSource(data, size));
|
||||
}
|
||||
|
||||
size_t write(Stream& stream)
|
||||
{
|
||||
if (!_pcb) {
|
||||
return 0;
|
||||
}
|
||||
return _write_from_source(new BufferedStreamDataSource<Stream>(stream, stream.available()));
|
||||
}
|
||||
|
||||
size_t write_P(PGM_P buf, size_t size)
|
||||
{
|
||||
if (!_pcb) {
|
||||
return 0;
|
||||
}
|
||||
ProgmemStream stream(buf, size);
|
||||
return _write_from_source(new BufferedStreamDataSource<ProgmemStream>(stream, size));
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
bool _is_timeout()
|
||||
{
|
||||
return millis() - _op_start_time > _timeout_ms;
|
||||
}
|
||||
|
||||
void _notify_error()
|
||||
{
|
||||
if (_connect_pending || _send_waiting) {
|
||||
esp_schedule();
|
||||
}
|
||||
}
|
||||
|
||||
size_t _write_from_source(DataSource* ds)
|
||||
{
|
||||
assert(_datasource == nullptr);
|
||||
assert(_send_waiting == 0);
|
||||
_datasource = ds;
|
||||
_written = 0;
|
||||
_op_start_time = millis();
|
||||
do {
|
||||
if (_write_some()) {
|
||||
_op_start_time = millis();
|
||||
}
|
||||
|
||||
if (!_datasource->available() || _is_timeout() || state() == CLOSED) {
|
||||
if (_is_timeout()) {
|
||||
DEBUGV(":wtmo\r\n");
|
||||
}
|
||||
delete _datasource;
|
||||
_datasource = nullptr;
|
||||
break;
|
||||
}
|
||||
|
||||
++_send_waiting;
|
||||
esp_yield();
|
||||
} while(true);
|
||||
_send_waiting = 0;
|
||||
return _written;
|
||||
}
|
||||
|
||||
bool _write_some()
|
||||
{
|
||||
if (!_datasource || !_pcb) {
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t left = _datasource->available();
|
||||
size_t can_send = tcp_sndbuf(_pcb);
|
||||
if (_pcb->snd_queuelen >= TCP_SND_QUEUELEN) {
|
||||
can_send = 0;
|
||||
}
|
||||
size_t will_send = (can_send < left) ? can_send : left;
|
||||
DEBUGV(":wr %d %d %d\r\n", will_send, left, _written);
|
||||
bool need_output = false;
|
||||
while( will_send && _datasource) {
|
||||
size_t next_chunk =
|
||||
will_send > _write_chunk_size ? _write_chunk_size : will_send;
|
||||
const uint8_t* buf = _datasource->get_buffer(next_chunk);
|
||||
if (state() == CLOSED) {
|
||||
need_output = false;
|
||||
break;
|
||||
}
|
||||
err_t err = tcp_write(_pcb, buf, next_chunk, TCP_WRITE_FLAG_COPY);
|
||||
DEBUGV(":wrc %d %d %d\r\n", next_chunk, will_send, (int) err);
|
||||
_datasource->release_buffer(buf, next_chunk);
|
||||
if (err == ERR_OK) {
|
||||
_written += next_chunk;
|
||||
need_output = true;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
will_send -= next_chunk;
|
||||
}
|
||||
if( need_output ) {
|
||||
tcp_output(_pcb);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void _write_some_from_cb()
|
||||
{
|
||||
if (_send_waiting == 1) {
|
||||
_send_waiting--;
|
||||
esp_schedule();
|
||||
}
|
||||
}
|
||||
|
||||
err_t _sent(tcp_pcb* pcb, uint16_t len)
|
||||
{
|
||||
(void) pcb;
|
||||
(void) len;
|
||||
DEBUGV(":sent %d\r\n", len);
|
||||
_write_some_from_cb();
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
void _consume(size_t size)
|
||||
{
|
||||
ptrdiff_t left = _rx_buf->len - _rx_buf_offset - size;
|
||||
if(left > 0) {
|
||||
_rx_buf_offset += size;
|
||||
} else if(!_rx_buf->next) {
|
||||
DEBUGV(":c0 %d, %d\r\n", size, _rx_buf->tot_len);
|
||||
if(_pcb) {
|
||||
tcp_recved(_pcb, _rx_buf->len);
|
||||
}
|
||||
pbuf_free(_rx_buf);
|
||||
_rx_buf = 0;
|
||||
_rx_buf_offset = 0;
|
||||
} else {
|
||||
DEBUGV(":c %d, %d, %d\r\n", size, _rx_buf->len, _rx_buf->tot_len);
|
||||
auto head = _rx_buf;
|
||||
_rx_buf = _rx_buf->next;
|
||||
_rx_buf_offset = 0;
|
||||
pbuf_ref(_rx_buf);
|
||||
if(_pcb) {
|
||||
tcp_recved(_pcb, head->len);
|
||||
}
|
||||
pbuf_free(head);
|
||||
}
|
||||
}
|
||||
|
||||
err_t _recv(tcp_pcb* pcb, pbuf* pb, err_t err)
|
||||
{
|
||||
(void) pcb;
|
||||
(void) err;
|
||||
if(pb == 0) { // connection closed
|
||||
DEBUGV(":rcl\r\n");
|
||||
_notify_error();
|
||||
abort();
|
||||
return ERR_ABRT;
|
||||
}
|
||||
|
||||
if(_rx_buf) {
|
||||
DEBUGV(":rch %d, %d\r\n", _rx_buf->tot_len, pb->tot_len);
|
||||
pbuf_cat(_rx_buf, pb);
|
||||
} else {
|
||||
DEBUGV(":rn %d\r\n", pb->tot_len);
|
||||
_rx_buf = pb;
|
||||
_rx_buf_offset = 0;
|
||||
}
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
void _error(err_t err)
|
||||
{
|
||||
(void) err;
|
||||
DEBUGV(":er %d 0x%08x\r\n", (int) err, (uint32_t) _datasource);
|
||||
tcp_arg(_pcb, NULL);
|
||||
tcp_sent(_pcb, NULL);
|
||||
tcp_recv(_pcb, NULL);
|
||||
tcp_err(_pcb, NULL);
|
||||
_pcb = NULL;
|
||||
_notify_error();
|
||||
}
|
||||
|
||||
err_t _connected(struct tcp_pcb *pcb, err_t err)
|
||||
{
|
||||
(void) err;
|
||||
assert(pcb == _pcb);
|
||||
assert(_connect_pending);
|
||||
esp_schedule();
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
err_t _poll(tcp_pcb*)
|
||||
{
|
||||
_write_some_from_cb();
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
static err_t _s_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *pb, err_t err)
|
||||
{
|
||||
return reinterpret_cast<ClientContext*>(arg)->_recv(tpcb, pb, err);
|
||||
}
|
||||
|
||||
static void _s_error(void *arg, err_t err)
|
||||
{
|
||||
reinterpret_cast<ClientContext*>(arg)->_error(err);
|
||||
}
|
||||
|
||||
static err_t _s_poll(void *arg, struct tcp_pcb *tpcb)
|
||||
{
|
||||
return reinterpret_cast<ClientContext*>(arg)->_poll(tpcb);
|
||||
}
|
||||
|
||||
static err_t _s_sent(void *arg, struct tcp_pcb *tpcb, uint16_t len)
|
||||
{
|
||||
return reinterpret_cast<ClientContext*>(arg)->_sent(tpcb, len);
|
||||
}
|
||||
|
||||
static err_t _s_connected(void* arg, struct tcp_pcb *pcb, err_t err)
|
||||
{
|
||||
return reinterpret_cast<ClientContext*>(arg)->_connected(pcb, err);
|
||||
}
|
||||
|
||||
private:
|
||||
tcp_pcb* _pcb;
|
||||
|
||||
pbuf* _rx_buf;
|
||||
size_t _rx_buf_offset;
|
||||
|
||||
discard_cb_t _discard_cb;
|
||||
void* _discard_cb_arg;
|
||||
|
||||
DataSource* _datasource = nullptr;
|
||||
size_t _written = 0;
|
||||
size_t _write_chunk_size = 256;
|
||||
uint32_t _timeout_ms = 5000;
|
||||
uint32_t _op_start_time = 0;
|
||||
uint8_t _send_waiting = 0;
|
||||
uint8_t _connect_pending = 0;
|
||||
|
||||
int8_t _refcnt;
|
||||
ClientContext* _next;
|
||||
};
|
||||
|
||||
#endif//CLIENTCONTEXT_H
|
114
Software/libraries/ESP8266WiFi/src/include/DataSource.h
Normal file
114
Software/libraries/ESP8266WiFi/src/include/DataSource.h
Normal file
@ -0,0 +1,114 @@
|
||||
/* DataSource.h - a read-only object similar to Stream, but with less methods
|
||||
* Copyright (c) 2016 Ivan Grokhotkov. All rights reserved.
|
||||
* This file is distributed under MIT license.
|
||||
*/
|
||||
#ifndef DATASOURCE_H
|
||||
#define DATASOURCE_H
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
class DataSource {
|
||||
public:
|
||||
virtual ~DataSource() {}
|
||||
virtual size_t available() = 0;
|
||||
virtual const uint8_t* get_buffer(size_t size) = 0;
|
||||
virtual void release_buffer(const uint8_t* buffer, size_t size) = 0;
|
||||
|
||||
};
|
||||
|
||||
class BufferDataSource : public DataSource {
|
||||
public:
|
||||
BufferDataSource(const uint8_t* data, size_t size) :
|
||||
_data(data),
|
||||
_size(size)
|
||||
{
|
||||
}
|
||||
|
||||
size_t available() override
|
||||
{
|
||||
return _size - _pos;
|
||||
}
|
||||
|
||||
const uint8_t* get_buffer(size_t size) override
|
||||
{
|
||||
assert(_pos + size <= _size);
|
||||
return _data + _pos;
|
||||
}
|
||||
|
||||
void release_buffer(const uint8_t* buffer, size_t size) override
|
||||
{
|
||||
assert(buffer == _data + _pos);
|
||||
_pos += size;
|
||||
}
|
||||
|
||||
protected:
|
||||
const uint8_t* _data;
|
||||
const size_t _size;
|
||||
size_t _pos = 0;
|
||||
};
|
||||
|
||||
template<typename TStream>
|
||||
class BufferedStreamDataSource : public DataSource {
|
||||
public:
|
||||
BufferedStreamDataSource(TStream& stream, size_t size) :
|
||||
_stream(stream),
|
||||
_size(size)
|
||||
{
|
||||
}
|
||||
|
||||
size_t available() override
|
||||
{
|
||||
return _size - _pos;
|
||||
}
|
||||
|
||||
const uint8_t* get_buffer(size_t size) override
|
||||
{
|
||||
assert(_pos + size <= _size);
|
||||
if (_bufferSize < size) {
|
||||
_buffer.reset(new uint8_t[size]);
|
||||
_bufferSize = size;
|
||||
}
|
||||
size_t cb = _stream.readBytes(reinterpret_cast<char*>(_buffer.get()), size);
|
||||
assert(cb == size);
|
||||
return _buffer.get();
|
||||
}
|
||||
|
||||
void release_buffer(const uint8_t* buffer, size_t size) override
|
||||
{
|
||||
(void) buffer;
|
||||
_pos += size;
|
||||
}
|
||||
|
||||
protected:
|
||||
TStream& _stream;
|
||||
std::unique_ptr<uint8_t[]> _buffer;
|
||||
size_t _size;
|
||||
size_t _pos = 0;
|
||||
size_t _bufferSize = 0;
|
||||
};
|
||||
|
||||
class ProgmemStream
|
||||
{
|
||||
public:
|
||||
ProgmemStream(PGM_P buf, size_t size) :
|
||||
_buf(buf),
|
||||
_left(size)
|
||||
{
|
||||
}
|
||||
|
||||
size_t readBytes(char* dst, size_t size)
|
||||
{
|
||||
size_t will_read = (_left < size) ? _left : size;
|
||||
memcpy_P((void*)dst, (PGM_VOID_P)_buf, will_read);
|
||||
_left -= will_read;
|
||||
_buf += will_read;
|
||||
return will_read;
|
||||
}
|
||||
|
||||
protected:
|
||||
PGM_P _buf;
|
||||
size_t _left;
|
||||
};
|
||||
|
||||
|
||||
#endif //DATASOURCE_H
|
418
Software/libraries/ESP8266WiFi/src/include/UdpContext.h
Normal file
418
Software/libraries/ESP8266WiFi/src/include/UdpContext.h
Normal file
@ -0,0 +1,418 @@
|
||||
/*
|
||||
UdpContext.h - UDP connection handling on top of lwIP
|
||||
|
||||
Copyright (c) 2014 Ivan Grokhotkov. 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
|
||||
*/
|
||||
#ifndef UDPCONTEXT_H
|
||||
#define UDPCONTEXT_H
|
||||
|
||||
class UdpContext;
|
||||
|
||||
extern "C" {
|
||||
void esp_yield();
|
||||
void esp_schedule();
|
||||
#include "lwip/init.h" // LWIP_VERSION_
|
||||
}
|
||||
|
||||
|
||||
#define GET_IP_HDR(pb) reinterpret_cast<ip_hdr*>(((uint8_t*)((pb)->payload)) - UDP_HLEN - IP_HLEN);
|
||||
#define GET_UDP_HDR(pb) reinterpret_cast<udp_hdr*>(((uint8_t*)((pb)->payload)) - UDP_HLEN);
|
||||
|
||||
class UdpContext
|
||||
{
|
||||
public:
|
||||
|
||||
typedef std::function<void(void)> rxhandler_t;
|
||||
|
||||
UdpContext()
|
||||
: _pcb(0)
|
||||
, _rx_buf(0)
|
||||
, _first_buf_taken(false)
|
||||
, _rx_buf_offset(0)
|
||||
, _refcnt(0)
|
||||
, _tx_buf_head(0)
|
||||
, _tx_buf_cur(0)
|
||||
, _tx_buf_offset(0)
|
||||
{
|
||||
_pcb = udp_new();
|
||||
#ifdef LWIP_MAYBE_XCC
|
||||
_mcast_ttl = 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
~UdpContext()
|
||||
{
|
||||
udp_remove(_pcb);
|
||||
_pcb = 0;
|
||||
if (_tx_buf_head)
|
||||
{
|
||||
pbuf_free(_tx_buf_head);
|
||||
_tx_buf_head = 0;
|
||||
_tx_buf_cur = 0;
|
||||
_tx_buf_offset = 0;
|
||||
}
|
||||
if (_rx_buf)
|
||||
{
|
||||
pbuf_free(_rx_buf);
|
||||
_rx_buf = 0;
|
||||
_rx_buf_offset = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void ref()
|
||||
{
|
||||
++_refcnt;
|
||||
}
|
||||
|
||||
void unref()
|
||||
{
|
||||
if(this != 0) {
|
||||
DEBUGV(":ur %d\r\n", _refcnt);
|
||||
if(--_refcnt == 0) {
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool connect(ip_addr_t addr, uint16_t port)
|
||||
{
|
||||
ip_addr_copy(_pcb->remote_ip, addr);
|
||||
_pcb->remote_port = port;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool listen(ip_addr_t addr, uint16_t port)
|
||||
{
|
||||
udp_recv(_pcb, &_s_recv, (void *) this);
|
||||
err_t err = udp_bind(_pcb, &addr, port);
|
||||
return err == ERR_OK;
|
||||
}
|
||||
|
||||
void disconnect()
|
||||
{
|
||||
udp_disconnect(_pcb);
|
||||
}
|
||||
|
||||
#if LWIP_VERSION_MAJOR == 1
|
||||
void setMulticastInterface(ip_addr_t addr)
|
||||
{
|
||||
udp_set_multicast_netif_addr(_pcb, addr);
|
||||
}
|
||||
#else
|
||||
void setMulticastInterface(const ip_addr_t& addr)
|
||||
{
|
||||
udp_set_multicast_netif_addr(_pcb, &addr);
|
||||
}
|
||||
#endif
|
||||
|
||||
void setMulticastTTL(int ttl)
|
||||
{
|
||||
#ifdef LWIP_MAYBE_XCC
|
||||
_mcast_ttl = ttl;
|
||||
#else
|
||||
udp_set_multicast_ttl(_pcb, ttl);
|
||||
#endif
|
||||
}
|
||||
|
||||
// warning: handler is called from tcp stack context
|
||||
// esp_yield and non-reentrant functions which depend on it will fail
|
||||
void onRx(rxhandler_t handler) {
|
||||
_on_rx = handler;
|
||||
}
|
||||
|
||||
size_t getSize() const
|
||||
{
|
||||
if (!_rx_buf)
|
||||
return 0;
|
||||
|
||||
return _rx_buf->len - _rx_buf_offset;
|
||||
}
|
||||
|
||||
uint32_t getRemoteAddress()
|
||||
{
|
||||
if (!_rx_buf)
|
||||
return 0;
|
||||
|
||||
ip_hdr* iphdr = GET_IP_HDR(_rx_buf);
|
||||
return iphdr->src.addr;
|
||||
}
|
||||
|
||||
uint16_t getRemotePort()
|
||||
{
|
||||
if (!_rx_buf)
|
||||
return 0;
|
||||
|
||||
udp_hdr* udphdr = GET_UDP_HDR(_rx_buf);
|
||||
return ntohs(udphdr->src);
|
||||
}
|
||||
|
||||
uint32_t getDestAddress()
|
||||
{
|
||||
ip_hdr* iphdr = GET_IP_HDR(_rx_buf);
|
||||
return iphdr->dest.addr;
|
||||
}
|
||||
|
||||
uint16_t getLocalPort()
|
||||
{
|
||||
if (!_pcb)
|
||||
return 0;
|
||||
|
||||
return _pcb->local_port;
|
||||
}
|
||||
|
||||
bool next()
|
||||
{
|
||||
if (!_rx_buf)
|
||||
return false;
|
||||
|
||||
if (!_first_buf_taken)
|
||||
{
|
||||
_first_buf_taken = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
auto head = _rx_buf;
|
||||
_rx_buf = _rx_buf->next;
|
||||
_rx_buf_offset = 0;
|
||||
|
||||
if (_rx_buf)
|
||||
{
|
||||
pbuf_ref(_rx_buf);
|
||||
}
|
||||
pbuf_free(head);
|
||||
return _rx_buf != 0;
|
||||
}
|
||||
|
||||
int read()
|
||||
{
|
||||
if (!_rx_buf || _rx_buf_offset == _rx_buf->len)
|
||||
return -1;
|
||||
|
||||
char c = reinterpret_cast<char*>(_rx_buf->payload)[_rx_buf_offset];
|
||||
_consume(1);
|
||||
return c;
|
||||
}
|
||||
|
||||
size_t read(char* dst, size_t size)
|
||||
{
|
||||
if (!_rx_buf)
|
||||
return 0;
|
||||
|
||||
size_t max_size = _rx_buf->len - _rx_buf_offset;
|
||||
size = (size < max_size) ? size : max_size;
|
||||
DEBUGV(":urd %d, %d, %d\r\n", size, _rx_buf->len, _rx_buf_offset);
|
||||
|
||||
memcpy(dst, reinterpret_cast<char*>(_rx_buf->payload) + _rx_buf_offset, size);
|
||||
_consume(size);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
int peek()
|
||||
{
|
||||
if (!_rx_buf || _rx_buf_offset == _rx_buf->len)
|
||||
return -1;
|
||||
|
||||
return reinterpret_cast<char*>(_rx_buf->payload)[_rx_buf_offset];
|
||||
}
|
||||
|
||||
void flush()
|
||||
{
|
||||
if (!_rx_buf)
|
||||
return;
|
||||
|
||||
_consume(_rx_buf->len - _rx_buf_offset);
|
||||
}
|
||||
|
||||
|
||||
size_t append(const char* data, size_t size)
|
||||
{
|
||||
if (!_tx_buf_head || _tx_buf_head->tot_len < _tx_buf_offset + size)
|
||||
{
|
||||
_reserve(_tx_buf_offset + size);
|
||||
}
|
||||
if (!_tx_buf_head || _tx_buf_head->tot_len < _tx_buf_offset + size)
|
||||
{
|
||||
DEBUGV("failed _reserve");
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t left_to_copy = size;
|
||||
while(left_to_copy)
|
||||
{
|
||||
// size already used in current pbuf
|
||||
size_t used_cur = _tx_buf_offset - (_tx_buf_head->tot_len - _tx_buf_cur->tot_len);
|
||||
size_t free_cur = _tx_buf_cur->len - used_cur;
|
||||
if (free_cur == 0)
|
||||
{
|
||||
_tx_buf_cur = _tx_buf_cur->next;
|
||||
continue;
|
||||
}
|
||||
size_t will_copy = (left_to_copy < free_cur) ? left_to_copy : free_cur;
|
||||
memcpy(reinterpret_cast<char*>(_tx_buf_cur->payload) + used_cur, data, will_copy);
|
||||
_tx_buf_offset += will_copy;
|
||||
left_to_copy -= will_copy;
|
||||
data += will_copy;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
bool send(ip_addr_t* addr = 0, uint16_t port = 0)
|
||||
{
|
||||
size_t data_size = _tx_buf_offset;
|
||||
pbuf* tx_copy = pbuf_alloc(PBUF_TRANSPORT, data_size, PBUF_RAM);
|
||||
if(!tx_copy){
|
||||
DEBUGV("failed pbuf_alloc");
|
||||
}
|
||||
else{
|
||||
uint8_t* dst = reinterpret_cast<uint8_t*>(tx_copy->payload);
|
||||
for (pbuf* p = _tx_buf_head; p; p = p->next) {
|
||||
size_t will_copy = (data_size < p->len) ? data_size : p->len;
|
||||
memcpy(dst, p->payload, will_copy);
|
||||
dst += will_copy;
|
||||
data_size -= will_copy;
|
||||
}
|
||||
}
|
||||
pbuf_free(_tx_buf_head);
|
||||
_tx_buf_head = 0;
|
||||
_tx_buf_cur = 0;
|
||||
_tx_buf_offset = 0;
|
||||
if(!tx_copy){
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if (!addr) {
|
||||
addr = &_pcb->remote_ip;
|
||||
port = _pcb->remote_port;
|
||||
}
|
||||
#ifdef LWIP_MAYBE_XCC
|
||||
uint16_t old_ttl = _pcb->ttl;
|
||||
if (ip_addr_ismulticast(addr)) {
|
||||
_pcb->ttl = _mcast_ttl;
|
||||
}
|
||||
#endif
|
||||
err_t err = udp_sendto(_pcb, tx_copy, addr, port);
|
||||
if (err != ERR_OK) {
|
||||
DEBUGV(":ust rc=%d\r\n", (int) err);
|
||||
}
|
||||
#ifdef LWIP_MAYBE_XCC
|
||||
_pcb->ttl = old_ttl;
|
||||
#endif
|
||||
pbuf_free(tx_copy);
|
||||
return err == ERR_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void _reserve(size_t size)
|
||||
{
|
||||
const size_t pbuf_unit_size = 128;
|
||||
if (!_tx_buf_head)
|
||||
{
|
||||
_tx_buf_head = pbuf_alloc(PBUF_TRANSPORT, pbuf_unit_size, PBUF_RAM);
|
||||
if (!_tx_buf_head)
|
||||
{
|
||||
return;
|
||||
}
|
||||
_tx_buf_cur = _tx_buf_head;
|
||||
_tx_buf_offset = 0;
|
||||
}
|
||||
|
||||
size_t cur_size = _tx_buf_head->tot_len;
|
||||
if (size < cur_size)
|
||||
return;
|
||||
|
||||
size_t grow_size = size - cur_size;
|
||||
|
||||
while(grow_size)
|
||||
{
|
||||
pbuf* pb = pbuf_alloc(PBUF_TRANSPORT, pbuf_unit_size, PBUF_RAM);
|
||||
if (!pb)
|
||||
{
|
||||
return;
|
||||
}
|
||||
pbuf_cat(_tx_buf_head, pb);
|
||||
if (grow_size < pbuf_unit_size)
|
||||
return;
|
||||
grow_size -= pbuf_unit_size;
|
||||
}
|
||||
}
|
||||
|
||||
void _consume(size_t size)
|
||||
{
|
||||
_rx_buf_offset += size;
|
||||
}
|
||||
|
||||
void _recv(udp_pcb *upcb, pbuf *pb,
|
||||
const ip_addr_t *addr, u16_t port)
|
||||
{
|
||||
(void) upcb;
|
||||
(void) addr;
|
||||
(void) port;
|
||||
if (_rx_buf)
|
||||
{
|
||||
// there is some unread data
|
||||
// chain the new pbuf to the existing one
|
||||
DEBUGV(":urch %d, %d\r\n", _rx_buf->tot_len, pb->tot_len);
|
||||
pbuf_cat(_rx_buf, pb);
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUGV(":urn %d\r\n", pb->tot_len);
|
||||
_first_buf_taken = false;
|
||||
_rx_buf = pb;
|
||||
_rx_buf_offset = 0;
|
||||
}
|
||||
if (_on_rx) {
|
||||
_on_rx();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if LWIP_VERSION_MAJOR == 1
|
||||
static void _s_recv(void *arg,
|
||||
udp_pcb *upcb, pbuf *p,
|
||||
ip_addr_t *addr, u16_t port)
|
||||
#else
|
||||
static void _s_recv(void *arg,
|
||||
udp_pcb *upcb, pbuf *p,
|
||||
const ip_addr_t *addr, u16_t port)
|
||||
#endif
|
||||
{
|
||||
reinterpret_cast<UdpContext*>(arg)->_recv(upcb, p, addr, port);
|
||||
}
|
||||
|
||||
private:
|
||||
udp_pcb* _pcb;
|
||||
pbuf* _rx_buf;
|
||||
bool _first_buf_taken;
|
||||
size_t _rx_buf_offset;
|
||||
int _refcnt;
|
||||
pbuf* _tx_buf_head;
|
||||
pbuf* _tx_buf_cur;
|
||||
size_t _tx_buf_offset;
|
||||
rxhandler_t _on_rx;
|
||||
#ifdef LWIP_MAYBE_XCC
|
||||
uint16_t _mcast_ttl;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif//CLIENTCONTEXT_H
|
38
Software/libraries/ESP8266WiFi/src/include/slist.h
Normal file
38
Software/libraries/ESP8266WiFi/src/include/slist.h
Normal file
@ -0,0 +1,38 @@
|
||||
#ifndef SLIST_H
|
||||
#define SLIST_H
|
||||
|
||||
template<typename T>
|
||||
class SList {
|
||||
public:
|
||||
SList() : _next(0) { }
|
||||
|
||||
protected:
|
||||
|
||||
static void _add(T* self) {
|
||||
T* tmp = _s_first;
|
||||
_s_first = self;
|
||||
self->_next = tmp;
|
||||
}
|
||||
|
||||
static void _remove(T* self) {
|
||||
if (_s_first == self) {
|
||||
_s_first = self->_next;
|
||||
self->_next = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
for (T* prev = _s_first; prev->_next; prev = prev->_next) {
|
||||
if (prev->_next == self) {
|
||||
prev->_next = self->_next;
|
||||
self->_next = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static T* _s_first;
|
||||
T* _next;
|
||||
};
|
||||
|
||||
|
||||
#endif //SLIST_H
|
583
Software/libraries/ESP8266WiFi/src/include/ssl.h
Normal file
583
Software/libraries/ESP8266WiFi/src/include/ssl.h
Normal file
@ -0,0 +1,583 @@
|
||||
/*
|
||||
* Copyright (c) 2007-2016, Cameron Rich
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* * Neither the name of the axTLS project nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @mainpage axTLS API
|
||||
*
|
||||
* @image html axolotl.jpg
|
||||
*
|
||||
* The axTLS library has features such as:
|
||||
* - The TLSv1 SSL client/server protocol
|
||||
* - No requirement to use any openssl libraries.
|
||||
* - A choice between AES block (128/256 bit) and RC4 (128 bit) stream ciphers.
|
||||
* - RSA encryption/decryption with variable sized keys (up to 4096 bits).
|
||||
* - Certificate chaining and peer authentication.
|
||||
* - Session resumption, session renegotiation.
|
||||
* - ASN.1, X.509, PKCS#8, PKCS#12 keys/certificates with DER/PEM encoding.
|
||||
* - Highly configurable compile time options.
|
||||
* - Portable across many platforms (written in ANSI C), and has language
|
||||
* bindings in C, C#, VB.NET, Java, Perl and Lua.
|
||||
* - Partial openssl API compatibility (via a wrapper).
|
||||
* - A very small footprint (around 50-60kB for the library in 'server-only'
|
||||
* mode).
|
||||
* - No dependencies on sockets - can use serial connections for example.
|
||||
* - A very simple API - ~ 20 functions/methods.
|
||||
*
|
||||
* A list of these functions/methods are described below.
|
||||
*
|
||||
* @ref c_api
|
||||
*
|
||||
* @ref bigint_api
|
||||
*
|
||||
* @ref csharp_api
|
||||
*
|
||||
* @ref java_api
|
||||
*/
|
||||
#ifndef HEADER_SSL_H
|
||||
#define HEADER_SSL_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* need to predefine before ssl_lib.h gets to it */
|
||||
#define SSL_SESSION_ID_SIZE 32
|
||||
|
||||
#define EXP_FUNC
|
||||
#define STDCALL
|
||||
// struct SSL_CTX_;
|
||||
typedef struct SSL_CTX_ SSL_CTX;
|
||||
typedef struct SSL_ SSL;
|
||||
typedef struct SSL_EXTENSIONS_ SSL_EXTENSIONS;
|
||||
|
||||
/* The optional parameters that can be given to the client/server SSL engine */
|
||||
#define SSL_CLIENT_AUTHENTICATION 0x00010000
|
||||
#define SSL_SERVER_VERIFY_LATER 0x00020000
|
||||
#define SSL_NO_DEFAULT_KEY 0x00040000
|
||||
#define SSL_DISPLAY_STATES 0x00080000
|
||||
#define SSL_DISPLAY_BYTES 0x00100000
|
||||
#define SSL_DISPLAY_CERTS 0x00200000
|
||||
#define SSL_DISPLAY_RSA 0x00400000
|
||||
#define SSL_CONNECT_IN_PARTS 0x00800000
|
||||
#define SSL_READ_BLOCKING 0x01000000
|
||||
|
||||
/* errors that can be generated */
|
||||
#define SSL_OK 0
|
||||
#define SSL_NOT_OK -1
|
||||
#define SSL_ERROR_DEAD -2
|
||||
#define SSL_CLOSE_NOTIFY -3
|
||||
#define SSL_ERROR_CONN_LOST -256
|
||||
#define SSL_ERROR_RECORD_OVERFLOW -257
|
||||
#define SSL_ERROR_SOCK_SETUP_FAILURE -258
|
||||
#define SSL_ERROR_INVALID_HANDSHAKE -260
|
||||
#define SSL_ERROR_INVALID_PROT_MSG -261
|
||||
#define SSL_ERROR_INVALID_HMAC -262
|
||||
#define SSL_ERROR_INVALID_VERSION -263
|
||||
#define SSL_ERROR_UNSUPPORTED_EXTENSION -264
|
||||
#define SSL_ERROR_INVALID_SESSION -265
|
||||
#define SSL_ERROR_NO_CIPHER -266
|
||||
#define SSL_ERROR_INVALID_CERT_HASH_ALG -267
|
||||
#define SSL_ERROR_BAD_CERTIFICATE -268
|
||||
#define SSL_ERROR_INVALID_KEY -269
|
||||
#define SSL_ERROR_FINISHED_INVALID -271
|
||||
#define SSL_ERROR_NO_CERT_DEFINED -272
|
||||
#define SSL_ERROR_NO_CLIENT_RENOG -273
|
||||
#define SSL_ERROR_NOT_SUPPORTED -274
|
||||
#define SSL_X509_OFFSET -512
|
||||
#define SSL_X509_ERROR(A) (SSL_X509_OFFSET+A)
|
||||
|
||||
#define X509_OK 0
|
||||
#define X509_NOT_OK -1
|
||||
#define X509_VFY_ERROR_NO_TRUSTED_CERT -2
|
||||
#define X509_VFY_ERROR_BAD_SIGNATURE -3
|
||||
#define X509_VFY_ERROR_NOT_YET_VALID -4
|
||||
#define X509_VFY_ERROR_EXPIRED -5
|
||||
#define X509_VFY_ERROR_SELF_SIGNED -6
|
||||
#define X509_VFY_ERROR_INVALID_CHAIN -7
|
||||
#define X509_VFY_ERROR_UNSUPPORTED_DIGEST -8
|
||||
#define X509_INVALID_PRIV_KEY -9
|
||||
#define X509_MAX_CERTS -10
|
||||
#define X509_VFY_ERROR_BASIC_CONSTRAINT -11
|
||||
|
||||
/* alert types that are recognized */
|
||||
#define SSL_ALERT_TYPE_WARNING 1
|
||||
#define SLL_ALERT_TYPE_FATAL 2
|
||||
|
||||
/* these are all the alerts that are recognized */
|
||||
#define SSL_ALERT_CLOSE_NOTIFY 0
|
||||
#define SSL_ALERT_UNEXPECTED_MESSAGE 10
|
||||
#define SSL_ALERT_BAD_RECORD_MAC 20
|
||||
#define SSL_ALERT_RECORD_OVERFLOW 22
|
||||
#define SSL_ALERT_HANDSHAKE_FAILURE 40
|
||||
#define SSL_ALERT_BAD_CERTIFICATE 42
|
||||
#define SSL_ALERT_UNSUPPORTED_CERTIFICATE 43
|
||||
#define SSL_ALERT_CERTIFICATE_EXPIRED 45
|
||||
#define SSL_ALERT_CERTIFICATE_UNKNOWN 46
|
||||
#define SSL_ALERT_ILLEGAL_PARAMETER 47
|
||||
#define SSL_ALERT_UNKNOWN_CA 48
|
||||
#define SSL_ALERT_DECODE_ERROR 50
|
||||
#define SSL_ALERT_DECRYPT_ERROR 51
|
||||
#define SSL_ALERT_INVALID_VERSION 70
|
||||
#define SSL_ALERT_NO_RENEGOTIATION 100
|
||||
#define SSL_ALERT_UNSUPPORTED_EXTENSION 110
|
||||
|
||||
/* The ciphers that are supported */
|
||||
#define SSL_AES128_SHA 0x2f
|
||||
#define SSL_AES256_SHA 0x35
|
||||
#define SSL_AES128_SHA256 0x3c
|
||||
#define SSL_AES256_SHA256 0x3d
|
||||
|
||||
/* build mode ids' */
|
||||
#define SSL_BUILD_SKELETON_MODE 0x01
|
||||
#define SSL_BUILD_SERVER_ONLY 0x02
|
||||
#define SSL_BUILD_ENABLE_VERIFICATION 0x03
|
||||
#define SSL_BUILD_ENABLE_CLIENT 0x04
|
||||
#define SSL_BUILD_FULL_MODE 0x05
|
||||
|
||||
/* offsets to retrieve configuration information */
|
||||
#define SSL_BUILD_MODE 0
|
||||
#define SSL_MAX_CERT_CFG_OFFSET 1
|
||||
#define SSL_MAX_CA_CERT_CFG_OFFSET 2
|
||||
#define SSL_HAS_PEM 3
|
||||
|
||||
/* default session sizes */
|
||||
#define SSL_DEFAULT_SVR_SESS 5
|
||||
#define SSL_DEFAULT_CLNT_SESS 1
|
||||
|
||||
/* X.509/X.520 distinguished name types */
|
||||
#define SSL_X509_CERT_COMMON_NAME 0
|
||||
#define SSL_X509_CERT_ORGANIZATION 1
|
||||
#define SSL_X509_CERT_ORGANIZATIONAL_NAME 2
|
||||
#define SSL_X509_CA_CERT_COMMON_NAME 3
|
||||
#define SSL_X509_CA_CERT_ORGANIZATION 4
|
||||
#define SSL_X509_CA_CERT_ORGANIZATIONAL_NAME 5
|
||||
|
||||
/* SSL object loader types */
|
||||
#define SSL_OBJ_X509_CERT 1
|
||||
#define SSL_OBJ_X509_CACERT 2
|
||||
#define SSL_OBJ_RSA_KEY 3
|
||||
#define SSL_OBJ_PKCS8 4
|
||||
#define SSL_OBJ_PKCS12 5
|
||||
|
||||
/**
|
||||
* @defgroup c_api Standard C API
|
||||
* @brief The standard interface in C.
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Establish a new client/server context.
|
||||
*
|
||||
* This function is called before any client/server SSL connections are made.
|
||||
*
|
||||
* Each new connection will use the this context's private key and
|
||||
* certificate chain. If a different certificate chain is required, then a
|
||||
* different context needs to be be used.
|
||||
*
|
||||
* There are two threading models supported - a single thread with one
|
||||
* SSL_CTX can support any number of SSL connections - and multiple threads can
|
||||
* support one SSL_CTX object each (the default). But if a single SSL_CTX
|
||||
* object uses many SSL objects in individual threads, then the
|
||||
* CONFIG_SSL_CTX_MUTEXING option needs to be configured.
|
||||
*
|
||||
* @param options [in] Any particular options. At present the options
|
||||
* supported are:
|
||||
* - SSL_SERVER_VERIFY_LATER (client only): Don't stop a handshake if the server
|
||||
* authentication fails. The certificate can be authenticated later with a
|
||||
* call to ssl_verify_cert().
|
||||
* - SSL_CLIENT_AUTHENTICATION (server only): Enforce client authentication
|
||||
* i.e. each handshake will include a "certificate request" message from the
|
||||
* server. Only available if verification has been enabled.
|
||||
* - SSL_DISPLAY_BYTES (full mode build only): Display the byte sequences
|
||||
* during the handshake.
|
||||
* - SSL_DISPLAY_STATES (full mode build only): Display the state changes
|
||||
* during the handshake.
|
||||
* - SSL_DISPLAY_CERTS (full mode build only): Display the certificates that
|
||||
* are passed during a handshake.
|
||||
* - SSL_DISPLAY_RSA (full mode build only): Display the RSA key details that
|
||||
* are passed during a handshake.
|
||||
* - SSL_CONNECT_IN_PARTS (client only): To use a non-blocking version of
|
||||
* ssl_client_new().
|
||||
* @param num_sessions [in] The number of sessions to be used for session
|
||||
* caching. If this value is 0, then there is no session caching. This option
|
||||
* is not used in skeleton mode.
|
||||
* @return A client/server context.
|
||||
*/
|
||||
EXP_FUNC SSL_CTX * STDCALL ssl_ctx_new(uint32_t options, int num_sessions);
|
||||
|
||||
/**
|
||||
* @brief Remove a client/server context.
|
||||
*
|
||||
* Frees any used resources used by this context. Each connection will be
|
||||
* sent a "Close Notify" alert (if possible).
|
||||
* @param ssl_ctx [in] The client/server context.
|
||||
*/
|
||||
EXP_FUNC void STDCALL ssl_ctx_free(SSL_CTX *ssl_ctx);
|
||||
|
||||
/**
|
||||
* @brief Allocates new SSL extensions structure and returns pointer to it
|
||||
*
|
||||
* @return ssl_ext Pointer to SSL_EXTENSIONS structure
|
||||
*
|
||||
*/
|
||||
EXP_FUNC SSL_EXTENSIONS * STDCALL ssl_ext_new();
|
||||
|
||||
/**
|
||||
* @brief Set the host name for SNI extension
|
||||
* @param ssl_ext pointer returned by ssl_ext_new
|
||||
* @param host_name pointer to a zero-terminated string containing host name
|
||||
*/
|
||||
EXP_FUNC void STDCALL ssl_ext_set_host_name(SSL_EXTENSIONS * ext, const char* host_name);
|
||||
|
||||
/**
|
||||
* @brief Set the maximum fragment size for the fragment size negotiation extension
|
||||
* @param ssl_ext pointer returned by ssl_ext_new
|
||||
* @param fragment_size fragment size, allowed values: 2^9, 2^10 ... 2^14
|
||||
*/
|
||||
EXP_FUNC void STDCALL ssl_ext_set_max_fragment_size(SSL_EXTENSIONS * ext, unsigned fragment_size);
|
||||
|
||||
/**
|
||||
* @brief Frees SSL extensions structure
|
||||
*
|
||||
* @param ssl_ext [in] Pointer to SSL_EXTENSION structure
|
||||
*
|
||||
*/
|
||||
EXP_FUNC void STDCALL ssl_ext_free(SSL_EXTENSIONS *ssl_ext);
|
||||
|
||||
/**
|
||||
* @brief (server only) Establish a new SSL connection to an SSL client.
|
||||
*
|
||||
* It is up to the application to establish the logical connection (whether it
|
||||
* is a socket, serial connection etc).
|
||||
* @param ssl_ctx [in] The server context.
|
||||
* @param client_fd [in] The client's file descriptor.
|
||||
* @return An SSL object reference.
|
||||
*/
|
||||
EXP_FUNC SSL * STDCALL ssl_server_new(SSL_CTX *ssl_ctx, int client_fd);
|
||||
|
||||
/**
|
||||
* @brief (client only) Establish a new SSL connection to an SSL server.
|
||||
*
|
||||
* It is up to the application to establish the initial logical connection
|
||||
* (whether it is a socket, serial connection etc).
|
||||
*
|
||||
* This is a normally a blocking call - it will finish when the handshake is
|
||||
* complete (or has failed). To use in non-blocking mode, set
|
||||
* SSL_CONNECT_IN_PARTS in ssl_ctx_new().
|
||||
* @param ssl_ctx [in] The client context.
|
||||
* @param client_fd [in] The client's file descriptor.
|
||||
* @param session_id [in] A 32 byte session id for session resumption. This
|
||||
* can be null if no session resumption is being used or required. This option
|
||||
* is not used in skeleton mode.
|
||||
* @param sess_id_size The size of the session id (max 32)
|
||||
* @param ssl_ext pointer to a structure with the activated SSL extensions and their values
|
||||
* @return An SSL object reference. Use ssl_handshake_status() to check
|
||||
* if a handshake succeeded.
|
||||
*/
|
||||
EXP_FUNC SSL * STDCALL ssl_client_new(SSL_CTX *ssl_ctx, int client_fd, const uint8_t *session_id, uint8_t sess_id_size, SSL_EXTENSIONS* ssl_ext);
|
||||
|
||||
/**
|
||||
* @brief Free any used resources on this connection.
|
||||
|
||||
* A "Close Notify" message is sent on this connection (if possible). It is up
|
||||
* to the application to close the socket or file descriptor.
|
||||
* @param ssl [in] The ssl object reference.
|
||||
*/
|
||||
EXP_FUNC void STDCALL ssl_free(SSL *ssl);
|
||||
|
||||
/**
|
||||
* @brief Read the SSL data stream.
|
||||
* If the socket is non-blocking and data is blocked then SSO_OK will be
|
||||
* returned.
|
||||
* @param ssl [in] An SSL object reference.
|
||||
* @param in_data [out] If the read was successful, a pointer to the read
|
||||
* buffer will be here. Do NOT ever free this memory as this buffer is used in
|
||||
* sucessive calls. If the call was unsuccessful, this value will be null.
|
||||
* @return The number of decrypted bytes:
|
||||
* - if > 0, then the handshaking is complete and we are returning the number
|
||||
* of decrypted bytes.
|
||||
* - SSL_OK if the handshaking stage is successful (but not yet complete).
|
||||
* - < 0 if an error.
|
||||
* @see ssl.h for the error code list.
|
||||
* @note Use in_data before doing any successive ssl calls.
|
||||
*/
|
||||
EXP_FUNC int STDCALL ssl_read(SSL *ssl, uint8_t **in_data);
|
||||
|
||||
/**
|
||||
* @brief Write to the SSL data stream.
|
||||
* if the socket is non-blocking and data is blocked then a check is made
|
||||
* to ensure that all data is sent (i.e. blocked mode is forced).
|
||||
* @param ssl [in] An SSL obect reference.
|
||||
* @param out_data [in] The data to be written
|
||||
* @param out_len [in] The number of bytes to be written.
|
||||
* @return The number of bytes sent, or if < 0 if an error.
|
||||
* @see ssl.h for the error code list.
|
||||
*/
|
||||
EXP_FUNC int STDCALL ssl_write(SSL *ssl, const uint8_t *out_data, int out_len);
|
||||
|
||||
/**
|
||||
* @brief Calculate the size of the encrypted data from what you are about to send
|
||||
* @param ssl [in] An SSL obect reference.
|
||||
* @param out_len [in] The number of bytes to be written.
|
||||
* @return The number of bytes that will be sent, or if < 0 if an error.
|
||||
* @see ssl.h for the error code list.
|
||||
*/
|
||||
EXP_FUNC int STDCALL ssl_calculate_write_length(SSL *ssl, int out_len);
|
||||
|
||||
/**
|
||||
* @brief Find an ssl object based on a file descriptor.
|
||||
*
|
||||
* Goes through the list of SSL objects maintained in a client/server context
|
||||
* to look for a file descriptor match.
|
||||
* @param ssl_ctx [in] The client/server context.
|
||||
* @param client_fd [in] The file descriptor.
|
||||
* @return A reference to the SSL object. Returns null if the object could not
|
||||
* be found.
|
||||
*/
|
||||
EXP_FUNC SSL * STDCALL ssl_find(SSL_CTX *ssl_ctx, int client_fd);
|
||||
|
||||
/**
|
||||
* @brief Get the session id for a handshake.
|
||||
*
|
||||
* This will be a 32 byte sequence and is available after the first
|
||||
* handshaking messages are sent.
|
||||
* @param ssl [in] An SSL object reference.
|
||||
* @return The session id as a 32 byte sequence.
|
||||
* @note A SSLv23 handshake may have only 16 valid bytes.
|
||||
*/
|
||||
EXP_FUNC const uint8_t * STDCALL ssl_get_session_id(const SSL *ssl);
|
||||
|
||||
/**
|
||||
* @brief Get the session id size for a handshake.
|
||||
*
|
||||
* This will normally be 32 but could be 0 (no session id) or something else.
|
||||
* @param ssl [in] An SSL object reference.
|
||||
* @return The size of the session id.
|
||||
*/
|
||||
EXP_FUNC uint8_t STDCALL ssl_get_session_id_size(const SSL *ssl);
|
||||
|
||||
/**
|
||||
* @brief Return the cipher id (in the SSL form).
|
||||
* @param ssl [in] An SSL object reference.
|
||||
* @return The cipher id. This will be one of the following:
|
||||
* - SSL_AES128_SHA (0x2f)
|
||||
* - SSL_AES256_SHA (0x35)
|
||||
* - SSL_RC4_128_SHA (0x05)
|
||||
* - SSL_RC4_128_MD5 (0x04)
|
||||
*/
|
||||
EXP_FUNC uint8_t STDCALL ssl_get_cipher_id(const SSL *ssl);
|
||||
|
||||
/**
|
||||
* @brief Return the status of the handshake.
|
||||
* @param ssl [in] An SSL object reference.
|
||||
* @return SSL_OK if the handshake is complete and ok.
|
||||
* @see ssl.h for the error code list.
|
||||
*/
|
||||
EXP_FUNC int STDCALL ssl_handshake_status(const SSL *ssl);
|
||||
|
||||
/**
|
||||
* @brief Retrieve various parameters about the axTLS engine.
|
||||
* @param offset [in] The configuration offset. It will be one of the following:
|
||||
* - SSL_BUILD_MODE The build mode. This will be one of the following:
|
||||
* - SSL_BUILD_SERVER_ONLY (basic server mode)
|
||||
* - SSL_BUILD_ENABLE_VERIFICATION (server can do client authentication)
|
||||
* - SSL_BUILD_ENABLE_CLIENT (client/server capabilties)
|
||||
* - SSL_BUILD_FULL_MODE (client/server with diagnostics)
|
||||
* - SSL_BUILD_SKELETON_MODE (skeleton mode)
|
||||
* - SSL_MAX_CERT_CFG_OFFSET The maximum number of certificates allowed.
|
||||
* - SSL_MAX_CA_CERT_CFG_OFFSET The maximum number of CA certificates allowed.
|
||||
* - SSL_HAS_PEM 1 if supported
|
||||
* @return The value of the requested parameter.
|
||||
*/
|
||||
EXP_FUNC int STDCALL ssl_get_config(int offset);
|
||||
|
||||
/**
|
||||
* @brief Display why the handshake failed.
|
||||
*
|
||||
* This call is only useful in a 'full mode' build. The output is to stdout.
|
||||
* @param error_code [in] An error code.
|
||||
* @see ssl.h for the error code list.
|
||||
*/
|
||||
EXP_FUNC void STDCALL ssl_display_error(int error_code);
|
||||
|
||||
/**
|
||||
* @brief Authenticate a received certificate.
|
||||
*
|
||||
* This call is usually made by a client after a handshake is complete and the
|
||||
* context is in SSL_SERVER_VERIFY_LATER mode.
|
||||
* @param ssl [in] An SSL object reference.
|
||||
* @return SSL_OK if the certificate is verified.
|
||||
*/
|
||||
EXP_FUNC int STDCALL ssl_verify_cert(const SSL *ssl);
|
||||
|
||||
/**
|
||||
* @brief Check if certificate fingerprint (SHA1) matches the one given.
|
||||
*
|
||||
* @param ssl [in] An SSL object reference.
|
||||
* @param fp [in] SHA1 fingerprint to match against
|
||||
* @return SSL_OK if the certificate is verified.
|
||||
*/
|
||||
EXP_FUNC int STDCALL ssl_match_fingerprint(const SSL *ssl, const uint8_t* fp);
|
||||
|
||||
/**
|
||||
* @brief Check if SHA256 hash of Subject Public Key Info matches the one given.
|
||||
*
|
||||
* @param ssl [in] An SSL object reference.
|
||||
* @param fp [in] SHA256 hash to match against
|
||||
* @return SSL_OK if the certificate is verified.
|
||||
*/
|
||||
EXP_FUNC int STDCALL ssl_match_spki_sha256(const SSL *ssl, const uint8_t* hash);
|
||||
|
||||
/**
|
||||
* @brief Retrieve an X.509 distinguished name component.
|
||||
*
|
||||
* When a handshake is complete and a certificate has been exchanged, then the
|
||||
* details of the remote certificate can be retrieved.
|
||||
*
|
||||
* This will usually be used by a client to check that the server's common
|
||||
* name matches the URL.
|
||||
*
|
||||
* @param ssl [in] An SSL object reference.
|
||||
* @param component [in] one of:
|
||||
* - SSL_X509_CERT_COMMON_NAME
|
||||
* - SSL_X509_CERT_ORGANIZATION
|
||||
* - SSL_X509_CERT_ORGANIZATIONAL_NAME
|
||||
* - SSL_X509_CA_CERT_COMMON_NAME
|
||||
* - SSL_X509_CA_CERT_ORGANIZATION
|
||||
* - SSL_X509_CA_CERT_ORGANIZATIONAL_NAME
|
||||
* @return The appropriate string (or null if not defined)
|
||||
* @note Verification build mode must be enabled.
|
||||
*/
|
||||
EXP_FUNC const char * STDCALL ssl_get_cert_dn(const SSL *ssl, int component);
|
||||
|
||||
/**
|
||||
* @brief Retrieve a Subject Alternative DNSName
|
||||
*
|
||||
* When a handshake is complete and a certificate has been exchanged, then the
|
||||
* details of the remote certificate can be retrieved.
|
||||
*
|
||||
* This will usually be used by a client to check that the server's DNS
|
||||
* name matches the URL.
|
||||
*
|
||||
* @param ssl [in] An SSL object reference.
|
||||
* @param dnsindex [in] The index of the DNS name to retrieve.
|
||||
* @return The appropriate string (or null if not defined)
|
||||
* @note Verification build mode must be enabled.
|
||||
*/
|
||||
EXP_FUNC const char * STDCALL ssl_get_cert_subject_alt_dnsname(const SSL *ssl, int dnsindex);
|
||||
|
||||
/**
|
||||
* @brief Force the client to perform its handshake again.
|
||||
*
|
||||
* For a client this involves sending another "client hello" message.
|
||||
* For the server is means sending a "hello request" message.
|
||||
*
|
||||
* This is a blocking call on the client (until the handshake completes).
|
||||
*
|
||||
* @param ssl [in] An SSL object reference.
|
||||
* @return SSL_OK if renegotiation instantiation was ok
|
||||
*/
|
||||
EXP_FUNC int STDCALL ssl_renegotiate(SSL *ssl);
|
||||
|
||||
/**
|
||||
* @brief Process a file that is in binary DER or ASCII PEM format.
|
||||
*
|
||||
* These are temporary objects that are used to load private keys,
|
||||
* certificates etc into memory.
|
||||
* @param ssl_ctx [in] The client/server context.
|
||||
* @param obj_type [in] The format of the file. Can be one of:
|
||||
* - SSL_OBJ_X509_CERT (no password required)
|
||||
* - SSL_OBJ_X509_CACERT (no password required)
|
||||
* - SSL_OBJ_RSA_KEY (AES128/AES256 PEM encryption supported)
|
||||
* - SSL_OBJ_PKCS8 (RC4-128 encrypted data supported)
|
||||
* - SSL_OBJ_PKCS12 (RC4-128 encrypted data supported)
|
||||
*
|
||||
* PEM files are automatically detected (if supported). The object type is
|
||||
* also detected, and so is not relevant for these types of files.
|
||||
* @param filename [in] The location of a file in DER/PEM format.
|
||||
* @param password [in] The password used. Can be null if not required.
|
||||
* @return SSL_OK if all ok
|
||||
* @note Not available in skeleton build mode.
|
||||
*/
|
||||
EXP_FUNC int STDCALL ssl_obj_load(SSL_CTX *ssl_ctx, int obj_type, const char *filename, const char *password);
|
||||
|
||||
/**
|
||||
* @brief Process binary data.
|
||||
*
|
||||
* These are temporary objects that are used to load private keys,
|
||||
* certificates etc into memory.
|
||||
* @param ssl_ctx [in] The client/server context.
|
||||
* @param obj_type [in] The format of the memory data.
|
||||
* @param data [in] The binary data to be loaded.
|
||||
* @param len [in] The amount of data to be loaded.
|
||||
* @param password [in] The password used. Can be null if not required.
|
||||
* @return SSL_OK if all ok
|
||||
* @see ssl_obj_load for more details on obj_type.
|
||||
*/
|
||||
EXP_FUNC int STDCALL ssl_obj_memory_load(SSL_CTX *ssl_ctx, int obj_type, const uint8_t *data, int len, const char *password);
|
||||
|
||||
#ifdef CONFIG_SSL_GENERATE_X509_CERT
|
||||
/**
|
||||
* @brief Create an X.509 certificate.
|
||||
*
|
||||
* This certificate is a self-signed v1 cert with a fixed start/stop validity
|
||||
* times. It is signed with an internal private key in ssl_ctx.
|
||||
*
|
||||
* @param ssl_ctx [in] The client/server context.
|
||||
* @param options [in] Not used yet.
|
||||
* @param dn [in] An array of distinguished name strings. The array is defined
|
||||
* by:
|
||||
* - SSL_X509_CERT_COMMON_NAME (0)
|
||||
* - If SSL_X509_CERT_COMMON_NAME is empty or not defined, then the
|
||||
* hostname will be used.
|
||||
* - SSL_X509_CERT_ORGANIZATION (1)
|
||||
* - If SSL_X509_CERT_ORGANIZATION is empty or not defined, then $USERNAME
|
||||
* will be used.
|
||||
* - SSL_X509_CERT_ORGANIZATIONAL_NAME (2)
|
||||
* - SSL_X509_CERT_ORGANIZATIONAL_NAME is optional.
|
||||
* @param cert_data [out] The certificate as a sequence of bytes.
|
||||
* @return < 0 if an error, or the size of the certificate in bytes.
|
||||
* @note cert_data must be freed when there is no more need for it.
|
||||
*/
|
||||
EXP_FUNC int STDCALL ssl_x509_create(SSL_CTX *ssl_ctx, uint32_t options, const char * dn[], uint8_t **cert_data);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Return the axTLS library version as a string.
|
||||
*/
|
||||
EXP_FUNC const char * STDCALL ssl_version(void);
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
87
Software/libraries/ESP8266WiFi/src/include/wl_definitions.h
Normal file
87
Software/libraries/ESP8266WiFi/src/include/wl_definitions.h
Normal file
@ -0,0 +1,87 @@
|
||||
/*
|
||||
wl_definitions.h - Library for Arduino Wifi shield.
|
||||
Copyright (c) 2011-2014 Arduino. All right reserved.
|
||||
|
||||
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
|
||||
*/
|
||||
/*
|
||||
* wl_definitions.h
|
||||
*
|
||||
* Created on: Mar 6, 2011
|
||||
* Author: dlafauci
|
||||
*/
|
||||
|
||||
#ifndef WL_DEFINITIONS_H_
|
||||
#define WL_DEFINITIONS_H_
|
||||
|
||||
// Maximum size of a SSID
|
||||
#define WL_SSID_MAX_LENGTH 32
|
||||
// Length of passphrase. Valid lengths are 8-63.
|
||||
#define WL_WPA_KEY_MAX_LENGTH 63
|
||||
// Length of key in bytes. Valid values are 5 and 13.
|
||||
#define WL_WEP_KEY_MAX_LENGTH 13
|
||||
// Size of a MAC-address or BSSID
|
||||
#define WL_MAC_ADDR_LENGTH 6
|
||||
// Size of a MAC-address or BSSID
|
||||
#define WL_IPV4_LENGTH 4
|
||||
// Maximum size of a SSID list
|
||||
#define WL_NETWORKS_LIST_MAXNUM 10
|
||||
// Maxmium number of socket
|
||||
#define MAX_SOCK_NUM 4
|
||||
// Socket not available constant
|
||||
#define SOCK_NOT_AVAIL 255
|
||||
// Default state value for Wifi state field
|
||||
#define NA_STATE -1
|
||||
//Maximum number of attempts to establish wifi connection
|
||||
#define WL_MAX_ATTEMPT_CONNECTION 10
|
||||
|
||||
typedef enum {
|
||||
WL_NO_SHIELD = 255, // for compatibility with WiFi Shield library
|
||||
WL_IDLE_STATUS = 0,
|
||||
WL_NO_SSID_AVAIL = 1,
|
||||
WL_SCAN_COMPLETED = 2,
|
||||
WL_CONNECTED = 3,
|
||||
WL_CONNECT_FAILED = 4,
|
||||
WL_CONNECTION_LOST = 5,
|
||||
WL_DISCONNECTED = 6
|
||||
} wl_status_t;
|
||||
|
||||
/* Encryption modes */
|
||||
enum wl_enc_type { /* Values map to 802.11 encryption suites... */
|
||||
ENC_TYPE_WEP = 5,
|
||||
ENC_TYPE_TKIP = 2,
|
||||
ENC_TYPE_CCMP = 4,
|
||||
/* ... except these two, 7 and 8 are reserved in 802.11-2007 */
|
||||
ENC_TYPE_NONE = 7,
|
||||
ENC_TYPE_AUTO = 8
|
||||
};
|
||||
|
||||
#if !defined(LWIP_INTERNAL) && !defined(__LWIP_TCP_H__)
|
||||
enum wl_tcp_state {
|
||||
CLOSED = 0,
|
||||
LISTEN = 1,
|
||||
SYN_SENT = 2,
|
||||
SYN_RCVD = 3,
|
||||
ESTABLISHED = 4,
|
||||
FIN_WAIT_1 = 5,
|
||||
FIN_WAIT_2 = 6,
|
||||
CLOSE_WAIT = 7,
|
||||
CLOSING = 8,
|
||||
LAST_ACK = 9,
|
||||
TIME_WAIT = 10
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif /* WL_DEFINITIONS_H_ */
|
691
Software/libraries/ESP8266WiFi/src/queue.h
Normal file
691
Software/libraries/ESP8266WiFi/src/queue.h
Normal file
@ -0,0 +1,691 @@
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)queue.h 8.5 (Berkeley) 8/20/94
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _SYS_QUEUE_H_
|
||||
#define _SYS_QUEUE_H_
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
/*
|
||||
* This file defines four types of data structures: singly-linked lists,
|
||||
* singly-linked tail queues, lists and tail queues.
|
||||
*
|
||||
* A singly-linked list is headed by a single forward pointer. The elements
|
||||
* are singly linked for minimum space and pointer manipulation overhead at
|
||||
* the expense of O(n) removal for arbitrary elements. New elements can be
|
||||
* added to the list after an existing element or at the head of the list.
|
||||
* Elements being removed from the head of the list should use the explicit
|
||||
* macro for this purpose for optimum efficiency. A singly-linked list may
|
||||
* only be traversed in the forward direction. Singly-linked lists are ideal
|
||||
* for applications with large datasets and few or no removals or for
|
||||
* implementing a LIFO queue.
|
||||
*
|
||||
* A singly-linked tail queue is headed by a pair of pointers, one to the
|
||||
* head of the list and the other to the tail of the list. The elements are
|
||||
* singly linked for minimum space and pointer manipulation overhead at the
|
||||
* expense of O(n) removal for arbitrary elements. New elements can be added
|
||||
* to the list after an existing element, at the head of the list, or at the
|
||||
* end of the list. Elements being removed from the head of the tail queue
|
||||
* should use the explicit macro for this purpose for optimum efficiency.
|
||||
* A singly-linked tail queue may only be traversed in the forward direction.
|
||||
* Singly-linked tail queues are ideal for applications with large datasets
|
||||
* and few or no removals or for implementing a FIFO queue.
|
||||
*
|
||||
* A list is headed by a single forward pointer (or an array of forward
|
||||
* pointers for a hash table header). The elements are doubly linked
|
||||
* so that an arbitrary element can be removed without a need to
|
||||
* traverse the list. New elements can be added to the list before
|
||||
* or after an existing element or at the head of the list. A list
|
||||
* may be traversed in either direction.
|
||||
*
|
||||
* A tail queue is headed by a pair of pointers, one to the head of the
|
||||
* list and the other to the tail of the list. The elements are doubly
|
||||
* linked so that an arbitrary element can be removed without a need to
|
||||
* traverse the list. New elements can be added to the list before or
|
||||
* after an existing element, at the head of the list, or at the end of
|
||||
* the list. A tail queue may be traversed in either direction.
|
||||
*
|
||||
* For details on the use of these macros, see the queue(3) manual page.
|
||||
*
|
||||
*
|
||||
* SLIST LIST STAILQ TAILQ
|
||||
* _HEAD + + + +
|
||||
* _HEAD_INITIALIZER + + + +
|
||||
* _ENTRY + + + +
|
||||
* _INIT + + + +
|
||||
* _EMPTY + + + +
|
||||
* _FIRST + + + +
|
||||
* _NEXT + + + +
|
||||
* _PREV - + - +
|
||||
* _LAST - - + +
|
||||
* _FOREACH + + + +
|
||||
* _FOREACH_SAFE + + + +
|
||||
* _FOREACH_REVERSE - - - +
|
||||
* _FOREACH_REVERSE_SAFE - - - +
|
||||
* _INSERT_HEAD + + + +
|
||||
* _INSERT_BEFORE - + - +
|
||||
* _INSERT_AFTER + + + +
|
||||
* _INSERT_TAIL - - + +
|
||||
* _CONCAT - - + +
|
||||
* _REMOVE_AFTER + - + -
|
||||
* _REMOVE_HEAD + - + -
|
||||
* _REMOVE + + + +
|
||||
* _SWAP + + + +
|
||||
*
|
||||
*/
|
||||
#ifdef QUEUE_MACRO_DEBUG
|
||||
/* Store the last 2 places the queue element or head was altered */
|
||||
struct qm_trace {
|
||||
unsigned long lastline;
|
||||
unsigned long prevline;
|
||||
const char *lastfile;
|
||||
const char *prevfile;
|
||||
};
|
||||
|
||||
#define TRACEBUF struct qm_trace trace;
|
||||
#define TRACEBUF_INITIALIZER { __FILE__, __LINE__, NULL, 0 } ,
|
||||
#define TRASHIT(x) do {(x) = (void *)-1;} while (0)
|
||||
#define QMD_SAVELINK(name, link) void **name = (void *)&(link)
|
||||
|
||||
#define QMD_TRACE_HEAD(head) do { \
|
||||
(head)->trace.prevline = (head)->trace.lastline; \
|
||||
(head)->trace.prevfile = (head)->trace.lastfile; \
|
||||
(head)->trace.lastline = __LINE__; \
|
||||
(head)->trace.lastfile = __FILE__; \
|
||||
} while (0)
|
||||
|
||||
#define QMD_TRACE_ELEM(elem) do { \
|
||||
(elem)->trace.prevline = (elem)->trace.lastline; \
|
||||
(elem)->trace.prevfile = (elem)->trace.lastfile; \
|
||||
(elem)->trace.lastline = __LINE__; \
|
||||
(elem)->trace.lastfile = __FILE__; \
|
||||
} while (0)
|
||||
|
||||
#else
|
||||
#define QMD_TRACE_ELEM(elem)
|
||||
#define QMD_TRACE_HEAD(head)
|
||||
#define QMD_SAVELINK(name, link)
|
||||
#define TRACEBUF
|
||||
#define TRACEBUF_INITIALIZER
|
||||
#define TRASHIT(x)
|
||||
#endif /* QUEUE_MACRO_DEBUG */
|
||||
|
||||
/*
|
||||
* Singly-linked List declarations.
|
||||
*/
|
||||
#define SLIST_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *slh_first; /* first element */ \
|
||||
}
|
||||
|
||||
#define SLIST_HEAD_INITIALIZER(head) \
|
||||
{ NULL }
|
||||
|
||||
#define SLIST_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *sle_next; /* next element */ \
|
||||
}
|
||||
|
||||
/*
|
||||
* Singly-linked List functions.
|
||||
*/
|
||||
#define SLIST_EMPTY(head) ((head)->slh_first == NULL)
|
||||
|
||||
#define SLIST_FIRST(head) ((head)->slh_first)
|
||||
|
||||
#define SLIST_FOREACH(var, head, field) \
|
||||
for ((var) = SLIST_FIRST((head)); \
|
||||
(var); \
|
||||
(var) = SLIST_NEXT((var), field))
|
||||
|
||||
#define SLIST_FOREACH_SAFE(var, head, field, tvar) \
|
||||
for ((var) = SLIST_FIRST((head)); \
|
||||
(var) && ((tvar) = SLIST_NEXT((var), field), 1); \
|
||||
(var) = (tvar))
|
||||
|
||||
#define SLIST_FOREACH_PREVPTR(var, varp, head, field) \
|
||||
for ((varp) = &SLIST_FIRST((head)); \
|
||||
((var) = *(varp)) != NULL; \
|
||||
(varp) = &SLIST_NEXT((var), field))
|
||||
|
||||
#define SLIST_INIT(head) do { \
|
||||
SLIST_FIRST((head)) = NULL; \
|
||||
} while (0)
|
||||
|
||||
#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \
|
||||
SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field); \
|
||||
SLIST_NEXT((slistelm), field) = (elm); \
|
||||
} while (0)
|
||||
|
||||
#define SLIST_INSERT_HEAD(head, elm, field) do { \
|
||||
SLIST_NEXT((elm), field) = SLIST_FIRST((head)); \
|
||||
SLIST_FIRST((head)) = (elm); \
|
||||
} while (0)
|
||||
|
||||
#define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
|
||||
|
||||
#define SLIST_REMOVE(head, elm, type, field) do { \
|
||||
QMD_SAVELINK(oldnext, (elm)->field.sle_next); \
|
||||
if (SLIST_FIRST((head)) == (elm)) { \
|
||||
SLIST_REMOVE_HEAD((head), field); \
|
||||
} \
|
||||
else { \
|
||||
struct type *curelm = SLIST_FIRST((head)); \
|
||||
while (SLIST_NEXT(curelm, field) != (elm)) \
|
||||
curelm = SLIST_NEXT(curelm, field); \
|
||||
SLIST_REMOVE_AFTER(curelm, field); \
|
||||
} \
|
||||
TRASHIT(*oldnext); \
|
||||
} while (0)
|
||||
|
||||
#define SLIST_REMOVE_AFTER(elm, field) do { \
|
||||
SLIST_NEXT(elm, field) = \
|
||||
SLIST_NEXT(SLIST_NEXT(elm, field), field); \
|
||||
} while (0)
|
||||
|
||||
#define SLIST_REMOVE_HEAD(head, field) do { \
|
||||
SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \
|
||||
} while (0)
|
||||
|
||||
#define SLIST_SWAP(head1, head2, type) do { \
|
||||
struct type *swap_first = SLIST_FIRST(head1); \
|
||||
SLIST_FIRST(head1) = SLIST_FIRST(head2); \
|
||||
SLIST_FIRST(head2) = swap_first; \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Singly-linked Tail queue declarations.
|
||||
*/
|
||||
#define STAILQ_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *stqh_first;/* first element */ \
|
||||
struct type **stqh_last;/* addr of last next element */ \
|
||||
}
|
||||
|
||||
#define STAILQ_HEAD_INITIALIZER(head) \
|
||||
{ NULL, &(head).stqh_first }
|
||||
|
||||
#define STAILQ_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *stqe_next; /* next element */ \
|
||||
}
|
||||
|
||||
/*
|
||||
* Singly-linked Tail queue functions.
|
||||
*/
|
||||
#define STAILQ_CONCAT(head1, head2) do { \
|
||||
if (!STAILQ_EMPTY((head2))) { \
|
||||
*(head1)->stqh_last = (head2)->stqh_first; \
|
||||
(head1)->stqh_last = (head2)->stqh_last; \
|
||||
STAILQ_INIT((head2)); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define STAILQ_EMPTY(head) ((head)->stqh_first == NULL)
|
||||
|
||||
#define STAILQ_FIRST(head) ((head)->stqh_first)
|
||||
|
||||
#define STAILQ_FOREACH(var, head, field) \
|
||||
for((var) = STAILQ_FIRST((head)); \
|
||||
(var); \
|
||||
(var) = STAILQ_NEXT((var), field))
|
||||
|
||||
|
||||
#define STAILQ_FOREACH_SAFE(var, head, field, tvar) \
|
||||
for ((var) = STAILQ_FIRST((head)); \
|
||||
(var) && ((tvar) = STAILQ_NEXT((var), field), 1); \
|
||||
(var) = (tvar))
|
||||
|
||||
#define STAILQ_INIT(head) do { \
|
||||
STAILQ_FIRST((head)) = NULL; \
|
||||
(head)->stqh_last = &STAILQ_FIRST((head)); \
|
||||
} while (0)
|
||||
|
||||
#define STAILQ_INSERT_AFTER(head, tqelm, elm, field) do { \
|
||||
if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL)\
|
||||
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
|
||||
STAILQ_NEXT((tqelm), field) = (elm); \
|
||||
} while (0)
|
||||
|
||||
#define STAILQ_INSERT_HEAD(head, elm, field) do { \
|
||||
if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL) \
|
||||
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
|
||||
STAILQ_FIRST((head)) = (elm); \
|
||||
} while (0)
|
||||
|
||||
#define STAILQ_INSERT_TAIL(head, elm, field) do { \
|
||||
STAILQ_NEXT((elm), field) = NULL; \
|
||||
*(head)->stqh_last = (elm); \
|
||||
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
|
||||
} while (0)
|
||||
|
||||
#define STAILQ_LAST(head, type, field) \
|
||||
(STAILQ_EMPTY((head)) ? NULL : \
|
||||
__containerof((head)->stqh_last, struct type, field.stqe_next))
|
||||
|
||||
#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)
|
||||
|
||||
#define STAILQ_REMOVE(head, elm, type, field) do { \
|
||||
QMD_SAVELINK(oldnext, (elm)->field.stqe_next); \
|
||||
if (STAILQ_FIRST((head)) == (elm)) { \
|
||||
STAILQ_REMOVE_HEAD((head), field); \
|
||||
} \
|
||||
else { \
|
||||
struct type *curelm = STAILQ_FIRST((head)); \
|
||||
while (STAILQ_NEXT(curelm, field) != (elm)) \
|
||||
curelm = STAILQ_NEXT(curelm, field); \
|
||||
STAILQ_REMOVE_AFTER(head, curelm, field); \
|
||||
} \
|
||||
TRASHIT(*oldnext); \
|
||||
} while (0)
|
||||
|
||||
#define STAILQ_REMOVE_AFTER(head, elm, field) do { \
|
||||
if ((STAILQ_NEXT(elm, field) = \
|
||||
STAILQ_NEXT(STAILQ_NEXT(elm, field), field)) == NULL) \
|
||||
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
|
||||
} while (0)
|
||||
|
||||
#define STAILQ_REMOVE_HEAD(head, field) do { \
|
||||
if ((STAILQ_FIRST((head)) = \
|
||||
STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \
|
||||
(head)->stqh_last = &STAILQ_FIRST((head)); \
|
||||
} while (0)
|
||||
|
||||
#define STAILQ_REMOVE_HEAD_UNTIL(head, elm, field) do { \
|
||||
if ((STAILQ_FIRST((head)) = STAILQ_NEXT((elm), field)) == NULL) \
|
||||
(head)->stqh_last = &STAILQ_FIRST((head)); \
|
||||
} while (0)
|
||||
|
||||
#define STAILQ_SWAP(head1, head2, type) do { \
|
||||
struct type *swap_first = STAILQ_FIRST(head1); \
|
||||
struct type **swap_last = (head1)->stqh_last; \
|
||||
STAILQ_FIRST(head1) = STAILQ_FIRST(head2); \
|
||||
(head1)->stqh_last = (head2)->stqh_last; \
|
||||
STAILQ_FIRST(head2) = swap_first; \
|
||||
(head2)->stqh_last = swap_last; \
|
||||
if (STAILQ_EMPTY(head1)) \
|
||||
(head1)->stqh_last = &STAILQ_FIRST(head1); \
|
||||
if (STAILQ_EMPTY(head2)) \
|
||||
(head2)->stqh_last = &STAILQ_FIRST(head2); \
|
||||
} while (0)
|
||||
|
||||
|
||||
/*
|
||||
* List declarations.
|
||||
*/
|
||||
#define LIST_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *lh_first; /* first element */ \
|
||||
}
|
||||
|
||||
#define LIST_HEAD_INITIALIZER(head) \
|
||||
{ NULL }
|
||||
|
||||
#define LIST_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *le_next; /* next element */ \
|
||||
struct type **le_prev; /* address of previous next element */ \
|
||||
}
|
||||
|
||||
/*
|
||||
* List functions.
|
||||
*/
|
||||
|
||||
#if (defined(_KERNEL) && defined(INVARIANTS))
|
||||
#define QMD_LIST_CHECK_HEAD(head, field) do { \
|
||||
if (LIST_FIRST((head)) != NULL && \
|
||||
LIST_FIRST((head))->field.le_prev != \
|
||||
&LIST_FIRST((head))) \
|
||||
panic("Bad list head %p first->prev != head", (head)); \
|
||||
} while (0)
|
||||
|
||||
#define QMD_LIST_CHECK_NEXT(elm, field) do { \
|
||||
if (LIST_NEXT((elm), field) != NULL && \
|
||||
LIST_NEXT((elm), field)->field.le_prev != \
|
||||
&((elm)->field.le_next)) \
|
||||
panic("Bad link elm %p next->prev != elm", (elm)); \
|
||||
} while (0)
|
||||
|
||||
#define QMD_LIST_CHECK_PREV(elm, field) do { \
|
||||
if (*(elm)->field.le_prev != (elm)) \
|
||||
panic("Bad link elm %p prev->next != elm", (elm)); \
|
||||
} while (0)
|
||||
#else
|
||||
#define QMD_LIST_CHECK_HEAD(head, field)
|
||||
#define QMD_LIST_CHECK_NEXT(elm, field)
|
||||
#define QMD_LIST_CHECK_PREV(elm, field)
|
||||
#endif /* (_KERNEL && INVARIANTS) */
|
||||
|
||||
#define LIST_EMPTY(head) ((head)->lh_first == NULL)
|
||||
|
||||
#define LIST_FIRST(head) ((head)->lh_first)
|
||||
|
||||
#define LIST_FOREACH(var, head, field) \
|
||||
for ((var) = LIST_FIRST((head)); \
|
||||
(var); \
|
||||
(var) = LIST_NEXT((var), field))
|
||||
|
||||
#define LIST_FOREACH_SAFE(var, head, field, tvar) \
|
||||
for ((var) = LIST_FIRST((head)); \
|
||||
(var) && ((tvar) = LIST_NEXT((var), field), 1); \
|
||||
(var) = (tvar))
|
||||
|
||||
#define LIST_INIT(head) do { \
|
||||
LIST_FIRST((head)) = NULL; \
|
||||
} while (0)
|
||||
|
||||
#define LIST_INSERT_AFTER(listelm, elm, field) do { \
|
||||
QMD_LIST_CHECK_NEXT(listelm, field); \
|
||||
if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\
|
||||
LIST_NEXT((listelm), field)->field.le_prev = \
|
||||
&LIST_NEXT((elm), field); \
|
||||
LIST_NEXT((listelm), field) = (elm); \
|
||||
(elm)->field.le_prev = &LIST_NEXT((listelm), field); \
|
||||
} while (0)
|
||||
|
||||
#define LIST_INSERT_BEFORE(listelm, elm, field) do { \
|
||||
QMD_LIST_CHECK_PREV(listelm, field); \
|
||||
(elm)->field.le_prev = (listelm)->field.le_prev; \
|
||||
LIST_NEXT((elm), field) = (listelm); \
|
||||
*(listelm)->field.le_prev = (elm); \
|
||||
(listelm)->field.le_prev = &LIST_NEXT((elm), field); \
|
||||
} while (0)
|
||||
|
||||
#define LIST_INSERT_HEAD(head, elm, field) do { \
|
||||
QMD_LIST_CHECK_HEAD((head), field); \
|
||||
if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL) \
|
||||
LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\
|
||||
LIST_FIRST((head)) = (elm); \
|
||||
(elm)->field.le_prev = &LIST_FIRST((head)); \
|
||||
} while (0)
|
||||
|
||||
#define LIST_NEXT(elm, field) ((elm)->field.le_next)
|
||||
|
||||
#define LIST_PREV(elm, head, type, field) \
|
||||
((elm)->field.le_prev == &LIST_FIRST((head)) ? NULL : \
|
||||
__containerof((elm)->field.le_prev, struct type, field.le_next))
|
||||
|
||||
#define LIST_REMOVE(elm, field) do { \
|
||||
QMD_SAVELINK(oldnext, (elm)->field.le_next); \
|
||||
QMD_SAVELINK(oldprev, (elm)->field.le_prev); \
|
||||
QMD_LIST_CHECK_NEXT(elm, field); \
|
||||
QMD_LIST_CHECK_PREV(elm, field); \
|
||||
if (LIST_NEXT((elm), field) != NULL) \
|
||||
LIST_NEXT((elm), field)->field.le_prev = \
|
||||
(elm)->field.le_prev; \
|
||||
*(elm)->field.le_prev = LIST_NEXT((elm), field); \
|
||||
TRASHIT(*oldnext); \
|
||||
TRASHIT(*oldprev); \
|
||||
} while (0)
|
||||
|
||||
#define LIST_SWAP(head1, head2, type, field) do { \
|
||||
struct type *swap_tmp = LIST_FIRST((head1)); \
|
||||
LIST_FIRST((head1)) = LIST_FIRST((head2)); \
|
||||
LIST_FIRST((head2)) = swap_tmp; \
|
||||
if ((swap_tmp = LIST_FIRST((head1))) != NULL) \
|
||||
swap_tmp->field.le_prev = &LIST_FIRST((head1)); \
|
||||
if ((swap_tmp = LIST_FIRST((head2))) != NULL) \
|
||||
swap_tmp->field.le_prev = &LIST_FIRST((head2)); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Tail queue declarations.
|
||||
*/
|
||||
#define TAILQ_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *tqh_first; /* first element */ \
|
||||
struct type **tqh_last; /* addr of last next element */ \
|
||||
TRACEBUF \
|
||||
}
|
||||
|
||||
#define TAILQ_HEAD_INITIALIZER(head) \
|
||||
{ NULL, &(head).tqh_first, TRACEBUF_INITIALIZER }
|
||||
|
||||
#define TAILQ_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *tqe_next; /* next element */ \
|
||||
struct type **tqe_prev; /* address of previous next element */ \
|
||||
TRACEBUF \
|
||||
}
|
||||
|
||||
/*
|
||||
* Tail queue functions.
|
||||
*/
|
||||
#if (defined(_KERNEL) && defined(INVARIANTS))
|
||||
#define QMD_TAILQ_CHECK_HEAD(head, field) do { \
|
||||
if (!TAILQ_EMPTY(head) && \
|
||||
TAILQ_FIRST((head))->field.tqe_prev != \
|
||||
&TAILQ_FIRST((head))) \
|
||||
panic("Bad tailq head %p first->prev != head", (head)); \
|
||||
} while (0)
|
||||
|
||||
#define QMD_TAILQ_CHECK_TAIL(head, field) do { \
|
||||
if (*(head)->tqh_last != NULL) \
|
||||
panic("Bad tailq NEXT(%p->tqh_last) != NULL", (head)); \
|
||||
} while (0)
|
||||
|
||||
#define QMD_TAILQ_CHECK_NEXT(elm, field) do { \
|
||||
if (TAILQ_NEXT((elm), field) != NULL && \
|
||||
TAILQ_NEXT((elm), field)->field.tqe_prev != \
|
||||
&((elm)->field.tqe_next)) \
|
||||
panic("Bad link elm %p next->prev != elm", (elm)); \
|
||||
} while (0)
|
||||
|
||||
#define QMD_TAILQ_CHECK_PREV(elm, field) do { \
|
||||
if (*(elm)->field.tqe_prev != (elm)) \
|
||||
panic("Bad link elm %p prev->next != elm", (elm)); \
|
||||
} while (0)
|
||||
#else
|
||||
#define QMD_TAILQ_CHECK_HEAD(head, field)
|
||||
#define QMD_TAILQ_CHECK_TAIL(head, headname)
|
||||
#define QMD_TAILQ_CHECK_NEXT(elm, field)
|
||||
#define QMD_TAILQ_CHECK_PREV(elm, field)
|
||||
#endif /* (_KERNEL && INVARIANTS) */
|
||||
|
||||
#define TAILQ_CONCAT(head1, head2, field) do { \
|
||||
if (!TAILQ_EMPTY(head2)) { \
|
||||
*(head1)->tqh_last = (head2)->tqh_first; \
|
||||
(head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \
|
||||
(head1)->tqh_last = (head2)->tqh_last; \
|
||||
TAILQ_INIT((head2)); \
|
||||
QMD_TRACE_HEAD(head1); \
|
||||
QMD_TRACE_HEAD(head2); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL)
|
||||
|
||||
#define TAILQ_FIRST(head) ((head)->tqh_first)
|
||||
|
||||
#define TAILQ_FOREACH(var, head, field) \
|
||||
for ((var) = TAILQ_FIRST((head)); \
|
||||
(var); \
|
||||
(var) = TAILQ_NEXT((var), field))
|
||||
|
||||
#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \
|
||||
for ((var) = TAILQ_FIRST((head)); \
|
||||
(var) && ((tvar) = TAILQ_NEXT((var), field), 1); \
|
||||
(var) = (tvar))
|
||||
|
||||
#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \
|
||||
for ((var) = TAILQ_LAST((head), headname); \
|
||||
(var); \
|
||||
(var) = TAILQ_PREV((var), headname, field))
|
||||
|
||||
#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \
|
||||
for ((var) = TAILQ_LAST((head), headname); \
|
||||
(var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \
|
||||
(var) = (tvar))
|
||||
|
||||
#define TAILQ_INIT(head) do { \
|
||||
TAILQ_FIRST((head)) = NULL; \
|
||||
(head)->tqh_last = &TAILQ_FIRST((head)); \
|
||||
QMD_TRACE_HEAD(head); \
|
||||
} while (0)
|
||||
|
||||
#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
|
||||
QMD_TAILQ_CHECK_NEXT(listelm, field); \
|
||||
if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\
|
||||
TAILQ_NEXT((elm), field)->field.tqe_prev = \
|
||||
&TAILQ_NEXT((elm), field); \
|
||||
else { \
|
||||
(head)->tqh_last = &TAILQ_NEXT((elm), field); \
|
||||
QMD_TRACE_HEAD(head); \
|
||||
} \
|
||||
TAILQ_NEXT((listelm), field) = (elm); \
|
||||
(elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field); \
|
||||
QMD_TRACE_ELEM(&(elm)->field); \
|
||||
QMD_TRACE_ELEM(&listelm->field); \
|
||||
} while (0)
|
||||
|
||||
#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
|
||||
QMD_TAILQ_CHECK_PREV(listelm, field); \
|
||||
(elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
|
||||
TAILQ_NEXT((elm), field) = (listelm); \
|
||||
*(listelm)->field.tqe_prev = (elm); \
|
||||
(listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field); \
|
||||
QMD_TRACE_ELEM(&(elm)->field); \
|
||||
QMD_TRACE_ELEM(&listelm->field); \
|
||||
} while (0)
|
||||
|
||||
#define TAILQ_INSERT_HEAD(head, elm, field) do { \
|
||||
QMD_TAILQ_CHECK_HEAD(head, field); \
|
||||
if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL) \
|
||||
TAILQ_FIRST((head))->field.tqe_prev = \
|
||||
&TAILQ_NEXT((elm), field); \
|
||||
else \
|
||||
(head)->tqh_last = &TAILQ_NEXT((elm), field); \
|
||||
TAILQ_FIRST((head)) = (elm); \
|
||||
(elm)->field.tqe_prev = &TAILQ_FIRST((head)); \
|
||||
QMD_TRACE_HEAD(head); \
|
||||
QMD_TRACE_ELEM(&(elm)->field); \
|
||||
} while (0)
|
||||
|
||||
#define TAILQ_INSERT_TAIL(head, elm, field) do { \
|
||||
QMD_TAILQ_CHECK_TAIL(head, field); \
|
||||
TAILQ_NEXT((elm), field) = NULL; \
|
||||
(elm)->field.tqe_prev = (head)->tqh_last; \
|
||||
*(head)->tqh_last = (elm); \
|
||||
(head)->tqh_last = &TAILQ_NEXT((elm), field); \
|
||||
QMD_TRACE_HEAD(head); \
|
||||
QMD_TRACE_ELEM(&(elm)->field); \
|
||||
} while (0)
|
||||
|
||||
#define TAILQ_LAST(head, headname) \
|
||||
(*(((struct headname *)((head)->tqh_last))->tqh_last))
|
||||
|
||||
#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
|
||||
|
||||
#define TAILQ_PREV(elm, headname, field) \
|
||||
(*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
|
||||
|
||||
#define TAILQ_REMOVE(head, elm, field) do { \
|
||||
QMD_SAVELINK(oldnext, (elm)->field.tqe_next); \
|
||||
QMD_SAVELINK(oldprev, (elm)->field.tqe_prev); \
|
||||
QMD_TAILQ_CHECK_NEXT(elm, field); \
|
||||
QMD_TAILQ_CHECK_PREV(elm, field); \
|
||||
if ((TAILQ_NEXT((elm), field)) != NULL) \
|
||||
TAILQ_NEXT((elm), field)->field.tqe_prev = \
|
||||
(elm)->field.tqe_prev; \
|
||||
else { \
|
||||
(head)->tqh_last = (elm)->field.tqe_prev; \
|
||||
QMD_TRACE_HEAD(head); \
|
||||
} \
|
||||
*(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \
|
||||
TRASHIT(*oldnext); \
|
||||
TRASHIT(*oldprev); \
|
||||
QMD_TRACE_ELEM(&(elm)->field); \
|
||||
} while (0)
|
||||
|
||||
#define TAILQ_SWAP(head1, head2, type, field) do { \
|
||||
struct type *swap_first = (head1)->tqh_first; \
|
||||
struct type **swap_last = (head1)->tqh_last; \
|
||||
(head1)->tqh_first = (head2)->tqh_first; \
|
||||
(head1)->tqh_last = (head2)->tqh_last; \
|
||||
(head2)->tqh_first = swap_first; \
|
||||
(head2)->tqh_last = swap_last; \
|
||||
if ((swap_first = (head1)->tqh_first) != NULL) \
|
||||
swap_first->field.tqe_prev = &(head1)->tqh_first; \
|
||||
else \
|
||||
(head1)->tqh_last = &(head1)->tqh_first; \
|
||||
if ((swap_first = (head2)->tqh_first) != NULL) \
|
||||
swap_first->field.tqe_prev = &(head2)->tqh_first; \
|
||||
else \
|
||||
(head2)->tqh_last = &(head2)->tqh_first; \
|
||||
} while (0)
|
||||
|
||||
#ifdef _KERNEL
|
||||
|
||||
/*
|
||||
* XXX insque() and remque() are an old way of handling certain queues.
|
||||
* They bogusly assumes that all queue heads look alike.
|
||||
*/
|
||||
|
||||
struct quehead {
|
||||
struct quehead *qh_link;
|
||||
struct quehead *qh_rlink;
|
||||
};
|
||||
|
||||
#ifdef __GNUC__
|
||||
|
||||
static __inline void
|
||||
insque(void *a, void *b)
|
||||
{
|
||||
struct quehead *element = (struct quehead *)a,
|
||||
*head = (struct quehead *)b;
|
||||
|
||||
element->qh_link = head->qh_link;
|
||||
element->qh_rlink = head;
|
||||
head->qh_link = element;
|
||||
element->qh_link->qh_rlink = element;
|
||||
}
|
||||
|
||||
static __inline void
|
||||
remque(void *a)
|
||||
{
|
||||
struct quehead *element = (struct quehead *)a;
|
||||
|
||||
element->qh_link->qh_rlink = element->qh_rlink;
|
||||
element->qh_rlink->qh_link = element->qh_link;
|
||||
element->qh_rlink = 0;
|
||||
}
|
||||
|
||||
#else /* !__GNUC__ */
|
||||
|
||||
void insque(void *a, void *b);
|
||||
void remque(void *a);
|
||||
|
||||
#endif /* __GNUC__ */
|
||||
|
||||
#endif /* _KERNEL */
|
||||
|
||||
#endif /* !_SYS_QUEUE_H_ */
|
Reference in New Issue
Block a user