mirror of
https://github.com/Zeal-Operating-System/ZealOS.git
synced 2024-12-27 07:46:33 +00:00
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:
parent
5a4bccc5b9
commit
68775b3b44
4 changed files with 74 additions and 42 deletions
|
@ -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";
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in a new issue