From 500c2e50b6abccddb357c176341d12d27a047cdd Mon Sep 17 00:00:00 2001 From: Andrea Date: Tue, 22 Mar 2022 19:39:49 +0000 Subject: [PATCH] Uthernet II: handle TCP connection failure. (PR #1070) --- help/toc.html | 2 +- help/uthernet.html | 28 +++++++++++++++++++--------- source/Uthernet2.cpp | 35 +++++++++++++++++++++++++---------- source/Uthernet2.h | 3 ++- 4 files changed, 47 insertions(+), 21 deletions(-) diff --git a/help/toc.html b/help/toc.html index a09a5e04..91981322 100644 --- a/help/toc.html +++ b/help/toc.html @@ -31,7 +31,7 @@
  • Sound
  • Clock
  • Super Serial card -
  • Uthernet network card +
  • Uthernet network cards
  • AppleWin Configuration
  • Using the Debugger
  • Resources
  • diff --git a/help/uthernet.html b/help/uthernet.html index ad8ece60..3cdc6a52 100644 --- a/help/uthernet.html +++ b/help/uthernet.html @@ -1,22 +1,23 @@ - Uthernet network card + Uthernet network cards -

    Uthernet network card

    +

    Uthernet network cards


    Overview:

    -

    The Uthernet network card coupled with the Contiki OS allows you to browse the +

    The Uthernet network cards coupled with the Contiki OS allow you to browse the internet on your Apple.

    Acknowledgment:

    -

    Uthernet (TFE) support in Applewin was made possible by implementing the GPL +

    Uthernet (TFE) support in AppleWin was made possible by implementing the GPL source written by Spiro Trikaliotis for the Vice emulator - http://vice-emu.sourceforge.net/index.html#developers

    +

    Uthernet II support in AppleWin has been contributed by Andrea (audetto) Odetti.

    Details:

    To enable ethernet support in AppleWin you must first download and install @@ -35,15 +36,15 @@

    After AppleWin starts, select the settings icon and then select the ethernet settings button.

    -

    Uthernet will be disabled. Select Uthernet from the list of available ethernet - emulations (currently the only one). +

    Uthernet will be disabled. Select Uthernet or (Uthernet II) from the list of available ethernet + emulations.

    Select the ethernet interface you want to work with. This must be a physical ethernet interface.

    If you have more than one interface you may need to select them in turn in order to get the text description for each interface vs what Npcap likes to use for - a reference. Select Ok. and then close AppleWin. + a reference.

    Note: Wireless does not work with WinPcap (but see WiFi Workaround). @@ -56,7 +57,7 @@ also grab a copy of the Uthernet/Contiki getting started guide http://www.a2retrosystems.com/a2UtherManual.pdf

    -

    When you run AppleWin again, select the contiki80pri.dsk image. Boot AppleWin. +

    Select the contiki80pri.dsk image. Boot AppleWin.

    Once Contiki is loaded then press Enter to clear the welcome screen and press ESC for a menu. @@ -87,5 +88,14 @@ if you are still having difficulty then you should refer to the VICE network support page for additional information - http://vicekb.trikaliotis.net/13-005.shtml

    - +

    Uthernet II: +

    +

    Most features of the Uthernet II are emulated, with the following caveats: +

    +

    + diff --git a/source/Uthernet2.cpp b/source/Uthernet2.cpp index 74d709d0..79970f52 100644 --- a/source/Uthernet2.cpp +++ b/source/Uthernet2.cpp @@ -216,31 +216,46 @@ Socket::~Socket() clearFD(); } +bool Socket::isOpen() const +{ + return (myFD != INVALID_SOCKET) && + ((sn_sr == W5100_SN_SR_ESTABLISHED) || (sn_sr == W5100_SN_SR_SOCK_UDP)); +} + void Socket::process() { if (myFD != INVALID_SOCKET && sn_sr == W5100_SN_SR_SOCK_INIT && (myErrno == SOCK_EINPROGRESS || myErrno == SOCK_EWOULDBLOCK)) { #ifdef _MSC_VER - FD_SET writefds; + FD_SET writefds, exceptfds; FD_ZERO(&writefds); + FD_ZERO(&exceptfds); FD_SET(myFD, &writefds); + FD_SET(myFD, &exceptfds); const timeval timeout = {0, 0}; - if (select(0, NULL, &writefds, NULL, &timeout) > 0) + if (select(0, NULL, &writefds, &exceptfds, &timeout) > 0) #else pollfd pfd = {.fd = myFD, .events = POLLOUT}; if (poll(&pfd, 1, 0) > 0) #endif { int err = 0; - socklen_t elen = sizeof err; - getsockopt(myFD, SOL_SOCKET, SO_ERROR, reinterpret_cast(&err), &elen); + socklen_t elen = sizeof(err); + const int res = getsockopt(myFD, SOL_SOCKET, SO_ERROR, reinterpret_cast(&err), &elen); - if (err == 0) + if (res == 0 && err == 0) { myErrno = 0; sn_sr = W5100_SN_SR_ESTABLISHED; #ifdef U2_LOG_STATE LogFileOutput("U2: TCP[]: Connected\n"); +#endif + } + else + { + clearFD(); +#ifdef U2_LOG_STATE + LogFileOutput("U2: TCP[]: Connection error: %d - %" ERROR_FMT "\n", res, STRERROR(err)); #endif } } @@ -614,7 +629,7 @@ void Uthernet2::receiveOnePacketIPRaw(const size_t i, const size_t lengthOfPaylo void Uthernet2::receiveOnePacketFromSocket(const size_t i) { Socket &socket = mySockets[i]; - if (socket.myFD != INVALID_SOCKET) + if (socket.isOpen()) { const uint16_t freeRoom = socket.getFreeRoom(); if (freeRoom > 32) // avoid meaningless reads @@ -718,7 +733,7 @@ void Uthernet2::sendDataMacRaw(const size_t i, std::vector &packet) con void Uthernet2::sendDataToSocket(const size_t i, std::vector &data) { Socket &socket = mySockets[i]; - if (socket.myFD != INVALID_SOCKET) + if (socket.isOpen()) { sockaddr_in destination = {}; destination.sin_family = AF_INET; @@ -809,7 +824,7 @@ void Uthernet2::resetRXTXBuffers(const size_t i) myMemory[socket.registerAddress + W5100_SN_RX_RD1] = 0x00; } -void Uthernet2::openSystemSocket(const size_t i, const int type, const int protocol, const int state) +void Uthernet2::openSystemSocket(const size_t i, const int type, const int protocol, const int status) { Socket &s = mySockets[i]; #ifdef _MSC_VER @@ -820,7 +835,7 @@ void Uthernet2::openSystemSocket(const size_t i, const int type, const int proto if (fd == INVALID_SOCKET) { #ifdef U2_LOG_STATE - const char *proto = state == W5100_SN_SR_SOCK_UDP ? "UDP" : "TCP"; + const char *proto = (status == W5100_SN_SR_SOCK_UDP) ? "UDP" : "TCP"; LogFileOutput("U2: %s[%" SIZE_T_FMT "]: socket error: %" ERROR_FMT "\n", proto, i, STRERROR(sock_error())); #endif s.clearFD(); @@ -831,7 +846,7 @@ void Uthernet2::openSystemSocket(const size_t i, const int type, const int proto u_long on = 1; ioctlsocket(fd, FIONBIO, &on); #endif - s.setFD(fd, state); + s.setFD(fd, status); } } diff --git a/source/Uthernet2.h b/source/Uthernet2.h index 752f0b5d..8b33af21 100644 --- a/source/Uthernet2.h +++ b/source/Uthernet2.h @@ -30,6 +30,7 @@ struct Socket socket_t myFD; int myErrno; + bool isOpen() const; void clearFD(); void setFD(const socket_t fd, const int status); void process(); @@ -106,7 +107,7 @@ private: void resetRXTXBuffers(const size_t i); void updateRSR(const size_t i); - void openSystemSocket(const size_t i, const int type, const int protocol, const int state); + void openSystemSocket(const size_t i, const int type, const int protocol, const int status); void openSocket(const size_t i); void closeSocket(const size_t i); void connectSocket(const size_t i);