Browse Source

fix #661, take the endpointurls from the networklayer when required

Julius Pfrommer 8 years ago
parent
commit
e15cdfacbe

+ 1 - 0
src/server/ua_server.c

@@ -464,6 +464,7 @@ UA_Server * UA_Server_new(const UA_ServerConfig config) {
     UA_String_copy(&server->config.applicationDescription.applicationUri, &server->namespaces[1]);
     server->namespacesSize = 2;
 
+    /* Create endpoints w/o endpointurl. It is added from the networklayers at startup */
     server->endpointDescriptions = UA_Array_new(server->config.networkLayersSize,
                                                 &UA_TYPES[UA_TYPES_ENDPOINTDESCRIPTION]);
     server->endpointDescriptionsSize = server->config.networkLayersSize;

+ 1 - 1
src/server/ua_server_binary.c

@@ -460,7 +460,7 @@ processRequest(UA_SecureChannel *channel, UA_Server *server, UA_UInt32 requestId
             return;
         }
         UA_Session_init(&anonymousSession);
-        anonymousSession.sessionId = UA_NODEID_NUMERIC(0,0);
+        anonymousSession.sessionId = UA_NODEID_GUID(0, UA_GUID_NULL);
         anonymousSession.channel = channel;
         session = &anonymousSession;
     }

+ 2 - 2
src/server/ua_server_internal.h

