void AfsAdmSvr_Action_StopRefresh (ASID idScope) { AfsAdmSvr_Enter(); for (size_t iOp = 0; iOp < l.cOperationsAllocated; ++iOp) { if (!l.aOperations[ iOp ].fInUse) continue; if (!l.aOperations[ iOp ].pAction) continue; if (l.aOperations[ iOp ].pAction->Action != ACTION_REFRESH) continue; if (l.aOperations[ iOp ].pAction->u.Refresh.idScope != idScope) continue; AfsAdmSvr_EndOperation (iOp); break; } if (GetAsidType (idScope) == itCELL) { AfsAdmSvr_MarkRefreshThread (idScope); } AfsAdmSvr_Leave(); }
LPASACTIONLIST AfsAdmSvr_GetOperations (UINT_PTR idClientSearch, ASID idCellSearch) { LPASACTIONLIST pList = AfsAdmSvr_CreateActionList(); AfsAdmSvr_Enter(); for (WORD iOp = 0; iOp < l.cOperationsAllocated; ++iOp) { if (!l.aOperations[ iOp ].fInUse) continue; if (!l.aOperations[ iOp ].pAction) continue; if (idClientSearch && ((UINT_PTR)idClientSearch != l.aOperations[ iOp ].pAction->idClient)) continue; if (idCellSearch && (idCellSearch != l.aOperations[ iOp ].pAction->idCell)) continue; ASACTION Action; memcpy (&Action, l.aOperations[ iOp ].pAction, sizeof(ASACTION)); Action.csecActive = (GetTickCount() - l.aOperations[ iOp ].dwTickStart) / 1000; if (!AfsAdmSvr_AddToActionList (&pList, &Action)) { AfsAdmSvr_FreeActionList (&pList); break; } } AfsAdmSvr_Leave(); return pList; }
BOOL AfsAdmSvr_AttachClient (LPCTSTR pszName, PVOID *pidClient, ULONG *pStatus) { AfsAdmSvr_Enter(); size_t iClient; for (iClient = 0; iClient < l.cClientsAllocated; ++iClient) { if (!l.aClients[ iClient ]) break; } if (!REALLOC (l.aClients, l.cClientsAllocated, 1+iClient, cREALLOC_CLIENTS)) { *pidClient = NULL; return FALSE; } if ((l.aClients[ iClient ] = New (CLIENTINFO)) == NULL) { *pidClient = NULL; return FALSE; } memset (l.aClients[ iClient ], 0x00, sizeof(CLIENTINFO)); lstrcpy (l.aClients[ iClient ]->szName, pszName); l.aClients[ iClient ]->timeLastPing = AfsAdmSvr_GetCurrentTime(); l.cClients ++; if (!AfsAdmSvr_ResolveName (&l.aClients[ iClient ]->ipAddress, l.aClients[ iClient ]->szName)) memset (&l.aClients[ iClient ]->ipAddress, 0x00, sizeof(SOCKADDR_IN)); *pidClient = (PVOID)(l.aClients[ iClient ]); AfsAdmSvr_Leave(); return TRUE; }
DWORD WINAPI AfsAdmSvr_AutoShutdownThread (LPVOID lp) { for (;;) { AfsAdmSvr_Enter(); BOOL fShutdown = l.fAutoShutdown; // If there are any clients connected, forcably disconnect any // that haven't pinged us for too long // for (size_t iClient = 0; iClient < l.cClientsAllocated; ++iClient) { if (!l.aClients[ iClient ]) continue; if (l.aClients[ iClient ]->timeLastPing + cminREQ_CLIENT_PING <= AfsAdmSvr_GetCurrentTime()) { Print (dlCONNECTION, "Client 0x%08lX idle for too long; detaching", l.aClients[ iClient ]); AfsAdmSvr_DetachClient ((UINT_PTR)l.aClients[ iClient ]); } } // If any operations are in progress, we can't shutdown. // if (l.cOperations) fShutdown = FALSE; // If any clients are still connected, we can't shutdown. // if (l.cClients) fShutdown = FALSE; // If we haven't been idle long enough, we can't shutdown // if (!l.timeLastIdleStart) fShutdown = FALSE; else if (l.timeLastIdleStart + cminAUTO_SHUTDOWN > AfsAdmSvr_GetCurrentTime()) fShutdown = FALSE; // That's it; can we stop now? // if (fShutdown) { Print ("Idle for too long; shutting down."); RpcMgmtStopServerListening (NULL); AfsAdmSvr_StopCallbackManagers(); } AfsAdmSvr_Leave(); if (fShutdown) break; Sleep (cminAUTO_SHUTDOWN_SLEEP * 60L * 1000L); } return 0; }
PVOID Leave_NULL_ (ULONG status, ULONG *pStatus, size_t iOp) { AfsAdmSvr_Leave(); if (pStatus) *pStatus = status; if (iOp != (size_t)-2) AfsAdmSvr_EndOperation (iOp); return NULL; }
BOOL Leave_TRUE_ (ULONG *pStatus, size_t iOp) { AfsAdmSvr_Leave(); if (pStatus) *pStatus = 0; if (iOp != (size_t)-2) AfsAdmSvr_EndOperation (iOp); return TRUE; }
BOOL Leave_FALSE_ (ULONG status, ULONG *pStatus, size_t iOp) { AfsAdmSvr_Leave(); if (pStatus) *pStatus = status; if (iOp != (size_t)-2) AfsAdmSvr_EndOperation (iOp); return FALSE; }
void AfsAdmSvr_StopCallbackManagers (void) { AfsAdmSvr_Enter(); if (l.cManagers) { l.fStopManagers = TRUE; SetEvent (l.heCallback); } AfsAdmSvr_Leave(); }
// AfsAdmSvr_Ping // ...reminds the admin server that the specified client is still around. // this call should be made at least every csecAFSADMSVR_CLIENT_PING // seconds, lest the admin server think you've disconnected. (The // client library TaAfsAdmSvrClient.lib automatically handles this.) // extern "C" int AfsAdmSvr_Ping (UINT_PTR idClient, ULONG *pStatus) { AfsAdmSvr_Enter(); if (!AfsAdmSvr_fIsValidClient (idClient)) return Leave_FALSE_(ERROR_INVALID_PARAMETER, pStatus); AfsAdmSvr_PingClient (idClient); AfsAdmSvr_Leave(); return TRUE; }
BOOL AfsAdmSvr_GetOperation (DWORD idAction, LPASACTION pAction) { AfsAdmSvr_Enter(); for (size_t iOp = 0; iOp < l.cOperationsAllocated; ++iOp) { if (!l.aOperations[ iOp ].fInUse) continue; if (!l.aOperations[ iOp ].pAction) continue; if (l.aOperations[ iOp ].pAction->idAction != idAction) continue; memcpy (pAction, l.aOperations[ iOp ].pAction, sizeof(ASACTION)); pAction->csecActive = (GetTickCount() - l.aOperations[ iOp ].dwTickStart) / 1000; AfsAdmSvr_Leave(); return TRUE; } AfsAdmSvr_Leave(); return FALSE; }
void AfsAdmSvr_EnableAutoShutdown (BOOL fEnable) { AfsAdmSvr_Enter(); l.fAutoShutdown = fEnable; if (fEnable) Print (dlDETAIL, TEXT("Auto-shutdown enabled, trigger = %lu minutes idle time"), cminAUTO_SHUTDOWN); else Print (dlDETAIL, TEXT("Auto-shutdown on idle disabled")); AfsAdmSvr_Leave(); }
void AfsAdmSvr_PingClient (UINT_PTR idClient) { AfsAdmSvr_Enter(); for (size_t iClient = 0; iClient < l.cClientsAllocated; ++iClient) { if (idClient == (UINT_PTR)(l.aClients[ iClient ])) { l.aClients[ iClient ]->timeLastPing = AfsAdmSvr_GetCurrentTime(); } } AfsAdmSvr_Leave(); }
// AfsAdmSvr_Disconnect // ...releases and invalidates the cookie representing the calling process. // extern "C" int AfsAdmSvr_Disconnect (UINT_PTR idClient, ULONG *pStatus) { AfsAdmSvr_Enter(); // Make sure this is a valid client, and free its l.aClients[] entry if so. // if (!AfsAdmSvr_fIsValidClient (idClient)) return Leave_FALSE_(ERROR_INVALID_PARAMETER, pStatus); Print (TEXT("Disconnected from client %s (ID 0x%08lX)"), AfsAdmSvr_GetClientName (idClient), idClient); AfsAdmSvr_DetachClient (idClient); AfsAdmSvr_Leave(); return TRUE; }
BOOL AfsAdmSvr_fIsValidClient (UINT_PTR idClient) { BOOL rc = FALSE; AfsAdmSvr_Enter(); for (size_t iClient = 0; !rc && iClient < l.cClientsAllocated; ++iClient) { if (idClient == (UINT_PTR)l.aClients[ iClient ]) { if (l.aClients[ iClient ]->timeLastPing + cminREQ_CLIENT_PING > AfsAdmSvr_GetCurrentTime()) rc = TRUE; } } AfsAdmSvr_Leave(); return rc; }
void AfsAdmSvr_DetachClient (UINT_PTR idClient) { AfsAdmSvr_Enter(); size_t iClient; for (iClient = 0; iClient < l.cClientsAllocated; ++iClient) { if (idClient == (UINT_PTR)(l.aClients[ iClient ])) break; } if (iClient < l.cClientsAllocated) { Delete (l.aClients[ iClient ]); l.aClients[ iClient ] = NULL; l.cClients --; } AfsAdmSvr_TestShutdown(); AfsAdmSvr_Leave(); }
LPCTSTR AfsAdmSvr_GetClientName (UINT_PTR idClient) { static TCHAR szName[ cchSTRING ]; LPCTSTR pszName = NULL; AfsAdmSvr_Enter(); for (size_t iClient = 0; !pszName && iClient < l.cClientsAllocated; ++iClient) { if (idClient == (UINT_PTR)(l.aClients[ iClient ])) { lstrcpy (szName, l.aClients[ iClient ]->szName); pszName = szName; } } AfsAdmSvr_Leave(); return pszName; }
LPSOCKADDR_IN AfsAdmSvr_GetClientAddress (UINT_PTR idClient) { static SOCKADDR_IN ipAddress; LPSOCKADDR_IN pAddress = NULL; AfsAdmSvr_Enter(); for (size_t iClient = 0; !pAddress && iClient < l.cClientsAllocated; ++iClient) { if (idClient == (UINT_PTR)(l.aClients[ iClient ])) { memcpy (&ipAddress, &l.aClients[ iClient ]->ipAddress, sizeof(SOCKADDR_IN)); pAddress = &ipAddress; } } AfsAdmSvr_Leave(); return pAddress; }
void AfsAdmSvr_EndOperation (size_t iOp) { AfsAdmSvr_Enter(); if ((iOp != (size_t)-1) && (iOp < l.cOperationsAllocated) && (l.aOperations[ iOp ].fInUse)) { if (l.aOperations[ iOp ].pAction) { Print (dlOPERATION, TEXT("Ending action 0x%08lX"), l.aOperations[ iOp ].pAction->idAction); AfsAdmSvr_PostCallback (cbtACTION, TRUE, l.aOperations[ iOp ].pAction); Delete (l.aOperations[ iOp ].pAction); } memset (&l.aOperations[ iOp ], 0x00, sizeof(l.aOperations[ iOp ])); l.cOperations --; } AfsAdmSvr_TestShutdown(); AfsAdmSvr_Leave(); }
void AfsAdmSvr_PostCallback (CALLBACKTYPE Type, BOOL fFinished, LPASACTION pAction, DWORD dwRemoveMe) { AfsAdmSvr_Enter(); if (l.pListCallbacks) { LPCALLBACKDATA pData = New (CALLBACKDATA); memset (pData, 0x00, sizeof(CALLBACKDATA)); pData->Type = Type; pData->fFinished = fFinished; if (pAction) { pData->pAction = New (ASACTION); memcpy (pData->pAction, pAction, sizeof(ASACTION)); } l.pListCallbacks->Add (pData); SetEvent (l.heCallback); } AfsAdmSvr_Leave(); }
void AfsAdmSvr_CallbackManager (void) { AfsAdmSvr_Enter(); if ((++l.cManagers) == 1) { l.heCallback = CreateEvent (NULL, TRUE, FALSE, TEXT("AfsAdmSvr_CallbackManager Event")); l.pListCallbacks = New (HASHLIST); } AfsAdmSvr_Leave(); for (;;) { WaitForSingleObjectEx (l.heCallback, INFINITE, FALSE); if (l.fStopManagers) break; // We must ensure that we don't block the server's operations because // a callback doesn't go through; since other operations may need // access to the l.pListCallbacks structure in order to queue new // callbacks, we can't leave it locked by issuing callbacks while // enumerating it. Instead we'll copy the list into a local copy, // clear it, and enumerate that local copy--other threads can then // continue to add new requests to l.pListCallbacks. // AfsAdmSvr_Enter(); LPHASHLIST pList = New (HASHLIST); LPENUM pEnum; for (pEnum = l.pListCallbacks->FindFirst(); pEnum; pEnum = pEnum->FindNext()) { LPCALLBACKDATA pData = (LPCALLBACKDATA)( pEnum->GetObject() ); pList->Add (pData); l.pListCallbacks->Remove (pData); } ResetEvent (l.heCallback); AfsAdmSvr_Leave(); // Now enumerate that copied list, and issue callbacks for each item. // for (pEnum = pList->FindFirst(); pEnum; pEnum = pEnum->FindNext()) { LPCALLBACKDATA pData = (LPCALLBACKDATA)( pEnum->GetObject() ); try { switch (pData->Type) { case cbtACTION: AfsAdmSvrCallback_Action (pData->pAction, pData->fFinished); break; } } catch(...) { ; } pList->Remove (pData); AfsAdmSvr_FreeCallbackData (pData); } Delete (pList); } AfsAdmSvr_Enter(); if ((--l.cManagers) == 0) { Delete (l.pListCallbacks); l.pListCallbacks = NULL; CloseHandle (l.heCallback); l.heCallback = NULL; } AfsAdmSvr_Leave(); }
size_t AfsAdmSvr_BeginOperation (UINT_PTR idClient, LPASACTION pAction) { AfsAdmSvr_Enter(); ++l.cOperations; size_t iOp; for (iOp = 0; iOp < l.cOperationsAllocated; ++iOp) { if (!l.aOperations[ iOp ].fInUse) break; } if (!REALLOC (l.aOperations, l.cOperationsAllocated, 1+iOp, cREALLOC_OPERATIONS)) { AfsAdmSvr_Leave(); return (size_t)(-1); } l.aOperations[ iOp ].idClient = idClient; l.aOperations[ iOp ].pAction = NULL; l.aOperations[ iOp ].fInUse = TRUE; if (pAction) { l.aOperations[ iOp ].pAction = New (ASACTION); memcpy (l.aOperations[ iOp ].pAction, pAction, sizeof(ASACTION)); l.aOperations[ iOp ].pAction->idAction = ++l.idActionLast; l.aOperations[ iOp ].pAction->idClient = idClient; l.aOperations[ iOp ].pAction->csecActive = 0; TCHAR szDesc[256]; switch (l.aOperations[ iOp ].pAction->Action) { case ACTION_REFRESH: wsprintf (szDesc, TEXT("Refresh (scope=0x%08lX)"), l.aOperations[ iOp ].pAction->u.Refresh.idScope); break; case ACTION_SCOUT: wsprintf (szDesc, TEXT("Scout (scope=0x%08lX)"), l.aOperations[ iOp ].pAction->u.Refresh.idScope); break; case ACTION_USER_CHANGE: wsprintf (szDesc, TEXT("ChangeUser (user=0x%08lX)"), l.aOperations[ iOp ].pAction->u.User_Change.idUser); break; case ACTION_USER_PW_CHANGE: wsprintf (szDesc, TEXT("SetUserPassword (user=0x%08lX)"), l.aOperations[ iOp ].pAction->u.User_Pw_Change.idUser); break; case ACTION_USER_UNLOCK: wsprintf (szDesc, TEXT("UnlockUser (user=0x%08lX)"), l.aOperations[ iOp ].pAction->u.User_Unlock.idUser); break; case ACTION_USER_CREATE: wsprintf (szDesc, TEXT("CreateUser (user=%s)"), l.aOperations[ iOp ].pAction->u.User_Create.szUser); break; case ACTION_USER_DELETE: wsprintf (szDesc, TEXT("CreateUser (user=0x%08lX)"), l.aOperations[ iOp ].pAction->u.User_Delete.idUser); break; case ACTION_GROUP_CHANGE: wsprintf (szDesc, TEXT("ChangeGroup (group=0x%08lX)"), l.aOperations[ iOp ].pAction->u.Group_Change.idGroup); break; case ACTION_GROUP_MEMBER_ADD: wsprintf (szDesc, TEXT("AddGroupMember (group=0x%08lX, user=0x%08lX)"), l.aOperations[ iOp ].pAction->u.Group_Member_Add.idGroup, l.aOperations[ iOp ].pAction->u.Group_Member_Add.idUser); break; case ACTION_GROUP_MEMBER_REMOVE: wsprintf (szDesc, TEXT("RemoveGroupMember (group=0x%08lX, user=0x%08lX)"), l.aOperations[ iOp ].pAction->u.Group_Member_Remove.idGroup, l.aOperations[ iOp ].pAction->u.Group_Member_Remove.idUser); break; case ACTION_GROUP_RENAME: wsprintf (szDesc, TEXT("RenameGroup (group=0x%08lX, new name=%s)"), l.aOperations[ iOp ].pAction->u.Group_Rename.idGroup, l.aOperations[ iOp ].pAction->u.Group_Rename.szNewName); break; case ACTION_GROUP_DELETE: wsprintf (szDesc, TEXT("CreateGroup (group=0x%08lX)"), l.aOperations[ iOp ].pAction->u.Group_Delete.idGroup); break; case ACTION_CELL_CHANGE: wsprintf (szDesc, TEXT("ChangeCell (cell=0x%08lX)"), l.aOperations[ iOp ].pAction->idCell); break; default: wsprintf (szDesc, TEXT("Unknown Action (#%lu)"), l.aOperations[ iOp ].pAction->Action); break; } Print (dlOPERATION, TEXT("Starting action 0x%08lX: %s"), l.aOperations[ iOp ].pAction->idAction, szDesc); AfsAdmSvr_PostCallback (cbtACTION, FALSE, l.aOperations[ iOp ].pAction); } l.aOperations[ iOp ].dwTickStart = GetTickCount(); AfsAdmSvr_Leave(); return iOp; }