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 "url.h"
#include "Connect.h"
#include "url.h"
#include "connection.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
/*
* connect gopher.floodgap.com:70
@ -24,7 +26,7 @@ enum {
kConnected = 4
};
Word StartUp(void)
Word StartUp(displayPtr fx)
{
word status;
word flags = 0;
@ -32,7 +34,7 @@ Word StartUp(void)
status = TCPIPStatus();
if (_toolErr)
{
LoadOneTool(54,0x0200);
LoadOneTool(54, 0x0201);
if (_toolErr) return -1;
status = 0;
@ -49,17 +51,18 @@ Word StartUp(void)
status = TCPIPGetConnectStatus();
if (!status)
{
TCPIPConnect(NULL);
TCPIPConnect(fx);
flags |= kConnected;
}
return flags;
}
void ShutDown(word flags)
void ShutDown(word flags, Boolean force, displayPtr fx)
{
if (flags & kConnected)
{
TCPIPDisconnect(false, NULL);
TCPIPDisconnect(force, fx);
if (_toolErr) return;
}
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)
{
URLComponents components;
ConnectBuffer buffer;
Connection buffer;
char *host;
char type;
if (ParseURL(url, strlen(url), &components))
if (!ParseURL(url, strlen(url), &components))
{
fprintf(stderr, "Invalid URL: %s\n", url);
return;
}
if (!url.host.length)
if (!components.host.length)
{
fprintf(stderr, "No host\n");
return;
}
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());
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);
ConnectionOpenC(&buffer, host, components.portNumber);
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);
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);
while (!ConnectionPoll(&buffer)) ; // wait for it to close.
@ -125,82 +277,22 @@ void do_url(const char *url)
free (host);
}
#endif
int main(int argc, char **argv)
{
Handle h;
ConnectBuffer buffer;
int i;
Word rv;
Word flags;
// getopt for -b binary
flags = StartUp(NULL);
#if 0
for (i = 1; i < argc; ++i)
{
do_url(argv[i]);
}
#endif
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);
ShutDown(flags, false, NULL);
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 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
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)
{
URLComponents data;
@ -475,19 +506,19 @@ void test(const char *url)
printf("%s (%s)\n", url, ok ? "ok" : "error");
URLGetComponentCString(url, &data, URLComponentScheme, buffer);
URLComponentGetC(url, &data, URLComponentScheme, buffer);
printf(" scheme: %s\n", buffer);
URLGetComponentCString(url, &data, URLComponentUser, buffer);
URLComponentGetC(url, &data, URLComponentUser, buffer);
printf(" username: %s\n", buffer);
URLGetComponentCString(url, &data, URLComponentPassword, buffer);
URLComponentGetC(url, &data, URLComponentPassword, buffer);
printf(" password: %s\n", buffer);
URLGetComponentCString(url, &data, URLComponentHost, buffer);
URLComponentGetC(url, &data, URLComponentHost, buffer);
printf(" host: %s\n", buffer);
URLGetComponentCString(url, &data, URLComponentPort, buffer);
URLComponentGetC(url, &data, URLComponentPort, buffer);
printf(" port: %s [%d]\n", buffer, data.portNumber);
URLGetComponentCString(url, &data, URLComponentPath, buffer);
@ -496,10 +527,10 @@ void test(const char *url)
URLGetComponentCString(url, &data, URLComponentParams, buffer);
printf(" params: %s\n", buffer);
URLGetComponentCString(url, &data, URLComponentQuery, buffer);
URLComponentGetC(url, &data, URLComponentQuery, buffer);
printf(" query: %s\n", buffer);
URLGetComponentCString(url, &data, URLComponentFragment, buffer);
URLComponentGetC(url, &data, URLComponentFragment, buffer);
printf(" fragment: %s\n", buffer);
free(buffer);
@ -517,3 +548,5 @@ int main(int argc, char **argv)
return 0;
}
#endif

8
url.h
View File

@ -53,11 +53,11 @@ typedef struct 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 URLGetComponentPString(const char *url, struct URLComponents *, int, char *);
//int URLGetComponentGSString(const char *url, struct URLComponents *, int, GSString255Ptr);
int URLComponentGet(const char *url, URLComponents *, int, char *);
int URLComponentGetC(const char *url, URLComponents *, int, char *);
//int URLComponentGetGS(const char *url, URLComponents *, int, GSString255Ptr);
#endif