This document details the changes between each release.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
- The library now, by default, puts the RX and TX buffers in RAM2 (DMAMEM).
This behaviour can be overridden by defining the new
QNETHERNET_BUFFERS_IN_RAM1
macro. - Added separate
stderr
output support with the newstderrPrint
variable. If set to NULL,stderr
defaults to the usualstdPrint
. - Added
MDNSClass::operator bool()
for determining whether mDNS has been started. - Added
MDNSClass::restart()
for when a cable has been disconnected for a while and then reconnected. - Added
EthernetFrameClass::setReceiveQueueSize(size)
for setting the receive queue size. This replaces theQNETHERNET_FRAME_QUEUE_SIZE
macro. - Added a way to disable raw frame support: define the new
QNETHERNET_DISABLE_RAW_FRAME_SUPPORT
macro. - Added a "Complete list of features" section to the README.
- Added
MDNSClass::hostname()
for returning the hostname of the responder, if running. - Added
EthernetUDP::operator bool()
. - Added an already-started check to
MDNSClass
. - New section in the README: "
operator bool()
andexplicit
". It addresses problems that may arise withexplicit operator bool()
. - Added
EthernetClient::connectionId()
for identifying connections across possibly multipleEthernetClient
objects. - Added
EthernetClass::isDHCPActive()
.
- Improved error code messages in
lwip_strerr(err)
. This is used whenLWIP_DEBUG
is defined. - Now shutting down mDNS too in
EthernetClass::end()
. - Now using overloads instead of default arguments in
EthernetClass
andEthernetUDP
. - Changed
EthernetClass
andMDNSClass
String
functions to takeconst char *
instead. - Made all
operator bool()
functionsexplicit
. See: https://en.cppreference.com/w/cpp/language/implicit_conversion#The_safe_bool_problem MDNSClass::removeService()
now returnsfalse
instead oftrue
if mDNS has not been started.- Enable definition of certain macros in
lwipopts.h
from the command line. - Changed API uses of
unsigned char
touint8_t
, for consistency.
- Removed the
QNETHERNET_FRAME_QUEUE_SIZE
macro and replaced it withEthernetFrame.setReceiveQueueSize(size)
.
- Disallow
stdin
in_write()
.
EthernetUDP::size()
: Returns the total size of the received packet data.- Added an optional "dns" parameter to the three-parameter Ethernet.begin() that defaults to unset. This ensures that the DNS server IP is set before the address-changed callback is called.
- Added configurable packet buffering to UDP reception with the new
EthernetUDP(queueSize)
constructor. The default and minimum queue size is 1. - Added configurable frame buffering to raw frame reception with the new
QNETHERNET_FRAME_QUEUE_SIZE
macro. Its default is 1. - Added a new "Configuration macros" section to the README that summarizes all the configuration macros.
- Changed
EthernetUDP::parsePacket()
to return zero for empty packets and -1 if nothing is available.
- Added a way to enable promiscuous mode: define the
QNETHERNET_PROMISCUOUS_MODE
macro. - Added a way to remove all the mDNS code: set
LWIP_MDNS_RESPONDER
to0
inlwipopts.h
. - Added support for ".local" name lookups.
- Added the ability, in the mDNS client, to specify a service name that's different from the host name.
- Added
EthernetClient::abort()
for killing connections without going through the TCP close process. - New sections in the README:
- "How to change the number of sockets", and
- "On connections that hang around after cable disconnect".
- An
EthernetServer
instance can now be created without setting the port. There are two newbegin()
functions for setting the port:begin(port)
begin(port, reuse)
- Moved CRC-32 lookup table to PROGMEM.
- Changed in
EthernetServer
:port()
returns anint32_t
instead of auint16_t
so that -1 can represent an unset port; non-negative values are still 16-bit quantitiesbegin(reuse)
now returns abool
instead ofvoid
, indicating success- The
EthernetServer
destructor now callsend()
- Removed some unneeded network interfaces:
- IEEE 802.1D MAC Bridge
- 6LowPAN
- PPP
- SLIP
- ZigBee Encapsulation Protocol
- Removed HTTPD options from
lwipopts.h
.
- Added a
util::StdioPrint
class, aPrint
decorator for stdio output files. It routesPrint
functions to a specificFILE*
. This exists mainly to make it easy to usePrintable
objects without needing a prior call tofflush()
. - Added
MDNSClass::maxServices()
. - Added
operator==()
andoperator!=()
operators forconst IPAddress
. They are in the usual namespace. These allow==
to be used withconst IPAddress
values without having to useconst_cast
, and also introduce the completely missing!=
operator. - Added a way to declare the
_write()
function as weak via a newQNETHERNET_WEAK_WRITE
macro. Defining this macro will cause the function to be declared as weak. - Implemented
EthernetFrameClass::availableForWrite()
. - Added size limiting to
EthernetFrameClass
write functions. - New
EthernetClass::waitForLink(timeout)
function that waits for a link to be detected. - Added a way to allow or disallow receiving frames addressed to specific MAC
addresses:
EthernetClass::setMACAddressAllowed(mac, flag)
- Updated
SNTPClient
example to useEthernetUDP::send()
instead ofbeginPacket()
/write()
/endPacket()
. - Updated
PixelPusherServer
example to use the frame average for the update period. - Implemented
EthernetHardwareStatus
enum for the deprecatedEthernet.hardwareStatus()
function. This replaces the zero return value with the new non-zeroEthernetOtherHardware
. - Cleaned up how internal IP addresses are used.
- Changed
_write()
(stdio) to do nothing if the requested length is zero because that's whatfwrite()
is specified to do. - Updated examples to use new
operator!=()
forIPAddress
. - Moved lwIP's heap to RAM2 (DMAMEM).
- Updated
EthernetFrame
-related documentation to explain that the API doesn't receive any known Ethernet frame types, including IPv4, ARP, and IPv6 (if enabled). - Clarified in the examples that
Ethernet.macAddress()
retrieves, not sets. - Changed
EthernetClass::setMACAddress(mac)
parameter toconst
. - Moved CRC-32 lookup table to RAM2 (DMAMEM).
- Made const those functions which could be made const.
- Updated examples and README to consider listeners and their relationship with a static IP and link detection.
- Fixed
EthernetUDP::send()
function to take the host and port as arguments, per its description. There's now two of them: one that takes anIPAddress
and another that takes achar *
hostname. - Fixed
enet_output_frame()
to correctly returnfalse
if Ethernet is not initialized. - Fixed not being able to set the DNS server IP before starting Ethernet.
- Fixed raw frame API to consider any padding bytes.
EthernetFrame
convenience functions that also write the header:beginFrame(dstAddr, srcAddr, typeOrLen)
beginVLANFrame(dstAddr, srcAddr, vlanInfo, typeOrLen)
qindesign::network::util
Print utility functions. Thebreakf
function parameter is used as the stopping condition inwriteFully()
.writeFully(Print &, buf, size, breakf = nullptr)
writeMagic(Print &, mac, breakf = nullptr)
enet_deinit()
now gracefully stops any transmission in progress before shutting down Ethernet.EthernetClass
functions:linkIsFullDuplex()
: Returns whether the link is full duplex (true
) or half duplex (false
).broadcastIP()
: Returns the broadcast IP address associated with the current local IP and subnet mask.
- Functions that return a pointer to the received data:
EthernetUDP::data()
EthernetFrame::data()
DNSClient::getServer(index)
function for retrieving a specific DNS server address.EthernetUDP::localPort()
: Returns the port to which the socket is bound.- Three new examples:
IPerfServer
OSCPrinter
PixelPusherServer
- The
EthernetClient::writeFully()
functions were changed to return the number of bytes actually written. These can break early if the connection was closed while attempting to send the bytes. - Changed
EthernetClient::writeFully()
functions to use the newwriteFully()
Print utility function. - Changed the
Ethernet
object to be a reference to a singleton. This matches how theEthernetFrame
object works. - Changed the
read(buf, len)
functions to allow a NULL buffer so that the caller can skip data without having to read into a buffer. - Moved internal classes and structs into an "internal" namespace to avoid any potential contflicts with user declarations.
- Removed IEEE 1588 initialization and timer read.
- Fixed
EthernetClient::availableForWrite()
to re-check the state after the call toEthernetClass::loop()
.
- Added a way to disable and enable Nagle's algorithm. The new functions are
EthernetClient::setNoDelay(flag)
andisNoDelay()
. - Implemented
EthernetServer::availableForWrite()
as the minimum availability of all the connections, or zero if there's no connections. - New
AppWithListenersTemplate
example. - Added
EthernetClass::operator bool()
for testing whether Ethernet is initialized. - Added a new way to send and receive raw Ethernet frames. There's a new
EthernetFrame
instance (ofEthernetFrameClass
) that is used similarly toEthernetUDP
. - New
RawFrameMonitor
example. - New
EthernetUDP::send(data, len)
function for sending a packet without having to usebeginPacket()
/write()
/endPacket()
. It causes less overhead.
- Changed
EthernetUDP::flush()
to be a no-op. - Reduced lwIP's
MEM_SIZE
to 16KiB from 24000. - Split
MDNSClass::addService()
into two overloaded functions: one with three arguments and one with four. No more defaulted TXT record function parameter; the three-argument version calls the four-argument version with NULL for that function. - Updated
keywords.txt
. - Updated
SNTPClient
example: Removed unneeded includes, made the packet buffer a global variable, and added setting the RTC and time. - Changed
EthernetClass::mtu()
tostatic size_t
. It was non-static andint
. - Updated
enet_output_frame(frame, len)
to check if the system is initialized.
- Removed
EthernetClass::sendRaw(frame, len)
because there's a newEthernetFrame
API with asend(frame, len)
function.
- Fixed the length check when sending raw Ethernet frames to exclude the FCS field. It checks that the length is in the range 60-1518 instead of 64-1522.
- Fixed
check_link_status()
to check if Ethernet is initialized before trying to access the PHY.
- Implemented
EthernetClass::setMACAddress(mac)
. - Added
EthernetServer::maxListeners()
,EthernetClient::maxSockets()
, andEthernetUDP::maxSockets()
so user code doesn't need to guess. These areconstexpr
functions that return the compile-time constants from the lwIP configuration. - Added
EthernetServer::port()
for returning the server's port. - Added
EthernetClass::setHostname(hostname)
andhostname()
for setting and getting the DHCP client option 12 hostname. - Added
EthernetClass::maxMulticastGroups()
constexpr
function. - Added a "Write immediacy" subsection to the README that addresses when data is sent over a connection. It's under the "How to write data to connections" section.
- Changed the default DHCP client option 12 hostname to "teensy-lwip".
- Stop the DHCP client when restarting
Ethernet
(inbegin(ip, mask, gateway)
andsetMACAddress(mac)
) to ensure that a static IP won't get overwritten by any previously running DHCP client. This also obviates the need to callEthernet.end()
before re-callingbegin
.
- Added a way to send raw Ethernet frames. The new function
is
EthernetClass::sendRaw(frame, len)
. - Added new sections to the README:
- "Sending raw Ethernet frames", and
- "How to implement VLAN tagging".
- Added calls to
loop()
inEthernetClient::connected()
andoperator bool()
. - Added
EthernetUDP::beginMulticast(ip, localPort, reuse)
, wherereuse
controls the SO_REUSEADDR socket option. - Added
EthernetClass::joinGroup(ip)
andleaveGroup(ip)
for joining and leaving a multicast group. - Added a "How to use multicast" section to the README.
- Changed
kMTU
type to besize_t
everywhere. - Added
stdPrint
as anextern
variable toQNEthernet.h
and moved it to theqindesign::network
namespace. - Changed transmit data buffers to be 64-byte aligned, for
"optimal performance".
See: IMXRT1060RM_rev2.pdf, "Table 41-38. Enhanced transmit buffer descriptor field definitions", page 2186. - Updated lwIP to v2.1.3.
- Changed
EthernetUDP::beginMulticast
to release resources if joining the group failed. - Increased MEMP_NUM_IGMP_GROUP to 9 to allow 8 multicast groups.
- Removed mention of the need to re-announce mDNS and adjusted the docs accordingly.
- Changed receive data buffers to be 64-byte aligned.
See: IMXRT1060RM_rev2.pdf, "Table 41-36. Receive buffer descriptor field definitions", page 2183. - Changed TA value in ENET_MMFR register to 2, per the chip docs.
- Multicast reception now works. Had to set the ENET_GAUR and ENET_GALR registers appropriately.
- Added example that uses
client.writeFully()
to the "How to write data to connections" README section. - Added
EthernetClient::close()
for closing a connection without waiting. It's similar tostop()
. - Added
DNSClient
class for interfacing with lwIP's DNS functions. - Added a "DNS" section to the README.
- Renamed the "How to write data to clients" README section to "How to write data to connections".
- Increased the maximum number of UDP sockets to 8.
- Updated
EthernetClass
,EthernetClient
, andEthernetUDP
to use the newDNSClient
class for DNS lookup and DNS server address setting.
- Added a check that
Entropy
has already been initialized before callingEntropy.Initialize()
. - Added a "How to write data to clients" section to the README that addresses how to fully send data to clients.
- Added
EthernetClient::writeFully()
functions that might help address problems with fully writing data to clients. - Added a new "Additional functions not in the Arduino API" section to the README.
- Added
EthernetClient::closeOutput()
for performing a half close on the client connection.
- Updated the
ServerWithAddressListener
example. It's more complete and could be used as a rudimentary basis for a complete server program.- Added a "Content-Type" header to the response,
- It now looks for an empty line before sending the response to the client,
- Added the ability to use a static IP,
- Added client and shutdown timeouts, and
- Added a list to the description at the top describing some additional things the program demonstrates.
- In
EthernetClass::end()
, moved setting the DNS to 0 to before DHCP is released. This ensures that any address-changed events happen after this. i.e. the DNS address will be 0 when an address-changed event happens.
- The Boolean-valued link state is now
EthernetClass::linkState()
. - Added a
_write()
definition so thatprintf
works and sends its output toSerial
. Parts of lwIP may useprintf
. This directs output to a newPrint *stdPrint
variable. It has a default of NULL, so there will be no output if not set by user code. - Now powering down the PHY in
enet_deinit()
. - Added calls to
loop()
inEthernetServer::accept()
andavailable()
to help avoid having to have the caller remember to call loop() if checking connectivity in a loop. - Added a call to
end()
in theQNMDNS
destructor. - Added a new externally-available
Print *stdPrint
variable forprintf
output, both for lwIP and optionally for user code. - Added the ability to set the SO_REUSEADDR socket option when listening on a port (both TCP and UDP).
- Added four examples and a "note on the examples" section in the README.
- FixedWidthServer
- LengthWidthServer
- ServerWithAddressListener
- SNTPClient
EthernetClass::linkStatus()
now returns anEthernetLinkStatus
enum. The Boolean version is nowEthernetClass::linkState()
.- The
EthernetLinkStatus
enum is no longer marked as deprecated. - Updated
EthernetClient
output functions to flush data when the send buffer is full and to always callloop()
before returning. This should obviate the need to callflush()
after writes and the need to callloop()
if writing in a loop. (flush()
is still useful, however, when you've finished sending a "section" of data.) - Changed
EthernetUDP::parsePacket()
to always callloop()
.
- Restarting
Ethernet
(viabegin()
or viaend()
/begin()
) now works properly. DHCP can now re-acquire an IP address. Something's weird aboutEventResponder
. It doesn't look like it's possible todetach()
thenattach()
, or callattach()
more than once. - Fixed
QNMDNS
to only callmdns_resp_init()
once. There's no corresponding "deinit" call.
- Added a new "survey of how connections work" section to the README.
- Added low-level link receive error stats collection.
- Now calling
EthernetClass::loop()
inEthernetUDP::parsePacket()
when it returns zero so that calls in a loop will move the stack forward. - Added
EthernetLinkStatus
enum (marked as deprecated) for compatibility with the Arduino API. Note thatEthernetClass::linkStatus()
is staying as abool
; comparison with the enumerators will work correctly. - Now sending a DHCPINFORM message to the network when using a manual IP configuration.
- Changed
EthernetClass::loop()
to bestatic
. - Changed all the internal "
yield()
to move the stack along" calls toEthernetClass::loop()
. Note that the calls withinwhile
loops in the external API functions were not changed.
- Fixed the driver to add and remove netif ext callback at the correct places. This solves the freeze problem when ending Ethernet, however when restarting, DHCP isn't able to get an IP address.
- Added a "Code style" section to the README.
- Added link-status and address-changed callbacks.
- New
EthernetServer::end()
function to stop listening. - Disabling the PLL before disabling the clock in
enet_deinit()
. This still doesn't solve the freeze problem when this function is called. - New
EthernetClass::linkSpeed()
function, used asEthernet.linkSpeed()
. It returns the link speed in Mbps.
- Changed all the delays to yields because
delay()
just loops and callsyield()
anyway. - No longer looping when checking the TCP send buffer in the client write
functions. Instead, just using an
if
. - The client now takes more opportunities to set the internal connection pointer
to NULL, meaning the caller doesn't necessarily need to guarantee they call
stop()
if other I/O functions are being used to check state or to write, for example. - Moved adding the netif callback to
enet_init()
so that the callback still gets an address-changed notification when setting a static address.
- Fixed client functions to also check for connected status.
- Fixed client
read()
andpeek()
to return -1 on no connection. - Added potential flushing in
EthernetClient::availableForWrite()
. This keeps things moving along if it always would return zero. - A listening server is now correctly added to the internal listening list. This
fixes
EthernetServer::operator bool()
.
- This CHANGELOG.
- Instructions in the README for how to use with Arduino.
- Added the ability to add TXT items to mDNS services.
- New
EthernetClass::waitForLocalIP(timeout)
function that waits for a DHCP-assigned address. - Added the ability to re-announce mDNS services. This is useful to prevent the entries from disappearing.
- Added mDNS notes to the README.
- Updated lwIP to v2.1.3-rc1.
- Moved global objects (
Ethernet
andMDNS
) into theqindesign::network
namespace.
- UDP multicast address check was checking the wrong byte.
- UDP multicast now IGMP joins the group.
- Updated lwIP to the "real" v2.1.2 release.
- The library now works with Arduino.
EthernetUDP::endPacket()
was usingnullptr
for the pbuf.EthernetUDP::beginPacket()
was not setting the output port.
- Small delays in
EthernetClient
output functions to allow data to flush. This allows user programs to avoid having to callyield()
themselves. - Flushing the output before closing the connection in
EthernetClient::stop()
. - Global Arduino-style
MDNS
object and a rename of the class toMDNSClass
. yield()
calls in theEthernetClient
input functions to allow user programs to avoid having to callyield()
themselves.
- Brought
Print::write
functions into scope for Client, Server, and UDP by using ausing Print::write
directive. - New centralized connection management.
- Removed all the atomic fences.
- Fixed
EthernetClass::begin()
return value; it was the opposite.
- Initial release.
Copyright (c) 2021-2022 Shawn Silverman