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 <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;
|
Word rv = 0;
|
||||||
|
|
||||||
|
|
||||||
|
if (dcb) dcb->transferCount = 0;
|
||||||
|
|
||||||
|
IncBusy();
|
||||||
TCPIPPoll();
|
TCPIPPoll();
|
||||||
|
DecBusy();
|
||||||
|
|
||||||
for(;;)
|
for(;;)
|
||||||
{
|
{
|
||||||
static char buffer[512];
|
static char buffer[512];
|
||||||
rrBuff rb;
|
rrBuff rb;
|
||||||
Word count;
|
Word count;
|
||||||
|
Word tcount;
|
||||||
|
|
||||||
IncBusy();
|
IncBusy();
|
||||||
rv = TCPIPReadTCP(ipid, 0, (Ref)buffer, 512, &rb);
|
rv = TCPIPReadTCP(ipid, 0, (Ref)buffer, 512, &rb);
|
||||||
|
@ -40,12 +47,69 @@ int read_binary(Word ipid, FILE *file)
|
||||||
continue;
|
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)
|
int ConnectLoop(char *host, Word port, Connection *connection)
|
||||||
|
|
14
gopher.c
14
gopher.c
|
@ -24,6 +24,16 @@
|
||||||
|
|
||||||
extern int setfiletype(const char *filename);
|
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
|
* connect gopher.floodgap.com:70
|
||||||
* send path
|
* send path
|
||||||
|
@ -32,8 +42,6 @@ extern int setfiletype(const char *filename);
|
||||||
* bin -- ends when connection is closed.
|
* bin -- ends when connection is closed.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int gopher_text(Word ipid, FILE *file)
|
static int gopher_text(Word ipid, FILE *file)
|
||||||
{
|
{
|
||||||
// text \r\n
|
// text \r\n
|
||||||
|
@ -397,7 +405,7 @@ int do_gopher(const char *url, URLComponents *components)
|
||||||
case '5':
|
case '5':
|
||||||
case '9':
|
case '9':
|
||||||
fsetbinary(file);
|
fsetbinary(file);
|
||||||
ok = read_binary(connection.ipid, file);
|
ok = gopher_binary(connection.ipid, file);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ok = gopher_text(connection.ipid, file);
|
ok = gopher_text(connection.ipid, file);
|
||||||
|
|
125
http.c
125
http.c
|
@ -21,6 +21,7 @@
|
||||||
#include <MiscTool.h>
|
#include <MiscTool.h>
|
||||||
#include <Memory.h>
|
#include <Memory.h>
|
||||||
#include <IntMath.h>
|
#include <IntMath.h>
|
||||||
|
#include <TimeTool.h>
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -44,6 +45,7 @@ static int do_http_0_9(
|
||||||
FILE *file,
|
FILE *file,
|
||||||
const char *filename)
|
const char *filename)
|
||||||
{
|
{
|
||||||
|
ReadBlock dcb;
|
||||||
int ok;
|
int ok;
|
||||||
|
|
||||||
char *cp;
|
char *cp;
|
||||||
|
@ -67,8 +69,8 @@ static int do_http_0_9(
|
||||||
TCPIPWriteTCP(ipid, "\r\n", 2, true, false);
|
TCPIPWriteTCP(ipid, "\r\n", 2, true, false);
|
||||||
DecBusy();
|
DecBusy();
|
||||||
|
|
||||||
ok = read_binary(ipid, file);
|
ok = read_binary(ipid, file, &dcb);
|
||||||
return 0;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -212,9 +214,9 @@ enum {
|
||||||
TE_chunked
|
TE_chunked
|
||||||
};
|
};
|
||||||
|
|
||||||
int http_read_chunked(ipid, file)
|
int http_read_chunked(word ipid, FILE *file)
|
||||||
{
|
{
|
||||||
|
ReadBlock dcb;
|
||||||
rlBuffer rb;
|
rlBuffer rb;
|
||||||
LongWord chunkSize;
|
LongWord chunkSize;
|
||||||
LongWord count;
|
LongWord count;
|
||||||
|
@ -225,7 +227,8 @@ int http_read_chunked(ipid, file)
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
|
char *cp;
|
||||||
|
|
||||||
// get the chunk size.
|
// get the chunk size.
|
||||||
// 0 indicates end.
|
// 0 indicates end.
|
||||||
for (;;)
|
for (;;)
|
||||||
|
@ -260,14 +263,20 @@ int http_read_chunked(ipid, file)
|
||||||
// now read the data.
|
// now read the data.
|
||||||
if (chunkSize == 0) return 0; // eof.
|
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 < 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.
|
// read CRLF.
|
||||||
for(;;)
|
for(;;)
|
||||||
{
|
{
|
||||||
ok = ReadLine2(ipid, &rl);
|
ok = ReadLine2(ipid, &rb);
|
||||||
if (ok == -1) return -1;
|
if (ok == -1) return -1;
|
||||||
if (ok == 0)
|
if (ok == 0)
|
||||||
{
|
{
|
||||||
|
@ -276,13 +285,17 @@ int http_read_chunked(ipid, file)
|
||||||
}
|
}
|
||||||
if (ok == 1)
|
if (ok == 1)
|
||||||
{
|
{
|
||||||
if (count) wtf
|
if (rb.bufferSize)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Unexpected data in chunked response.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int read_response(Word ipid, FILE *file, Handle dict)
|
int read_response(Word ipid, FILE *file, Handle dict)
|
||||||
|
@ -298,6 +311,9 @@ int read_response(Word ipid, FILE *file, Handle dict)
|
||||||
int transferEncoding;
|
int transferEncoding;
|
||||||
|
|
||||||
LongWord contentSize;
|
LongWord contentSize;
|
||||||
|
|
||||||
|
int haveTime = 0;
|
||||||
|
timeGSRec time;
|
||||||
|
|
||||||
|
|
||||||
contentSize = 0;
|
contentSize = 0;
|
||||||
|
@ -342,6 +358,30 @@ int read_response(Word ipid, FILE *file, Handle dict)
|
||||||
return -1;
|
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)
|
if (transferEncoding == -1)
|
||||||
|
@ -355,57 +395,20 @@ int read_response(Word ipid, FILE *file, Handle dict)
|
||||||
{
|
{
|
||||||
// identity.
|
// identity.
|
||||||
// just read contentLength bytes.
|
// 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)
|
ReadBlock dcb;
|
||||||
{
|
int ok;
|
||||||
continue;
|
|
||||||
}
|
dcb.requestCount = contentSize;
|
||||||
|
ok = read_binary_size(ipid, file, &dcb);
|
||||||
IncBusy();
|
|
||||||
terr = TCPIPReadTCP(ipid, 2, (Ref)0, count, &rr);
|
if (!ok) return -1;
|
||||||
DecBusy();
|
if (dcb.transferCount != dcb.requestCount)
|
||||||
|
{
|
||||||
if (_toolErr) break;
|
fprintf(stderr, "Read error - requested %ld, received %ld\n",
|
||||||
|
dcb.requestCount, dcb.transferCount);
|
||||||
if (rr.rrBuffCount)
|
return -1;
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -514,6 +517,7 @@ static int do_http_1_1(
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (ok == 200)
|
if (ok == 200)
|
||||||
{
|
{
|
||||||
if (!flags._I)
|
if (!flags._I)
|
||||||
|
@ -522,7 +526,6 @@ static int do_http_1_1(
|
||||||
DisposeHandle(dict);
|
DisposeHandle(dict);
|
||||||
|
|
||||||
|
|
||||||
//ok = read_binary(ipid, file);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,14 @@
|
||||||
#define CLI() asm { cli }
|
#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);
|
int setfiletype(const char *filename);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue