mirror of
https://github.com/sheumann/NetDisk.git
synced 2024-11-27 19:49:38 +00:00
Support for HTTP redirects.
This commit is contained in:
parent
133c7f17b1
commit
179c0afe56
119
http.c
119
http.c
@ -14,6 +14,7 @@
|
||||
#include "http.h"
|
||||
#include "tcpconnection.h"
|
||||
#include "strcasecmp.h"
|
||||
#include "seturl.h"
|
||||
|
||||
#define buffTypePointer 0x0000 /* For TCPIPReadTCP() */
|
||||
#define buffTypeHandle 0x0001
|
||||
@ -70,31 +71,52 @@ Boolean BuildHTTPRequest(Session *sess, char *resourceStr) {
|
||||
} while (round++ == 0);
|
||||
|
||||
sess->httpRequestRange = sess->httpRequest + rangeOffset;
|
||||
|
||||
UpdateRequestRange(sess, sess->desiredStart, sess->desiredEnd);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
void UpdateRequestRange(Session *sess, unsigned long start, unsigned long end) {
|
||||
int count =
|
||||
snprintf(sess->httpRequestRange, 10+1+10+5, "%lu-%lu\r\n\r\n", start, end);
|
||||
|
||||
sess->desiredStart = start;
|
||||
sess->desiredEnd = end;
|
||||
|
||||
sess->httpRequestLen = sess->httpRequestRange - sess->httpRequest + count;
|
||||
}
|
||||
|
||||
#pragma debug -1
|
||||
|
||||
enum RequestResult DoHTTPRequest(Session *sess) {
|
||||
top:;
|
||||
rlrBuff rlrBuff = {0};
|
||||
Word tcpError;
|
||||
Boolean wantRedirect = FALSE;
|
||||
Boolean wantRedirect = FALSE, gotRedirect = FALSE;
|
||||
enum RequestResult result;
|
||||
|
||||
sess->responseCode = 0;
|
||||
|
||||
/* Send out request */
|
||||
result = NETWORK_ERROR;
|
||||
tcpError = TCPIPWriteTCP(sess->ipid, sess->httpRequest,
|
||||
sess->httpRequestLen, TRUE, FALSE);
|
||||
if (tcpError || toolerror())
|
||||
goto errorReturn;
|
||||
unsigned int netErrors = 0;
|
||||
do {
|
||||
if (!sess->tcpLoggedIn || netErrors) {
|
||||
if (StartTCPConnection(sess) != 0)
|
||||
goto errorReturn;
|
||||
}
|
||||
tcpError = TCPIPWriteTCP(sess->ipid, sess->httpRequest,
|
||||
sess->httpRequestLen, TRUE, FALSE);
|
||||
if (tcpError || toolerror()) {
|
||||
if (netErrors == 0) {
|
||||
netErrors++;
|
||||
continue;
|
||||
} else {
|
||||
goto errorReturn;
|
||||
}
|
||||
}
|
||||
} while (0);
|
||||
|
||||
/* Get response status line & headers */
|
||||
LongWord startTime = GetTick();
|
||||
@ -158,7 +180,7 @@ top:;
|
||||
response++;
|
||||
|
||||
|
||||
switch(sess->responseCode) {
|
||||
switch((unsigned int)sess->responseCode) {
|
||||
/* "Partial content" response, as expected */
|
||||
case 206:
|
||||
break;
|
||||
@ -190,21 +212,25 @@ top:;
|
||||
while (response < responseEnd - 2) {
|
||||
enum ResponseHeader header = UNKNOWN_HEADER;
|
||||
|
||||
if (strncasecmp(response, "Content-Range:", 14) == 0) {
|
||||
response += 14;
|
||||
header = CONTENT_RANGE;
|
||||
} else if (strncasecmp(response, "Content-Length:", 15) == 0) {
|
||||
response += 15;
|
||||
header = CONTENT_LENGTH;
|
||||
} else if (strncasecmp(response, "Transfer-Encoding:", 18) == 0) {
|
||||
response += 18;
|
||||
header = TRANSFER_ENCODING;
|
||||
} else if (strncasecmp(response, "Content-Encoding:", 17) == 0) {
|
||||
response += 17;
|
||||
header = CONTENT_ENCODING;
|
||||
} else if (strncasecmp(response, "Location:", 9) == 0) {
|
||||
response += 9;
|
||||
header = LOCATION;
|
||||
if (wantRedirect) {
|
||||
if (strncasecmp(response, "Location:", 9) == 0) {
|
||||
response += 9;
|
||||
header = LOCATION;
|
||||
}
|
||||
} else {
|
||||
if (strncasecmp(response, "Content-Range:", 14) == 0) {
|
||||
response += 14;
|
||||
header = CONTENT_RANGE;
|
||||
} else if (strncasecmp(response, "Content-Length:", 15) == 0) {
|
||||
response += 15;
|
||||
header = CONTENT_LENGTH;
|
||||
} else if (strncasecmp(response, "Transfer-Encoding:", 18) == 0) {
|
||||
response += 18;
|
||||
header = TRANSFER_ENCODING;
|
||||
} else if (strncasecmp(response, "Content-Encoding:", 17) == 0) {
|
||||
response += 17;
|
||||
header = CONTENT_ENCODING;
|
||||
}
|
||||
}
|
||||
|
||||
while ((*response == ' ' || *response == '\t') && response < responseEnd)
|
||||
@ -240,7 +266,9 @@ top:;
|
||||
case CONTENT_LENGTH:
|
||||
errno = 0;
|
||||
sess->contentLength = strtoul(response, &endPtr, 10);
|
||||
if (errno || sess->contentLength == 0)
|
||||
if (errno)
|
||||
goto errorReturn;
|
||||
if (sess->contentLength == 0 && !wantRedirect)
|
||||
goto errorReturn;
|
||||
response = endPtr;
|
||||
break;
|
||||
@ -254,7 +282,23 @@ top:;
|
||||
}
|
||||
break;
|
||||
|
||||
case LOCATION: /*TODO*/ ;
|
||||
case LOCATION:
|
||||
endPtr = response;
|
||||
char c;
|
||||
while ((c = *endPtr)!=0 && c!='\r' && c!='\n' && c!=' ' && c!='\t')
|
||||
endPtr++;
|
||||
if (c == '\0' || c == '\n')
|
||||
goto errorReturn;
|
||||
if (wantRedirect) {
|
||||
*endPtr = '\0';
|
||||
if (SetURL(sess, response, FALSE, TRUE) != SETURL_SUCCESSFUL) {
|
||||
result = REDIRECT_ERROR;
|
||||
goto errorReturn;
|
||||
}
|
||||
*endPtr = c;
|
||||
response = endPtr;
|
||||
gotRedirect = TRUE;
|
||||
}
|
||||
|
||||
/* Unknown headers: ignored */
|
||||
case UNKNOWN_HEADER:
|
||||
@ -275,14 +319,35 @@ top:;
|
||||
response++;
|
||||
}
|
||||
|
||||
/* Wanted redirect, but to Location header found */
|
||||
/* Wanted redirect: Retry with new location if we got it. */
|
||||
if (wantRedirect) {
|
||||
result = UNSUPPORTED_RESPONSE;
|
||||
if (gotRedirect) {
|
||||
DisposeHandle(rlrBuff.rlrBuffHandle);
|
||||
goto top;
|
||||
} else {
|
||||
result = UNSUPPORTED_RESPONSE;
|
||||
goto errorReturn;
|
||||
}
|
||||
}
|
||||
|
||||
/* See if we got what we wanted */
|
||||
if (sess->expectedLength != 0 && sess->totalLength != sess->expectedLength) {
|
||||
result = DIFFERENT_LENGTH;
|
||||
goto errorReturn;
|
||||
}
|
||||
|
||||
result = NOT_DESIRED_CONTENT;
|
||||
if (sess->rangeStart != sess->desiredStart)
|
||||
goto errorReturn;
|
||||
if (sess->rangeEnd != sess->desiredEnd)
|
||||
goto errorReturn;
|
||||
if (sess->contentLength != 0
|
||||
&& sess->contentLength != (sess->desiredEnd - sess->desiredStart + 1))
|
||||
goto errorReturn;
|
||||
|
||||
result = REQUEST_SUCCESSFUL;
|
||||
DisposeHandle(rlrBuff.rlrBuffHandle);
|
||||
return REQUEST_SUCCESSFUL;
|
||||
return result;
|
||||
|
||||
errorReturn:
|
||||
if (rlrBuff.rlrBuffHandle != NULL) {
|
||||
|
3
http.h
3
http.h
@ -12,6 +12,9 @@ enum RequestResult {
|
||||
EXCESSIVE_REDIRECTS,
|
||||
UNSUPPORTED_RESPONSE,
|
||||
UNSUPPORTED_HEADER_VALUE,
|
||||
REDIRECT_ERROR,
|
||||
NOT_DESIRED_CONTENT,
|
||||
DIFFERENT_LENGTH, /* Might be considered successful later */
|
||||
};
|
||||
|
||||
Boolean BuildHTTPRequest(Session *sess, char *resourceStr);
|
||||
|
9
main.c
9
main.c
@ -17,7 +17,7 @@ redirects to:
|
||||
http://ia800505.us.archive.org/16/items/a2gs_System_1.0_1986_Apple_FW/System_1.0_1986_Apple_FW.2mg
|
||||
*/
|
||||
|
||||
char *defaultURL = "http://ia800505.us.archive.org/16/items/a2gs_System_1.0_1986_Apple_FW/System_1.0_1986_Apple_FW.2mg";
|
||||
char *defaultURL = "http://archive.org/download/a2gs_System_1.0_1986_Apple_FW/System_1.0_1986_Apple_FW.2mg";
|
||||
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
@ -60,14 +60,9 @@ int main(int argc, char **argv) {
|
||||
printf("=========\n");
|
||||
printf("\n", i);
|
||||
|
||||
int err;
|
||||
if ((err = StartTCPConnection(&sess)) != 0) {
|
||||
printf("StartTCPConnection error %i\n", err);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
enum RequestResult requestResult = DoHTTPRequest(&sess);
|
||||
printf("RequestResult %i\n", requestResult);
|
||||
printf("Response code %lu\n", sess.responseCode);
|
||||
|
||||
if (requestResult == REQUEST_SUCCESSFUL) {
|
||||
printf("rangeStart = %lu\n", sess.rangeStart);
|
||||
|
@ -24,7 +24,7 @@ typedef struct Session {
|
||||
LongWord httpRequestLen;
|
||||
|
||||
/* HTTP response code */
|
||||
unsigned long responseCode;
|
||||
LongWord responseCode;
|
||||
|
||||
/* IP address and TCP port of host */
|
||||
LongWord ipAddr;
|
||||
@ -42,6 +42,11 @@ typedef struct Session {
|
||||
LongWord rangeStart, rangeEnd, totalLength;
|
||||
/* Value reported by server in Content-Length header */
|
||||
LongWord contentLength;
|
||||
|
||||
/* Desired start/end of range for next request */
|
||||
LongWord desiredStart, desiredEnd;
|
||||
/* Expected length of disk image */
|
||||
LongWord expectedLength;
|
||||
} Session;
|
||||
|
||||
#endif
|
||||
|
@ -1,7 +1,7 @@
|
||||
#pragma noroot
|
||||
|
||||
#define aspNetworkErr 1
|
||||
#define aspNoRespErr 2
|
||||
#define NETWORK_ERR 1
|
||||
#define NO_RESP_ERR 2
|
||||
|
||||
#include <tcpip.h>
|
||||
#include <stdlib.h>
|
||||
@ -26,15 +26,15 @@ Word StartTCPConnection(Session *sess) {
|
||||
sess->ipid =
|
||||
TCPIPLogin(userid(), sess->ipAddr, sess->port, 0, 0x40);
|
||||
if (toolerror())
|
||||
return aspNetworkErr;
|
||||
return NETWORK_ERR;
|
||||
|
||||
tcperr = TCPIPOpenTCP(sess->ipid);
|
||||
if (toolerror()) {
|
||||
TCPIPLogout(sess->ipid);
|
||||
return aspNetworkErr;
|
||||
return NETWORK_ERR;
|
||||
} else if (tcperr != tcperrOK) {
|
||||
TCPIPLogout(sess->ipid);
|
||||
return aspNoRespErr;
|
||||
return NO_RESP_ERR;
|
||||
}
|
||||
|
||||
initialTime = GetTick();
|
||||
@ -45,7 +45,7 @@ Word StartTCPConnection(Session *sess) {
|
||||
if (mySRBuff.srState != TCPSESTABLISHED) {
|
||||
TCPIPAbortTCP(sess->ipid);
|
||||
TCPIPLogout(sess->ipid);
|
||||
return aspNoRespErr;
|
||||
return NO_RESP_ERR;
|
||||
}
|
||||
|
||||
sess->tcpLoggedIn = TRUE;
|
||||
|
Loading…
Reference in New Issue
Block a user