Browse Source

Fixed publish request limit handling

Respond with oldest publish request when the publish request limit
has been reached.

Fixed incorrect error code for too many subscriptions.
Mattias Bornhager 7 years ago
parent
commit
349a6b723c

+ 5 - 5
src/server/ua_services_subscription.c

@@ -60,7 +60,7 @@ Service_CreateSubscription(UA_Server *server, UA_Session *session,
 
 
     if((server->config.maxSubscriptionsPerSession != 0) &&
     if((server->config.maxSubscriptionsPerSession != 0) &&
        (UA_Session_getNumSubscriptions(session) >= server->config.maxSubscriptionsPerSession)) {
        (UA_Session_getNumSubscriptions(session) >= server->config.maxSubscriptionsPerSession)) {
-        response->responseHeader.serviceResult = UA_STATUSCODE_BADTOOMANYOPERATIONS;
+        response->responseHeader.serviceResult = UA_STATUSCODE_BADTOOMANYSUBSCRIPTIONS;
         return;
         return;
    }
    }
     /* Create the subscription */
     /* Create the subscription */
@@ -438,12 +438,12 @@ Service_Publish(UA_Server *server, UA_Session *session,
         return;
         return;
     }
     }
 
 
+    /* Handle too many subscriptions to free resources before trying to allocate
+     * resources for the new publish request. If the limit has been reached the
+     * oldest publish request shall be responded */
     if((server->config.maxPublishReqPerSession != 0 ) &&
     if((server->config.maxPublishReqPerSession != 0 ) &&
        (UA_Session_getNumPublishReq(session) >= server->config.maxPublishReqPerSession)){
        (UA_Session_getNumPublishReq(session) >= server->config.maxPublishReqPerSession)){
-        subscriptionSendError(session->channel, requestId,
-                              request->requestHeader.requestHandle,
-                              UA_STATUSCODE_BADTOOMANYPUBLISHREQUESTS);
-        return;
+       UA_Subscription_reachedPublishReqLimit( server,session);
     }
     }
 
 
     UA_PublishResponseEntry *entry =
     UA_PublishResponseEntry *entry =

+ 43 - 0
src/server/ua_subscription.c

@@ -377,7 +377,50 @@ UA_Subscription_publishCallback(UA_Server *server, UA_Subscription *sub) {
         /* Repeat sending responses right away if there are more notifications
         /* Repeat sending responses right away if there are more notifications
          * to send */
          * to send */
         UA_Subscription_publishCallback(server, sub);
         UA_Subscription_publishCallback(server, sub);
+}
+
+void
+UA_Subscription_reachedPublishReqLimit(UA_Server *server,  UA_Session *session) {
+    UA_LOG_DEBUG_SESSION(server->config.logger, session,
+                         "Reached number of publish request limit");
+
+
+    /* Dequeue a response */
+    UA_PublishResponseEntry *pre = UA_Session_getPublishReq(session);
+
+    /* Cannot publish without a response */
+    if(!pre) {
+       UA_LOG_FATAL_SESSION(server->config.logger, session, "No publish requests available");
     }
     }
+
+    UA_PublishResponse *response = &pre->response;
+    UA_NotificationMessage *message = &response->notificationMessage;
+
+    /* <-- The point of no return --> */
+
+    /* Remove the response from the response queue */
+    UA_Session_removePublishReq(session, pre);
+
+    /* Set up the response. Note that this response has no related subscription id */
+    response->responseHeader.timestamp = UA_DateTime_now();
+    response->responseHeader.serviceResult = UA_STATUSCODE_BADTOOMANYPUBLISHREQUESTS;
+    response->subscriptionId = 0;
+    response->moreNotifications = false;
+    message->publishTime = response->responseHeader.timestamp;
+    message->sequenceNumber = 0;
+    response->availableSequenceNumbersSize = 0;
+
+    /* Send the response */
+    UA_LOG_DEBUG_SESSION(server->config.logger, session,
+                         "Sending out a publish response triggered by too many publish requests");
+    UA_SecureChannel_sendBinaryMessage(session->channel,
+                                       pre->requestId, response,
+                                       &UA_TYPES[UA_TYPES_PUBLISHRESPONSE]);
+
+    /* Free the response */
+    UA_Array_delete(response->results, response->resultsSize,
+                    &UA_TYPES[UA_TYPES_UINT32]);
+    UA_free(pre); /* no need for UA_PublishResponse_deleteMembers */
 }
 }
 
 
 UA_StatusCode
 UA_StatusCode

+ 2 - 0
src/server/ua_subscription.h

@@ -145,4 +145,6 @@ UA_Subscription_removeRetransmissionMessage(UA_Subscription *sub, UA_UInt32 sequ
 void
 void
 UA_Subscription_answerPublishRequestsNoSubscription(UA_Server *server, UA_Session *session);
 UA_Subscription_answerPublishRequestsNoSubscription(UA_Server *server, UA_Session *session);
 
 
+void
+UA_Subscription_reachedPublishReqLimit(UA_Server *server,  UA_Session *session);
 #endif /* UA_SUBSCRIPTION_H_ */
 #endif /* UA_SUBSCRIPTION_H_ */