QTSS_Error QTSSCallbacks::QTSS_GetNumAttributes(QTSS_Object inObject, UInt32* outNumValues) { if (outNumValues == NULL) return QTSS_BadArgument; if (inObject == NULL) return QTSS_BadArgument; OSMutexLocker locker(((QTSSDictionary*)inObject)->GetMutex()); QTSSDictionaryMap* theMap = NULL; *outNumValues = 0; // Get the Static Attribute count theMap = ((QTSSDictionary*)inObject)->GetDictionaryMap(); if (theMap != NULL) *outNumValues += theMap->GetNumNonRemovedAttrs(); // Get the Instance Attribute count theMap = ((QTSSDictionary*)inObject)->GetInstanceDictMap(); if (theMap != NULL) *outNumValues += theMap->GetNumNonRemovedAttrs(); return QTSS_NoErr; }
void RTSPRequestInterface::Initialize() { //make a partially complete header StringFormatter headerFormatter(sPremadeHeaderPtr.Ptr, kStaticHeaderSizeInBytes); PutStatusLine(&headerFormatter, qtssSuccessOK, RTSPProtocol::k10Version); headerFormatter.Put(QTSServerInterface::GetServerHeader()); headerFormatter.PutEOL(); headerFormatter.Put(RTSPProtocol::GetHeaderString(qtssCSeqHeader)); headerFormatter.Put(sColonSpace); sPremadeHeaderPtr.Len = headerFormatter.GetCurrentOffset(); Assert(sPremadeHeaderPtr.Len < kStaticHeaderSizeInBytes); StringFormatter noServerInfoHeaderFormatter(sPremadeNoHeaderPtr.Ptr, kStaticHeaderSizeInBytes); PutStatusLine(&noServerInfoHeaderFormatter, qtssSuccessOK, RTSPProtocol::k10Version); noServerInfoHeaderFormatter.Put(RTSPProtocol::GetHeaderString(qtssCSeqHeader)); noServerInfoHeaderFormatter.Put(sColonSpace); sPremadeNoHeaderPtr.Len = noServerInfoHeaderFormatter.GetCurrentOffset(); Assert(sPremadeNoHeaderPtr.Len < kStaticHeaderSizeInBytes); //Setup all the dictionary stuff for (UInt32 x = 0; x < qtssRTSPReqNumParams; x++) QTSSDictionaryMap::GetMap(QTSSDictionaryMap::kRTSPRequestDictIndex)-> SetAttribute(x, sAttributes[x].fAttrName, sAttributes[x].fFuncPtr, sAttributes[x].fAttrDataType, sAttributes[x].fAttrPermission); QTSSDictionaryMap* theHeaderMap = QTSSDictionaryMap::GetMap(QTSSDictionaryMap::kRTSPHeaderDictIndex); for (UInt32 y = 0; y < qtssNumHeaders; y++) theHeaderMap->SetAttribute(y, RTSPProtocol::GetHeaderString(y).Ptr, NULL, qtssAttrDataTypeCharArray, qtssAttrModeRead | qtssAttrModePreempSafe); }
QTSS_Error QTSSDictionary::CreateObjectValue(QTSS_AttributeID inAttrID, UInt32* outIndex, QTSSDictionary** newObject, QTSSDictionaryMap* inMap, UInt32 inFlags) { // Check first to see if this is a static attribute or an instance attribute QTSSDictionaryMap* theMap = fMap; DictValueElement* theAttrs = fAttributes; if (QTSSDictionaryMap::IsInstanceAttrID(inAttrID)) { theMap = fInstanceMap; theAttrs = fInstanceAttrs; } if (theMap == NULL) return QTSS_AttrDoesntExist; SInt32 theMapIndex = theMap->ConvertAttrIDToArrayIndex(inAttrID); // If there is a mutex, make this action atomic. OSMutexLocker locker(fMutexP); if (theMapIndex < 0) return QTSS_AttrDoesntExist; if ((!(inFlags & kDontObeyReadOnly)) && (!theMap->IsWriteable(theMapIndex))) return QTSS_ReadOnly; if (theMap->IsRemoved(theMapIndex)) return QTSS_AttrDoesntExist; if (theMap->GetAttrType(theMapIndex) != qtssAttrDataTypeQTSS_Object) return QTSS_BadArgument; UInt32 numValues = theAttrs[theMapIndex].fNumAttributes; // if normal QTSSObjects have been added, then we can't add a dynamic one if (!theAttrs[theMapIndex].fIsDynamicDictionary && (numValues > 0)) return QTSS_ReadOnly; QTSSDictionary* oldDict = NULL; *outIndex = numValues; // add the object into the next spot UInt32 len = sizeof(QTSSDictionary*); QTSSDictionary* dict = CreateNewDictionary(inMap, fMutexP); // kind of a hack to avoid the check in SetValue theAttrs[theMapIndex].fIsDynamicDictionary = false; QTSS_Error err = SetValue(inAttrID, *outIndex, &dict, len, inFlags); if (err != QTSS_NoErr) { delete dict; return err; } if (oldDict != NULL) { delete oldDict; } theAttrs[theMapIndex].fIsDynamicDictionary = true; *newObject = dict; return QTSS_NoErr; }
QTSS_Error QTSSDictionary::GetValueAsString(QTSS_AttributeID inAttrID, UInt32 inIndex, char** outString) { void* tempValueBuffer; UInt32 tempValueLen = 0; if (outString == NULL) return QTSS_BadArgument; OSMutexLocker locker(fMutexP); QTSS_Error theErr = this->GetValuePtr(inAttrID, inIndex, &tempValueBuffer, &tempValueLen, true); if (theErr != QTSS_NoErr) return theErr; QTSSDictionaryMap* theMap = fMap; if (QTSSDictionaryMap::IsInstanceAttrID(inAttrID)) theMap = fInstanceMap; if (theMap == NULL) return QTSS_AttrDoesntExist; SInt32 theMapIndex = theMap->ConvertAttrIDToArrayIndex(inAttrID); Assert(theMapIndex >= 0); *outString = QTSSDataConverter::ValueToString(tempValueBuffer, tempValueLen, theMap->GetAttrType(theMapIndex)); return QTSS_NoErr; }
void QTSSMessages::Initialize() { QTSSDictionaryMap* theMap = QTSSDictionaryMap::GetMap(QTSSDictionaryMap::kTextMessagesDictIndex); Assert(theMap != nullptr); for (UInt32 x = 0; x < qtssMsgNumParams; x++) theMap->SetAttribute(x, sMessagesKeyStrings[x], nullptr, qtssAttrDataTypeCharArray, qtssAttrModeRead | qtssAttrModePreempSafe); }
QTSS_Error QTSSCallbacks::QTSS_DoService(QTSS_ServiceID inID, QTSS_ServiceFunctionArgsPtr inArgs) { // Make sure that the service ID is in fact valid QTSSDictionaryMap* theMap = QTSSDictionaryMap::GetMap(QTSSDictionaryMap::kServiceDictIndex); SInt32 theIndex = theMap->ConvertAttrIDToArrayIndex(inID); if (theIndex < 0) return QTSS_IllegalService; // Get the service function QTSS_ServiceFunctionPtr theFunction = (QTSS_ServiceFunctionPtr)theMap->GetAttrFunction(theIndex); // Invoke it, return the result. return (theFunction)(inArgs); }
QTSS_Error QTSSCallbacks::QTSS_AddStaticAttribute(QTSS_ObjectType inObjectType, const char* inAttrName, void* inUnused, QTSS_AttrDataType inAttrDataType) { Assert(inUnused == NULL); QTSS_ModuleState* theState = (QTSS_ModuleState*)OSThread::GetMainThreadData(); if (OSThread::GetCurrent() != NULL) theState = (QTSS_ModuleState*)OSThread::GetCurrent()->GetThreadData(); // Static attributes can only be added before modules have had their Initialize role invoked. if ((theState == NULL) || (theState->curRole != QTSS_Register_Role)) return QTSS_OutOfState; UInt32 theDictionaryIndex = QTSSDictionaryMap::GetMapIndex(inObjectType); if (theDictionaryIndex == QTSSDictionaryMap::kIllegalDictionary) return QTSS_BadArgument; QTSSDictionaryMap* theMap = QTSSDictionaryMap::GetMap(theDictionaryIndex); return theMap->AddAttribute(inAttrName, NULL, inAttrDataType, qtssAttrModeRead | qtssAttrModeWrite | qtssAttrModePreempSafe); }
void QTSServerPrefs::RereadServerPreferences(Bool16 inWriteMissingPrefs) { OSMutexLocker locker(&fPrefsMutex); QTSSDictionaryMap* theMap = QTSSDictionaryMap::GetMap(QTSSDictionaryMap::kPrefsDictIndex); for (UInt32 x = 0; x < theMap->GetNumAttrs(); x++) { // // Look for a pref in the file that matches each pref in the dictionary char* thePrefTypeStr = NULL; char* thePrefName = NULL; ContainerRef server = fPrefsSource->GetRefForServer(); ContainerRef pref = fPrefsSource->GetPrefRefByName( server, theMap->GetAttrName(x) ); char* thePrefValue = NULL; if (pref != NULL) thePrefValue = fPrefsSource->GetPrefValueByRef( pref, 0, &thePrefName, (char**)&thePrefTypeStr); if ((thePrefValue == NULL) && (x < qtssPrefsNumParams)) // Only generate errors for server prefs { // // There is no pref, use the default and log an error if (::strlen(sPrefInfo[x].fDefaultValue) > 0) { // // Only log this as an error if there is a default (an empty string // doesn't count). If there is no default, we will constantly print // out an error message... QTSSModuleUtils::LogError( QTSSModuleUtils::GetMisingPrefLogVerbosity(), qtssServerPrefMissing, 0, sAttributes[x].fAttrName, sPrefInfo[x].fDefaultValue); } this->SetPrefValue(x, 0, sPrefInfo[x].fDefaultValue, sAttributes[x].fAttrDataType); if (sPrefInfo[x].fAdditionalDefVals != NULL) { // // Add additional default values if they exist for (UInt32 y = 0; sPrefInfo[x].fAdditionalDefVals[y] != NULL; y++) this->SetPrefValue(x, y+1, sPrefInfo[x].fAdditionalDefVals[y], sAttributes[x].fAttrDataType); } if (inWriteMissingPrefs) { // // Add this value into the file, cuz we need it. pref = fPrefsSource->AddPref( server, sAttributes[x].fAttrName, QTSSDataConverter::TypeToTypeString(sAttributes[x].fAttrDataType)); fPrefsSource->AddPrefValue(pref, sPrefInfo[x].fDefaultValue); if (sPrefInfo[x].fAdditionalDefVals != NULL) { for (UInt32 a = 0; sPrefInfo[x].fAdditionalDefVals[a] != NULL; a++) fPrefsSource->AddPrefValue(pref, sPrefInfo[x].fAdditionalDefVals[a]); } } continue; } QTSS_AttrDataType theType = QTSSDataConverter::TypeStringToType(thePrefTypeStr); if ((x < qtssPrefsNumParams) && (theType != sAttributes[x].fAttrDataType)) // Only generate errors for server prefs { // // The pref in the file has the wrong type, use the default and log an error if (::strlen(sPrefInfo[x].fDefaultValue) > 0) { // // Only log this as an error if there is a default (an empty string // doesn't count). If there is no default, we will constantly print // out an error message... QTSSModuleUtils::LogError( qtssWarningVerbosity, qtssServerPrefWrongType, 0, sAttributes[x].fAttrName, sPrefInfo[x].fDefaultValue); } this->SetPrefValue(x, 0, sPrefInfo[x].fDefaultValue, sAttributes[x].fAttrDataType); if (sPrefInfo[x].fAdditionalDefVals != NULL) { // // Add additional default values if they exist for (UInt32 z = 0; sPrefInfo[x].fAdditionalDefVals[z] != NULL; z++) this->SetPrefValue(x, z+1, sPrefInfo[x].fAdditionalDefVals[z], sAttributes[x].fAttrDataType); } if (inWriteMissingPrefs) { // // Remove it out of the file and add in the default. fPrefsSource->RemovePref(pref); pref = fPrefsSource->AddPref( server, sAttributes[x].fAttrName, QTSSDataConverter::TypeToTypeString(sAttributes[x].fAttrDataType)); fPrefsSource->AddPrefValue(pref, sPrefInfo[x].fDefaultValue); if (sPrefInfo[x].fAdditionalDefVals != NULL) { for (UInt32 b = 0; sPrefInfo[x].fAdditionalDefVals[b] != NULL; b++) fPrefsSource->AddPrefValue(pref, sPrefInfo[x].fAdditionalDefVals[b]); } } continue; } UInt32 theNumValues = 0; if ((x < qtssPrefsNumParams) && (!sPrefInfo[x].fAllowMultipleValues)) theNumValues = 1; this->SetPrefValuesFromFileWithRef(pref, x, theNumValues); } // // Do any special pref post-processing this->UpdateAuthScheme(); QTSSModuleUtils::SetEnableRTSPErrorMsg(fEnableRTSPErrMsg); QTSSRollingLog::SetCloseOnWrite(fCloseLogsOnWrite); // // In case we made any changes, write out the prefs file (void)fPrefsSource->WritePrefsFile(); }
QTSS_Error QTSSDictionary::GetValuePtr(QTSS_AttributeID inAttrID, UInt32 inIndex, void** outValueBuffer, UInt32* outValueLen, Bool16 isInternal) { // Check first to see if this is a static attribute or an instance attribute QTSSDictionaryMap* theMap = fMap; DictValueElement* theAttrs = fAttributes; if (QTSSDictionaryMap::IsInstanceAttrID(inAttrID)) { theMap = fInstanceMap; theAttrs = fInstanceAttrs; } if (theMap == NULL) return QTSS_AttrDoesntExist; SInt32 theMapIndex = theMap->ConvertAttrIDToArrayIndex(inAttrID); if (theMapIndex < 0) return QTSS_AttrDoesntExist; if (theMap->IsRemoved(theMapIndex)) return QTSS_AttrDoesntExist; if ((!isInternal) && (!theMap->IsPreemptiveSafe(theMapIndex)) && !this->IsLocked()) return QTSS_NotPreemptiveSafe; // An iterated attribute cannot have a param retrieval function if ((inIndex > 0) && (theMap->GetAttrFunction(theMapIndex) != NULL)) return QTSS_BadIndex; // Check to make sure the index parameter is legal if ((inIndex > 0) && (inIndex >= theAttrs[theMapIndex].fNumAttributes)) return QTSS_BadIndex; // Retrieve the parameter char* theBuffer = theAttrs[theMapIndex].fAttributeData.Ptr; *outValueLen = theAttrs[theMapIndex].fAttributeData.Len; Bool16 cacheable = theMap->IsCacheable(theMapIndex); if ( (theMap->GetAttrFunction(theMapIndex) != NULL) && ((cacheable && (*outValueLen == 0)) || !cacheable) ) { // If function is cacheable: // If the parameter doesn't have a value assigned yet, and there is an attribute // retrieval function provided, invoke that function now. // If function is *not* cacheable: // always call the function theBuffer = (char*)theMap->GetAttrFunction(theMapIndex)(this, outValueLen); //If the param retrieval function didn't return an explicit value for this attribute, //refetch the parameter out of the array, in case the function modified it. if (theBuffer == NULL) { theBuffer = theAttrs[theMapIndex].fAttributeData.Ptr; *outValueLen = theAttrs[theMapIndex].fAttributeData.Len; } } #if DEBUG else // Make sure we aren't outside the bounds of attribute memory Assert(theAttrs[theMapIndex].fAllocatedLen >= (theAttrs[theMapIndex].fAttributeData.Len * (theAttrs[theMapIndex].fNumAttributes))); #endif // Return an error if there is no data for this attribute if (*outValueLen == 0) return QTSS_ValueNotFound; theBuffer += theAttrs[theMapIndex].fAttributeData.Len * inIndex; *outValueBuffer = theBuffer; // strings need an extra dereference - moved it up if ((theMap->GetAttrType(theMapIndex) == qtssAttrDataTypeCharArray) && (theAttrs[theMapIndex].fNumAttributes > 1)) { char** string = (char**)theBuffer; *outValueBuffer = *string; //*outValueLen = strlen(*string) + 1; *outValueLen = strlen(*string); } return QTSS_NoErr; }
QTSS_Error QTSSDictionary::SetValue(QTSS_AttributeID inAttrID, UInt32 inIndex, const void* inBuffer, UInt32 inLen, UInt32 inFlags) { // Check first to see if this is a static attribute or an instance attribute QTSSDictionaryMap* theMap = fMap; DictValueElement* theAttrs = fAttributes; if (QTSSDictionaryMap::IsInstanceAttrID(inAttrID)) { theMap = fInstanceMap; theAttrs = fInstanceAttrs; } if (theMap == NULL) return QTSS_AttrDoesntExist; SInt32 theMapIndex = theMap->ConvertAttrIDToArrayIndex(inAttrID); // If there is a mutex, make this action atomic. OSMutexLocker locker(fMutexP); if (theMapIndex < 0) return QTSS_AttrDoesntExist; if ((!(inFlags & kDontObeyReadOnly)) && (!theMap->IsWriteable(theMapIndex))) return QTSS_ReadOnly; if (theMap->IsRemoved(theMapIndex)) return QTSS_AttrDoesntExist; if (theAttrs[theMapIndex].fIsDynamicDictionary) return QTSS_ReadOnly; UInt32 numValues = theAttrs[theMapIndex].fNumAttributes; QTSS_AttrDataType dataType = theMap->GetAttrType(theMapIndex); UInt32 attrLen = inLen; if (dataType == qtssAttrDataTypeCharArray) { if (inIndex > 0) attrLen = sizeof(char*); // value just contains a pointer if ((numValues == 1) && (inIndex == 1)) { // we're adding a second value, so we need to change the storage from directly // storing the string to an array of string pointers // creating new memory here just to create a null terminated string // instead of directly using the old storage as the old storage didn't // have its string null terminated UInt32 tempStringLen = theAttrs[theMapIndex].fAttributeData.Len; char* temp = NEW char[tempStringLen + 1]; ::memcpy(temp, theAttrs[theMapIndex].fAttributeData.Ptr, tempStringLen); temp[tempStringLen] = '\0'; delete [] theAttrs[theMapIndex].fAttributeData.Ptr; //char* temp = theAttrs[theMapIndex].fAttributeData.Ptr; theAttrs[theMapIndex].fAllocatedLen = 16 * sizeof(char*); theAttrs[theMapIndex].fAttributeData.Ptr = NEW char[theAttrs[theMapIndex].fAllocatedLen]; theAttrs[theMapIndex].fAttributeData.Len = sizeof(char*); // store off original string as first value in array *(char**)theAttrs[theMapIndex].fAttributeData.Ptr = temp; // question: why isn't theAttrs[theMapIndex].fAllocatedInternally set to true? theAttrs[theMapIndex].fAllocatedInternally = true; } }
/*这是本类最重要的函数:先遍历服务器的属性列表,逐个用预设值文件设置各指定的属性,若预设值出错,就用默认值代替,然后设置认证格式, RTP/RTCP包头打印选项,日志写关闭,最后将调整后的预设值内容写入xml预设值文件 */ void QTSServerPrefs::RereadServerPreferences(Bool16 inWriteMissingPrefs) { OSMutexLocker locker(&fPrefsMutex); //得到服务器预设值字典对象 QTSSDictionaryMap* theMap = QTSSDictionaryMap::GetMap(QTSSDictionaryMap::kPrefsDictIndex); //遍历服务器的属性列表,逐个用预设值文件设置该指定的属性 for (UInt32 x = 0; x < theMap->GetNumAttrs(); x++) { // Look for a pref in the file that matches each pref in the dictionary char* thePrefTypeStr = NULL; char* thePrefName = NULL; char* thePrefValue = NULL; ContainerRef server = fPrefsSource->GetRefForServer();/* 在fRootTag下获取子Tag SERVER并返回,没有就生成它 */ ContainerRef pref = fPrefsSource->GetPrefRefByName( server, theMap->GetAttrName(x) );/* 得到子Tag SERVER指定属性名的子Tag */ /* 假如不空,返回指定Tag的指定index的子Tag的value,得到指定Tag的NAME和TYPE属性值,对Tag的情况作了分析 */ if (pref != NULL) thePrefValue = fPrefsSource->GetPrefValueByRef( pref, 0, &thePrefName,(char**)&thePrefTypeStr); /* 假如得到的属性值是空的, */ if ((thePrefValue == NULL) && (x < qtssPrefsNumParams)) // Only generate errors for server prefs { // 假如没有设置值,但有默认值,使用默认值,并在日志中记录 // There is no pref, use the default and log an error if (::strlen(sPrefInfo[x].fDefaultValue) > 0) { // 假如有默认值(空字符串不算),仅在日志中记录;假如没有默认值,在屏幕上打印出来 // Only log this as an error if there is a default (an empty string // doesn't count). If there is no default, we will constantly print // out an error message... QTSSModuleUtils::LogError( QTSSModuleUtils::GetMisingPrefLogVerbosity(), qtssServerPrefMissing, 0, sAttributes[x].fAttrName, sPrefInfo[x].fDefaultValue); } //用默认值设置相应的服务器属性值 this->SetPrefValue(x, 0, sPrefInfo[x].fDefaultValue, sAttributes[x].fAttrDataType); //假如还有附加的默认值,也要依次设置上 if (sPrefInfo[x].fAdditionalDefVals != NULL) { // Add additional default values if they exist for (UInt32 y = 0; sPrefInfo[x].fAdditionalDefVals[y] != NULL; y++) this->SetPrefValue(x, y+1, sPrefInfo[x].fAdditionalDefVals[y], sAttributes[x].fAttrDataType); } //假如第2个入参为true,生成指定属性值和数据类型的Tag,加入Tag内嵌队列中,并返回该Tag,即将该属性及其(多个)属性值,补充写入xml预配置文件 if (inWriteMissingPrefs) { // Add this value into the file, because we need it. pref = fPrefsSource->AddPref( server, sAttributes[x].fAttrName, QTSSDataConverter::TypeToTypeString(sAttributes[x].fAttrDataType)); // 再写入指定的属性值 fPrefsSource->AddPrefValue(pref, sPrefInfo[x].fDefaultValue); //如果有多重值,也一并写入 if (sPrefInfo[x].fAdditionalDefVals != NULL) { for (UInt32 a = 0; sPrefInfo[x].fAdditionalDefVals[a] != NULL; a++) fPrefsSource->AddPrefValue(pref, sPrefInfo[x].fAdditionalDefVals[a]); } } continue; //跳到下一个索引 } QTSS_AttrDataType theType = QTSSDataConverter::TypeStringToType(thePrefTypeStr); // 假如有预设值,但是数据类型不对,使用默认值,并记录错误 // The pref in the file has the wrong type, use the default and log an error if ((x < qtssPrefsNumParams) && (theType != sAttributes[x].fAttrDataType)) // Only generate errors for server prefs { // 假如有默认值(空字符串不算),仅在日志中记录;假如没有默认值,在屏幕上打印出来 if (::strlen(sPrefInfo[x].fDefaultValue) > 0) { // Only log this as an error if there is a default (an empty string // doesn't count). If there is no default, we will constantly print // out an error message... QTSSModuleUtils::LogError( qtssWarningVerbosity, qtssServerPrefWrongType, 0, sAttributes[x].fAttrName, sPrefInfo[x].fDefaultValue); } //用默认值设置相应的服务器属性值 this->SetPrefValue(x, 0, sPrefInfo[x].fDefaultValue, sAttributes[x].fAttrDataType); //假如还有附加的默认值,也要依次设置上 if (sPrefInfo[x].fAdditionalDefVals != NULL) { // Add additional default values if they exist for (UInt32 z = 0; sPrefInfo[x].fAdditionalDefVals[z] != NULL; z++) this->SetPrefValue(x, z+1, sPrefInfo[x].fAdditionalDefVals[z], sAttributes[x].fAttrDataType); } //假如第2个入参为true,先删除该Tag,再增加新的Tag,设置其属性,及其(多个)属性值 // Remove it out of the file and add in the default. if (inWriteMissingPrefs) { fPrefsSource->RemovePref(pref); pref = fPrefsSource->AddPref( server, sAttributes[x].fAttrName, QTSSDataConverter::TypeToTypeString(sAttributes[x].fAttrDataType)); fPrefsSource->AddPrefValue(pref, sPrefInfo[x].fDefaultValue); if (sPrefInfo[x].fAdditionalDefVals != NULL) { for (UInt32 b = 0; sPrefInfo[x].fAdditionalDefVals[b] != NULL; b++) fPrefsSource->AddPrefValue(pref, sPrefInfo[x].fAdditionalDefVals[b]); } } continue;//跳到下一个索引 } /* 设置单值属性标志,用于下面的函数QTSSPrefs::SetPrefValuesFromFileWithRef()中的第三个参数 */ UInt32 theNumValues = 0; if ((x < qtssPrefsNumParams) && (!sPrefInfo[x].fAllowMultipleValues)) theNumValues = 1; //用预设值文件设置该指定的属性 this->SetPrefValuesFromFileWithRef(pref, x, theNumValues); } // Do any special pref post-processing //先得到认证格式的预设值,再用其设置数据成员fAuthScheme this->UpdateAuthScheme(); //获取服务器RTP/RTCP包头打印选项的预设值,解析并重新设置数据成员fPacketHeaderPrintfOptions this->UpdatePrintfOptions(); //用数据成员fEnableRTSPErrMsg设置QTSSModuleUtils::sEnableRTSPErrorMsg QTSSModuleUtils::SetEnableRTSPErrorMsg(fEnableRTSPErrMsg); //用数据成员fCloseLogsOnWrite设置QTSSRollingLog中的静态变量sCloseOnWrite QTSSRollingLog::SetCloseOnWrite(fCloseLogsOnWrite); // In case we made any changes, write out the prefs file,将经过调整后的预设值内容写入xml预设值文件 (void)fPrefsSource->WritePrefsFile(); }