arduino stuffs
Diffstat (limited to 'libraries/Ethernet/src/EthernetClient.cpp')
-rw-r--r--libraries/Ethernet/src/EthernetClient.cpp215
1 files changed, 215 insertions, 0 deletions
diff --git a/libraries/Ethernet/src/EthernetClient.cpp b/libraries/Ethernet/src/EthernetClient.cpp
new file mode 100644
index 0000000..e2406d7
--- /dev/null
+++ b/libraries/Ethernet/src/EthernetClient.cpp
@@ -0,0 +1,215 @@
+/* Copyright 2018 Paul Stoffregen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this
+ * software and associated documentation files (the "Software"), to deal in the Software
+ * without restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+ * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <Arduino.h>
+#include "Ethernet.h"
+#include "Dns.h"
+#include "utility/w5100.h"
+
+int EthernetClient::connect(const char * host, uint16_t port)
+{
+ DNSClient dns; // Look up the host first
+ IPAddress remote_addr;
+
+ if (sockindex < MAX_SOCK_NUM) {
+ if (Ethernet.socketStatus(sockindex) != SnSR::CLOSED) {
+ Ethernet.socketDisconnect(sockindex); // TODO: should we call stop()?
+ }
+ sockindex = MAX_SOCK_NUM;
+ }
+ dns.begin(Ethernet.dnsServerIP());
+ if (!dns.getHostByName(host, remote_addr)) return 0; // TODO: use _timeout
+ return connect(remote_addr, port);
+}
+
+int EthernetClient::connect(IPAddress ip, uint16_t port)
+{
+ if (sockindex < MAX_SOCK_NUM) {
+ if (Ethernet.socketStatus(sockindex) != SnSR::CLOSED) {
+ Ethernet.socketDisconnect(sockindex); // TODO: should we call stop()?
+ }
+ sockindex = MAX_SOCK_NUM;
+ }
+#if defined(ESP8266) || defined(ESP32)
+ if (ip == IPAddress((uint32_t)0) || ip == IPAddress(0xFFFFFFFFul)) return 0;
+#else
+ if (ip == IPAddress(0ul) || ip == IPAddress(0xFFFFFFFFul)) return 0;
+#endif
+ sockindex = Ethernet.socketBegin(SnMR::TCP, 0);
+ if (sockindex >= MAX_SOCK_NUM) return 0;
+ Ethernet.socketConnect(sockindex, rawIPAddress(ip), port);
+ uint32_t start = millis();
+ while (1) {
+ uint8_t stat = Ethernet.socketStatus(sockindex);
+ if (stat == SnSR::ESTABLISHED) return 1;
+ if (stat == SnSR::CLOSE_WAIT) return 1;
+ if (stat == SnSR::CLOSED) return 0;
+ if (millis() - start > _timeout) break;
+ delay(1);
+ }
+ Ethernet.socketClose(sockindex);
+ sockindex = MAX_SOCK_NUM;
+ return 0;
+}
+
+int EthernetClient::availableForWrite(void)
+{
+ if (sockindex >= MAX_SOCK_NUM) return 0;
+ return Ethernet.socketSendAvailable(sockindex);
+}
+
+size_t EthernetClient::write(uint8_t b)
+{
+ return write(&b, 1);
+}
+
+size_t EthernetClient::write(const uint8_t *buf, size_t size)
+{
+ if (sockindex >= MAX_SOCK_NUM) return 0;
+ if (Ethernet.socketSend(sockindex, buf, size)) return size;
+ setWriteError();
+ return 0;
+}
+
+int EthernetClient::available()
+{
+ if (sockindex >= MAX_SOCK_NUM) return 0;
+ return Ethernet.socketRecvAvailable(sockindex);
+ // TODO: do the Wiznet chips automatically retransmit TCP ACK
+ // packets if they are lost by the network? Someday this should
+ // be checked by a man-in-the-middle test which discards certain
+ // packets. If ACKs aren't resent, we would need to check for
+ // returning 0 here and after a timeout do another Sock_RECV
+ // command to cause the Wiznet chip to resend the ACK packet.
+}
+
+int EthernetClient::read(uint8_t *buf, size_t size)
+{
+ if (sockindex >= MAX_SOCK_NUM) return 0;
+ return Ethernet.socketRecv(sockindex, buf, size);
+}
+
+int EthernetClient::peek()
+{
+ if (sockindex >= MAX_SOCK_NUM) return -1;
+ if (!available()) return -1;
+ return Ethernet.socketPeek(sockindex);
+}
+
+int EthernetClient::read()
+{
+ uint8_t b;
+ if (Ethernet.socketRecv(sockindex, &b, 1) > 0) return b;
+ return -1;
+}
+
+void EthernetClient::flush()
+{
+ while (sockindex < MAX_SOCK_NUM) {
+ uint8_t stat = Ethernet.socketStatus(sockindex);
+ if (stat != SnSR::ESTABLISHED && stat != SnSR::CLOSE_WAIT) return;
+ if (Ethernet.socketSendAvailable(sockindex) >= W5100.SSIZE) return;
+ }
+}
+
+void EthernetClient::stop()
+{
+ if (sockindex >= MAX_SOCK_NUM) return;
+
+ // attempt to close the connection gracefully (send a FIN to other side)
+ Ethernet.socketDisconnect(sockindex);
+ unsigned long start = millis();
+
+ // wait up to a second for the connection to close
+ do {
+ if (Ethernet.socketStatus(sockindex) == SnSR::CLOSED) {
+ sockindex = MAX_SOCK_NUM;
+ return; // exit the loop
+ }
+ delay(1);
+ } while (millis() - start < _timeout);
+
+ // if it hasn't closed, close it forcefully
+ Ethernet.socketClose(sockindex);
+ sockindex = MAX_SOCK_NUM;
+}
+
+uint8_t EthernetClient::connected()
+{
+ if (sockindex >= MAX_SOCK_NUM) return 0;
+
+ uint8_t s = Ethernet.socketStatus(sockindex);
+ return !(s == SnSR::LISTEN || s == SnSR::CLOSED || s == SnSR::FIN_WAIT ||
+ (s == SnSR::CLOSE_WAIT && !available()));
+}
+
+uint8_t EthernetClient::status()
+{
+ if (sockindex >= MAX_SOCK_NUM) return SnSR::CLOSED;
+ return Ethernet.socketStatus(sockindex);
+}
+
+// the next function allows us to use the client returned by
+// EthernetServer::available() as the condition in an if-statement.
+bool EthernetClient::operator==(const EthernetClient& rhs)
+{
+ if (sockindex != rhs.sockindex) return false;
+ if (sockindex >= MAX_SOCK_NUM) return false;
+ if (rhs.sockindex >= MAX_SOCK_NUM) return false;
+ return true;
+}
+
+// https://github.com/per1234/EthernetMod
+// from: https://github.com/ntruchsess/Arduino-1/commit/937bce1a0bb2567f6d03b15df79525569377dabd
+uint16_t EthernetClient::localPort()
+{
+ if (sockindex >= MAX_SOCK_NUM) return 0;
+ uint16_t port;
+ SPI.beginTransaction(SPI_ETHERNET_SETTINGS);
+ port = W5100.readSnPORT(sockindex);
+ SPI.endTransaction();
+ return port;
+}
+
+// https://github.com/per1234/EthernetMod
+// returns the remote IP address: http://forum.arduino.cc/index.php?topic=82416.0
+IPAddress EthernetClient::remoteIP()
+{
+ if (sockindex >= MAX_SOCK_NUM) return IPAddress((uint32_t)0);
+ uint8_t remoteIParray[4];
+ SPI.beginTransaction(SPI_ETHERNET_SETTINGS);
+ W5100.readSnDIPR(sockindex, remoteIParray);
+ SPI.endTransaction();
+ return IPAddress(remoteIParray);
+}
+
+// https://github.com/per1234/EthernetMod
+// from: https://github.com/ntruchsess/Arduino-1/commit/ca37de4ba4ecbdb941f14ac1fe7dd40f3008af75
+uint16_t EthernetClient::remotePort()
+{
+ if (sockindex >= MAX_SOCK_NUM) return 0;
+ uint16_t port;
+ SPI.beginTransaction(SPI_ETHERNET_SETTINGS);
+ port = W5100.readSnDPORT(sockindex);
+ SPI.endTransaction();
+ return port;
+}
+
+