Retired Document
Important: This sample code may not represent best practices for current development. The project may use deprecated symbols and illustrate technologies and techniques that are no longer recommended.
OTSimpleDownloadHTTPTest.c
/* |
File: OTSimpleDownloadHTTPTest.c |
Contains: A test program for the simple HTTP download sample. |
Written by: Quinn "The Eskimo!" |
Copyright: Copyright © 1997-1999 by Apple Computer, Inc., All Rights Reserved. |
You may incorporate this Apple sample source code into your program(s) without |
restriction. This Apple sample source code has been provided "AS IS" and the |
responsibility for its operation is yours. You are not permitted to redistribute |
this Apple sample source code as "Apple sample source code" after having made |
changes. If you're going to re-distribute the source, we require that you make |
it clear in the source that the code was descended from Apple sample source |
code, but that you've made changes. |
Change History (most recent first): |
3/02/2001 Chad Jones Updated to Metroworks Codewarrior Pro IDE 4.1. Also carbonized for OSX. |
7/23/1999 Karl Groethe Updated for Metrowerks Codewarror Pro 2.1 |
*/ |
///////////////////////////////////////////////////////////////////// |
// Pick up our own prototype. |
#include "OTSimpleDownloadHTTP.h" |
///////////////////////////////////////////////////////////////////// |
// OTDebugStr is not defined in any OT header files, but it is |
// exported by the libraries, so we define the prototype here. |
extern pascal void OTDebugStr(const char* str); |
///////////////////////////////////////////////////////////////////// |
#if defined(__MWERKS__) |
# include <Threads.h> |
# include <string.h> |
# include <stdio.h> |
# include <ctype.h> |
#endif |
enum { |
kNotHTTPURLErr = -666, |
kWhatImplementationErr = -667 |
}; |
enum { |
kDownloadSimple, |
kDownloadFaster |
}; |
//These are my versions of PStrCat and PStrCopy. |
StringPtr PStrCat(StringPtr dst, ConstStr255Param src); |
StringPtr PStrCopy(StringPtr dst, ConstStr255Param src); |
StringPtr PStrCat(StringPtr dst, ConstStr255Param src) |
{ |
SInt16 size = src[0]; |
if (0xff - dst[0] < size) |
size = 0xff - dst[0]; |
BlockMoveData(&src[1], &dst[dst[0]], size); |
dst[0] = dst[0] + size; |
return dst; |
} |
StringPtr PStrCopy(StringPtr dst, ConstStr255Param src) |
{ |
dst[0] = src[0]; BlockMoveData(&src[1], &dst[1], src[0]); return dst; |
} |
static OSStatus DownloadURL(const char *urlString) |
{ |
OSStatus err; |
size_t hostCharCount; |
char hostName[256]; |
Str255 tickCountString; |
Str255 destFileName; |
FSSpec destFSSpec; |
short destFileRefNum; |
char httpGetCommand[256]; |
OTTimeStamp startTime; |
UInt32 timeToDownload; |
long fileSize; |
err = noErr; |
// First check that the urlString begins with "http://" |
if ( strspn(urlString, "http://") != strlen("http://") ) { |
err = kNotHTTPURLErr; |
} |
// Now skip over the "http://" and extract the host name. |
if (err == noErr) { |
// Skip over the "http://". |
urlString += strlen("http://"); |
// Count the characters before the next slash. |
hostCharCount = strcspn(urlString, "/"); |
// Extract those characters from the URL into hostName |
// and then make sure it's null terminated. |
(void) strncpy(hostName, urlString, hostCharCount); |
hostName[hostCharCount] = 0; |
urlString += hostCharCount; |
// Add a ":80" to the host name if necessary. |
if ( strchr( hostName, ':' ) == nil ) { |
strcat( hostName, ":80" ); |
} |
if (err == noErr) { |
NumToString(TickCount(), tickCountString); |
PStrCopy(destFileName, "\pSimpleDownload#"); |
PStrCat(destFileName, tickCountString); |
(void) FSMakeFSSpec(0, 0, destFileName, &destFSSpec); |
(void) FSpCreate(&destFSSpec, 'R*ch', 'TEXT', 0); |
err = FSpOpenDF(&destFSSpec, fsRdWrPerm, &destFileRefNum); |
if (err != noErr) { |
destFileRefNum = 0; |
} |
} |
if (err == noErr) { |
// Now place the URL into the HTTP command that we send to DownloadHTTPSimple. |
if ( *urlString == 0 ) { |
urlString = "/"; |
} |
(void) sprintf(httpGetCommand, "GET %s HTTP/1.0%c%c%c%c", urlString, 13, 10, 13, 10); |
printf("Calling DownloadHTTPXxxx(Ò%sÓ, Ò%sÓ, %04x).\n", hostName, urlString, destFileRefNum); |
fflush(stdout); |
OTGetTimeStamp(&startTime); |
err = DownloadHTTPSimple(hostName, httpGetCommand, destFileRefNum); |
timeToDownload = OTElapsedMicroseconds(&startTime); |
} |
if (err == noErr) { |
MoreAssert(GetFPos(destFileRefNum, &fileSize) == noErr); //Assertion Fails if: GetFPos failed |
printf("Bytes downloaded: %ld.\n", fileSize); |
printf("Time to download: %ldus.\n", timeToDownload); |
printf("Bytes per second: %f.\n", (float) fileSize / (((float) timeToDownload) / 1000000.0) ); |
fflush(stdout); |
} |
// Clean up. |
if (destFileRefNum != 0) { |
(void) FSClose(destFileRefNum); |
} |
if (err != noErr) { |
//(void) FSpDelete(&destFSSpec); |
} |
} |
return (err); |
} |
static UInt32 gLastPrinted = 0; |
static pascal OSStatus ProgressThread(void *junkParam) |
{ |
#pragma unused(junkParam) |
OSStatus junk; |
while (true) { |
if ( TickCount() > (gLastPrinted + 60) ) { |
printf("."); |
fflush(stdout); |
gLastPrinted = TickCount(); |
} |
junk = YieldToAnyThread(); |
MoreAssert(junk == noErr); //Assertion fails if: YieldToAnyThread failed |
} |
return (noErr); |
} |
static const char *defaultURLs[10] = { |
"http://www.apple.com", |
"http://www.apple.com/developer/", |
"http://developer.apple.com/dev/opentransport/", |
"http://developer.apple.com/technotes/index.html", |
"", |
"", |
"", |
"", |
"", |
"" |
}; |
int main(void) |
{ |
OSStatus err; |
OSStatus junk; |
char urlString[256]; |
UInt32 i; |
ThreadID progressThread; |
#if defined(__MWERKS__) |
SIOUXSettings.autocloseonquit = FALSE; // don't close the SIOUX window on program termination |
SIOUXSettings.asktosaveonclose = FALSE; // don't offer to save on a close |
#endif |
printf("OTDownloadHTTP!\n"); |
printf("-- Downloads a URL using OT's thread support\n"); |
printf("-- or using notifiers.\n"); |
printf("\n"); |
fflush(stdout); |
err = InitOpenTransportInContext(kInitOTForApplicationMask, nil); |
if (err == noErr) { |
for (i = 0; i < 10; i++) { |
if ( *defaultURLs[i] != 0 ) { |
printf("%ld> %s\n", i, defaultURLs[i]); |
fflush(stdout); |
} |
} |
printf("\n"); |
printf("Enter a URL (or type a number from the above list):\n"); |
fflush(stdout); |
scanf("%s", (char *)&urlString); |
if ( strlen(urlString) == 1 && isdigit(urlString[0])) { |
strcpy( urlString, defaultURLs[ urlString[0] - '0' ] ); |
} |
if ( urlString[0] == 0 ) { |
strcpy( urlString, defaultURLs[0] ); |
} |
err = NewThread(kCooperativeThread, |
NewThreadEntryUPP((void *) &ProgressThread), nil, |
0, kCreateIfNeeded, |
nil, |
&progressThread); |
if (err == noErr) { |
err = DownloadURL(urlString); |
junk = DisposeThread(progressThread, nil, true); |
MoreAssert(junk == noErr); //Assertion fails if: DisposeThread failed |
} |
CloseOpenTransportInContext(nil); |
} |
if (err == noErr) { |
printf("Success.\n"); |
} else { |
printf("Failed with error %ld.\n", err); |
} |
printf("Done.\n"); |
fflush(stdout); |
return(0); |
} |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-01-14