@@ -53,10 +53,10 @@ struct UA_Server {
     size_t externalNamespacesSize;
     UA_ExternalNamespace *externalNamespaces;
 #endif
-     
+
     /* Jobs with a repetition interval */
     LIST_HEAD(RepeatedJobsList, RepeatedJobs) repeatedJobs;
-    
+
 #ifdef UA_ENABLE_MULTITHREADING
     /* Dispatch queue head for the worker threads (the tail should not be in the same cache line) */
     struct cds_wfcq_head dispatchQueue_head;

+ 0 - 3
src/server/ua_server_worker.c

@@ -588,9 +588,6 @@ UA_StatusCode UA_Server_run_startup(UA_Server *server) {
     for(size_t i = 0; i < server->config.networkLayersSize; i++) {
         UA_ServerNetworkLayer *nl = &server->config.networkLayers[i];
         result |= nl->start(nl, server->config.logger);
-        for(size_t j = 0; j < server->endpointDescriptionsSize; j++) {
-            UA_String_copy(&nl->discoveryUrl, &server->endpointDescriptions[j].endpointUrl);
-        }
     }
 
     return result;

+ 40 - 37
src/server/ua_services_discovery.c

@@ -42,21 +42,16 @@ void Service_FindServers(UA_Server *server, UA_Session *session,
 
 void Service_GetEndpoints(UA_Server *server, UA_Session *session, const UA_GetEndpointsRequest *request,
                           UA_GetEndpointsResponse *response) {
-    UA_LOG_DEBUG_SESSION(server->config.logger, session, "Processing GetEndpointsRequest");
-    /* Test if one of the networklayers exposes the discoveryUrl of the requested endpoint */
-    /* Disabled, servers in a virtualbox don't know their external hostname */
-    /* UA_Boolean foundUri = false; */
-    /* for(size_t i = 0; i < server->config.networkLayersSize; i++) { */
-    /*     if(UA_String_equal(&request->endpointUrl, &server->config.networkLayers[i].discoveryUrl)) { */
-    /*         foundUri = true; */
-    /*         break; */
-    /*     } */
-    /* } */
-    /* if(!foundUri) { */
-    /*     response->endpointsSize = 0; */
-    /*     return; */
-    /* } */
-    
+    /* If the client expects to see a specific endpointurl, mirror it back. If
+       not, clone the endpoints with the discovery url of all networklayers. */
+    const UA_String *endpointUrl = &request->endpointUrl;
+    if(endpointUrl->length > 0) {
+        UA_LOG_DEBUG_SESSION(server->config.logger, session, "Processing GetEndpointsRequest with endpointUrl \"%.*s\"",
+                             endpointUrl->length, endpointUrl->data);
+    } else {
+        UA_LOG_DEBUG_SESSION(server->config.logger, session, "Processing GetEndpointsRequest with an empty endpointUrl");
+    }
+
     /* test if the supported binary profile shall be returned */
 #ifdef NO_ALLOCA
     UA_Boolean relevant_endpoints[server->endpointDescriptionsSize];
@@ -64,15 +59,15 @@ void Service_GetEndpoints(UA_Server *server, UA_Session *session, const UA_GetEn
     UA_Boolean *relevant_endpoints = UA_alloca(sizeof(UA_Byte) * server->endpointDescriptionsSize);
 #endif
     size_t relevant_count = 0;
-    for(size_t j = 0; j < server->endpointDescriptionsSize; j++) {
-        relevant_endpoints[j] = false;
-        if(request->profileUrisSize == 0) {
+    if(request->profileUrisSize == 0) {
+        for(size_t j = 0; j < server->endpointDescriptionsSize; j++)
             relevant_endpoints[j] = true;
-            relevant_count++;
-            continue;
-        }
-        for(size_t i = 0; i < request->profileUrisSize; i++) {
-            if(UA_String_equal(&request->profileUris[i], &server->endpointDescriptions[j].transportProfileUri)) {
+        relevant_count = server->endpointDescriptionsSize;
+    } else {
+        for(size_t j = 0; j < server->endpointDescriptionsSize; j++) {
+            for(size_t i = 0; i < request->profileUrisSize; i++) {
+                if(!UA_String_equal(&request->profileUris[i], &server->endpointDescriptions[j].transportProfileUri))
+                    continue;
                 relevant_endpoints[j] = true;
                 relevant_count++;
                 break;
@@ -85,32 +80,40 @@ void Service_GetEndpoints(UA_Server *server, UA_Session *session, const UA_GetEn
         return;
     }
 
-    response->endpoints = UA_malloc(sizeof(UA_EndpointDescription) * relevant_count);
+    /* Clone the endpoint for each networklayer? */
+    size_t clone_times = 1;
+    UA_Boolean nl_endpointurl = false;
+    if(endpointUrl->length == 0) {
+        clone_times = server->config.networkLayersSize;
+        nl_endpointurl = true;
+    }
+
+    response->endpoints = UA_Array_new(relevant_count * clone_times, &UA_TYPES[UA_TYPES_ENDPOINTDESCRIPTION]);
     if(!response->endpoints) {
         response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
         return;
     }
+    response->endpointsSize = relevant_count * clone_times;
 
     size_t k = 0;
     UA_StatusCode retval = UA_STATUSCODE_GOOD;
-    for(size_t j = 0; j < server->endpointDescriptionsSize && retval == UA_STATUSCODE_GOOD; j++) {
-        if(!relevant_endpoints[j])
-            continue;
-        retval = UA_EndpointDescription_copy(&server->endpointDescriptions[j], &response->endpoints[k]);
-        if(retval != UA_STATUSCODE_GOOD)
-            break;
-        /* replace endpoint's URL to the requested one if provided */
-        if(request->endpointUrl.length > 0){
-            UA_String_deleteMembers(&response->endpoints[k].endpointUrl);
-            retval = UA_String_copy(&request->endpointUrl, &response->endpoints[k].endpointUrl);
+    for(size_t i = 0; i < clone_times; i++) {
+        if(nl_endpointurl)
+            endpointUrl = &server->config.networkLayers[i].discoveryUrl;
+        for(size_t j = 0; j < server->endpointDescriptionsSize; j++) {
+            if(!relevant_endpoints[j])
+                continue;
+            retval |= UA_EndpointDescription_copy(&server->endpointDescriptions[j], &response->endpoints[k]);
+            retval = UA_String_copy(endpointUrl, &response->endpoints[k].endpointUrl);
+            k++;
         }
-        k++;
     }
 
     if(retval != UA_STATUSCODE_GOOD) {
         response->responseHeader.serviceResult = retval;
-        UA_Array_delete(response->endpoints, --k, &UA_TYPES[UA_TYPES_ENDPOINTDESCRIPTION]);
+        UA_Array_delete(response->endpoints, response->endpointsSize, &UA_TYPES[UA_TYPES_ENDPOINTDESCRIPTION]);
+        response->endpoints = NULL;
+        response->endpointsSize = 0;
         return;
     }
-    response->endpointsSize = relevant_count;
 }

+ 6 - 0
src/server/ua_services_session.c

@@ -9,6 +9,8 @@ void Service_CreateSession(UA_Server *server, UA_SecureChannel *channel,
         response->responseHeader.serviceResult = UA_STATUSCODE_BADSECURECHANNELIDINVALID;
         return;
     }
+
+    /* Copy the server's endpoint into the response */
     response->responseHeader.serviceResult =
         UA_Array_copy(server->endpointDescriptions, server->endpointDescriptionsSize,
                       (void**)&response->serverEndpoints, &UA_TYPES[UA_TYPES_ENDPOINTDESCRIPTION]);
@@ -16,6 +18,10 @@ void Service_CreateSession(UA_Server *server, UA_SecureChannel *channel,
         return;
     response->serverEndpointsSize = server->endpointDescriptionsSize;
 
+    /* Mirror back the endpointUrl */
+    for(size_t i = 0; i < response->serverEndpointsSize; i++)
+        UA_String_copy(&request->endpointUrl, &response->serverEndpoints[i].endpointUrl);
+
     UA_Session *newSession;
     response->responseHeader.serviceResult =
         UA_SessionManager_createSession(&server->sessionManager, channel, request, &newSession);