/* * Copyright (c) 2002 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * 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@ */ /*! * @header CNSLPlugin */ #ifndef _CNSLPlugin_ #define _CNSLPlugin_ 1 #include #include #include #include #include #include #include #include #include #include #include // for _POSIX_THREADS #include // for pthread_*_t #include "NSLDebugLog.h" #include "CNSLResult.h" #include "CNSLTimingUtils.h" #define kTaskInterval 2 #define kNodeTimerIntervalImmediate 1 // Fire ASAP #define kOncePerDay 1*60*60*24 #define kKeepTimerAroundAfterFiring kOncePerDay // 1 day interval on timers #define kMaxTimeBetweenNodeLookups 30*60 // 30 minutes #define kMinTimeBetweenEmptyResults 1000 #define kHTTPServiceType "http" #define kAFPServiceType "afp" #define kNFSServiceType "nfs" #define kFTPServiceType "ftp" #define kSMBServiceType "smb" #define kRAdminServiceType "radminx" #define kLaserWriterServiceType "LaserWriter" #define kDSNAttrLocation "dsAttrTypeStandard:Location" const CFStringRef kDSNSLQueuedSearchSAFE_CFSTR = CFSTR("DS NSL Queued Search"); const CFStringRef kNetworkChangeNSLCopyStringCallbackSAFE_CFSTR = CFSTR("NetworkChangeNSLCopyStringCallback"); const CFStringRef kDSNAttrRecordNameSAFE_CFSTR = CFSTR(kDSNAttrRecordName); const CFStringRef kDS1AttrLocationSAFE_CFSTR = CFSTR(kDS1AttrLocation); const CFStringRef kDS1AttrCommentSAFE_CFSTR = CFSTR(kDS1AttrComment); const CFStringRef kDS1AttrServiceTypeSAFE_CFSTR = CFSTR(kDS1AttrServiceType); const CFStringRef kDSNAttrRecordTypeSAFE_CFSTR = CFSTR(kDSNAttrRecordType); const CFStringRef kDSStdRecordTypePrefixSAFE_CFSTR = CFSTR(kDSStdRecordTypePrefix); const CFStringRef kDSNativeRecordTypePrefixSAFE_CFSTR = CFSTR(kDSNativeRecordTypePrefix); const CFStringRef kDSNAttrURLSAFE_CFSTR = CFSTR(kDSNAttrURL); const CFStringRef kDSNAttrLocationSAFE_CFSTR = CFSTR(kDSNAttrLocation); const CFStringRef kDNSTextRecordSAFE_CFSTR = CFSTR("dsAttrTypeStandard:DNSTextRecord"); const CFStringRef kDS1AttrPtrSAFE_CFSTR = CFSTR(kDS1AttrPort); const CFStringRef kDSStdRecordTypeAFPServerSAFE_CFSTR = CFSTR(kDSStdRecordTypeAFPServer); const CFStringRef kDSStdRecordTypeSMBServerSAFE_CFSTR = CFSTR(kDSStdRecordTypeSMBServer); const CFStringRef kDSStdRecordTypeNFSSAFE_CFSTR = CFSTR(kDSStdRecordTypeNFS); const CFStringRef kDSStdRecordTypeFTPServerSAFE_CFSTR = CFSTR(kDSStdRecordTypeFTPServer); const CFStringRef kDSStdRecordTypeWebServerSAFE_CFSTR = CFSTR(kDSStdRecordTypeWebServer); const CFStringRef kDotSAFE_CFSTR = CFSTR("."); const CFStringRef kEmptySAFE_CFSTR = CFSTR(""); const CFStringRef kDotUnderscoreTCPSAFE_CFSTR = CFSTR("._tcp."); const CFStringRef kUnderscoreSAFE_CFSTR = CFSTR("_"); #define kSecondsBeforeStartingNewNodeLookup 1 // time to wait before starting new network traffic enum eBuffType { kRecordListType = 'RecL', kClientSideParsingBuff = 'StdB' }; typedef struct NodeData { CFStringRef fNodeName; // this is what our plugin is going to find tDataList* fDSName; // this is the converted DS construct UInt32 fTimeStamp; // this is when the node was last "found" bool fIsADefaultNode; // is this node one that is considered "local" by plugin? uInt32 fSignature; // signature of plugin registering this CFMutableDictionaryRef fServicesRefTable; } NodeData; typedef struct sNSLContextData { // LDAP *fHost; //LDAP session handle // uInt32 fConfigTableIndex; //gConfigTable Hash index // char *fName; //LDAP domain name ie. ldap.apple.com // int fPort; //LDAP port number - default is 389 // int fType; //KW type of reference entry - not used yet // int msgId; //LDAP session call handle mainly used for searches // bool authCallActive; //indicates if authentication was made through the API //call and if set means don't use config file auth name/password // char *authAccountName; //Account name used in auth // char *authPassword; //Password used in auth // LDAPMessage *pResult; //LDAP message last result // uInt32 fRecNameIndex; //index used to cycle through all requested Rec Names // uInt32 fRecTypeIndex; //index used to cycle through all requested Rec Types // uInt32 fTotalRecCount; //count of all retrieved records // uInt32 fLimitRecSearch; //client specified limit of number of records to return // uInt32 fAttrIndex; //index used to cycle through all requested Attrs uInt32 offset; //offset into the data buffer // uInt32 index; // uInt32 attrCnt; // char *fOpenRecordType; //record type used to open a record // char *fOpenRecordName; //record name used to open a record } sNSLContextData; typedef enum { kClearOutStaleNodes, // check each node's timestamp and compare to last time we did a lookup kClearOutAllNodes // just get rid of them. } NodeDataMessageType; typedef struct NSLNodeHandlerContext { CFMutableDictionaryRef fDictionary; NodeDataMessageType fMessage; void* fDataPtr; CFMutableArrayRef fNodesToRemove; } NSLNodeHandlerContext; #define kMaxNumOutstandingSearches 6 void SearchStarted( void ); void SearchCompleted( void ); class CNSLServiceLookupThread; class CNSLDirNodeRep; class TCFResources; class CPlugInRef; class CDataBuff; class CNSLPlugin : public CDSServerModule { friend class CNSLServiceLookupThread; public: CNSLPlugin ( void ); virtual ~CNSLPlugin ( void ); virtual sInt32 InitPlugin ( void ) = 0; void WaitForInit ( void ); virtual sInt32 Validate ( const char *inVersionStr, const uInt32 inSignature ); Boolean IsActive ( void ); virtual sInt32 ProcessRequest ( void *inData ); virtual sInt32 SetServerIdleRunLoopRef ( CFRunLoopRef idleRunLoopRef ); virtual sInt32 SetPluginState ( const uInt32 inState ); virtual void ActivateSelf ( void ); virtual void DeActivateSelf ( void ); #pragma mark virtual sInt32 NSLSearchTickler ( void ); virtual void CancelCurrentlyQueuedSearches ( void ); void AddNode ( CFStringRef nodeNameRef, Boolean isLocalNode = false ); void AddNode ( const char* nodeName, Boolean isLocalNode = false ); void RemoveNode ( CFStringRef nodeNameRef ); virtual void NodeLookupComplete ( void ); // node lookup thread calls this when it finishes void LockPlugin ( void ) { pthread_mutex_lock( &mPluginLock ); } void UnlockPlugin ( void ) { pthread_mutex_unlock( &mPluginLock ); } pthread_mutex_t mPluginLock; void LockOpenRefTable ( void ) { pthread_mutex_lock( &mOpenRefTableLock ); } void UnlockOpenRefTable ( void ) { pthread_mutex_unlock( &mOpenRefTableLock ); } pthread_mutex_t mOpenRefTableLock; void LockSearchQueue ( void ) { pthread_mutex_lock( &mSearchQueueLock ); } void UnlockSearchQueue ( void ) { pthread_mutex_unlock( &mSearchQueueLock ); } pthread_mutex_t mSearchQueueLock; void LockPublishedNodes ( void ) { pthread_mutex_lock( &mQueueLock ); } void UnlockPublishedNodes ( void ) { pthread_mutex_unlock( &mQueueLock ); } pthread_mutex_t mQueueLock; void LockSearchLookupTimer ( void ) { pthread_mutex_lock( &mSearchLookupTimerLock ); } void UnlockSearchLookupTimer ( void ) { pthread_mutex_unlock( &mSearchLookupTimerLock ); } pthread_mutex_t mSearchLookupTimerLock; void LockNodeLookupTimer ( void ) { pthread_mutex_lock( &mNodeLookupTimerLock ); } void UnlockNodeLookupTimer ( void ) { pthread_mutex_unlock( &mNodeLookupTimerLock ); } pthread_mutex_t mNodeLookupTimerLock; void StartNodeLookup ( void ); // this should fire off some threads in the subclass void ClearOutAllNodes ( void ); virtual const char* GetProtocolPrefixString ( void ) = 0; // this is used for top of the node's path "NSL" virtual const char* GetLocalNodeString ( void ); // the node that should get mapped to the "Local" node virtual Boolean IsLocalNode ( const char *inNode ); virtual Boolean IsADefaultOnlyNode ( const char *inNode ); virtual Boolean OKToStartNewSearch ( void ); virtual void StartNextQueuedSearch ( void ); sInt16 NumOutstandingSearches ( void ); static CNSLPlugin* TheNSLPlugin ( void ) { return gsTheNSLPlugin; } static CNSLPlugin* gsTheNSLPlugin; CFRunLoopRef GetRunLoopRef ( void ) { return mRunLoopRef; } void HandleNetworkTransitionIfTime( void ); void PeriodicNodeLookupTask ( void ); virtual char* CreateNSLTypeFromRecType( char *inRecType, Boolean* needToFree ); virtual char* CreateRecTypeFromURL ( char *inNSLType, Boolean* needToFree ); virtual CFStringRef CreateRecTypeFromNativeType ( char *inNativeType ); virtual CFStringRef CreateRecTypeFromNativeType ( CFStringRef inNativeType ); protected: #pragma mark virtual CFStringRef GetBundleIdentifier ( void ) = 0; virtual void NewNodeLookup ( void ) = 0; virtual Boolean OKToOpenUnPublishedNode ( const char* parentNodeName ) = 0; virtual void NewServiceLookup ( char* serviceType, CNSLDirNodeRep* nodeDirRep ) = 0; void QueueNewSearch ( CNSLServiceLookupThread* newLookup ); void StartSubNodeLookup ( char* parentNodeName ); void StartServicesLookup ( char* serviceType, CNSLDirNodeRep* nodeDirRep ); sInt32 HandleRequest ( void *inData ); virtual sInt32 DoPlugInCustomCall ( sDoPlugInCustomCall *inData ); virtual sInt32 GetDirNodeInfo ( sGetDirNodeInfo *inData ); virtual Boolean PluginSupportsServiceType( const char* serviceType ) {return true;} // plugins to override if needed sInt32 GetAttributeEntry ( sGetAttributeEntry *inData ); sInt32 GetAttributeValue ( sGetAttributeValue *inData ); sInt32 OpenDirNode ( sOpenDirNode *inData ); sInt32 CloseDirNode ( sCloseDirNode *inData ); sInt32 GetRecordList ( sGetRecordList *inData ); virtual sInt32 OpenRecord ( sOpenRecord *inData ); virtual sInt32 CloseRecord ( sCloseRecord *inData ); virtual sInt32 CreateRecord ( sCreateRecord *inData ); virtual sInt32 DeleteRecord ( sDeleteRecord *inData ); virtual sInt32 FlushRecord ( sFlushRecord *inData ); virtual sInt32 AddAttributeValue ( sAddAttributeValue *inData ); virtual sInt32 RemoveAttribute ( sRemoveAttribute *inData ); virtual sInt32 RemoveAttributeValue ( sRemoveAttributeValue *inData ); virtual sInt32 SetAttributeValue ( sSetAttributeValue *inData ); virtual sInt32 HandleNetworkTransition ( sHeader *inData ); virtual Boolean ReadOnlyPlugin ( void ) { return true; } virtual Boolean IsClientAuthorizedToCreateRecords ( sCreateRecord *inData ); virtual Boolean ResultMatchesRequestCriteria( const CNSLResult* result, sGetRecordList* request ); virtual sInt32 RegisterService ( tRecordReference recordRef, CFDictionaryRef service ); virtual sInt32 DeregisterService ( tRecordReference recordRef, CFDictionaryRef service ); sInt32 RetrieveResults ( sGetRecordList* inData, CNSLDirNodeRep* nodeRep ); // when node lookup is complete, any nodes that are stale should get unpublished virtual void ClearOutStaleNodes ( void ); void ZeroLastNodeLookupStartTime ( void ) { mLastNodeLookupStartTime = 0; } UInt32 GetLastNodeLookupStartTime ( void ) { return mLastNodeLookupStartTime; } virtual UInt32 GetTimeBetweenNodeLookups ( void ) { return kOncePerDay; } // plugins can override if they need to void InstallNodeLookupTimer ( void ); void UnInstallNodeLookupTimer ( void ); void ResetNodeLookupTimer ( UInt32 timeTillNewLookup ); uInt32 GetSignature( void ) { return mSignature; } CFMutableDictionaryRef mOpenRefTable; CFMutableDictionaryRef mPublishedNodes; // we keep track of published nodes here Boolean mActivatedByNSL; uInt32 mState; time_t mTransitionCheckTime; private: virtual sInt32 Initialize ( void ); void InstallSearchTickler ( void ); void UnInstallSearchTickler ( void ); CFRunLoopRef mRunLoopRef; CFRunLoopTimerRef mTimerRef; CFRunLoopTimerRef mNodeLookupTimerRef; Boolean mSearchTicklerInstalled; Boolean mNodeLookupTimerInstalled; CFMutableArrayRef mSearchQueue; UInt32 mLastNodeLookupStartTime; char* mDSLocalNodeLabel; char* mDSNetworkNodeLabel; char* mDSTopLevelNodeLabel; double mLastTimeEmptyResultsReturned; uInt32 mSignature; }; NodeData * AllocateNodeData(); void DeallocateNodeData( NodeData *nodeData ); UInt32 GetCurrentTime( void ); // returns current time in seconds CFStringEncoding NSLGetSystemEncoding( UInt32* outRegion=NULL ); // read the contents of /var/root/.CFUserTextEncoding #define MAX_DOMAIN_LABEL 63 CFStringRef CreateRFC1034HostLabelFromUTF8Name( CFStringRef UTF8NameRef, UInt32 maxNameLength = MAX_DOMAIN_LABEL ); #endif // #ifndef