Add even more of the source
This should be about everything needed to build so far?
This commit is contained in:
parent
af3619d4fa
commit
849723c9cf
547 changed files with 149239 additions and 0 deletions
417
APIModules/QTSSDemoSMILModule.bproj/QTSSDemoSMILModule.cpp
Normal file
417
APIModules/QTSSDemoSMILModule.bproj/QTSSDemoSMILModule.cpp
Normal file
|
@ -0,0 +1,417 @@
|
|||
/*
|
||||
*
|
||||
* @APPLE_LICENSE_HEADER_START@
|
||||
*
|
||||
* Copyright (c) 1999-2008 Apple Inc. All Rights Reserved.
|
||||
*
|
||||
* This file contains Original Code and/or Modifications of Original Code
|
||||
* as defined in and that are subject to the Apple Public Source License
|
||||
* Version 2.0 (the 'License'). You may not use this file except in
|
||||
* compliance with the License. Please obtain a copy of the License at
|
||||
* http://www.opensource.apple.com/apsl/ and read it before using this
|
||||
* file.
|
||||
*
|
||||
* The Original Code and all software distributed under the License are
|
||||
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
|
||||
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
|
||||
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
|
||||
* Please see the License for the specific language governing rights and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @APPLE_LICENSE_HEADER_END@
|
||||
*
|
||||
*/
|
||||
/*
|
||||
File: QTSSDemoSMILModule.cpp
|
||||
|
||||
Contains:
|
||||
|
||||
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
<smil>
|
||||
<head>
|
||||
<layout>
|
||||
<root-layout width="240" height="160" background-color="black" />
|
||||
<region id="region_1" background-color="black" left="0" top="0" width="240" height="160" />
|
||||
</layout>
|
||||
</head>
|
||||
<body>
|
||||
<seq>
|
||||
<video src="Blue%20Indigo/George%D5s%20Blues" alt="Cool Jazz" region="region_1" />
|
||||
<video src="rtsp://17.333.33.333/catwalk.mov"" alt="Streaming Jazz" region="region_1" begin="2s" />
|
||||
</seq>
|
||||
</body>
|
||||
</smil>
|
||||
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "SafeStdLib.h"
|
||||
#include <dirent.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "QTSSDemoSMILModule.h"
|
||||
#include "OSArrayObjectDeleter.h"
|
||||
#include "StringParser.h"
|
||||
#include "StrPtrLen.h"
|
||||
#include "OSFileSource.h"
|
||||
#include "OSMemory.h"
|
||||
#include "OSHeaders.h"
|
||||
#include "ev.h"
|
||||
#include "QTFile.h"
|
||||
#include "QTTrack.h"
|
||||
#include "QTHintTrack.h"
|
||||
#include "QTSSModuleUtils.h"
|
||||
#include "OSMutex.h"
|
||||
|
||||
#define HTTP_FILE_ASYNC 1
|
||||
#define HTTP_FILE_DEBUGGING 1
|
||||
|
||||
// STATIC DATA
|
||||
// For processing the requests
|
||||
static char* sResponseHeader = "HTTP/1.0 200 OK\r\nServer: QTSS/2.0\r\nContent-Type: video/quicktime\r\n\r\n";
|
||||
static QTSS_PrefsObject sPrefs = NULL;
|
||||
|
||||
static StrPtrLen sPathSeparator("/");
|
||||
static StrPtrLen sRTSPUrlPrefix("rtsp://");
|
||||
static StrPtrLen sRefMovieBufPrefix("rtsptext\r");
|
||||
static StrPtrLen sRespHeaderPrefix("HTTP/1.0 200 OK\r\nServer: QTSS/2.0\r\nConnection: Close");
|
||||
static StrPtrLen sContentLengthHeaderTag("\r\nContent-Length: ");
|
||||
static StrPtrLen sContentTypeHeaderTag("\r\nContent-Type: ");
|
||||
static StrPtrLen sConnectionKeepAliveTag("Keep-Alive");
|
||||
static StrPtrLen sQuickTimeMimeType("video/quicktime");
|
||||
static StrPtrLen sUnknownMimeType("application/unknown");
|
||||
static StrPtrLen sGifMimeType("image/gif");
|
||||
static StrPtrLen sSdpMimeType("application/sdp");
|
||||
static StrPtrLen sSmilMimeType("application/smil");
|
||||
static StrPtrLen sQTSuffix("qt");
|
||||
static StrPtrLen sMovSuffix("mov");
|
||||
static StrPtrLen sGifSuffix("gif");
|
||||
static StrPtrLen sSdpSuffix("sdp");
|
||||
static StrPtrLen sSmiSuffix("smi");
|
||||
static StrPtrLen sSmilSuffix("smil");
|
||||
|
||||
|
||||
// FUNCTIONS
|
||||
static QTSS_Error QTSSDemoSMILDispatch(QTSS_Role inRole, QTSS_RoleParamPtr inParams);
|
||||
static QTSS_Error Register(QTSS_Register_Params* inParams);
|
||||
static QTSS_Error Initialize(QTSS_Initialize_Params* inParams);
|
||||
static QTSS_Error FilterRequest(QTSS_Filter_Params* inParams);
|
||||
// For processing the requests
|
||||
|
||||
|
||||
//Demo stuff
|
||||
struct HitCount {
|
||||
char url[512];
|
||||
int hitcount;
|
||||
};
|
||||
|
||||
static HitCount gHitcountArray[100] = {};
|
||||
|
||||
//protos
|
||||
void CountHit(char* url);
|
||||
void GenerateHotHitSMIL(char* buffer);
|
||||
int HitCountCompare(const void * hitCount1, const void *hitCount2);
|
||||
QTSS_Error CountRequest( QTSS_RTSPRequestObject inRTSPRequest, QTSS_ClientSessionObject inClientSession,
|
||||
QTSS_RTSPSessionObject inRTSPSession, QTSS_CliSesClosingReason *inCloseReasonPtr );
|
||||
void InitHitCountFromFile();
|
||||
|
||||
|
||||
//funcs
|
||||
|
||||
void InitHitCountFromFile()
|
||||
{
|
||||
FILE* hitfile = fopen("hitcount.txt", "r");
|
||||
|
||||
if (hitfile == NULL) return;
|
||||
|
||||
int c = 0;
|
||||
int i = 0;
|
||||
while ( (c = fscanf(hitfile, "%s %d", gHitcountArray[i].url, &gHitcountArray[i].hitcount)) == 2 )
|
||||
{
|
||||
qtss_printf("%s %d\n", gHitcountArray[i].url, gHitcountArray[i].hitcount);
|
||||
i++;
|
||||
}
|
||||
|
||||
fclose(hitfile);
|
||||
}
|
||||
|
||||
void WriteHitCountToFile()
|
||||
{
|
||||
FILE* hitfile = fopen("hitcount.txt", "w");
|
||||
|
||||
int i=0;
|
||||
for (i=0;gHitcountArray[i].url[0] && i<512; i++)
|
||||
{
|
||||
qtss_fprintf(hitfile, "%s %d\n", gHitcountArray[i].url, gHitcountArray[i].hitcount);
|
||||
}
|
||||
|
||||
fclose(hitfile);
|
||||
}
|
||||
|
||||
void CountHit(char* url)
|
||||
{
|
||||
#if HTTP_FILE_DEBUGGING
|
||||
qtss_printf("Counting Hit for \"%s\"\n", url);
|
||||
#endif
|
||||
|
||||
if ( url == NULL )
|
||||
return;
|
||||
|
||||
int i=0;
|
||||
for (i=0;gHitcountArray[i].url[0] && i<512; i++)
|
||||
{
|
||||
if ( strcmp(url, gHitcountArray[i].url ) == 0)
|
||||
{
|
||||
gHitcountArray[i].hitcount++;
|
||||
qsort(&gHitcountArray, i+1, sizeof(HitCount), &HitCountCompare);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
::strcpy(gHitcountArray[i].url, url);
|
||||
gHitcountArray[i].hitcount++;
|
||||
|
||||
qsort(&gHitcountArray, i+1, sizeof(HitCount), &HitCountCompare);
|
||||
}
|
||||
|
||||
int HitCountCompare(const void * hitCount1, const void *hitCount2)
|
||||
{
|
||||
return ((const HitCount*)hitCount2)->hitcount - ((const HitCount*)hitCount1)->hitcount;
|
||||
}
|
||||
|
||||
|
||||
QTSS_Error ClientSessionClosing(QTSS_ClientSessionClosing_Params* inParams)
|
||||
{
|
||||
#if HTTP_FILE_DEBUGGING
|
||||
qtss_printf("ClientSessionClosing\n");
|
||||
#endif
|
||||
return CountRequest(NULL, inParams->inClientSession, NULL, &inParams->inReason);
|
||||
}
|
||||
|
||||
QTSS_Error CountRequest( QTSS_RTSPRequestObject inRTSPRequest, QTSS_ClientSessionObject inClientSession,
|
||||
QTSS_RTSPSessionObject inRTSPSession, QTSS_CliSesClosingReason *inCloseReasonPtr )
|
||||
{
|
||||
|
||||
char urlBuf[256] = { 0 };
|
||||
StrPtrLen url(urlBuf, 256 -1);
|
||||
(void)QTSS_GetValue(inClientSession, qtssCliSesFullURL, 0, url.Ptr, &url.Len);
|
||||
|
||||
CountHit( url.Ptr );
|
||||
WriteHitCountToFile();
|
||||
|
||||
return QTSS_NoErr;
|
||||
}
|
||||
|
||||
void GenerateHotHitSMIL(char* buffer)
|
||||
{
|
||||
char smilTemplate[8192] = {};
|
||||
char* templateCursor = smilTemplate;
|
||||
char* bufferCursor = buffer;
|
||||
|
||||
FILE* smilTemplateFile = fopen("template.smil", "r");
|
||||
if (smilTemplateFile != NULL)
|
||||
{
|
||||
int len = fread(smilTemplate, sizeof(char), sizeof(smilTemplate), smilTemplateFile);
|
||||
|
||||
smilTemplate[len] = '\0';
|
||||
|
||||
fclose(smilTemplateFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy(smilTemplate, "<smil>\n"
|
||||
" <head>\n"
|
||||
" <layout>\n"
|
||||
" </layout>\n"
|
||||
" </head>\n"
|
||||
" <body>\n"
|
||||
" <seq>\n"
|
||||
" <video src=\"%s\" />\n"
|
||||
" </seq>\n"
|
||||
" </body>\n"
|
||||
"</smil>\n");
|
||||
}
|
||||
|
||||
int hitNum = 0;
|
||||
char* p = NULL;
|
||||
while ( (p = strstr(templateCursor, "%s")) != 0 )
|
||||
{
|
||||
char saveCh = p[2];
|
||||
p[2] = '\0';
|
||||
int len = qtss_sprintf(bufferCursor, templateCursor, gHitcountArray[hitNum++].url);
|
||||
p[2] = saveCh;
|
||||
bufferCursor += len;
|
||||
templateCursor = &p[2];
|
||||
}
|
||||
|
||||
strcat(bufferCursor, templateCursor);
|
||||
|
||||
#if HTTP_FILE_DEBUGGING
|
||||
qtss_printf("smil generated:\n%s\n", buffer);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// FUNCTION IMPLEMENTATIONS
|
||||
|
||||
QTSS_Error QTSSDemoSMILModule_Main(void* inPrivateArgs)
|
||||
{
|
||||
return _stublibrary_main(inPrivateArgs, QTSSDemoSMILDispatch);
|
||||
}
|
||||
|
||||
|
||||
QTSS_Error QTSSDemoSMILDispatch(QTSS_Role inRole, QTSS_RoleParamPtr inParams)
|
||||
{
|
||||
#if HTTP_FILE_DEBUGGING
|
||||
qtss_printf("QTSSDemoSMILDispatch\n");
|
||||
#endif
|
||||
|
||||
switch (inRole)
|
||||
{
|
||||
case QTSS_Register_Role:
|
||||
return Register(&inParams->regParams);
|
||||
case QTSS_Initialize_Role:
|
||||
return Initialize(&inParams->initParams);
|
||||
case QTSS_RTSPFilter_Role:
|
||||
return FilterRequest(&inParams->rtspFilterParams);
|
||||
case QTSS_ClientSessionClosing_Role:
|
||||
return ClientSessionClosing(&inParams->clientSessionClosingParams);
|
||||
}
|
||||
return QTSS_NoErr;
|
||||
}
|
||||
|
||||
|
||||
QTSS_Error Register(QTSS_Register_Params* inParams)
|
||||
{
|
||||
#if HTTP_FILE_DEBUGGING
|
||||
qtss_printf("Register\n");
|
||||
#endif
|
||||
// Do role & attribute setup
|
||||
(void)QTSS_AddRole(QTSS_Initialize_Role);
|
||||
(void)QTSS_AddRole(QTSS_RTSPFilter_Role);
|
||||
(void)QTSS_AddRole(QTSS_ClientSessionClosing_Role);
|
||||
|
||||
// Tell the server our name!
|
||||
static char* sModuleName = "QTSSDemoSMILModule";
|
||||
::strcpy(inParams->outModuleName, sModuleName);
|
||||
|
||||
return QTSS_NoErr;
|
||||
}
|
||||
|
||||
QTSS_Error Initialize(QTSS_Initialize_Params* inParams)
|
||||
{
|
||||
#if HTTP_FILE_DEBUGGING
|
||||
qtss_printf("Initialize\n");
|
||||
#endif
|
||||
// Setup module utils
|
||||
QTSSModuleUtils::Initialize(inParams->inMessages, inParams->inServer, inParams->inErrorLogStream);
|
||||
|
||||
// Get prefs object
|
||||
sPrefs = inParams->inPrefs;
|
||||
|
||||
InitHitCountFromFile();
|
||||
|
||||
return QTSS_NoErr;
|
||||
}
|
||||
|
||||
|
||||
QTSS_Error FilterRequest(QTSS_Filter_Params* inParams)
|
||||
{
|
||||
#if HTTP_FILE_DEBUGGING
|
||||
qtss_printf("FilterRequest\n");
|
||||
#endif
|
||||
|
||||
static Bool16 sFalse = false;
|
||||
|
||||
QTSS_RTSPRequestObject theRequest = inParams->inRTSPRequest;
|
||||
|
||||
// Initial state.
|
||||
StrPtrLen theFullRequest;
|
||||
StrPtrLen reqMethod;
|
||||
StrPtrLen reqStr;
|
||||
StrPtrLen httpVersion;
|
||||
|
||||
(void)QTSS_GetValuePtr(theRequest, qtssRTSPReqFullRequest, 0, (void**)&theFullRequest.Ptr, &theFullRequest.Len);
|
||||
StringParser fullRequest(&theFullRequest);
|
||||
|
||||
// Parsing the HTTP request
|
||||
fullRequest.ConsumeWord(&reqMethod);
|
||||
if ( !(reqMethod.Equal(StrPtrLen("GET")) || reqMethod.Equal(StrPtrLen("HEAD"))) )
|
||||
// It's not a "Get" or a "Head" request
|
||||
return QTSS_NoErr;
|
||||
|
||||
fullRequest.ConsumeWhitespace();
|
||||
if ( !fullRequest.Expect('/') )
|
||||
// Improperly formed request
|
||||
return QTSS_NoErr;
|
||||
|
||||
fullRequest.ConsumeUntil(&reqStr, StringParser::sEOLWhitespaceMask);
|
||||
if( reqStr.Len == 0 )
|
||||
//if a file or directory name is not given, return
|
||||
return QTSS_NoErr;
|
||||
|
||||
if ( !reqStr.Equal(StrPtrLen("Popular.smil")) )
|
||||
return QTSS_NoErr;
|
||||
|
||||
// If it's a "Head" request send the Head response header back and just return
|
||||
if ( reqMethod.Equal(StrPtrLen("HEAD")) )
|
||||
{
|
||||
QTSS_Write(theRequest, sResponseHeader, ::strlen(sResponseHeader), NULL, 0);
|
||||
return QTSS_NoErr;
|
||||
}
|
||||
|
||||
// Create a buffer to store data.
|
||||
char theFileBuffer[8192];
|
||||
char contentLength[256];
|
||||
|
||||
// Before sending any response, set keep alive to off for this connection
|
||||
// Regardless of what the client sends, the server always closes the connection after sending the file
|
||||
(void)QTSS_SetValue(theRequest, qtssRTSPReqRespKeepAlive, 0, &sFalse, sizeof(sFalse));
|
||||
|
||||
#if HTTP_FILE_DEBUGGING
|
||||
qtss_printf("Creating a smil file\n");
|
||||
#endif
|
||||
// Create a ref movie buffer for the single file. It is of the form:
|
||||
// rtsptext\r
|
||||
// rtsp://servername/filepath
|
||||
char smilFileBuf[8192] = {0};
|
||||
|
||||
GenerateHotHitSMIL(smilFileBuf);
|
||||
|
||||
qtss_sprintf(contentLength, "%"_U32BITARG_"", (UInt32) ::strlen(smilFileBuf));
|
||||
// Allocate memory for theFileBuffer
|
||||
// Write the HTTP header prefix into the buffer
|
||||
::strcpy(theFileBuffer, sRespHeaderPrefix.Ptr);
|
||||
::strcat(theFileBuffer, sContentLengthHeaderTag.Ptr);
|
||||
// Write the remaining part of the HTTP header into the file buffer
|
||||
::strcat(theFileBuffer, contentLength);
|
||||
::strcat(theFileBuffer, sContentTypeHeaderTag.Ptr);
|
||||
::strcat(theFileBuffer, sSmilMimeType.Ptr);
|
||||
::strcat(theFileBuffer, "\r\n\r\n");
|
||||
|
||||
// Write the smil file created above to the file buffer
|
||||
::strcat(theFileBuffer, smilFileBuf);
|
||||
|
||||
// Write the contents of the file buffer to the request stream and return
|
||||
QTSS_Write(theRequest, theFileBuffer, strlen(theFileBuffer), NULL, 0);
|
||||
|
||||
#if HTTP_FILE_DEBUGGING
|
||||
qtss_printf("Wrote the smil file to the request stream. Successful!\n");
|
||||
#endif
|
||||
|
||||
return QTSS_NoErr;
|
||||
}
|
41
APIModules/QTSSDemoSMILModule.bproj/QTSSDemoSMILModule.h
Normal file
41
APIModules/QTSSDemoSMILModule.bproj/QTSSDemoSMILModule.h
Normal file
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
*
|
||||
* @APPLE_LICENSE_HEADER_START@
|
||||
*
|
||||
* Copyright (c) 1999-2008 Apple Inc. All Rights Reserved.
|
||||
*
|
||||
* This file contains Original Code and/or Modifications of Original Code
|
||||
* as defined in and that are subject to the Apple Public Source License
|
||||
* Version 2.0 (the 'License'). You may not use this file except in
|
||||
* compliance with the License. Please obtain a copy of the License at
|
||||
* http://www.opensource.apple.com/apsl/ and read it before using this
|
||||
* file.
|
||||
*
|
||||
* The Original Code and all software distributed under the License are
|
||||
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
|
||||
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
|
||||
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
|
||||
* Please see the License for the specific language governing rights and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @APPLE_LICENSE_HEADER_END@
|
||||
*
|
||||
*/
|
||||
/*
|
||||
File: QTSSDemoSMILModule.h
|
||||
|
||||
Contains:
|
||||
*/
|
||||
|
||||
#ifndef __QTSSDEMOSMILMODULE_H__
|
||||
#define __QTSSDEMOSMILMODULE_H__
|
||||
|
||||
#include "QTSS.h"
|
||||
|
||||
extern "C"
|
||||
{
|
||||
QTSS_Error QTSSDemoSMILModule_Main(void* inPrivateArgs);
|
||||
}
|
||||
|
||||
#endif // __QTSSDEMOSMILMODULE_H__
|
Loading…
Add table
Add a link
Reference in a new issue