This commit is contained in:
Kelvin Sherlock 2012-03-11 18:48:45 -04:00
parent f718cd8afb
commit c2742808da
3 changed files with 229 additions and 104 deletions

276
gopher.c
View File

@ -4,10 +4,12 @@
#include <tcpip.h> #include <tcpip.h>
//#include "url.h" #include "url.h"
#include "Connect.h" #include "connection.h"
#include <stdio.h> #include <stdio.h>
#include <string.h>
#include <stdlib.h>
/* /*
* connect gopher.floodgap.com:70 * connect gopher.floodgap.com:70
@ -24,7 +26,7 @@ enum {
kConnected = 4 kConnected = 4
}; };
Word StartUp(void) Word StartUp(displayPtr fx)
{ {
word status; word status;
word flags = 0; word flags = 0;
@ -32,7 +34,7 @@ Word StartUp(void)
status = TCPIPStatus(); status = TCPIPStatus();
if (_toolErr) if (_toolErr)
{ {
LoadOneTool(54,0x0200); LoadOneTool(54, 0x0201);
if (_toolErr) return -1; if (_toolErr) return -1;
status = 0; status = 0;
@ -49,17 +51,18 @@ Word StartUp(void)
status = TCPIPGetConnectStatus(); status = TCPIPGetConnectStatus();
if (!status) if (!status)
{ {
TCPIPConnect(NULL); TCPIPConnect(fx);
flags |= kConnected; flags |= kConnected;
} }
return flags; return flags;
} }
void ShutDown(word flags) void ShutDown(word flags, Boolean force, displayPtr fx)
{ {
if (flags & kConnected) if (flags & kConnected)
{ {
TCPIPDisconnect(false, NULL); TCPIPDisconnect(force, fx);
if (_toolErr) return; if (_toolErr) return;
} }
if (flags & kStarted) if (flags & kStarted)
@ -73,51 +76,200 @@ void ShutDown(word flags)
} }
} }
#if 0
int gopher_binary(Word ipid, FILE *file)
{
// gopher binary support.
// format: raw data until eof.
Word rv = 0;
for(;;)
{
static char buffer[512];
rrBuff rb;
Word count;
TCPIPPoll();
rv = TCPIPReadTCP(ipid, 0, (Ref)buffer, 512, &rb);
count = rb.rrBuffCount;
if (rv == 0 && count == 0) continue;
if (rv && !count) break;
if (!count) continue;
fwrite(buffer, count, 1, file);
}
return rv;
}
int gopher_text(Word ipid, FILE *file)
{
// text \r\n
// ...
// . \r\n
// any leading '.' must be doubled.
enum {
kStateText = 0,
kStateCR,
kStateEOL,
kStateDot,
kStateDotCR,
kStateEOF
};
static char buffer[256];
unsigned state = kStateEOL;
int rv = 0;
// I have bad luck with ReadLineTCP.
while (state != kStateEOF)
{
static char buffer[512];
rrBuff rb;
Word count;
Word i;
TCPIPPoll();
rv = TCPIPReadTCP(ipid, 0, (Ref)buffer, 512, &rb);
count = rb.rrBuffCount;
if (rv == 0 && count == 0) continue;
//fprintf(stderr, "rv = %x, count = %u\n", rv, rb.rrBuffCount);
//if (rv == tcperrConClosing) rv = 0;
if (rv && !count) break;
if (!count) continue;
// scan the buffer for a line.
for (i = 0; i < count; ++i)
{
char c = buffer[i];
if (c == '.')
{
if (state == kStateEOL) state = kStateDot;
else fputc(c, file);
continue;
}
if (c == '\r')
{
if (state == kStateDot) state = kStateDotCR;
else state = kStateCR;
continue;
}
if (c == '\n')
{
if (state == kStateCR)
{
state = kStateEOL;
fputc('\n', file);
}
else if (state == kStateDotCR)
{
state = kStateEOF;
break;
}
// otherwise, silently drop?
continue;
}
{
state = kStateText; // reset if kStateDot.
// . and \r will be silently dropped
fputc(c, file);
}
}
}
if (state != kStateEOF)
fprintf(stderr, "warning: eof not detected\n");
return rv;
}
void do_url(const char *url) void do_url(const char *url)
{ {
URLComponents components; URLComponents components;
ConnectBuffer buffer; Connection buffer;
char *host; char *host;
char type;
if (ParseURL(url, strlen(url), &components)) if (!ParseURL(url, strlen(url), &components))
{ {
fprintf(stderr, "Invalid URL: %s\n", url); fprintf(stderr, "Invalid URL: %s\n", url);
return; return;
} }
if (!url.host.length)
if (!components.host.length)
{ {
fprintf(stderr, "No host\n"); fprintf(stderr, "No host\n");
return; return;
} }
if (!components.portNumber) components.portNumber = 70; if (!components.portNumber) components.portNumber = 70;
host = malloc(url.host.length + 1);
URLComponentGetCString(url, &components, host, URLComponentHost);
ConnectInit(&buffer, myID); host = malloc(components.host.length + 1);
URLComponentGetC(url, &components, URLComponentHost, host);
ConnectionInit(&buffer, MMStartUp());
ConnectionOpenC(&buffer, host, components.portNumber);
ConnectCString(&buffer, host, components.portNumber);
if (components.path.length)
{
rv = TCPIPWriteTCP(buffer.ipid,
url + components.path.location,
components.path.length,
0, 0);
}
rv = TCPIPWriteTCP(buffer.ipid, "\r\n", 2, 1, 0);
while (!ConnectionPoll(&buffer)) ; while (!ConnectionPoll(&buffer)) ;
if (buffer.state == ConnectionStateError)
if (buffer.state == kConnectionStateError)
{ {
fprintf(stderr, "Unable to open host: %s:%u\n", host, components.portNumber); fprintf(stderr, "Unable to open host: %s:%u\n",
host,
components.portNumber);
free(host); free(host);
return; return;
} }
// connected....
// path is /[type][resource]
// where [type] is 1 char and the leading / is ignored.
if (components.path.length <= 1)
{
// / or blank
type = '1'; // directory
}
else if (components.path.length == 2)
{
// / type
// invalid -- treat as /
type = 1;
}
else
{
type = url[components.path.location+1];
TCPIPWriteTCP(
buffer.ipid,
url + components.path.location + 2,
components.path.length - 2,
0,
0);
}
//
TCPIPWriteTCP(buffer.ipid, "\r\n", 2, true, 0);
// 5 and 9 are binary, 1 is dir, all others text.
if (type == 1 || type == 9)
gopher_binary(buffer.ipid, stdout);
else
gopher_text(buffer.ipid, stdout);
fflush(stdout);
ConnectionClose(&buffer); ConnectionClose(&buffer);
while (!ConnectionPoll(&buffer)) ; // wait for it to close. while (!ConnectionPoll(&buffer)) ; // wait for it to close.
@ -125,82 +277,22 @@ void do_url(const char *url)
free (host); free (host);
} }
#endif
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
Handle h;
ConnectBuffer buffer;
int i; int i;
Word rv;
Word flags; Word flags;
// getopt for -b binary flags = StartUp(NULL);
#if 0
for (i = 1; i < argc; ++i) for (i = 1; i < argc; ++i)
{ {
do_url(argv[i]); do_url(argv[i]);
} }
#endif
ShutDown(flags, false, NULL);
flags = StartUp();
fprintf(stdout, "flags: %u\n", flags);
ConnectionInit(&buffer, MMStartUp());
rv = ConnectionOpen(&buffer, "\pgopher.floodgap.com", 70);
while (!rv)
{
rv = ConnectionPoll(&buffer);
}
if (buffer.state == ConnectStateConnected)
{
fprintf(stdout, "Connected!\n");
}
fprintf(stdout, "%x %x %x\n", rv, buffer.state, buffer.terr);
rv = TCPIPWriteTCP(buffer.ipid, "\r\n", 2, 1, 0);
if (rv)
{
fprintf(stdout, "TCPIPWriteTCP: %x\n", rv);
}
for(;;)
{
rrBuff rb;
//rlrBuff rb;
Handle h;
Word count;
TCPIPPoll();
rv = TCPIPReadTCP(buffer.ipid, 2, NULL, 4096, &rb);
//rv = TCPIPReadLineTCP(buffer.ipid, "\p\r\n", 2, NULL, 4096, &rb);
if (rv) break;
h = rb.rrBuffHandle;
count = rb.rrBuffCount;
if (!h) continue;
HLock(h);
fwrite(*h, count, 1, stdout);
fputs("", stdout);
DisposeHandle(h);
}
rv = ConnectionClose(&buffer);
while (!rv)
{
rv = ConnectionPoll(&buffer);
}
fprintf(stdout, "%x %x %x\n", rv, buffer.state, buffer.terr);
ShutDown(flags);
return 0;
} }

49
url.c
View File

@ -26,7 +26,7 @@ enum {
* *
*/ */
int URLGetComponentCString(const char *url, struct URLComponents *components, int type, char *dest) int URLComponentGetC(const char *url, URLComponents *components, int type, char *dest)
{ {
URLRange *rangePtr; URLRange *rangePtr;
URLRange r; URLRange r;
@ -53,6 +53,35 @@ int URLGetComponentCString(const char *url, struct URLComponents *components, in
} }
} }
// pstring.
int URLComponentGet(const char *url, URLComponents *components, int type, char *dest)
{
URLRange *rangePtr;
URLRange r;
if (!url || !components) return -1;
if (type < URLComponentScheme || type > URLComponentPathAndQuery) return -1;
rangePtr = &components->scheme;
r = rangePtr[type];
if (!dest) return r.length;
else if (r.length > 255) return -1;
else
{
dest[0] = r.length;
if (r.length)
{
memcpy(dest + 1, url + r.location, r.length);
}
return r.length;
}
}
#if 0 #if 0
int schemeType(const char *string) int schemeType(const char *string)
@ -460,6 +489,8 @@ int ParseURL(const char *url, int length, struct URLComponents *components)
} }
#ifdef TEST
void test(const char *url) void test(const char *url)
{ {
URLComponents data; URLComponents data;
@ -475,19 +506,19 @@ void test(const char *url)
printf("%s (%s)\n", url, ok ? "ok" : "error"); printf("%s (%s)\n", url, ok ? "ok" : "error");
URLGetComponentCString(url, &data, URLComponentScheme, buffer); URLComponentGetC(url, &data, URLComponentScheme, buffer);
printf(" scheme: %s\n", buffer); printf(" scheme: %s\n", buffer);
URLGetComponentCString(url, &data, URLComponentUser, buffer); URLComponentGetC(url, &data, URLComponentUser, buffer);
printf(" username: %s\n", buffer); printf(" username: %s\n", buffer);
URLGetComponentCString(url, &data, URLComponentPassword, buffer); URLComponentGetC(url, &data, URLComponentPassword, buffer);
printf(" password: %s\n", buffer); printf(" password: %s\n", buffer);
URLGetComponentCString(url, &data, URLComponentHost, buffer); URLComponentGetC(url, &data, URLComponentHost, buffer);
printf(" host: %s\n", buffer); printf(" host: %s\n", buffer);
URLGetComponentCString(url, &data, URLComponentPort, buffer); URLComponentGetC(url, &data, URLComponentPort, buffer);
printf(" port: %s [%d]\n", buffer, data.portNumber); printf(" port: %s [%d]\n", buffer, data.portNumber);
URLGetComponentCString(url, &data, URLComponentPath, buffer); URLGetComponentCString(url, &data, URLComponentPath, buffer);
@ -496,10 +527,10 @@ void test(const char *url)
URLGetComponentCString(url, &data, URLComponentParams, buffer); URLGetComponentCString(url, &data, URLComponentParams, buffer);
printf(" params: %s\n", buffer); printf(" params: %s\n", buffer);
URLGetComponentCString(url, &data, URLComponentQuery, buffer); URLComponentGetC(url, &data, URLComponentQuery, buffer);
printf(" query: %s\n", buffer); printf(" query: %s\n", buffer);
URLGetComponentCString(url, &data, URLComponentFragment, buffer); URLComponentGetC(url, &data, URLComponentFragment, buffer);
printf(" fragment: %s\n", buffer); printf(" fragment: %s\n", buffer);
free(buffer); free(buffer);
@ -517,3 +548,5 @@ int main(int argc, char **argv)
return 0; return 0;
} }
#endif

8
url.h
View File

@ -53,11 +53,11 @@ typedef struct URLComponents {
} URLComponents; } URLComponents;
int ParseURL(const char *url, int length, struct URLComponents *components); int ParseURL(const char *url, int length, URLComponents *components);
int URLGetComponentCString(const char *url, struct URLComponents *, int, char *); int URLComponentGet(const char *url, URLComponents *, int, char *);
int URLGetComponentPString(const char *url, struct URLComponents *, int, char *); int URLComponentGetC(const char *url, URLComponents *, int, char *);
//int URLGetComponentGSString(const char *url, struct URLComponents *, int, GSString255Ptr); //int URLComponentGetGS(const char *url, URLComponents *, int, GSString255Ptr);
#endif #endif