📄 resource.c
字号:
SSMStatus SSM_ClientDestroyResource(SSMControlConnection * connection, SSMResourceID rid, SSMResourceType objType){ SSMStatus rv; SSMResource *res = NULL; PRIntn clientCount; rv = SSMControlConnection_GetResource(connection, rid, &res); if (rv != PR_SUCCESS) goto done; PR_ASSERT(res); /* If the object is of the right type, free the reference. */ if (!SSM_IsAKindOf(res, objType)) { rv = SSM_ERR_BAD_RESOURCE_TYPE; goto done; } SSM_LockResource(res); clientCount = --(res->m_clientCount); SSM_DEBUG("Free client ref - rsrcid: %ld --clientcnt: %ld\n", res->m_id, res->m_clientCount); /* Also release the resource that was added when the client got * its resource */ SSM_FreeResource(res); PR_ASSERT(clientCount >= 0); if((clientCount == 0) && (res->m_threadCount > 0)) { SSM_DEBUG("ClientDestroy: Shutting down resource %ld.\n", (long)res->m_id); rv = SSM_ShutdownResource(res, SSM_ERR_CLIENT_DESTROY); if (rv != PR_SUCCESS) goto locked_done; }locked_done: SSM_UnlockResource(res);done: if (res != NULL) rv = SSM_FreeResource(res); SSM_DEBUG("ClientDestroy returning status %d.\n", rv); return rv;}SSMStatus SSM_MessageFormatResource(SSMResource *res, char *fmt, PRIntn numParams, char ** value, char **resultStr){ SSMStatus rv = SSM_FAILURE; if (res->m_print_func) rv = (*(res->m_print_func))(res, fmt, numParams, value, resultStr); return rv;}SSMStatusSSMResource_Shutdown(SSMResource *res, SSMStatus status){ SSMStatus rv = PR_SUCCESS; SSM_LockResource(res); if ((res->m_status == PR_SUCCESS) || (res->m_status == SSM_ERR_CLIENT_DESTROY)) { SSM_DEBUG("Shutting down %s with rid %ld. Status == %d.\n", res->m_class->m_className, (long) res->m_id, status); res->m_status = status; /* If there is a thread waiting for us to shut down, notify it. */ if (res->m_waitThread) SSM_NotifyResource(res); } else rv = SSM_ERR_ALREADY_SHUT_DOWN; res->m_resourceShutdown = PR_TRUE; SSM_UnlockResource(res); return rv;}voidSSMResource_Invariant(SSMResource *res){#ifdef DEBUG if (res) { PR_ASSERT(res->m_id != 0); PR_ASSERT(SSM_IsAKindOf(res, SSM_RESTYPE_RESOURCE)); PR_ASSERT(res->m_refCount >= 0); PR_ASSERT(res->m_destroy_func != NULL); PR_ASSERT(res->m_shutdown_func != NULL); PR_ASSERT(res->m_getids_func != NULL); PR_ASSERT(res->m_get_func != NULL); PR_ASSERT(res->m_set_func != NULL); PR_ASSERT(res->m_connection != NULL); }#endif}SSMStatusSSMResource_Create(void *arg, SSMControlConnection * connection, SSMResource **res){ /* never instantiate a bare SSMResource */ *res = NULL; return PR_FAILURE;}SSMStatusSSMResource_GetAttr(SSMResource *res, SSMAttributeID fieldID, SSMResourceAttrType attrType, SSMAttributeValue *value){ return SSM_ERR_BAD_ATTRIBUTE_ID;}SSMStatusSSMResource_GetAttrIDs(SSMResource *res, SSMAttributeID **ids, PRIntn *count){ /* return 0 attributes */ *ids = (SSMAttributeID *) PR_CALLOC(0); *count = 0; return PR_SUCCESS;}SSMStatusSSMResource_SetAttr(SSMResource *res, SSMAttributeID attrID, SSMAttributeValue *value){ return PR_FAILURE; /* nothing client-accessible in the base class */}SSMStatusSSMResource_Pickle(SSMResource *res, PRIntn * len, void **value){ return PR_FAILURE;}SSMStatusSSMResource_Unpickle(SSMResource ** res, SSMControlConnection *conn, PRIntn len, void * value){ return PR_FAILURE;}SSMStatusSSMResource_HTML(SSMResource *res, PRIntn * len, void ** value){ return PR_FAILURE;}SSMStatus SSMResource_Print(SSMResource *res, char *fmt, PRIntn numParams, char ** value, char **resultStr){ PR_ASSERT(res != NULL && fmt != NULL && resultStr != NULL); if (numParams > 3) SSM_DEBUG("SSMResource_Print: too many parameters!\n"); switch (numParams) { case (3): *resultStr = PR_smprintf(fmt, res->m_id, *value, *(value+1),*(value+2)); break; case (2): *resultStr = PR_smprintf(fmt, res->m_id, *value, *(value+1)); break; case (1): *resultStr = PR_smprintf(fmt, res->m_id, *value); break; default: *resultStr = PR_smprintf(fmt, res->m_id); } if (*resultStr == NULL) { return PR_FAILURE; } return PR_SUCCESS;}SSMStatusSSMResource_FormSubmitHandler(SSMResource *res, HTTPRequest *req){ return SSM_HTTPDefaultCommandHandler(req);}voidSSM_LockResource(SSMResource *res){ PR_EnterMonitor(res->m_lock);}SSMStatusSSM_UnlockResource(SSMResource *res){ return PR_ExitMonitor(res->m_lock);}SSMStatusSSM_WaitResource(SSMResource *res, PRIntervalTime ticks){ return PR_Wait(res->m_lock, ticks);}SSMStatusSSM_NotifyResource(SSMResource *res){ return PR_Notify(res->m_lock);}/* Wait for a resource to shut down. ### mwelch We use WaitResource() in another context, namely where data connections hand over a newly opened port number to their control connections. Can we guard against the case where we have an initializing data connection upon which a thread decides to wait for shutdown?*/SSMStatusSSM_WaitForResourceShutdown(SSMResource *res){ SSMStatus rv = PR_SUCCESS; SSM_LockResource(res); PR_ASSERT(res->m_waitThread == NULL); if (res->m_waitThread) rv = PR_FAILURE; else if (!res->m_resourceShutdown) { res->m_waitThread = PR_GetCurrentThread(); do SSM_WaitResource(res, PR_INTERVAL_NO_TIMEOUT); while (res->m_threadCount > 0); res->m_waitThread = NULL; } else { rv = SSM_ERR_ALREADY_SHUT_DOWN; } SSM_UnlockResource(res); return rv;}char * SSM_ResourceClassName(SSMResource *res){ return res->m_class->m_className;}void SSM_LockUIEvent(SSMResource * res){ if (res->m_UILock == NULL) res->m_UILock = PR_NewMonitor(); PR_ASSERT(res->m_UILock); PR_EnterMonitor(res->m_UILock);}SSMStatus SSM_UnlockUIEvent(SSMResource *res){ PR_ASSERT(res->m_UILock); if (res->m_UILock != NULL) { return PR_ExitMonitor(res->m_UILock); } return PR_FAILURE;}SSMStatus SSM_WaitUIEvent(SSMResource * res, PRIntervalTime ticks){ PR_ASSERT(res->m_UILock); if (res->m_UILock) { res->m_UIBoolean = PR_FALSE; while (!res->m_UIBoolean) PR_Wait(res->m_UILock, ticks); return PR_ExitMonitor(res->m_UILock); } /* if we used UILock once, chances are we'll need it again? */ return PR_FAILURE;}SSMStatus SSM_NotifyUIEvent(SSMResource * res){ SSMStatus rv = PR_FAILURE; PR_ASSERT(res->m_UILock); if (res->m_UILock) { PR_EnterMonitor(res->m_UILock); res->m_UIBoolean = PR_TRUE; rv =PR_Notify(res->m_UILock); PR_ExitMonitor(res->m_UILock); } return rv;}SSMStatus SSM_WaitForOKCancelEvent(SSMResource *res, PRIntervalTime ticks){ PRStatus rv; if (res->m_UILock == NULL) { /* We might have been waken up by a spurious notify, * so we don't allocate a new monitor every time. */ res->m_UILock = PR_NewMonitor(); } PR_EnterMonitor(res->m_UILock); rv = PR_Wait(res->m_UILock, ticks); PR_ExitMonitor(res->m_UILock); return rv;}SSMStatus SSM_NotifyOKCancelEvent(SSMResource *res){ SSMStatus rv = PR_FAILURE; if (res->m_UILock) { PR_EnterMonitor(res->m_UILock); rv = PR_Notify(res->m_UILock); PR_ExitMonitor(res->m_UILock); } return rv;}SSMStatusSSM_HandlePromptReply(SSMResource *res, char *reply){ /* Currently, only SSMPKCS12Context supports this, * perhaps in the future we'll add more general support. */ if (!SSM_IsAKindOf(res, SSM_RESTYPE_PKCS12_CONTEXT)) { return PR_FAILURE; } return SSMPKCS12Context_ProcessPromptReply(res, reply);}PRThread *SSM_CreateThread(SSMResource *res, void (*func)(void *arg)){ PRThread *thd = NULL; PR_ASSERT(res != NULL); PR_ASSERT(func != NULL); SSM_LockResource(res); thd = SSM_CreateAndRegisterThread(PR_USER_THREAD, func, (void *)res, PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_UNJOINABLE_THREAD, 0); if (thd) { res->m_threadCount++; } SSM_UnlockResource(res); return thd;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -