#include #include <68K\Hs.h> #include #include "peer.h" #include "httptest.h" #include "HTTPLibTest.h" // application resource defines #include "AppStdIO.h" #define DOWNLOAD_BUFFER_SIZE (8192) #define __SKIP_WRITE 0 /********************************************************************* * Local variables *********************************************************************/ #if 0 static Char *ProxyHost = "10.0.0.112"; static Int32 ProxyPort = 8001; static Char *NoProxyHost = ""; #endif static UInt16 gRefNum = sysInvalidRefNum; static HS_HTTPLibHandle gLibHandle = NULL; static HS_HTTPLibAppInfo gAppInfo; static HS_HTTPLibNetLibInfo gNetLibInfo; static HS_HTTPLibPeer gPeer; static Char title[50]; #define FrmSetTitle(...) if(0){} UInt32 gstartTicks; UInt32 gstopTicks; UInt32 glatencyTicks; Boolean gErrorFlag = false; /********************************************************************* * Function declaration *********************************************************************/ Int32 PrvTunnelingCallback(HS_HTTPLibStream in_stream, Char* buf, Int32 len, void *aux); /********************************************************************* * Data structure *********************************************************************/ enum { kDownloadState_None, kDownloadState_Request, kDownloadState_RequestWithPost, kDownloadState_RequestWithChunkEncoding, kDownloadState_ReceiveHeader, kDownloadState_ReceiveContent, kDownloadState_Close, kDownloadState_Done, kDownloadState_Error, kDownloadState_Cancel, kDownloadState_Abort, kDownloadState_Max }; typedef struct { HS_HTTPLibStream fHTTPStream; Int32 fState; Int32 fCurrentLength; Int32 fContentLength; Char *fBuffer; Int32 fBufferLen; Char *fPostData; Int32 fPostDataLen; Int32 fPostedLen; } DownloadInfo; /********************************************************************* * Functions *********************************************************************/ Err PrvHTTPLibInitialize(void) { Err err = errNone; /* load the library */ if( gRefNum == sysInvalidRefNum ) { err = SysLibFind(HS_HTTPLibName, &gRefNum); if (err) { err = SysLibLoad(HS_HTTPLibDBType, HS_HTTPLibID, &gRefNum); } if (err) { return err; } } err = HS_HTTPLibOpen(gRefNum); /* gPeer */ MemSet(&gPeer, sizeof(HS_HTTPLibPeer), 0); gPeer.HS_HTTPLibPeerTCPOpen = &PrvTCPOpen; gPeer.HS_HTTPLibPeerTCPClose = &PrvTCPClose; gPeer.HS_HTTPLibPeerTCPIsConnected = &PrvTCPIsConnected; gPeer.HS_HTTPLibPeerTCPConnect = &PrvTCPConnect; gPeer.HS_HTTPLibPeerTCPRead = &PrvTCPRead; gPeer.HS_HTTPLibPeerTCPWrite = &PrvTCPWrite; gPeer.HS_HTTPLibPeerTCPCanReadWrite = &PrvTCPCanReadWrite; gAppInfo.maxSockets = 3; gAppInfo.isForeground = true; gAppInfo.cookieMaxJarSize = (UInt16)300 * (UInt16)1024; PrvPeerInitialize(); gLibHandle = HS_HTTPLibInitialize(gRefNum, &gAppInfo, &gNetLibInfo, &gPeer); /* set callbacks */ //HS_HTTPLibSetSSLServerCertConfirmProc(gRefNum, gLibHandle, &test_confirm_cb, (HS_HTTPLibOpaque)gLibHandle); //HS_HTTPLibSetTunnelingCallback(gRefNum, gLibHandle, &PrvTunnelingCallback, NULL); /* set timeout time */ HS_HTTPLibSetConnectTimeOut(gRefNum, gLibHandle, -1); HS_HTTPLibSetReqTimeOut(gRefNum, gLibHandle, -1); HS_HTTPLibSetRspTimeOut(gRefNum, gLibHandle, 10 * 1000); /* set proxy info */ //HS_HTTPLibSetProxy(gRefNum, gLibHandle, ProxyHost, StrLen(ProxyHost), ProxyPort, ProxyPort, NoProxyHost, 0); //HS_HTTPLibSetUseProxy(gRefNum, gLibHandle, true); return err; } Err PrvHTTPLibFinalize(void) { Err err; UInt16 count; HS_HTTPLibFinalize(gRefNum, gLibHandle); PrvPeerFinalize(); err = HS_HTTPLibClose(gRefNum, &count); /* unload the library */ if( gRefNum != sysInvalidRefNum ){ SysLibRemove(gRefNum); gRefNum = sysInvalidRefNum; } return err; } Int32 PrvTunnelingCallback(HS_HTTPLibStream in_stream, Char* buf, Int32 len, void *aux) { return 0; } #if __SKIP_WRITE /********************************************************************* * Store Functions *********************************************************************/ static void set_text(Char *str) { FileHand file; UInt32 mode = fileModeAppend; Int32 nwritten = 0; Err err = errNone; if (str == NULL) return; file = FileOpen (0, "httpdata.pdb", 0, 0, mode, &err); if (file != 0) { nwritten = FileWrite (file, str, StrLen(str), 1, &err); FileClose(file); } } #endif /********************************************************************* * Download Functions *********************************************************************/ static Int32 download_open(DownloadInfo *self) { return 0;//dummy } static Int32 download_write(DownloadInfo *self, Int32 in_len) { #if __SKIP_WRITE // this code works, but don't want overhead for throughput test Char *buffer; if (in_len == 0) return 0; buffer = MemPtrNew(in_len); if (buffer) { MemMove(buffer, self->fBuffer, in_len); set_text(buffer); buffer[in_len] = 0; MemPtrFree(buffer); } #endif return 0;//dummy } static void download_close(DownloadInfo *self) { if(self->fHTTPStream){ HS_HTTPLibStreamClose(gRefNum, self->fHTTPStream ); /* Close HTTP */ HS_HTTPLibStreamDelete(gRefNum, self->fHTTPStream ); self->fHTTPStream = NULL; } } static Int32 download_do_request(DownloadInfo *self) { Int32 result; result = HS_HTTPLibStreamSendRequest(gRefNum, self->fHTTPStream, NULL); if(result == httpErrorOK){ self->fState = kDownloadState_ReceiveHeader; }else if(result == httpErrorWouldBlock){ /* do nothing */ }else{ self->fState = kDownloadState_Error; } result = httpErrorWouldBlock; return result; } static Int32 download_do_request_withpost(DownloadInfo *self) { Int32 result; Int32 writtenLen; result = HS_HTTPLibStreamSendRequestWithPostData(gRefNum, self->fHTTPStream, self->fPostData, self->fPostDataLen - self->fPostedLen, &writtenLen, NULL); if(writtenLen > 0){ self->fPostData += writtenLen; self->fPostedLen += writtenLen; } if(result == httpErrorOK){ self->fState = kDownloadState_ReceiveHeader; }else if(result == httpErrorWouldBlock){ /* do nothing */ }else{ Char error[30]; StrIToA(error, result); FrmCustomAlert(ErrorAlert, "request withpost", error, ""); self->fState = kDownloadState_Error; } result = httpErrorWouldBlock; return result; } static Int32 download_receive_header(DownloadInfo *self) { Int32 result; Int32 len=0; //HS_HTTPLibVHandle hdrH=NULL; result = HS_HTTPLibStreamReceiveResponse(gRefNum, self->fHTTPStream, NULL, 0, &len, NULL); //hdrH = HS_HTTPLibStreamGetResponseHeader(gRefNum, self->fHTTPStream); switch(result){ case httpErrorOK: //self->fState = kDownloadState_ReceiveContent; case httpErrorWouldBlock: if(HS_HTTPLibStreamIsHeaderReceived(gRefNum, self->fHTTPStream)){ self->fState = kDownloadState_ReceiveContent; self->fContentLength = HS_HTTPLibStreamGetContentLength(gRefNum, self->fHTTPStream); } else { Int32 hLen; hLen = HS_HTTPLibStreamGetResponseHeaderLength(gRefNum, self->fHTTPStream); // when hLen > 0, start content timer // everything up to here is latency! glatencyTicks = TimGetTicks(); } break; default: self->fState = kDownloadState_Error; break; } result = httpErrorWouldBlock; return result; } static Int32 download_receive_content(DownloadInfo *self) { Int32 result; Int32 len; result = HS_HTTPLibStreamReceiveResponse(gRefNum, self->fHTTPStream, self->fBuffer, self->fBufferLen, &len, NULL); switch(result){ case httpErrorOK: case httpErrorWouldBlock: case httpErrorIOSleep: if(len > 0){ download_write(self, len); self->fCurrentLength += len; } else { if(len == 0){ download_write(self, len);/* for ExchangeManager GUI */ } } if(self->fContentLength > 0){ if(self->fContentLength <= self->fCurrentLength){ self->fState = kDownloadState_Close; } } if(result == httpErrorOK){ self->fContentLength += self->fCurrentLength; self->fState = kDownloadState_Close; } break; default: self->fState = kDownloadState_Error; break; } result = httpErrorWouldBlock; return result; } static Int32 download_receive_close(DownloadInfo *self) { download_close(self); self->fState = kDownloadState_Done; return httpErrorWouldBlock; } static Int32 download_receive_done(DownloadInfo *self) { return httpErrorOK; } static Int32 download_receive_error(DownloadInfo *self) { download_close(self); self->fState = kDownloadState_Abort; gErrorFlag = true; return httpErrorWouldBlock; } static Int32 download_receive_cancel(DownloadInfo *self) { download_close(self); self->fState = kDownloadState_Abort; return httpErrorWouldBlock; } static Int32 download_receive_abort(DownloadInfo *self) { return httpErrorOK; } static DownloadInfo * DonwloadInfoNew(Char *urlP) { DownloadInfo *infoP = NULL; infoP = (DownloadInfo *)MemPtrNew(sizeof(DownloadInfo)); if(!infoP) return NULL; MemSet(infoP, sizeof(DownloadInfo), 0); infoP->fState = kDownloadState_Request; infoP->fCurrentLength = 0; infoP->fContentLength = 0; infoP->fBufferLen = DOWNLOAD_BUFFER_SIZE; infoP->fPostDataLen = 0; infoP->fPostData = NULL; infoP->fPostedLen = 0; infoP->fBuffer = MemPtrNew(DOWNLOAD_BUFFER_SIZE); infoP->fHTTPStream = HS_HTTPLibStreamNew(gRefNum, gLibHandle); if(!infoP->fHTTPStream) goto error; download_open(infoP); return infoP; error: if(infoP->fBuffer){ MemPtrFree(infoP->fBuffer); } if(infoP->fHTTPStream){ HS_HTTPLibStreamClose(gRefNum, infoP->fHTTPStream); /* Close HTTP */ HS_HTTPLibStreamDelete(gRefNum, infoP->fHTTPStream); } MemPtrFree(infoP); return NULL; } static void DonwloadInfoFree(DownloadInfo *self) { if(!self) return; if(self->fBuffer){ MemPtrFree(self->fBuffer); } if(self->fHTTPStream){ HS_HTTPLibStreamClose(gRefNum, self->fHTTPStream); /* Close HTTP */ HS_HTTPLibStreamDelete(gRefNum, self->fHTTPStream); } MemPtrFree(self); } static Int32 DownloadInfoProgress(DownloadInfo *self) { Int32 result = httpErrorOK; switch(self->fState){ case kDownloadState_None: break; case kDownloadState_Request: FrmSetTitle(FrmGetFormPtr(MainForm), NULL); StrCopy(title, "Requesting"); result = download_do_request(self); break; case kDownloadState_RequestWithPost: FrmSetTitle(FrmGetFormPtr(MainForm), NULL); StrCopy(title, "Requesting w/ post"); result = download_do_request_withpost(self); break; case kDownloadState_ReceiveHeader: FrmSetTitle(FrmGetFormPtr(MainForm), NULL); StrCopy(title, "Receive Header"); result = download_receive_header(self); //HsExtTraceText (gTraceContext, kHsExtTraceLevelDevInfo, // "result: %ld", result); break; case kDownloadState_ReceiveContent: FrmSetTitle(FrmGetFormPtr(MainForm), NULL); StrCopy(title, "Receive Content"); result = download_receive_content(self); break; case kDownloadState_Close: result = download_receive_close(self); break; case kDownloadState_Done: FrmSetTitle(FrmGetFormPtr(MainForm), NULL); StrCopy(title, "Done"); result = download_receive_done(self); break; case kDownloadState_Error: FrmSetTitle(FrmGetFormPtr(MainForm), NULL); StrCopy(title, "Error"); result = download_receive_error(self); break; case kDownloadState_Cancel: FrmSetTitle(FrmGetFormPtr(MainForm), NULL); StrCopy(title, "Canceling"); result = download_receive_cancel(self); break; case kDownloadState_Abort: result = download_receive_abort(self); break; default: result = httpErrorOK; break; } FrmSetTitle(FrmGetFormPtr(MainForm), title); return result; } void PrvHTTPLibTestGet(Char *urlP) { DownloadInfo *self; Int32 result; UInt32 secs; UInt32 msecs; UInt32 ticks; UInt32 ticksPerSecond=SysTicksPerSecond(); UInt32 thruput; self = DonwloadInfoNew(urlP); result = HS_HTTPLibStreamCreateRequest(gRefNum, self->fHTTPStream, httpMethodGET, urlP, StrLen(urlP), "", 0, "", 0, httpVersion_1_1, false, false, httpSSLFlagConnV2V3TLS); // override the "gzip, deflate" default HS_HTTPLibStreamAddHeader(gRefNum, self->fHTTPStream, httpHeaderIDAcceptEncoding, "*/*", 3); result = -1; // start timer gstartTicks = TimGetTicks (); gErrorFlag = false; while(result != httpErrorOK){ result = DownloadInfoProgress(self); } // stop timer gstopTicks = TimGetTicks(); if (!gErrorFlag) { secs = (gstopTicks-gstartTicks) / ticksPerSecond; ticks = (gstopTicks-gstartTicks) % ticksPerSecond; msecs = (ticks * 1000) / ticksPerSecond; printf("Total Time : %ld s %ld ms\n", secs, msecs); secs = (glatencyTicks-gstartTicks) / ticksPerSecond; ticks = (glatencyTicks-gstartTicks) % ticksPerSecond; msecs = (ticks * 1000) / ticksPerSecond; printf("Resp Latency: %ld s %ld ms\n", secs, msecs); printf("Total Bytes : %ld bytes\n", self->fContentLength); if (gstopTicks-glatencyTicks){ // Simulator sometimes showed '0' time elapsed thruput = (self->fContentLength*ticksPerSecond)/(gstopTicks - glatencyTicks); printf("Throughput : %ld bytes/sec\n", thruput); } else ; } else { ; } DonwloadInfoFree(self); } void PrvHTTPLibTestPost(Char *urlP, Char *postDataP) { DownloadInfo *self; Int32 result; self = DonwloadInfoNew(urlP); result = HS_HTTPLibStreamCreateRequest(gRefNum, self->fHTTPStream, httpMethodPOST, urlP, StrLen(urlP), "", 0, "", 0, httpVersion_1_1, false, false, httpSSLFlagConnV2V3TLS); HS_HTTPLibStreamSetPostData(gRefNum, self->fHTTPStream, httpPostURLENCODED, NULL, StrLen(postDataP)); self->fPostData = postDataP; self->fPostDataLen = StrLen(postDataP); self->fState = kDownloadState_RequestWithPost; result = -1; while(result != httpErrorOK){ result = DownloadInfoProgress(self); } DonwloadInfoFree(self); }