Ver código fonte

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 anos atrás
pai
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) &&
        (UA_Session_getNumSubscriptions(session) >= server->config.maxSubscriptionsPerSession)) {
-        response->responseHeader.serviceResult = UA_STATUSCODE_BADTOOMANYOPERATIONS;
+        response->responseHeader.serviceResult = UA_STATUSCODE_BADTOOMANYSUBSCRIPTIONS;
         return;
    }
     /* Create the subscription */
@@ -438,12 +438,12 @@ Service_Publish(UA_Server *server, UA_Session *session,
         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 ) &&
        (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 =

+ 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
          * to send */
         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

+ 2 - 0
src/server/ua_subscription.h

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