216 static IPStack *stack =
nullptr;
245 uint32_t timeoutMs = 5000) {
246 if (result.fromString(host))
return true;
247 if (!
ipIsUp())
return false;
248 for (
int n = 0; n < 2; n++) {
250 if (server == 0)
continue;
251 if (dnsQuery(server, host, timeoutMs / 2, result))
return true;
263 if (s < 0)
return -1;
264 TCPSocket &t = _tcp[s];
267 t.localPort = ephemeralPort();
271 uint32_t start = millis();
273 if (millis() - start >= timeoutMs) {
290 !_tcp[s].orphan && _tcp[s].gen == gen;
293 uint8_t
tcpGen(
int s)
const {
return _tcp[s].gen; }
306 return (
int)_tcp[s].rx.available();
312 return _tcp[s].rx.peek();
316 int tcpRead(
int s, uint8_t *data,
size_t len) {
318 TCPSocket &t = _tcp[s];
319 size_t n = t.rx.read(data, len);
320 if (n > 0) windowUpdate(t);
325 size_t tcpWrite(
int s,
const uint8_t *data,
size_t len, uint32_t timeoutMs) {
326 TCPSocket &t = _tcp[s];
329 uint32_t start = millis();
332 if (!t.inUse || t.gen != gen || !canSend(t))
break;
333 size_t n = t.tx.write(data + done, len - done);
339 if (millis() - start >= timeoutMs)
break;
348 TCPSocket &t = _tcp[s];
350 uint32_t start = millis();
351 while (t.inUse && t.gen == gen && t.tx.available() > 0 && canSend(t) &&
352 millis() - start < timeoutMs) {
360 TCPSocket &t = _tcp[s];
380 uint32_t start = millis();
381 while (t.inUse && t.gen == gen && millis() - start < timeoutMs &&
386 if (!t.inUse || t.gen != gen)
return;
397 for (
auto &l : _listeners)
398 if (l == port)
return true;
399 for (
auto &l : _listeners) {
410 for (
auto &l : _listeners)
411 if (l == port) l = 0;
419 TCPSocket &t = _tcp[i];
420 if (!t.inUse || t.orphan || t.localPort != port)
continue;
423 if (t.rx.available() == 0)
continue;
424 }
else if (t.accepted) {
434 size_t tcpWriteAll(uint16_t port,
const uint8_t *data,
size_t len,
435 uint32_t timeoutMs) {
438 TCPSocket &t = _tcp[i];
439 if (t.inUse && !t.orphan && t.accepted && t.localPort == port &&
441 result =
tcpWrite(i, data, len, timeoutMs);
450 if (port == 0) port = ephemeralPort();
452 if (_udp[i].inUse && _udp[i].localPort == port)
return -1;
455 UDPSocket &u = _udp[i];
469 _udp[s].inUse =
false;
471 _udp[s].rxRemaining = 0;
481 return sendUdp(_udp[s].localPort, ip, port, data, len);
487 UDPSocket &u = _udp[s];
488 u.rx.discard(u.rxRemaining);
490 if (u.rx.available() < 8)
return 0;
494 port = get16(hdr + 4);
495 u.rxRemaining = get16(hdr + 6);
496 return (
int)u.rxRemaining;
503 int udpRead(
int s, uint8_t *data,
size_t len) {
504 UDPSocket &u = _udp[s];
505 if (len > u.rxRemaining) len = u.rxRemaining;
506 size_t n = u.rx.read(data, len);
513 return _udp[s].rxRemaining > 0 ? _udp[s].rx.peek() : -1;
518 UDPSocket &u = _udp[s];
519 u.rx.discard(u.rxRemaining);
529 virtual void ipWrite(
const uint8_t *data,
size_t len) = 0;
542 bool ipInput(
const uint8_t *data,
size_t len,
bool reply =
true) {
543 if (len < 20 || (data[0] >> 4) != 4)
return false;
544 size_t ihl = (data[0] & 0x0F) * 4;
545 size_t total = get16(data + 2);
546 if (ihl < 20 || total > len || total < ihl)
return false;
548 memcpy(&dst, data + 16, 4);
549 if (dst !=
ipLocal())
return false;
550 if ((get16(data + 6) & 0x3FFF) != 0)
return false;
553 if (c.
result() != 0)
return false;
555 memcpy(&src, data + 12, 4);
556 const uint8_t *payload = data + ihl;
557 size_t plen = total - ihl;
560 return icmpInput(data, total, ihl);
562 return udpInput(src, dst, payload, plen);
564 return tcpInput(src, dst, payload, plen, reply);
572 for (
auto &t : _tcp) {
573 if (!t.inUse)
continue;
576 if (t.orphan || !t.accepted) freeTcp(t);
584 bool accepted =
false;
585 bool ackPending =
false;
586 bool finQueued =
false;
587 bool finSent =
false;
591 uint16_t localPort = 0;
592 uint16_t remotePort = 0;
603 uint32_t deadline = 0;
610 uint16_t localPort = 0;
611 size_t rxRemaining = 0;
613 RingBuffer<TINYPPP_UDP_RX_BUFFER> rx;
619 uint16_t _nextPort = 0;
622 bool _inPoll =
false;
624 void *_idleRef =
nullptr;
627 uint16_t _dnsPort = 0;
629 bool _dnsDone =
false;
630 ip4_t _dnsResult = 0;
632 static uint16_t get16(
const uint8_t *p) {
633 return (uint16_t)((p[0] << 8) | p[1]);
635 static uint32_t get32(
const uint8_t *p) {
636 return (uint32_t)p[0] << 24 | (uint32_t)p[1] << 16 | (uint32_t)p[2] << 8 |
639 static void put16(uint8_t *p, uint16_t v) {
643 static void put32(uint8_t *p, uint32_t v) {
645 p[1] = (v >> 16) & 0xFF;
646 p[2] = (v >> 8) & 0xFF;
650 static bool seqLT(uint32_t a, uint32_t b) {
return (int32_t)(a - b) < 0; }
651 static bool seqGT(uint32_t a, uint32_t b) {
return (int32_t)(a - b) > 0; }
654 if (_idle) _idle(_idleRef);
659 uint16_t ephemeralPort() {
660 if (_nextPort == 0) _nextPort = 49152 + (uint16_t)(random(16000));
661 for (
int tries = 0; tries < 100; tries++) {
662 uint16_t p = _nextPort++;
663 if (_nextPort < 49152) _nextPort = 49152;
664 if (!portInUse(p))
return p;
669 bool portInUse(uint16_t port)
const {
670 for (
const auto &t : _tcp)
671 if (t.inUse && t.localPort == port) return true;
672 for (
const auto &u : _udp)
673 if (u.inUse && u.localPort == port) return true;
674 return port == _dnsPort;
677 bool listening(uint16_t port)
const {
678 for (
auto l : _listeners)
679 if (l != 0 && l == port) return true;
687 bool sendIP(uint8_t proto,
ip4_t dst,
const uint8_t *hdr,
size_t hdrLen,
688 const uint8_t *d1,
size_t n1,
const uint8_t *d2 =
nullptr,
693 put16(ip + 2, (uint16_t)(20 + hdrLen + n1 + n2));
694 put16(ip + 4, _ipId++);
695 put16(ip + 6, 0x4000);
700 memcpy(ip + 12, &src, 4);
701 memcpy(ip + 16, &dst, 4);
704 put16(ip + 10, c.result());
713 void pseudoHeader(Checksum &c, uint8_t proto,
ip4_t src,
ip4_t dst,
715 c.add((
const uint8_t *)&src, 4);
716 c.add((
const uint8_t *)&dst, 4);
718 c.add16((uint16_t)len);
723 bool icmpInput(
const uint8_t *data,
size_t total,
size_t ihl) {
724 if (total < ihl + 8 || data[ihl] != 8)
return false;
725 if (!_ping)
return false;
726 const uint8_t *icmp = data + ihl;
727 size_t len = total - ihl;
730 if (c.result() != 0)
return true;
732 uint8_t hdr[4] = {0, 0, 0, 0};
735 r.add(icmp + 4, len - 4);
736 put16(hdr + 2, r.result());
738 memcpy(&src, data + 12, 4);
739 sendIP(
IP_ICMP, src, hdr, 4, icmp + 4, len - 4);
745 bool sendUdp(uint16_t srcPort,
ip4_t dst, uint16_t dstPort,
746 const uint8_t *data,
size_t len) {
750 put16(hdr + 2, dstPort);
751 put16(hdr + 4, (uint16_t)(len + 8));
757 uint16_t sum = c.result();
758 put16(hdr + 6, sum == 0 ? 0xFFFF : sum);
759 return sendIP(
IP_UDP, dst, hdr, 8, data, len);
762 bool udpInput(
ip4_t src,
ip4_t dst,
const uint8_t *p,
size_t len) {
763 if (len < 8)
return false;
764 size_t ulen = get16(p + 4);
765 if (ulen < 8 || ulen > len)
return false;
766 if (get16(p + 6) != 0) {
768 pseudoHeader(c,
IP_UDP, src, dst, ulen);
770 if (c.result() != 0)
return true;
772 uint16_t srcPort = get16(p);
773 uint16_t dstPort = get16(p + 2);
774 const uint8_t *data = p + 8;
775 size_t dlen = ulen - 8;
776 if (_dnsPort != 0 && dstPort == _dnsPort) {
777 dnsInput(data, dlen);
780 for (
auto &u : _udp) {
781 if (!u.inUse || u.localPort != dstPort)
continue;
782 if (u.rx.free() >= dlen + 8) {
784 memcpy(hdr, &src, 4);
785 put16(hdr + 4, srcPort);
786 put16(hdr + 6, (uint16_t)dlen);
788 u.rx.write(data, dlen);
797 bool dnsQuery(
ip4_t server,
const char *host, uint32_t timeoutMs,
801 _dnsId = (uint16_t)random(0xFFFF);
803 put16(q + 2, 0x0100);
807 const char *label = host;
809 const char *dot = strchr(label,
'.');
810 size_t l = dot ? (size_t)(dot - label) : strlen(label);
811 if (l == 0 || l > 63 || n + l + 6 >
sizeof(q))
return false;
813 memcpy(q + n, label, l);
816 if (*label ==
'.') label++;
823 _dnsPort = ephemeralPort();
827 uint32_t start = millis();
829 while (millis() - start < timeoutMs) {
830 if (sent == 0 || millis() - sent >= 1000) {
831 sendUdp(_dnsPort, server, 53, q, n);
833 if (sent == 0) sent = 1;
837 ok = _dnsResult != 0;
843 const uint8_t *b = (
const uint8_t *)&_dnsResult;
844 result = IPAddress(b[0], b[1], b[2], b[3]);
850 static size_t dnsSkipName(
const uint8_t *p,
size_t len,
size_t pos) {
853 if (l == 0)
return pos + 1;
854 if ((l & 0xC0) == 0xC0)
return pos + 2;
860 void dnsInput(
const uint8_t *p,
size_t len) {
861 if (len < 12 || get16(p) != _dnsId || !(p[2] & 0x80))
return;
863 if ((p[3] & 0x0F) != 0)
return;
864 size_t qd = get16(p + 4), an = get16(p + 6);
866 for (
size_t i = 0; i < qd; i++) {
867 pos = dnsSkipName(p, len, pos);
868 if (pos == 0)
return;
871 for (
size_t i = 0; i < an; i++) {
872 pos = dnsSkipName(p, len, pos);
873 if (pos == 0 || pos + 10 > len)
return;
874 uint16_t type = get16(p + pos), cls = get16(p + pos + 2);
875 size_t rdlen = get16(p + pos + 8);
877 if (pos + rdlen > len)
return;
878 if (type == 1 && cls == 1 && rdlen == 4) {
879 memcpy(&_dnsResult, p + pos, 4);
891 if (!_tcp[i].inUse) found = i;
896 if (_tcp[i].orphan) {
901 if (found < 0)
return -1;
902 TCPSocket &t = _tcp[found];
903 uint8_t gen = t.gen + 1;
905 t.orphan = t.accepted = t.ackPending = t.finQueued = t.finSent =
false;
911 t.iss = (uint32_t)micros() * 2654435761u ^ (uint32_t)random(0x7FFFFFFF);
913 t.sndNxt = t.iss + 1;
916 uint16_t mtu =
ipMtu();
917 t.mss = mtu > 40 ? mtu - 40 : 536;
919 t.timer = t.deadline = 0;
924 void freeTcp(TCPSocket &t) {
928 t.timer = t.deadline = 0;
933 static bool canSend(
const TCPSocket &t) {
939 uint16_t window(TCPSocket &t) {
940 size_t w = t.rx.free();
941 if (w > 0xFFFF) w = 0xFFFF;
942 t.advWnd = (uint16_t)w;
947 uint16_t rcvMss()
const {
948 uint16_t mtu =
ipMtu();
949 uint16_t mss = mtu > 40 ? mtu - 40 : 536;
955 bool sendSegment(TCPSocket &t, uint32_t seq, uint8_t flags,
size_t offset,
957 const uint8_t *p1 =
nullptr, *p2 =
nullptr;
958 size_t n1 = len > 0 ? t.tx.contiguous(offset, len, p1) : 0;
959 size_t n2 = n1 < len ? t.tx.contiguous(offset + n1, len - n1, p2) : 0;
960 if (n1 + n2 != len)
return false;
961 t.ackPending =
false;
962 return sendTcp(t.localPort, t.remotePort, t.remoteIP, seq, t.rcvNxt, flags,
963 window(t), p1, n1, p2, n2);
966 bool sendTcp(uint16_t localPort, uint16_t remotePort,
ip4_t remoteIP,
967 uint32_t seq, uint32_t ack, uint8_t flags, uint16_t wnd,
968 const uint8_t *p1 =
nullptr,
size_t n1 = 0,
969 const uint8_t *p2 =
nullptr,
size_t n2 = 0) {
971 size_t hlen = (flags &
TCP_SYN) ? 24 : 20;
972 put16(hdr, localPort);
973 put16(hdr + 2, remotePort);
975 put32(hdr + 8, (flags &
TCP_ACK) ? ack : 0);
976 hdr[12] = (uint8_t)((hlen / 4) << 4);
978 put16(hdr + 14, wnd);
984 put16(hdr + 22, rcvMss());
987 pseudoHeader(c,
IP_TCP,
ipLocal(), remoteIP, hlen + n1 + n2);
989 if (n1) c.add(p1, n1);
990 if (n2) c.add(p2, n2);
991 put16(hdr + 16, c.result());
992 return sendIP(
IP_TCP, remoteIP, hdr, hlen, p1, n1, p2, n2);
995 void armTimer(TCPSocket &t) {
996 t.timer = millis() + t.rto;
997 if (t.timer == 0) t.timer = 1;
1000 void sendSyn(TCPSocket &t) {
1003 sendSegment(t, t.iss, flags, 0, 0);
1007 void sendAck(TCPSocket &t) { sendSegment(t, t.sndNxt,
TCP_ACK, 0, 0); }
1009 void sendReset(TCPSocket &t) {
1015 void replyReset(
ip4_t src,
const uint8_t *p,
size_t segLen) {
1016 uint8_t flags = p[13];
1019 sendTcp(get16(p + 2), get16(p), src, get32(p + 8), 0,
TCP_RST, 0);
1021 sendTcp(get16(p + 2), get16(p), src, 0, get32(p + 4) + segLen,
1027 void output(TCPSocket &t) {
1032 size_t queued = t.tx.available();
1033 while (!t.finSent) {
1034 size_t offset = t.sndNxt - t.sndUna;
1035 if (offset >= queued)
break;
1036 uint32_t inFlight = t.sndNxt - t.sndUna;
1037 if (inFlight >= t.sndWnd)
break;
1038 size_t len = queued - offset;
1039 if (len > t.mss) len = t.mss;
1040 if (len > t.sndWnd - inFlight) len = t.sndWnd - inFlight;
1041 if (!sendSegment(t, t.sndNxt,
TCP_ACK |
TCP_PSH, offset, len))
break;
1043 if (t.timer == 0) armTimer(t);
1045 if (t.finQueued && !t.finSent && t.sndNxt - t.sndUna == queued) {
1051 if (t.timer == 0) armTimer(t);
1054 if (t.timer == 0 && queued > 0 && t.sndWnd == 0) armTimer(t);
1058 void retransmit(TCPSocket &t) {
1067 size_t queued = t.tx.available();
1069 size_t len = queued < t.mss ? queued : t.mss;
1071 if (t.sndWnd == 0) len = 1;
1073 if (seqLT(t.sndNxt, t.sndUna + len)) t.sndNxt = t.sndUna + len;
1074 }
else if (t.finSent) {
1083 void windowUpdate(TCPSocket &t) {
1087 size_t free = t.rx.free();
1088 size_t threshold = t.rx.size() / 2;
1089 if (threshold > rcvMss()) threshold = rcvMss();
1090 if (t.advWnd < threshold && free >= threshold) sendAck(t);
1093 void processTimers() {
1094 uint32_t now = millis();
1095 for (
auto &t : _tcp) {
1096 if (!t.inUse)
continue;
1097 if (t.deadline != 0 && (int32_t)(now - t.deadline) >= 0) {
1106 if (t.timer != 0 && (int32_t)(now - t.timer) >= 0) {
1111 if (t.orphan || !t.accepted) freeTcp(t);
1114 t.rto = t.rto * 2 > 16000 ? 16000 : t.rto * 2;
1121 for (
auto &t : _tcp) {
1122 if (t.inUse && t.ackPending) sendAck(t);
1126 void enterTimeWait(TCPSocket &t) {
1130 if (t.deadline == 0) t.deadline = 1;
1133 void parseOptions(TCPSocket &t,
const uint8_t *opt,
size_t len) {
1136 uint8_t kind = opt[i];
1137 if (kind == 0)
break;
1142 if (i + 1 >= len || opt[i + 1] < 2 || i + opt[i + 1] > len)
break;
1143 if (kind == 2 && opt[i + 1] == 4) {
1144 uint16_t mss = get16(opt + i + 2);
1145 if (mss >= 64 && mss < t.mss) t.mss = mss;
1151 bool tcpInput(
ip4_t src,
ip4_t dst,
const uint8_t *p,
size_t len,
1153 if (len < 20)
return false;
1154 size_t hlen = (p[12] >> 4) * 4;
1155 if (hlen < 20 || hlen > len)
return false;
1157 pseudoHeader(c,
IP_TCP, src, dst, len);
1159 if (c.result() != 0)
return true;
1161 uint16_t srcPort = get16(p), dstPort = get16(p + 2);
1162 uint32_t seq = get32(p + 4), ack = get32(p + 8);
1163 uint8_t flags = p[13];
1164 uint32_t wnd = get16(p + 14);
1165 const uint8_t *data = p + hlen;
1166 size_t dlen = len - hlen;
1167 size_t segLen = dlen + ((flags &
TCP_SYN) ? 1 : 0) + ((flags &
TCP_FIN) ? 1 : 0);
1169 TCPSocket *ts =
nullptr;
1170 for (
auto &t : _tcp) {
1172 t.remotePort == srcPort && t.remoteIP == src) {
1178 if (ts ==
nullptr) {
1180 listening(dstPort)) {
1182 if (s < 0)
return true;
1183 TCPSocket &t = _tcp[s];
1184 t.localPort = dstPort;
1185 t.remotePort = srcPort;
1189 parseOptions(t, p + 20, hlen - 20);
1194 if (!reply)
return false;
1195 replyReset(src, p, segLen);
1202 bool ackOk = (flags &
TCP_ACK) && ack == t.iss + 1;
1203 if ((flags &
TCP_ACK) && !ackOk) {
1204 replyReset(src, p, segLen);
1211 if ((flags &
TCP_SYN) && ackOk) {
1215 parseOptions(t, p + 20, hlen - 20);
1227 if (seq == t.rcvNxt) {
1230 if (t.orphan || !t.accepted) freeTcp(t);
1237 else t.ackPending =
true;
1240 if (segLen > 0 && seq != t.rcvNxt) {
1241 if (seqLT(seq, t.rcvNxt) && seqGT(seq + dlen, t.rcvNxt)) {
1243 size_t skip = t.rcvNxt - seq;
1248 t.ackPending =
true;
1252 if (!(flags &
TCP_ACK))
return true;
1255 if (ack != t.iss + 1) {
1256 replyReset(src, p, segLen);
1268 if (seqGT(ack, t.sndNxt)) {
1269 t.ackPending =
true;
1273 bool finAcked =
false;
1274 if (seqGT(ack, t.sndUna)) {
1275 size_t acked = ack - t.sndUna;
1276 size_t dataAcked = acked < t.tx.available() ? acked : t.tx.available();
1277 t.tx.discard(dataAcked);
1282 if (t.sndUna != t.sndNxt) armTimer(t);
1284 if (t.finSent && t.sndUna == t.sndNxt) finAcked =
true;
1294 if (finAcked) enterTimeWait(t);
1300 if (t.orphan) freeTcp(t);
1306 t.ackPending =
true;
1318 size_t n = t.orphan ? dlen : t.rx.write(data, dlen);
1320 t.ackPending =
true;
1321 if (n < dlen) flags &= ~TCP_FIN;
1324 if ((flags &
TCP_FIN) && seq + dlen == t.rcvNxt) {
1326 t.ackPending =
true;
1332 if (finAcked) enterTimeWait(t);