Forbid some operations in asynchronous callbacks 22/30322/8
authorMarcin Niesluchowski <m.niesluchow@samsung.com>
Fri, 14 Nov 2014 12:18:32 +0000 (13:18 +0100)
committerLukasz Wojciechowski <l.wojciechow@partner.samsung.com>
Fri, 14 Nov 2014 22:02:59 +0000 (14:02 -0800)
In following cases cynara api operations regarding same cynara_async
structure called from within callbacks will return
CYNARA_API_OPERATION_NOT_ALLOWED:
- always within cynara_status_callback
- within cynara_response_callback called with
  CYNARA_CALL_CAUSE_SERVICE_NOT_AVAILABLE or CYNARA_CALL_CAUSE_FINISH
  cause.

It regards following api funtions:
- cynara_async_check_cache()
- cynara_async_create_request()
- cynara_async_process()
- cynara_async_cancel_request()

Change-Id: I1db22e0735e1905c4709c7f4c650cc8ca3f9b454

src/client-async/logic/Logic.cpp
src/client-async/logic/Logic.h
src/include/cynara-client-async.h

index 9725d64..5e0157d 100644 (file)
@@ -43,7 +43,7 @@
 namespace Cynara {
 
 Logic::Logic(cynara_status_callback callback, void *userStatusData)
-    : m_statusCallback(callback, userStatusData) {
+    : m_statusCallback(callback, userStatusData), m_operationPermitted(true) {
     m_socketClient = std::make_shared<SocketClientAsync>(
         PathConfig::SocketPath::client, std::make_shared<ProtocolClient>());
 
@@ -55,6 +55,7 @@ Logic::Logic(cynara_status_callback callback, void *userStatusData)
 }
 
 Logic::~Logic() {
+    m_operationPermitted = false;
     for (auto &kv : m_checks) {
         if (!kv.second.cancelled())
             kv.second.callback().onFinish(kv.first);
@@ -64,6 +65,9 @@ Logic::~Logic() {
 
 int Logic::checkCache(const std::string &client, const std::string &session,
                       const std::string &user, const std::string &privilege) {
+    if (!m_operationPermitted)
+        return CYNARA_API_OPERATION_NOT_ALLOWED;
+
     if (!checkCacheValid())
         return CYNARA_API_CACHE_MISS;
 
@@ -74,6 +78,9 @@ int Logic::createRequest(const std::string &client, const std::string &session,
                          const std::string &user, const std::string &privilege,
                          cynara_check_id &checkId, cynara_response_callback callback,
                          void *userResponseData) {
+    if (!m_operationPermitted)
+        return CYNARA_API_OPERATION_NOT_ALLOWED;
+
     if (!ensureConnection())
         return CYNARA_API_SERVICE_NOT_AVAILABLE;
 
@@ -86,14 +93,16 @@ int Logic::createRequest(const std::string &client, const std::string &session,
     m_checks.insert(CheckPair(sequenceNumber, CheckData(key, session, responseCallback)));
     m_socketClient->appendRequest(std::make_shared<CheckRequest>(key, sequenceNumber));
 
-    m_statusCallback.onStatusChange(m_socketClient->getSockFd(),
-                                    cynara_async_status::CYNARA_STATUS_FOR_RW);
+    onStatusChange(m_socketClient->getSockFd(), cynara_async_status::CYNARA_STATUS_FOR_RW);
     checkId = static_cast<cynara_check_id>(sequenceNumber);
 
     return CYNARA_API_SUCCESS;
 }
 
 int Logic::process(void) {
+    if (!m_operationPermitted)
+        return CYNARA_API_OPERATION_NOT_ALLOWED;
+
     bool completed;
     while (true) {
         int ret = completeConnection(completed);
@@ -108,6 +117,9 @@ int Logic::process(void) {
 }
 
 int Logic::cancelRequest(cynara_check_id checkId) {
+    if (!m_operationPermitted)
+        return CYNARA_API_OPERATION_NOT_ALLOWED;
+
     if (!ensureConnection())
         return CYNARA_API_SERVICE_NOT_AVAILABLE;
 
@@ -119,8 +131,7 @@ int Logic::cancelRequest(cynara_check_id checkId) {
 
     it->second.cancel();
     it->second.callback().onCancel(it->first);
-    m_statusCallback.onStatusChange(m_socketClient->getSockFd(),
-                                    cynara_async_status::CYNARA_STATUS_FOR_RW);
+    onStatusChange(m_socketClient->getSockFd(), cynara_async_status::CYNARA_STATUS_FOR_RW);
 
     return CYNARA_API_SUCCESS;
 }
@@ -144,8 +155,8 @@ void Logic::prepareRequestsToSend(void) {
 bool Logic::processOut(void) {
     switch (m_socketClient->sendToCynara()) {
         case Socket::SendStatus::ALL_DATA_SENT:
-            m_statusCallback.onStatusChange(m_socketClient->getSockFd(),
-                                            cynara_async_status::CYNARA_STATUS_FOR_READ);
+            onStatusChange(m_socketClient->getSockFd(),
+                           cynara_async_status::CYNARA_STATUS_FOR_READ);
         case Socket::SendStatus::PARTIAL_DATA_SENT:
             return true;
         default:
@@ -238,12 +249,11 @@ bool Logic::connect(void) {
     switch (m_socketClient->connect()) {
         case Socket::ConnectionStatus::CONNECTION_SUCCEEDED:
             prepareRequestsToSend();
-            m_statusCallback.onStatusChange(m_socketClient->getSockFd(), socketDataStatus());
+            onStatusChange(m_socketClient->getSockFd(), socketDataStatus());
             return true;
         case Socket::ConnectionStatus::CONNECTION_IN_PROGRESS:
             prepareRequestsToSend();
-            m_statusCallback.onStatusChange(m_socketClient->getSockFd(),
-                                            cynara_async_status::CYNARA_STATUS_FOR_RW);
+            onStatusChange(m_socketClient->getSockFd(), cynara_async_status::CYNARA_STATUS_FOR_RW);
             return true;
         default:
             onServiceNotAvailable();
@@ -257,7 +267,7 @@ int Logic::completeConnection(bool &completed) {
             completed = true;
             return CYNARA_API_SUCCESS;
         case Socket::ConnectionStatus::CONNECTION_SUCCEEDED:
-            m_statusCallback.onStatusChange(m_socketClient->getSockFd(), socketDataStatus());
+            onStatusChange(m_socketClient->getSockFd(), socketDataStatus());
             completed = true;
             return CYNARA_API_SUCCESS;
         case Socket::ConnectionStatus::CONNECTION_IN_PROGRESS:
@@ -271,19 +281,29 @@ int Logic::completeConnection(bool &completed) {
     }
 }
 
+void Logic::onStatusChange(int sock, cynara_async_status status) {
+    m_operationPermitted = false;
+    m_statusCallback.onStatusChange(sock, status);
+    m_operationPermitted = true;
+}
+
 void Logic::onServiceNotAvailable(void)
 {
+    m_operationPermitted = false;
     for (auto &kv : m_checks) {
         if (!kv.second.cancelled())
             kv.second.callback().onDisconnected(kv.first);
     }
     m_checks.clear();
     m_sequenceContainer.clear();
+    m_operationPermitted = true;
 }
 
 void Logic::onDisconnected(void) {
+    m_operationPermitted = false;
     m_cache->clear();
     m_statusCallback.onDisconnected();
+    m_operationPermitted = true;
 }
 
 } // namespace Cynara
index 0bca98e..6f30fdb 100644 (file)
@@ -59,6 +59,7 @@ private:
     SocketClientAsyncPtr m_socketClient;
     CheckMap m_checks;
     SequenceContainer m_sequenceContainer;
+    bool m_operationPermitted;
 
     bool checkCacheValid(void);
     void prepareRequestsToSend(void);
@@ -71,6 +72,7 @@ private:
     bool ensureConnection(void);
     bool connect(void);
     int completeConnection(bool &completed);
+    void onStatusChange(int sock, cynara_async_status status);
     void onServiceNotAvailable(void);
     void onDisconnected(void);
 };
index 536e5d7..b9675f1 100644 (file)
@@ -84,6 +84,8 @@ typedef enum {
  *    (CYNARA_CALL_CAUSE_FINISH)
  * 4) when connection to cynara service was broken and cannot be established again
  *    - probably cynara is unoperational (CYNARA_CALL_CAUSE_SERVICE_NOT_AVAILABLE)
+ * Api functions called during this callback with CYNARA_CALL_CAUSE_SERVICE_NOT_AVAILABLE
+ * or CYNARA_CALL_CAUSE_FINISH cause will return CYNARA_API_OPERATION_NOT_ALLOWED.
  *
  * \param[in] check_id Number identifying check request. Number is generated in
  *            cynara_async_create_request() and returned to user. It can be used to match
@@ -113,6 +115,7 @@ typedef void (*cynara_response_callback) (cynara_check_id check_id, cynara_async
  * Note, that provided file descriptor is used internally by libcynara
  * so user should not use it in other way than waiting on it in event loop.
  * In particular user should not write to, read from or close this fd.
+ * CYNARA_API_OPERATION_NOT_ALLOWED will be returned for every api function called in this callback.
  *
  * \param[in] old_fd Old descriptor which should be unregistered from event loop,
  *            Special value -1 is used when callback is called after first
@@ -240,7 +243,10 @@ void cynara_async_finish(cynara_async *p_cynara);
  *
  * \par Important notes:
  * Call to cynara_async_check_cache() needs cynara_async structure to be created first.
- * Use cynara_async_initialize() before calling this function.
+ * Use cynara_async_initialize() before calling this function. cynara_async_check_cache() called
+ * from within cynara_status_callback or cynara_response_callback with
+ * CYNARA_CALL_CAUSE_SERVICE_NOT_AVAILABLE or CYNARA_CALL_CAUSE_FINISH cause will return
+ * CYNARA_API_OPERATION_NOT_ALLOWED.
  *
  * \param[in] p_cynara cynara_async structure.
  * \param[in] client Application or process identifier.
@@ -306,6 +312,9 @@ int cynara_async_check_cache(cynara_async *p_cynara, const char *client, const c
  * If function fails (returns negative error code) request won't be generated and won't be pending,
  * callback function won't be ever called and user_response_data won't be remembered by library.
  * Also no check_id will be generated and *p_check_id value should be ignored.
+ * cynara_async_create_request() called from within cynara_status_callback or
+ * cynara_response_callback with CYNARA_CALL_CAUSE_SERVICE_NOT_AVAILABLE or CYNARA_CALL_CAUSE_FINISH
+ * cause will return CYNARA_API_OPERATION_NOT_ALLOWED.
  *
  * \param[in] p_cynara cynara_async structure.
  * \param[in] client Application or process identifier.
@@ -359,7 +368,9 @@ int cynara_async_create_request(cynara_async *p_cynara, const char *client,
  *
  * \par Important notes:
  * Call to cynara_async_process() requires initialized cynara_async structure. For this use
- * cynara_async_initialize().
+ * cynara_async_initialize(). cynara_async_process() called from within cynara_status_callback or
+ * cynara_response_callback with CYNARA_CALL_CAUSE_SERVICE_NOT_AVAILABLE or CYNARA_CALL_CAUSE_FINISH
+ * cause will return CYNARA_API_OPERATION_NOT_ALLOWED.
  *
  * \param[in] p_cynara cynara_async structure.
  *
@@ -398,7 +409,9 @@ int cynara_async_process(cynara_async *p_cynara);
  *
  * \par Important notes:
  * Call to cynara_async_cancel_request() needs cynara_async structure to be created first. For this
- * use cynara_async_initialize().
+ * use cynara_async_initialize(). cynara_async_cancel_request() called from within
+ * cynara_status_callback or cynara_response_callback with CYNARA_CALL_CAUSE_SERVICE_NOT_AVAILABLE
+ * or CYNARA_CALL_CAUSE_FINISH cause will return CYNARA_API_OPERATION_NOT_ALLOWED.
  *
  * \param[in] p_cynara cynara_async structure.
  * \param[in] check_id Check id to be cancelled