Fix TCP RST ACK loop bug.

Fix Gopher client filename bug using filename character validation.
Increase TCP timeout in TCPConnectionCreate.
Move default AutoComplete position left a bit, just enough so that new windows' [X] button is visible.
This commit is contained in:
TomAwezome 2021-11-04 05:39:55 -04:00
parent 5a4bccc5b9
commit 68775b3b44
4 changed files with 74 additions and 42 deletions

View file

@ -1,18 +1,18 @@
/* Gopher client for TempleOS/Sockets /* Gopher client for TempleOS/Sockets
by Declan Hoare 2020 by Declan Hoare 2020
ported to ZealOS by TomAwezome in 2021 ported to ZealOS and modified by TomAwezome in 2021
Public Domain - No Warranty */ Public Domain - No Warranty */
#define GOPHER_CLIENT_LOADED #define GOPHER_CLIENT_LOADED
#ifndef GOPHER_ASSOCIATIONS #ifndef GOPHER_ASSOCIATIONS
#define GOPHER_ASSOCIATIONS #define GOPHER_ASSOCIATIONS
U8* gopher_associations[256]; U8 *gopher_associations[256];
#endif #endif
I64 GopherOpen(U8* host, U16 port, U8* selector, U8* query) I64 GopherOpen(U8 *host, U16 port, U8 *selector, U8 *query)
{ {
U8* line; U8 *line;
I64 sock; I64 sock;
if (host == NULL) if (host == NULL)
@ -37,8 +37,7 @@ I64 GopherOpen(U8* host, U16 port, U8* selector, U8* query)
line = StrPrint(NULL, "%s\t%s\r\n", selector, query); line = StrPrint(NULL, "%s\t%s\r\n", selector, query);
} }
sock(CTCPSocket *)->timeout = TCP_TIMEOUT*5; sock(CTCPSocket *)->timeout = TCP_TIMEOUT * 5;
// sendString(sock, line, 0); // sendString(sock, line, 0);
TCPSocketSendString(sock, line); TCPSocketSendString(sock, line);
@ -47,13 +46,15 @@ I64 GopherOpen(U8* host, U16 port, U8* selector, U8* query)
return sock; return sock;
} }
public I64 GopherDl #define GOPHER_BUFF_SIZE BLK_SIZE * 64
(U8* host, U16 port = 70, U8* selector, U8* query = NULL, U8* dest)
public I64 GopherDl(U8 *host, U16 port = 70, U8 *selector, U8 *query = NULL, U8 *dest)
{ {
CFile* f; CFile *f;
U8 buf[BLK_SIZE]; U8 buf[BLK_SIZE];
I64 data_len = 0, total_len = 0, got, sock; // U8 buf[GOPHER_BUFF_SIZE];
I64 data_len = 0, total_len = 0, got, sock;
f = FOpen(dest, "w"); f = FOpen(dest, "w");
if (!f) if (!f)
{ {
@ -62,7 +63,7 @@ public I64 GopherDl
} }
sock = GopherOpen(host, port, selector, query); sock = GopherOpen(host, port, selector, query);
if (sock < 0) if (sock <= 0)
{ {
return sock; return sock;
} }
@ -74,6 +75,7 @@ public I64 GopherDl
if (got <= 0) if (got <= 0)
{ {
if (data_len != 0 && !FBlkWrite(f, buf)) if (data_len != 0 && !FBlkWrite(f, buf))
// if (data_len != 0 && !FBlkWrite(f, buf,, GOPHER_BUFF_SIZE))
{ {
break; break;
} }
@ -84,23 +86,27 @@ public I64 GopherDl
data_len += got; data_len += got;
total_len += got; total_len += got;
if (data_len == BLK_SIZE) if (data_len == BLK_SIZE)
// if (data_len == GOPHER_BUFF_SIZE)
{ {
if (!FBlkWrite(f, buf)) if (!FBlkWrite(f, buf))
// if (!FBlkWrite(f, buf,, GOPHER_BUFF_SIZE))
{ {
break; break;
} }
data_len = 0; data_len = 0;
} }
} }
PrintErr("Write failed, %s may be corrupted\n", dest); PrintErr("Write failed, %s may be corrupted\n", dest);
FClose(f); FClose(f);
return -1; return -1;
} }
U0 PrintEscaped(U8* txt, U8* backslashes = "") U0 PrintEscaped(U8 *txt, U8 *backslashes = "")
{ {
U8* cur; U8 *cur;
U8 offending; U64 offending;
while (cur = StrFirstOcc(txt, "$$\\\"")) while (cur = StrFirstOcc(txt, "$$\\\""))
{ {
@ -116,26 +122,39 @@ U0 PrintEscaped(U8* txt, U8* backslashes = "")
} }
txt = cur + 1; txt = cur + 1;
} }
"%s", txt; "%s", txt;
} }
U8* GopherBasename(U8* selector) U8 *GopherBasename(U8 *selector)
{ {
U8* lastslash = StrLastOcc(selector, "/"); U8 *lastslash = StrLastOcc(selector, "/"), *result;
if (lastslash == NULL) if (lastslash == NULL)
{ {
return selector; result = selector;
} }
else else
{ {
return lastslash + 1; result = lastslash + 1;
} }
//BAD FOR FILENAMES: ? / | = %
result = StrReplace(result, "?", "");
result = StrReplace(result, "/", "",, TRUE);
result = StrReplace(result, "|", "",, TRUE);
result = StrReplace(result, "=", "",, TRUE);
result = StrReplace(result, "%", "",, TRUE);
// result = StrNew("TEST.TXT");
SysLog("%s\n", result);
return result;
} }
U0 GopherTextView(U8* host, U16 port, U8* selector) U0 GopherTextView(U8 *host, U16 port, U8 *selector)
{ {
U8* basename; U8 *basename;
U8* tmpname; U8 *tmpname;
DirMake("::/Tmp/Gopher"); DirMake("::/Tmp/Gopher");
@ -155,12 +174,12 @@ U0 GopherTextView(U8* host, U16 port, U8* selector)
Free(tmpname); Free(tmpname);
} }
U0 GopherLine(U8* line) U0 GopherLine(U8 *line)
{ {
U8 type; U64 type;
U8* display; U8 *display;
U8* selector; U8 *selector;
U8* host = NULL; U8 *host = NULL;
U16 port = 0; U16 port = 0;
if (*line == 0) if (*line == 0)
@ -202,7 +221,7 @@ U0 GopherLine(U8* line)
} }
if (!*host) if (!*host)
return; return;
switch (type) switch (type)
{ {
@ -223,11 +242,10 @@ U0 GopherLine(U8* line)
"\n"; "\n";
} }
public I64 GopherMenu public I64 GopherMenu(U8 *host, U16 port = 70, U8 *selector = "/", U8 *query = NULL)
(U8* host, U16 port = 70, U8* selector = "/", U8* query = NULL)
{ {
I64 sock, n; I64 sock, n;
U8 buf[256]; U8 buf[256];
sock = GopherOpen(host, port, selector, query); sock = GopherOpen(host, port, selector, query);
if (sock <= 0) if (sock <= 0)
@ -256,7 +274,7 @@ class CQueryForm
{ {
U8 query[65] format "$$DA-P,A=\"Query:%s\"$$"; U8 query[65] format "$$DA-P,A=\"Query:%s\"$$";
}; };
U0 GopherQueryPrompt(U8* host, U16 port, U8* selector) U0 GopherQueryPrompt(U8 *host, U16 port, U8 *selector)
{ {
CQueryForm form; CQueryForm form;
@ -271,12 +289,13 @@ class CDlForm
{ {
U8 name[256] format "$$DA-P,LEN=255,A=\"FileName:%s\"$$"; U8 name[256] format "$$DA-P,LEN=255,A=\"FileName:%s\"$$";
}; };
U0 GopherDlPrompt(U8* host, U16 port, U8* selector) U0 GopherDlPrompt(U8 *host, U16 port, U8 *selector)
{ {
CDlForm form; CDlForm form;
U8* basename; U8 *basename;
basename = GopherBasename(selector); basename = GopherBasename(selector);
MemSet(form.name, 0, 256);
MemCopy(form.name, basename, MemCopy(form.name, basename,
MinI64(StrLen(basename), sizeof(form.name) - 1)); MinI64(StrLen(basename), sizeof(form.name) - 1));
form.name[255] = 0; form.name[255] = 0;
@ -286,11 +305,21 @@ U0 GopherDlPrompt(U8* host, U16 port, U8* selector)
} }
} }
public I64 Gopher(U8 *hostname)
{
return GopherMenu(hostname);
}
MemSetI64(gopher_associations, "GopherDlPrompt", 256); MemSetI64(gopher_associations, "GopherDlPrompt", 256);
gopher_associations['0'] = "GopherTextView"; gopher_associations['0'] = "GopherTextView";
gopher_associations['1'] = "GopherMenu"; gopher_associations['1'] = "GopherMenu";
gopher_associations['7'] = "GopherQueryPrompt"; gopher_associations['7'] = "GopherQueryPrompt";
/* Include this file from your HomeSys, then add more associations */ /* Include this file from your Net/Load.CC, then add more associations */
"\n\nTry using GopherMenu to connect to a gopher server, for example:\n\n"
" $FG,2$GopherMenu(\"gopher.floodgap.com\");$FG$\n\n"; DocMax;
"\n\nTry using Gopher to connect to a gopher server, for example:"
"\n\n$FG,2$ Gopher(\"gopher.floodgap.com\");$FG$"
"\n\n$FG,2$ GopherMenu(\"eyeblea.ch\",70,\"/~zealos\");$FG$"
"\n\n$FG,2$ Gopher(\"codevoid.de\");$FG$"
"\n\n";

View file

@ -1449,7 +1449,7 @@ CTCPSocket *TCPConnectionCreate(U8 *hostname, U16 port)
if (current->family == AF_INET && (current->socket_type == 0 || current->socket_type == SOCKET_STREAM)) if (current->family == AF_INET && (current->socket_type == 0 || current->socket_type == SOCKET_STREAM))
{ // TODO: IPV6 support ! { // TODO: IPV6 support !
socket_addr.address.address = EndianU32(current->address(CSocketAddressIPV4 *)->address.address); // ?? why are bits flipped here socket_addr.address.address = EndianU32(current->address(CSocketAddressIPV4 *)->address.address); // ?? why are bits flipped here
AddressInfoFree(info); AddressInfoFree(info);
result = TCPSocket(AF_INET); result = TCPSocket(AF_INET);
@ -1458,7 +1458,7 @@ CTCPSocket *TCPConnectionCreate(U8 *hostname, U16 port)
NetErr("TCP CONNECTION CREATE: Failed to create new TCP Socket."); NetErr("TCP CONNECTION CREATE: Failed to create new TCP Socket.");
return NULL; return NULL;
} }
result->timeout = TCP_TIMEOUT; result->timeout = TCP_TIMEOUT * 3; // generous
error = TCPSocketConnect(result, &socket_addr); error = TCPSocketConnect(result, &socket_addr);
if (error < 0) if (error < 0)
{ {

View file

@ -276,6 +276,9 @@ I64 TCPHandleRefuse(CIPV4Packet *packet, CTCPHeader *header, I64 length)
// review RFC Reset-Generation ... // review RFC Reset-Generation ...
if (Bt(&header->flags, TCPf_RST) && Bt(&header->flags, TCPf_ACK))
return 0; // bail: we probably sent an RST earlier, and this is the acknowledgement
de_index = TCPSend(packet->destination_ip_address, de_index = TCPSend(packet->destination_ip_address,
EndianU16(header->destination_port), EndianU16(header->destination_port),
packet->source_ip_address, packet->source_ip_address,

View file

@ -150,7 +150,7 @@ public U0 ACInit(U8 *mask=NULL)
ACMainFileListTraverse(mask); ACMainFileListTraverse(mask);
ACDWordsLoad; ACDWordsLoad;
RegDefault("AutoComplete", "ac.col = TEXT_COLS-31;ac.row = 10;"); RegDefault("AutoComplete", "ac.col = TEXT_COLS-34;ac.row = 10;");
RegExe("AutoComplete"); RegExe("AutoComplete");
LBtr(&ac.flags, ACf_INIT_IN_PROGRESS); LBtr(&ac.flags, ACf_INIT_IN_PROGRESS);
LBts(&sys_run_level, RLf_AUTOCOMPLETE); LBts(&sys_run_level, RLf_AUTOCOMPLETE);