mirror of
https://github.com/ksherlock/gopher.git
synced 2025-02-08 17:30:23 +00:00
common code, http chunked responses.
This commit is contained in:
parent
9f570ffc82
commit
f67e5f11a8
72
common.c
72
common.c
@ -12,19 +12,26 @@
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "connection.h"
|
||||
#include "prototypes.h"
|
||||
#include "connection.h"
|
||||
|
||||
int read_binary(Word ipid, FILE *file)
|
||||
int read_binary(Word ipid, FILE *file, ReadBlock *dcb)
|
||||
{
|
||||
Word rv = 0;
|
||||
|
||||
|
||||
if (dcb) dcb->transferCount = 0;
|
||||
|
||||
IncBusy();
|
||||
TCPIPPoll();
|
||||
DecBusy();
|
||||
|
||||
for(;;)
|
||||
{
|
||||
static char buffer[512];
|
||||
rrBuff rb;
|
||||
Word count;
|
||||
Word tcount;
|
||||
|
||||
IncBusy();
|
||||
rv = TCPIPReadTCP(ipid, 0, (Ref)buffer, 512, &rb);
|
||||
@ -40,12 +47,69 @@ int read_binary(Word ipid, FILE *file)
|
||||
continue;
|
||||
}
|
||||
|
||||
fwrite(buffer, 1, count, file);
|
||||
tcount = fwrite(buffer, 1, count, file);
|
||||
if (dcb) dcb->transferCount += tcount;
|
||||
|
||||
if (tcount != count) return -1;
|
||||
|
||||
}
|
||||
|
||||
return rv;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ReadTCP will only return if the entire request is fulfilled or the connection closes,
|
||||
// so it could just do that. For a large request, this is probably nicer.
|
||||
int read_binary_size(Word ipid, FILE *file, ReadBlock *dcb)
|
||||
{
|
||||
Word rv = 0;
|
||||
LongWord size;
|
||||
if (!dcb) return -1;
|
||||
|
||||
dcb->transferCount = 0;
|
||||
size = dcb->requestCount;
|
||||
if (!size) return 0;
|
||||
|
||||
IncBusy();
|
||||
TCPIPPoll();
|
||||
DecBusy();
|
||||
|
||||
for(;;)
|
||||
{
|
||||
static char buffer[512];
|
||||
rrBuff rb;
|
||||
Word count;
|
||||
Word tcount;
|
||||
|
||||
count = 512;
|
||||
if (count > size) count = size;
|
||||
|
||||
IncBusy();
|
||||
rv = TCPIPReadTCP(ipid, 0, (Ref)buffer, count, &rb);
|
||||
DecBusy();
|
||||
|
||||
count = rb.rrBuffCount;
|
||||
if (!count)
|
||||
{
|
||||
if (rv) break;
|
||||
IncBusy();
|
||||
TCPIPPoll();
|
||||
DecBusy();
|
||||
continue;
|
||||
}
|
||||
|
||||
tcount = fwrite(buffer, 1, count, file);
|
||||
|
||||
dcb->transferCount += tcount;
|
||||
size -= tcount;
|
||||
|
||||
if (tcount != count) return -1;
|
||||
|
||||
if (!size) return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
int ConnectLoop(char *host, Word port, Connection *connection)
|
||||
|
14
gopher.c
14
gopher.c
@ -24,6 +24,16 @@
|
||||
|
||||
extern int setfiletype(const char *filename);
|
||||
|
||||
static int gopher_binary(Word ipid, FILE *file)
|
||||
{
|
||||
ReadBlock dcb;
|
||||
int ok;
|
||||
|
||||
ok = read_binary(ipid, file, &dcb);
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
/*
|
||||
* connect gopher.floodgap.com:70
|
||||
* send path
|
||||
@ -32,8 +42,6 @@ extern int setfiletype(const char *filename);
|
||||
* bin -- ends when connection is closed.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
static int gopher_text(Word ipid, FILE *file)
|
||||
{
|
||||
// text \r\n
|
||||
@ -397,7 +405,7 @@ int do_gopher(const char *url, URLComponents *components)
|
||||
case '5':
|
||||
case '9':
|
||||
fsetbinary(file);
|
||||
ok = read_binary(connection.ipid, file);
|
||||
ok = gopher_binary(connection.ipid, file);
|
||||
break;
|
||||
default:
|
||||
ok = gopher_text(connection.ipid, file);
|
||||
|
125
http.c
125
http.c
@ -21,6 +21,7 @@
|
||||
#include <MiscTool.h>
|
||||
#include <Memory.h>
|
||||
#include <IntMath.h>
|
||||
#include <TimeTool.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
@ -44,6 +45,7 @@ static int do_http_0_9(
|
||||
FILE *file,
|
||||
const char *filename)
|
||||
{
|
||||
ReadBlock dcb;
|
||||
int ok;
|
||||
|
||||
char *cp;
|
||||
@ -67,8 +69,8 @@ static int do_http_0_9(
|
||||
TCPIPWriteTCP(ipid, "\r\n", 2, true, false);
|
||||
DecBusy();
|
||||
|
||||
ok = read_binary(ipid, file);
|
||||
return 0;
|
||||
ok = read_binary(ipid, file, &dcb);
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
||||
@ -212,9 +214,9 @@ enum {
|
||||
TE_chunked
|
||||
};
|
||||
|
||||
int http_read_chunked(ipid, file)
|
||||
int http_read_chunked(word ipid, FILE *file)
|
||||
{
|
||||
|
||||
ReadBlock dcb;
|
||||
rlBuffer rb;
|
||||
LongWord chunkSize;
|
||||
LongWord count;
|
||||
@ -225,7 +227,8 @@ int http_read_chunked(ipid, file)
|
||||
|
||||
for (;;)
|
||||
{
|
||||
|
||||
char *cp;
|
||||
|
||||
// get the chunk size.
|
||||
// 0 indicates end.
|
||||
for (;;)
|
||||
@ -260,14 +263,20 @@ int http_read_chunked(ipid, file)
|
||||
// now read the data.
|
||||
if (chunkSize == 0) return 0; // eof.
|
||||
|
||||
ok = read_binary(ipid, file, chunkSize);
|
||||
dcb.requestCount = chunkSize;
|
||||
ok = read_binary_size(ipid, file, &dcb);
|
||||
if (ok < 0) return -1;
|
||||
if (ok != chunkSize) return -1;
|
||||
|
||||
if (dcb.requestCount != dcb.transferCount)
|
||||
{
|
||||
fprintf(stderr, "Read error - requested %ld, received %ld\n",
|
||||
dcb.requestCount, dcb.transferCount);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// read CRLF.
|
||||
for(;;)
|
||||
{
|
||||
ok = ReadLine2(ipid, &rl);
|
||||
ok = ReadLine2(ipid, &rb);
|
||||
if (ok == -1) return -1;
|
||||
if (ok == 0)
|
||||
{
|
||||
@ -276,13 +285,17 @@ int http_read_chunked(ipid, file)
|
||||
}
|
||||
if (ok == 1)
|
||||
{
|
||||
if (count) wtf
|
||||
if (rb.bufferSize)
|
||||
{
|
||||
fprintf(stderr, "Unexpected data in chunked response.\n");
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int read_response(Word ipid, FILE *file, Handle dict)
|
||||
@ -298,6 +311,9 @@ int read_response(Word ipid, FILE *file, Handle dict)
|
||||
int transferEncoding;
|
||||
|
||||
LongWord contentSize;
|
||||
|
||||
int haveTime = 0;
|
||||
timeGSRec time;
|
||||
|
||||
|
||||
contentSize = 0;
|
||||
@ -342,6 +358,30 @@ int read_response(Word ipid, FILE *file, Handle dict)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
value = DictionaryGet(dict, "Last-Modified", 13, &valueSize);
|
||||
if (value && valueSize <= 255)
|
||||
{
|
||||
char *pstring;
|
||||
|
||||
pstring = (char *)malloc(valueSize + 1);
|
||||
if (pstring)
|
||||
{
|
||||
*pstring = valueSize;
|
||||
memcpy(pstring + 1, value, valueSize);
|
||||
|
||||
// parse the last-modified timestamp.
|
||||
// 0x0e00 is rfc 822 format.
|
||||
// (which is now obsoleted by rfc 2822 but close enough)
|
||||
tiParseDateString(&time, pstring, 0x0e00);
|
||||
if (!_toolErr)
|
||||
{
|
||||
haveTime = 1;
|
||||
}
|
||||
free(pstring);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ?
|
||||
if (transferEncoding == -1)
|
||||
@ -355,57 +395,20 @@ int read_response(Word ipid, FILE *file, Handle dict)
|
||||
{
|
||||
// identity.
|
||||
// just read contentLength bytes.
|
||||
|
||||
static srBuff sr;
|
||||
static rrBuff rr;
|
||||
|
||||
int terr;
|
||||
|
||||
// todo -- time out if no data for 30 seconds?
|
||||
|
||||
while (contentSize)
|
||||
{
|
||||
LongWord count = 256;
|
||||
|
||||
IncBusy();
|
||||
TCPIPPoll();
|
||||
TCPIPStatusTCP(ipid, &sr);
|
||||
DecBusy();
|
||||
|
||||
count = sr.srRcvQueued;
|
||||
if (count > contentSize) count = contentSize;
|
||||
|
||||
if (count == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
IncBusy();
|
||||
terr = TCPIPReadTCP(ipid, 2, (Ref)0, count, &rr);
|
||||
DecBusy();
|
||||
|
||||
if (_toolErr) break;
|
||||
|
||||
if (rr.rrBuffCount)
|
||||
{
|
||||
Handle h = rr.rrBuffHandle;
|
||||
HLock(h);
|
||||
|
||||
fwrite(*(char **)h, 1, count, file);
|
||||
contentSize -= rr.rrBuffCount;
|
||||
|
||||
DisposeHandle(h);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (terr && !rr.rrMoreFlag)
|
||||
{
|
||||
fprintf(stderr, "read error\n");
|
||||
return -1;
|
||||
}
|
||||
ReadBlock dcb;
|
||||
int ok;
|
||||
|
||||
dcb.requestCount = contentSize;
|
||||
ok = read_binary_size(ipid, file, &dcb);
|
||||
|
||||
if (!ok) return -1;
|
||||
if (dcb.transferCount != dcb.requestCount)
|
||||
{
|
||||
fprintf(stderr, "Read error - requested %ld, received %ld\n",
|
||||
dcb.requestCount, dcb.transferCount);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -514,6 +517,7 @@ static int do_http_1_1(
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
if (ok == 200)
|
||||
{
|
||||
if (!flags._I)
|
||||
@ -522,7 +526,6 @@ static int do_http_1_1(
|
||||
DisposeHandle(dict);
|
||||
|
||||
|
||||
//ok = read_binary(ipid, file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -14,7 +14,14 @@
|
||||
#define CLI() asm { cli }
|
||||
|
||||
|
||||
int read_binary(unsigned ipid, FILE *file);
|
||||
typedef struct ReadBlock
|
||||
{
|
||||
LongWord requestCount;
|
||||
LongWord transferCount;
|
||||
} ReadBlock;
|
||||
|
||||
int read_binary(unsigned ipid, FILE *file, ReadBlock *);
|
||||
int read_binary_size(unsigned ipid, FILE *file, ReadBlock *);
|
||||
|
||||
int setfiletype(const char *filename);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user