Uthernet II: handle TCP connection failure. (PR #1070)

This commit is contained in:
Andrea 2022-03-22 19:39:49 +00:00 committed by GitHub
parent cdd360bdfe
commit 500c2e50b6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 47 additions and 21 deletions

View File

@ -31,7 +31,7 @@
<li><a href="sound.html">Sound</a> <li><a href="sound.html">Sound</a>
<li><a href="clock.html">Clock</a> <li><a href="clock.html">Clock</a>
<li><a href="card-ssc.html">Super Serial card</a> <li><a href="card-ssc.html">Super Serial card</a>
<li><a href="uthernet.html">Uthernet network card</a> <li><a href="uthernet.html">Uthernet network cards</a>
<li><a href="configuration.html">AppleWin Configuration</a> <li><a href="configuration.html">AppleWin Configuration</a>
<li><a href="dbg-toc-intro.html">Using the Debugger</a> <li><a href="dbg-toc-intro.html">Using the Debugger</a>
<li><a href="resources.html">Resources</a></li> <li><a href="resources.html">Resources</a></li>

View File

@ -1,22 +1,23 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html> <html>
<head> <head>
<title>Uthernet network card</title> <title>Uthernet network cards</title>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252"> <meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
</head> </head>
<body style="FONT-FAMILY: verdana; BACKGROUND-COLOR: rgb(255,255,255)" alink="#008000" <body style="FONT-FAMILY: verdana; BACKGROUND-COLOR: rgb(255,255,255)" alink="#008000"
link="#008000" vlink="#008000"> link="#008000" vlink="#008000">
<h2 style="COLOR: rgb(0,128,0)">Uthernet network card</h2> <h2 style="COLOR: rgb(0,128,0)">Uthernet network cards</h2>
<hr size="4"> <hr size="4">
<p style="FONT-WEIGHT: bold">Overview: <p style="FONT-WEIGHT: bold">Overview:
</p> </p>
<P>The Uthernet network card coupled with the Contiki OS allows you to browse the <P>The Uthernet network cards coupled with the Contiki OS allow you to browse the
internet on your Apple.</P> internet on your Apple.</P>
<P style="FONT-WEIGHT: bold">Acknowledgment: <P style="FONT-WEIGHT: bold">Acknowledgment:
</P> </P>
<P>Uthernet (TFE) support in Applewin was made possible by implementing the GPL <P>Uthernet (TFE) support in AppleWin was made possible by implementing the GPL
source written by Spiro Trikaliotis for the Vice emulator - <A href="http://vice-emu.sourceforge.net/index.html#developers"> source written by Spiro Trikaliotis for the Vice emulator - <A href="http://vice-emu.sourceforge.net/index.html#developers">
http://vice-emu.sourceforge.net/index.html#developers</A></P> http://vice-emu.sourceforge.net/index.html#developers</A></P>
<P><A href="https://a2retrosystems.com/">Uthernet II</A> support in AppleWin has been contributed by Andrea (audetto) Odetti.</P>
<P style="FONT-WEIGHT: bold">Details: <P style="FONT-WEIGHT: bold">Details:
</P> </P>
<P>To enable ethernet support in AppleWin you must first download and install <P>To enable ethernet support in AppleWin you must first download and install
@ -35,15 +36,15 @@
<P>After AppleWin starts, select the settings icon and then select the ethernet <P>After AppleWin starts, select the settings icon and then select the ethernet
settings button. settings button.
</P> </P>
<P>Uthernet will be disabled. Select Uthernet from the list of available ethernet <P>Uthernet will be disabled. Select Uthernet or (Uthernet II) from the list of available ethernet
emulations (currently the only one). emulations.
</P> </P>
<P>Select the ethernet interface you want to work with. This must be a physical <P>Select the ethernet interface you want to work with. This must be a physical
ethernet interface. ethernet interface.
</P> </P>
<P>If you have more than one interface you may need to select them in turn in order <P>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 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.
</P> </P>
<P><span style="font-weight: bold;">Note:</span> Wireless does not work <P><span style="font-weight: bold;">Note:</span> Wireless does not work
with WinPcap (but see <A href="uthernet-wifi-workaround.html">WiFi Workaround</A>). with WinPcap (but see <A href="uthernet-wifi-workaround.html">WiFi Workaround</A>).
@ -56,7 +57,7 @@
also grab a copy of the Uthernet/Contiki getting started guide <A href="http://www.a2retrosystems.com/a2UtherManual.pdf"> also grab a copy of the Uthernet/Contiki getting started guide <A href="http://www.a2retrosystems.com/a2UtherManual.pdf">
http://www.a2retrosystems.com/a2UtherManual.pdf</A> http://www.a2retrosystems.com/a2UtherManual.pdf</A>
</P> </P>
<P>When you run AppleWin again, select the contiki80pri.dsk image. Boot AppleWin. <P>Select the contiki80pri.dsk image. Boot AppleWin.
</P> </P>
<P>Once Contiki is loaded then press Enter to clear the welcome screen and press <P>Once Contiki is loaded then press Enter to clear the welcome screen and press
ESC for a menu. ESC for a menu.
@ -87,5 +88,14 @@
if you are still having difficulty then you should refer to the VICE network if you are still having difficulty then you should refer to the VICE network
support page for additional information - <A href="http://vicekb.trikaliotis.net/13-005.shtml"> support page for additional information - <A href="http://vicekb.trikaliotis.net/13-005.shtml">
http://vicekb.trikaliotis.net/13-005.shtml</A></P> http://vicekb.trikaliotis.net/13-005.shtml</A></P>
</body> <P style="FONT-WEIGHT: bold">Uthernet II:
</P>
<P>Most features of the Uthernet II are emulated, with the following caveats:
<ul>
<li>PPPoE, interrupts and SPI are not implemented</li>
<li>server side is not well tested</li>
<li>after loading a save-state file, TCP and UDP sockets are closed</li>
</ul>
</P>
</body>
</html> </html>

View File

@ -216,31 +216,46 @@ Socket::~Socket()
clearFD(); 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() void Socket::process()
{ {
if (myFD != INVALID_SOCKET && sn_sr == W5100_SN_SR_SOCK_INIT && (myErrno == SOCK_EINPROGRESS || myErrno == SOCK_EWOULDBLOCK)) if (myFD != INVALID_SOCKET && sn_sr == W5100_SN_SR_SOCK_INIT && (myErrno == SOCK_EINPROGRESS || myErrno == SOCK_EWOULDBLOCK))
{ {
#ifdef _MSC_VER #ifdef _MSC_VER
FD_SET writefds; FD_SET writefds, exceptfds;
FD_ZERO(&writefds); FD_ZERO(&writefds);
FD_ZERO(&exceptfds);
FD_SET(myFD, &writefds); FD_SET(myFD, &writefds);
FD_SET(myFD, &exceptfds);
const timeval timeout = {0, 0}; const timeval timeout = {0, 0};
if (select(0, NULL, &writefds, NULL, &timeout) > 0) if (select(0, NULL, &writefds, &exceptfds, &timeout) > 0)
#else #else
pollfd pfd = {.fd = myFD, .events = POLLOUT}; pollfd pfd = {.fd = myFD, .events = POLLOUT};
if (poll(&pfd, 1, 0) > 0) if (poll(&pfd, 1, 0) > 0)
#endif #endif
{ {
int err = 0; int err = 0;
socklen_t elen = sizeof err; socklen_t elen = sizeof(err);
getsockopt(myFD, SOL_SOCKET, SO_ERROR, reinterpret_cast<char *>(&err), &elen); const int res = getsockopt(myFD, SOL_SOCKET, SO_ERROR, reinterpret_cast<char *>(&err), &elen);
if (err == 0) if (res == 0 && err == 0)
{ {
myErrno = 0; myErrno = 0;
sn_sr = W5100_SN_SR_ESTABLISHED; sn_sr = W5100_SN_SR_ESTABLISHED;
#ifdef U2_LOG_STATE #ifdef U2_LOG_STATE
LogFileOutput("U2: TCP[]: Connected\n"); 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 #endif
} }
} }
@ -614,7 +629,7 @@ void Uthernet2::receiveOnePacketIPRaw(const size_t i, const size_t lengthOfPaylo
void Uthernet2::receiveOnePacketFromSocket(const size_t i) void Uthernet2::receiveOnePacketFromSocket(const size_t i)
{ {
Socket &socket = mySockets[i]; Socket &socket = mySockets[i];
if (socket.myFD != INVALID_SOCKET) if (socket.isOpen())
{ {
const uint16_t freeRoom = socket.getFreeRoom(); const uint16_t freeRoom = socket.getFreeRoom();
if (freeRoom > 32) // avoid meaningless reads if (freeRoom > 32) // avoid meaningless reads
@ -718,7 +733,7 @@ void Uthernet2::sendDataMacRaw(const size_t i, std::vector<uint8_t> &packet) con
void Uthernet2::sendDataToSocket(const size_t i, std::vector<uint8_t> &data) void Uthernet2::sendDataToSocket(const size_t i, std::vector<uint8_t> &data)
{ {
Socket &socket = mySockets[i]; Socket &socket = mySockets[i];
if (socket.myFD != INVALID_SOCKET) if (socket.isOpen())
{ {
sockaddr_in destination = {}; sockaddr_in destination = {};
destination.sin_family = AF_INET; destination.sin_family = AF_INET;
@ -809,7 +824,7 @@ void Uthernet2::resetRXTXBuffers(const size_t i)
myMemory[socket.registerAddress + W5100_SN_RX_RD1] = 0x00; 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]; Socket &s = mySockets[i];
#ifdef _MSC_VER #ifdef _MSC_VER
@ -820,7 +835,7 @@ void Uthernet2::openSystemSocket(const size_t i, const int type, const int proto
if (fd == INVALID_SOCKET) if (fd == INVALID_SOCKET)
{ {
#ifdef U2_LOG_STATE #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())); LogFileOutput("U2: %s[%" SIZE_T_FMT "]: socket error: %" ERROR_FMT "\n", proto, i, STRERROR(sock_error()));
#endif #endif
s.clearFD(); s.clearFD();
@ -831,7 +846,7 @@ void Uthernet2::openSystemSocket(const size_t i, const int type, const int proto
u_long on = 1; u_long on = 1;
ioctlsocket(fd, FIONBIO, &on); ioctlsocket(fd, FIONBIO, &on);
#endif #endif
s.setFD(fd, state); s.setFD(fd, status);
} }
} }

View File

@ -30,6 +30,7 @@ struct Socket
socket_t myFD; socket_t myFD;
int myErrno; int myErrno;
bool isOpen() const;
void clearFD(); void clearFD();
void setFD(const socket_t fd, const int status); void setFD(const socket_t fd, const int status);
void process(); void process();
@ -106,7 +107,7 @@ private:
void resetRXTXBuffers(const size_t i); void resetRXTXBuffers(const size_t i);
void updateRSR(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 openSocket(const size_t i);
void closeSocket(const size_t i); void closeSocket(const size_t i);
void connectSocket(const size_t i); void connectSocket(const size_t i);