vjmuzik / nativeethernet Goto Github PK
View Code? Open in Web Editor NEWThis project forked from paulstoffregen/ethernet
Native Ethernet library for Teensy 4.1
Home Page: http://www.pjrc.com/teensy/td_libs_Ethernet.html
License: MIT License
This project forked from paulstoffregen/ethernet
Native Ethernet library for Teensy 4.1
Home Page: http://www.pjrc.com/teensy/td_libs_Ethernet.html
License: MIT License
Just udpated my PLatformio native ethernet to a fresh zip from here and get
.platformio\packages\framework-arduinoteensy\libraries\NativeEthernet\src\NativeEthernetClient.cpp: In member function 'virtual int EthernetClient::connect(const char*, uint16_t)':
C:\Users\david.platformio\packages\framework-arduinoteensy\libraries\NativeEthernet\src\NativeEthernetClient.cpp:45:5: error: 'host_name' was not declared in this scope
host_name = host;
^
*** [.pio\build\pre_and_post_hooks\lib37c\NativeEthernet\NativeEthernetClient.cpp.o] Error 1
I assume the host_name is only used for TLS as its declared
#if FNET_CFG_TLS
fnet_tls_desc_t tls_desc = 0;
bool _tls_en = false;
const char* host_name = NULL;
fnet_uint8_t* ca_certificate_buffer = (fnet_uint8_t*)mbedtls_test_ca_crt; /* Certificate data. /
fnet_size_t ca_certificate_buffer_size = mbedtls_test_ca_crt_len; / Size of the certificate buffer. */
#endif
I assume it can be managed by adding "#if FNET_CFG_TLS" around its use
Hi,
Whenever we try to run a example sketch without the PHY connected to a network, Ethernet.begin(mac) takes approximately 60000 milliseconds to start. If Ethernet.begin(mac, ip) it takes about 18 minutes to start. The moment a network jack is plugged in, Ethernet.begin() immediately executes.
Is there any way to overcome Ethernet.begin() getting stuck while the board is not connected to a network?
Kind regards
I have a case where I periodically want to send a small number 3-4 of small udp packets. When I send 2 in succession only the second one makes it through to the other side.
Is this a bug? should I be checking that the previous packet has been sent somehow?
The official Arduino documentation says the write
method will return the number of bytes actually written, as is expected for most socket programming. This library does not do that, and I'm thus unable to properly stream voluminous data. Is there another function I can call subsequent to write
to determine the number of bytes just written?
It appears that the MAC ID used by the library is not unique. I tested it on 2 Teensy 4.1.
Below is the source piece and the output it generates. It can be seen that even by setting the MAC ID read by Teensy (or another with random values) once Ethernet.begin() is used, the MAC ID is changed to the same value even on two different Teesny4.1s.
Wireshark confirms the MAC ID that is displayed and set by the library.
//Ethernet init
uint8_t macId[32]; //no need to initialize, it is hardcoded
teensyMAC(macId);
SerialDBG_println("MAC ID before Ethernet Begin");
sprintf(buff, "Ethernet mac address: %02X:%02X:%02X:%02X:%02X:%02X \n", macId[0], macId[1], macId[2], macId[3], macId[4], macId[5]);
SerialDBG_println(buff);
Ethernet.begin(macId);
SerialDBG_println("MAC ID after Ethernet begin");
sprintf(buff, "Ethernet mac address: %02X:%02X:%02X:%02X:%02X:%02X \n", macId[0], macId[1], macId[2], macId[3], macId[4], macId[5]);
SerialDBG_println(buff);
Ethernet.MACAddress(macId);
SerialDBG_println("MAC ID after read Ethernet.MACAddress()");
sprintf(buff, "Ethernet mac address: %02X:%02X:%02X:%02X:%02X:%02X \n", macId[0], macId[1], macId[2], macId[3], macId[4], macId[5]);
SerialDBG_println(buff);
MAC ID before Ethernet Begin
Ethernet mac address: 04:E9:E5:0C:52:73
MAC ID after Ethernet begin
Ethernet mac address: 72:65:73:73:3A:20
MAC ID after read Ethernet.MACAddress()
Ethernet mac address: 72:65:73:73:3A:20
Good afternoon,
I tried to use the NativeEthernet inside IntervalTimer function, however, after 1-2 minute(s), the NativeEthernet freezes for no appearent reason (it stops receiving packets, however the led on the magjack kit stills work and windows continues sending packets). When i move the NativeEthernet instructions inside the loop function, the NativeEthernet works perfectly (without freeze), except if there is a long delay instruction (as below ; if there is a long delay instruction, NativeEthernet also freezes ).
Below, there is a code that freezes.
Do you know how to solve it ?
Thank you
My Source code:
#include <NativeEthernet.h>
#include <NativeEthernetUdp.h>
EthernetUDP myUDP;
byte ip[] = {192, 168, 1, 177};
byte mac[] = {0x04, 0xE9, 0xE5, 0x00, 0x69, 0xEC};
#define NET_PORT 6450
uint8_t netPacket[1470];
unsigned short packetSize;
//IntervalTimer myTimerLoopNetwork;
void setup() {
Ethernet.begin(mac,ip);
myUDP.begin(NET_PORT);
// Ethernet._fnet_poll.end(); // Note : poll is useless in my case and i wanted to know if it changes something or not (sadly it changes nothing)
// myTimerLoopNetwork.begin(loopNetwork, 100);
}
void loop() {
loopNetwork();
delay(100);
}
//bool isLoopNetwork=false;
void loopNetwork(){
// if(isLoopNetwork) return;
// isLoopNetwork=true;
packetSize = myUDP.parsePacket();
if (packetSize){
// isLoopNetwork=false;
myUDP.read(netPacket, packetSize);
Serial.print((char)(netPacket[0]));
Serial.println(" test_for_freeze");
}
// isLoopNetwork=false;
}
NativeEthernet/src/NativeEthernet.cpp
Lines 293 to 294 in 92540fd
This code will hang if I want to set a static IP but don't yet have a cable plugged in. I waited for a while and it looks like the link status is never set to something other than Unknown
(0
). Is link_callback
supposed to be called at all in this case?
It's been my experience that a return of -1 means EOF and a return of 0 means "nothing available". Why does this function return the opposite? I know this may just be a convention thing, it just seems odd to me here.
Hello, I have my Teensy board and am trying my hand at Ethernet. Unfortunately I can not get the "WebServer.ino" example to work. Is there anything to consider with this example, or is it enough to flash the program and plug in the Ethernet cable? When I try this, I get in my browser unfortunately only an error.
/*
Web Server
A simple web server that shows the value of the analog input pins.
using an Arduino Wiznet Ethernet shield.
Circuit:
* Ethernet shield attached to pins 10, 11, 12, 13
* Analog inputs attached to pins A0 through A5 (optional)
created 18 Dec 2009
by David A. Mellis
modified 9 Apr 2012
by Tom Igoe
modified 02 Sept 2015
by Arturo Guadalupi
*/
#include <SPI.h>
#include <NativeEthernet.h>
// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = {
0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED
};
IPAddress ip(192, 168, 1, 177);
// Initialize the Ethernet server library
// with the IP address and port you want to use
// (port 80 is default for HTTP):
EthernetServer server(80);
void setup() {
// You can use Ethernet.init(pin) to configure the CS pin
//Ethernet.init(10); // Most Arduino shields
//Ethernet.init(5); // MKR ETH shield
//Ethernet.init(0); // Teensy 2.0
//Ethernet.init(20); // Teensy++ 2.0
//Ethernet.init(15); // ESP8266 with Adafruit Featherwing Ethernet
//Ethernet.init(33); // ESP32 with Adafruit Featherwing Ethernet
// Open serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
Serial.println("Ethernet WebServer Example");
// start the Ethernet connection and the server:
Ethernet.begin(mac, ip);
// Check for Ethernet hardware present
if (Ethernet.hardwareStatus() == EthernetNoHardware) {
Serial.println("Ethernet shield was not found. Sorry, can't run without hardware. :(");
while (true) {
delay(1); // do nothing, no point running without Ethernet hardware
}
}
if (Ethernet.linkStatus() == LinkOFF) {
Serial.println("Ethernet cable is not connected.");
}
// start the server
server.begin();
Serial.print("server is at ");
Serial.println(Ethernet.localIP());
}
void loop() {
// listen for incoming clients
EthernetClient client = server.available();
if (client) {
Serial.println("new client");
// an http request ends with a blank line
boolean currentLineIsBlank = true;
while (client.connected()) {
if (client.available()) {
char c = client.read();
Serial.write(c);
// if you've gotten to the end of the line (received a newline
// character) and the line is blank, the http request has ended,
// so you can send a reply
if (c == '\n' && currentLineIsBlank) {
// send a standard http response header
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println("Connection: close"); // the connection will be closed after completion of the response
client.println("Refresh: 5"); // refresh the page automatically every 5 sec
client.println();
client.println("<!DOCTYPE HTML>");
client.println("<html>");
// output the value of each analog input pin
for (int analogChannel = 0; analogChannel < 6; analogChannel++) {
int sensorReading = analogRead(analogChannel);
client.print("analog input ");
client.print(analogChannel);
client.print(" is ");
client.print(sensorReading);
client.println("<br />");
}
client.println("</html>");
break;
}
if (c == '\n') {
// you're starting a new line
currentLineIsBlank = true;
} else if (c != '\r') {
// you've gotten a character on the current line
currentLineIsBlank = false;
}
}
}
// give the web browser time to receive the data
delay(1);
// close the connection:
client.stop();
Serial.println("client disconnected");
}
}
I often like to call flush() before calling close() (In this case, it's stop()), however, EthernetClient::flush() seems to hang. To work around this, I'm just calling stop() without the flush().
I am new to UDP communication and I was trying to run UDPSendReceiveString.ino example but I dont know how to find my local network ethernet ip and mac. On linux I tried config -a and ip a which give me enp0s31f6
(I understand this represent the ethernet) but I there is no IP address and I dont know how to paste my MAC address in the form 4c:...:2e
to the template below:
byte mac[] = {
0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED
};
Following code doesn't work with the Native Ethernet library.
The code works with STM32duino with LWIP and with the WIZNet library
#include "Arduino.h"
#include <TeensyID.h>
#include <NativeEthernet.h>
#include <NativeEthernetUdp.h>
uint8_t mac[6];
IPAddress localIP(10, 101, 1, 201);
IPAddress subnet(255, 255, 0, 0);
uint16_t localPort = 8001;
IPAddress remoteIP(10, 101, 1, 100);
uint16_t remotePort = 8000;
EthernetUDP udp;
void setup() {
teensyMAC(mac);
Serial.begin(9600);
Ethernet.begin(mac, localIP);
udp.begin(localPort);
}
void loop() {
String message;
int size;
size = udp.parsePacket();
if (size > 0) {
// Fill the msg with all of the available bytes
while (size--) {
message += (char)(udp.read());
}
Serial.println(message);
message = String();
}
}
The application stop working when reaching message += (char)(udp.read());
If using the standard C++ string library it works as expected. Also when using a char buffer array.
This example works
#include "Arduino.h"
#include <TeensyID.h>
#include <NativeEthernet.h>
#include <NativeEthernetUdp.h>
#include <string>
using namespace std;
uint8_t mac[6];
IPAddress localIP(10, 101, 1, 201);
IPAddress subnet(255, 255, 0, 0);
uint16_t localPort = 8001;
IPAddress remoteIP(10, 101, 1, 100);
uint16_t remotePort = 8000;
EthernetUDP udp;
void setup() {
teensyMAC(mac);
Serial.begin(9600);
Ethernet.begin(mac, localIP);
udp.begin(localPort);
}
void loop() {
string message;
int size;
size = udp.parsePacket();
if (size > 0) {
// Fill the msg with all of the available bytes
while (size--) {
message += (char)(udp.read());
}
Serial.println(message.c_str());
message.erase();
}
}
I'm putting together a device that reads two ADCs (simultaneous sampling) and sends the values over TouchOSC. I originally had all the networking stuff worked out on the esp32, but switched to the Teensy because of more flexible SPI hardware, plus availability of the esp32 boards with onboard ethernet wasn't great so it looked like getting them wouldn't meet my deadline.
I stripped my original code down to the bare minimum.
#include <NativeEthernet.h>
//#include <NativeEthernetUdp.h>
// Extract the hardware MAC from uC itself, and stuff it into an array
uint8_t mac[6];
void teensyMAC(uint8_t *mac) {
for(uint8_t by=0; by<2; by++) mac[by]=(HW_OCOTP_MAC1 >> ((1-by)*8)) & 0xFF;
for(uint8_t by=0; by<4; by++) mac[by+2]=(HW_OCOTP_MAC0 >> ((3-by)*8)) & 0xFF;
Serial.printf("MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
}
// Mirror the enum EthernetHardwareStatus in NativeEthernet.h so we can print a human readable value.
// Shouldn't this enum be updated to have a 'NativeEthernet" value?
char HWStatus[][14] = {"EthNoHardware",
"EthernetW5100",
"EthernetW5200",
"EthernetW5500"};
//// buffers for receiving and sending data. Currently unused.
//char packetBuffer[UDP_TX_PACKET_MAX_SIZE]; // buffer to hold incoming packet,
//char ReplyBuffer[] = "acknowledged"; // a string to send back
//
//// An EthernetUDP instance to let us send and receive packets over UDP
//EthernetUDP udp;
//
////IP address to send UDP data to:
//const char * udpAddress = "192.168.1.50";
const int udpPort = 8000;
//
//// Not connected yet!
//boolean connected = false;
int ledPin = 13;
int value = 0;
void setup(void) {
Serial.begin(115200);
pinMode(ledPin, OUTPUT);
digitalWrite(ledPin, HIGH);
Ethernet.setStackHeap(1024 * 64);
Ethernet.setSocketSize(1024 * 16);
Ethernet.setSocketNum(1);
teensyMAC(mac);
Ethernet.begin(mac);
Serial.print("IP address: ");
Serial.println(Ethernet.localIP());
Serial.send_now();
Serial.println(HWStatus[Ethernet.hardwareStatus()]);
Serial.send_now();
// This sketch will run indefinitely with mDNS commented out, hangs then reboots when enabled.
MDNS.begin("Teensy41", 1); //.local Domain name and number of services
MDNS.setServiceName("Teensy41_OSC"); //Uncomment to change service name
MDNS.addService("_osc._udp", udpPort);
}
void loop(void) {
// Count loop iterations, toggle LED and print value every 10 million loops as an alternative to blocking with delay()
if((value % 10000000) == 0) {
digitalWrite(ledPin, !digitalRead(ledPin));
Serial.print("Loop: ");
Serial.println(value / 10000000);
Serial.send_now();
fnet_service_poll(); // Is this even necessary to call by the user? Ideally, the ethernet library should
// run a timer to automatically execute housekeeping tasks. Is this already done?
// It didn't seem to make a difference when the mDNS service was enabled.
if (value >= 1000000000 ) value = 0;
}
value++;
}
The number of iterations before the hang varies, and occasionally it won't reboot at all, requiring manual intervention.
In the setup() I want to connect to a MQTT broker, this works fine when the broker is online but fails when the broker is not online. I expected that the connect() function returns a false when it cannot connect but instead the system does not get anything back and freezes...
bool connectMQTT()
{
EthernetClient testcl;
char sIp[15] = "192.168.2.44";
IPAddress MQTTbrokerIP = parseIP(sIp);
if(testcl.connect(MQTTbrokerIP, settingMQTTport)){
return true;
else{
return false;
}
I noticed that there is a memory leak in EthernetMDNS: in its begin()
function it allocates memory on the heap of the service descriptors (service_desc
) which is never freed. I might run into the case where I am calling EthernetMDNS::begin()
multiple times (each time the ethernet cable is re-plugged) and then would have a memory leak.
I am willing to prepare a patch which just removes the service_desc alltogether since it never seems to be used anyways. Would you be interested?
Hi,
For a project we are trying to monitor a status protocol sent on local network over TCP and post these status messages over HTTPS to a InfluxDB instance on AWS at https://www.influxdata.com/products/influxdb-cloud/.
Posting a string to a test instance over LAN to a IP works fine, but whenever we try to post to the AWS subdomain we are greeted with this response:
HTTP/1.1 400 Bad Request
Server: awselb/2.0
Date: Mon, 27 Sep 2021 18:13:02 GMT
Content-Type: text/html
Content-Length: 122
Connection: close
Since we verified the headers and body of the post are correct when we post locally, and posting to AWS works when using Postman, we are at a loss at the moment. Unfortunately I have no information about the configuration of the server we try to POST to.
As a test we set-up the WebClientRepeatingTLS example using our own POST headers and body.
#include <NativeEthernet.h>
uint8_t mac[6];
void teensyMAC(uint8_t *mac) {
for (uint8_t by = 0; by < 2; by++) mac[by] = (HW_OCOTP_MAC1 >> ((1 - by) * 8)) & 0xFF;
for (uint8_t by = 0; by < 4; by++) mac[by + 2] = (HW_OCOTP_MAC0 >> ((3 - by) * 8)) & 0xFF;
Serial.printf("MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
}
// initialize the library instance:
EthernetClient client;
const int port = 443;
char server[] = "influxdata.com";
//IPAddress server(192, 168, 1, 246);
String outputMSG = "measurementName,tagKey=tagValue fieldKey=1i";
unsigned long lastConnectionTime = 0; // last time you connected to the server, in milliseconds
const unsigned long postingInterval = 5 * 1000; // delay between updates, in milliseconds
void setup() {
teensyMAC(mac);
Serial.begin(9600);
while (!Serial) {
;
}
Serial.println("Initialize Ethernet with DHCP:");
if (Ethernet.begin(mac) == 0) {
Serial.println("Failed to configure Ethernet using DHCP");
if (Ethernet.hardwareStatus() == EthernetNoHardware) {
Serial.println("Ethernet shield was not found. Sorry, can't run without hardware. :(");
while (true) {
delay(1);
}
}
if (Ethernet.linkStatus() == LinkOFF) {
Serial.println("Ethernet cable is not connected.");
}
} else {
Serial.print(" DHCP assigned IP ");
Serial.println(Ethernet.localIP());
}
delay(1000);
}
void loop() {
if (client.available()) {
char c = client.read();
Serial.write(c);
}
if (millis() - lastConnectionTime > postingInterval) {
httpRequest();
}
}
void httpRequest() {
client.stop();
Serial.print("Content-Length: ");
Serial.println(outputMSG.length());
Serial.println("");
if (client.connect(server, port, true)) {
Serial.println("connecting to ");
Serial.print(server);
Serial.print(":");
Serial.println(port);
client.println("POST /api/v2/write?org=ORG_HERE&bucket=BUCKET_HERE&precision=s HTTP/1.1");
client.println("Host: https://eu-central-1-1.aws.cloud2.influxdata.com");
client.println("Authorization: Token <<TOKEN HERE>>");
client.println("Content-Type: text/plain");
client.print("Content-Length: ");
client.println(outputMSG.length());
client.println("Accept-Encoding: gzip, deflate, br");
client.println("Connection: keep-alive");
client.println();
client.println(outputMSG);
client.println();
lastConnectionTime = millis();
} else {
Serial.println("connection failed");
}
Could anyone help us understand why the post to aws is not going through?
Cheers,
Boy
I have a Teensy 4.1 sketch which uses the NativeEternet library. I am using the latest versions of TeensyDuino and NativeEthernet.
My program gets a static IP and runs without ANY problems. The program uses the watchdog to restart every 48 hours. And often it restarts and everything works well.
Every once in a while, the Teensy cannot be reached on the net.
When this happens and the Teensy restarts, it picks a "0.0.0.0" IP
Normally, when the board is not connected to the network, the code blocks and it never gets a static IP. So I do not know how it returns with IP = 0.0.0.0 ?
Disconnecting power and reconnecting does NOT solve the problem.
Leaving the board disconnected for a minute or so somehow fixes the issue and everything goes back to working normally.
Is this a hardware or a software problem?
Thanks.
I cannot get this library to work with the Pubsubclient library to connect to MQTT over ethernet. I used the example from pubsubclient and replace Ethernet.h with NativeEthernet.h. Is there anything more I need to do?
Other Ethernet functionality works ๐
In a scenario where I am handling a reconnect after the server restarts, I am starting a new client as follows:
EthernetClient client = EthernetClient();
client.connect(ip, port);
FDOS_LOG.printf("Ethernet client connect:%d\n", client.connected());
While this works perfectly the first time, the second time this client will never have bytes available() for reading. It does write properly (the remote server sees the data). Similar code works fine with the WifiClient (esp32 implementation).
Before creating the new client, I am calling .stop on the previous one.
when connecting top the server using a browser, it works fine untill it suddenly grinds to a halt and stops updating. After some searching, it seems the server halts for a while and then it starts running again. This behaviour results in lots of timeout errors
`
byte mac[] = {0x04, 0xe9, 0xe5, 0x0d, 0xd6, 0x4b};
IPAddress ip(10, 116, 114, 134); // IP address, may need to change depending on network
EthernetServer server(80); // create a server at port 80
EthernetClient client;
char HTTP_req[REQ_BUF_SZ] = {0}; // buffered HTTP request stored as null terminated string
char req_index = 0; // index into HTTP_req buffer
uint32_t ethping = 0;
String loc = "loop";
void ethernet_init() {
// start the Ethernet connection and the server:
Ethernet.begin(mac); // DHCP
//Ethernet.begin(mac,ip); // Static IP
// Check for Ethernet hardware present
if (Ethernet.hardwareStatus() == EthernetNoHardware) {
if (Serial)Serial.println("Ethernet shield was not found. Sorry, can't run without hardware. :(");
error_blink(ETHERNET_NO_HARDWARE);
do {
if (Serial)Serial.println("Please connect Ethernet shield");
error_blink();// do nothing, no point running without Ethernet hardware
}
while (Ethernet.hardwareStatus() == EthernetNoHardware);
error_blink(PULSE);
}
if (Ethernet.linkStatus() != LinkON) {
if (Serial)Serial.println("Ethernet cable is not connected.");
error_blink(ETHERNET_NO_CABLE);
do {
if (Serial)Serial.println("Please connect Ethernet cable");
error_blink();// do nothing, no point running without Ethernet cable
}
while (Ethernet.hardwareStatus() == LinkOFF);
error_blink(PULSE);
}
// start the server
server.begin();
if (Serial) {
Serial.print("server is at ");
Serial.println(Ethernet.localIP());
}
}
void ethernet_client() {
client = server.available(); // try to get client
if (client) { // got client?
boolean currentLineIsBlank = true;
if (Serial) Serial.println("Client");
while (client.connected()) {
loc = "ethc";
can0.events();
error_blink();
if (client.available()) { // client data available to read
char c = client.read(); // read 1 byte (character) from client
// limit the size of the stored received HTTP request
// buffer first part of HTTP request in HTTP_req array (string)
// leave last element in array as 0 to null terminate string (REQ_BUF_SZ - 1)
if (req_index < (REQ_BUF_SZ - 1)) {
HTTP_req[req_index] = c; // save HTTP request character
req_index++;
}
// last line of client request is blank and ends with \n
// respond to client only after last line received
if (c == '\n' && currentLineIsBlank) {
if (Serial) Serial.println("XML request");
loc = "ethx";
// send a standard http response header
client.println("HTTP/1.1 200 OK");
// remainder of header follows below, depending on if
// web page or XML page is requested
// Ajax request - send XML file
if (strstr(HTTP_req, "HVPC_inputs")) {
// send rest of HTTP header
client.println("Content-Type: text/xml");
client.println("Connection: keep-alive");
client.println();
Settings();
// send XML file containing input states
XML_response(client);
}
else { // web page request
if (Serial) Serial.println("Page request");
// send rest of HTTP header
client.println("Content-Type: text/html");
client.println("Connection: keep-alive");
client.println();
// send web page
File webFile = SD.open("index.htm"); // open web page file
if (webFile) {
error_blink(SENDING_FILE);
loc = "ethf";
char file_buffer[ETH_BUFFER_SIZE];
int avail;
while (avail = webFile.available()) {
int to_read = min(avail, ETH_BUFFER_SIZE);
if (to_read != webFile.read(file_buffer, to_read)) {
break;
}
client.write(file_buffer, to_read);
}
webFile.close();
error_blink(PULSE);
}
}
// display received HTTP request on serial port
if (Serial) Serial.println(HTTP_req);
// reset buffer index and all buffer elements to 0
req_index = 0;
StrClear(HTTP_req, REQ_BUF_SZ);
if (Serial) Serial.println("cleared");
break;
}
// every line of text received from the client ends with \r\n
if (c == '\n') {
// last character on line of received text
// starting new line with next character read
currentLineIsBlank = true;
}
else if (c != '\r') {
// a text character was received from client
currentLineIsBlank = false;
}
} // end if (client.available())
} // end while (client.connected())
delay(1); // give the web browser time to receive the data
client.stop(); // close the connection
client = 0;
Ethernet.maintain();
if (Serial)
{
Serial.println("Client stopped");
Serial.println();
Serial.print("server is at ");
Serial.println(Ethernet.localIP());
}
}
}
`
Hi!
In the FNET-TCP stack. In the file "fnet_tcp.c" in the function: "static fnet_bool_t _fnet_tcp_add_inpbuf( fnet_socket_if_t *sk, fnet_netbuf_t *insegment, fnet_flag_t *ackparam )", there are two lines which often cause Nullpointer exceptions...
/* If the temporary buffer received the lost segment
* move the data from the temporary buffer to the input buffer of the socket.*/
Line 1: if(FNET_TCP_COMP_GE(seq, fnet_ntohl(FNET_TCP_SEQ(cb->tcpcb_rcvchain)))) => Data Access Violation
Line 2: cb->tcpcb_count -= cb->tcpcb_rcvchain->total_length; => Data Access Violation
I tried the code without the whole "lost segment"-part and the lock-ups are gone, BUT: after a certain time... (after a few hours) i don't receive data anymore and no client can connect to the teensy anymore...
Sorry for my bad english,
Anyways thanks for your awesome library... it would be nice if this could be fixed, because otherwise it's all perfect for me! :)
First: Thank you very much for your excellent work!
Board: Teensy 4.1
IDE: Platformio
Latest version of NativeEthernet library
I successfully followed the example 'WebClientRepeatingTLS' and could read from the page 'pjrc.com/about/contact.html'.
However I was not successful to get rootCa verification working. Is it supported?
I downloaded the root certificate DST Root CA X3 in the base64 encoded form from pjrc.com.
const char *dst_root_ca =
"-----BEGIN CERTIFICATE-----\n"
"MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/\n"
"MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT\n"
"DkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVow\n"
"PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD\n"
"Ew5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB\n"
"AN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4O\n"
"rz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEq\n"
"OLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9b\n"
"xiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw\n"
"7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaD\n"
"aeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV\n"
"HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqG\n"
"SIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69\n"
"ikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXr\n"
"AvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZz\n"
"R8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5\n"
"JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo\n"
"Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ\n"
"-----END CERTIFICATE-----";
and entered the certificate through:
client.setCACert((char *)dst_root_ca, strlen(dst_root_ca));
But I got error messages:
Initialize Ethernet with DHCP:
DHCP assigned IP 192.168.1.102
You're connected to the network, IP = 192.168.1.102
TLS ca certificate error.
connecting...
HTTP/1.1 400 Bad Request
Date: Sun, 14 Mar 2021 18:10:08 GMT
Server: Apache/2.4.18 (Ubuntu)
Strict-Transport-Security: max-age=15552000
Cache-Control: stale-while-revalidate=30
Content-Length: 441
Connection: close
Content-Type: text/html; charset=iso-8859-1
Your browser sent a request that this server could not understand.
Reason: You're speaking plain HTTP to an SSL-enabled server port.
Instead use the HTTPS scheme to access this URL, please.
This function always seems to return the size
value, no matter what I pass in. If nothing's available, or something less than size
is available, it should return that number.
Is this function even intended to be called without first checking "socket-available" or some such, and then using that value for size
?
How fast can I expect Udp.parsePacket() to be? In this example code, I am parsing UDP packets and toggling a GPIO pin to see how fast the code runs IRL. The parsing takes 330nS. I expected (based on the clock speeds and the 100MBps interface) the speeds to be orders of magnitude higher... 330ns is around 550 clock cycles. I just want to know if there is something I can do to improve this or that the library is focused on compatibility, not performance. Thanks!
#include <NativeEthernet.h>
byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
IPAddress ip(192, 168, 1, 177);
unsigned int localPort = 6454; // local port to listen on
// buffers for receiving and sending data
#define UDP_TX_PACKET_MAX_SIZE 1480
unsigned char packetBuffer[UDP_TX_PACKET_MAX_SIZE]; // buffer to hold incoming packet,
char ReplyBuffer[] = "acknowledged"; // a string to send back
// An EthernetUDP instance to let us send and receive packets over UDP
EthernetUDP Udp;
const int PIN_0 = 38;
int packetSize = 0;
void setup() {
// noInterrupts();
teensyMAC(mac);
pinMode(PIN_0, OUTPUT);
Ethernet.begin(mac, ip);
Udp.begin(localPort);
}
void loop() {
while (1) {
digitalToggleFast(PIN_0);
//delayNanoseconds(1);
packetSize = Udp.parsePacket();
if (packetSize) {
Udp.read(packetBuffer, UDP_TX_PACKET_MAX_SIZE);
}
}
}
/*********************** teensyMAC *********************/
void teensyMAC(uint8_t *mac)
{
for (uint8_t by = 0; by < 2; by++) mac[by] = (HW_OCOTP_MAC1 >> ((1 - by) * 8)) & 0xFF;
for (uint8_t by = 0; by < 4; by++) mac[by + 2] = (HW_OCOTP_MAC0 >> ((3 - by) * 8)) & 0xFF;
}
I have so far used Arduino Mega2560 and Arduino Due + Ethernet shield when accessing devices on my local network. This worked well, but the performance of Teensy 4.1 is so much higher that I started to port some of my programs. Some of my programs read information from two Philips Hue Bridges. Scanning any of these two devices usually takes less than 50us (Teensy 4.1) but approx. once per hour (there is no fixed frequency to the event) Teensy's NativeEthernet reading of client.available()) take approx. 1700ms which is far too long for the rest of my program. I would rather like to interrupt these rare long processing or preferably like to start processing an incoming data stream whilst it is being received.
Therefore on Arduino Due I always put whilst( !client.available() && timeNow < maxTime) in front of the processing, which gave me the smallest wait time between if(client.connect(server,port)) and the begin of the processing or broke the processes after a given (too long waiting) time.
The following cut out of a test program shows the issue with client.available() in depth
unsigned long A_NOW=millis();
unsigned long StopWait=A_NOW+WaitTime;
while(StopWait > millis())
{
delayMicroseconds(10);
if(client.available()>0) {Serial.print("\tc.avail: "); Serial.print(client.available()); break;}
}
unsigned long B_NOW=millis();
if(B_NOW-A_NOW > 25)
{
Serial.print("\n\tLONG wait: B_NO-A_NOW="); Serial.println(B_NOW-A_NOW);
Serial.print(" WaitTime:"); Serial.println(WaitTime);
Serial.print(" StopWait:"); Serial.println(StopWait);
Serial.print(" A_NOW:"); Serial.println(A_NOW);
Serial.print(" B_NOW:"); Serial.println(B_NOW);
Serial.print(" millis:"); Serial.println(millis());
Serial.print("\tclient.available(): "); Serial.print(client.available());
}
The USB Serial output reads
c.avail: 2048
LONG wait: B_NO-A_NOW=1789
WaitTime:100
StopWait:95247
A_NOW:95147
B_NOW:96936 millis:96936
client.available(): 2048
I have also tried !client.available(), elapsedMillis && elapsedMicros and it produces the same behaviour. I successfully used Arduino Due so far and never saw such behaviour (but reading the HueBridge took far longer).
The process is not interrupted by any ISR and is not part of an ISR.
Is there anything I can do or is there anything I am doing wrong?
First of all thanks for your hard work!
When I run the basic WebServer example I start to get connection timeouts and resets if I push server even a bit.
I'm using Apache Benchmark to generate the load: ab -k -c 1 -n 20 http://192.168.1.177/
If I keep the -n
small things work as expected. With values bigger than 100 I will most of the time get either a connection reset from the server with apr_socket_recv: Connection reset by peer (54)
or the client times out after a while apr_pollset_poll: The timeout specified has expired (70007)
. When the Apache Benchmark is waiting for the response that never comes but has not timed out yet the website loads just fine I create a new connection for example using a browser.
I have tested pretty much the same code with Arduino Uno and the ESP8266 and ESP32 chips and I see no problems. This is why expect the problem not to be in my test setup. I also just updated the lib to the latest master. I also have the latest version of your FNET fork. My Teensyduino version is 1.5.3. I can also reproduce the same behaviour with other load testing tools. I have not tried another computer, network or ethernet chip or Teensy.
Adding client.close()
before client.stop()
did not improve the situation.
Have a nice weekend!
Code such as this silently fails to change the recv buf size, and incoming packets never arrive
// start UDP
Ethernet.setSocketSize(1620 * 3);
Udp.begin(T_PORT);
I looked at the code and found this:
void EthernetClass::setSocketSize(size_t _socket_size)
{
if(socket_size != 0) return;
socket_size = _socket_size;
}
This effectively disallows setting of the size unless the size is zero. No idea who sets the initial value, but it isn't zero when I call setSocketSize, and so my call has no effect. I doubt that is what was intended, but please let me know if I am missing something here. I changed the code to this:
void EthernetClass::setSocketSize(size_t _socket_size)
{
//if(socket_size != 0) return;
socket_size = _socket_size;
}
And now all is working fine for me. I think what you want here is something like (NOTE: I do not know where the actual max packet size is to be found. I just used a made up symbol MAX_MTU here...)
void EthernetClass::setSocketSize(size_t _socket_size)
{
if(_socket_size > MAX_MTU) _socket_size = MAX_MTU;
socket_size = _socket_size;
}
I found this:
#define UDP_TX_PACKET_MAX_SIZE 2048
but it is never used. In any case, I think programs should be allowed to set the recv buf size up to the actual limit of the physical transport, whatever that might be...
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.