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