Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java OPC-UA Client Eclipse Milo endpoint URL changes to localhost

I am using Java OPC-UA client Eclipse Milo. Whenever I create a session using endpoint URL of server, method UaTcpStackClient.getEndpoints() changes URL to localhost.

String endpointUrl = "opc.tcp://10.8.0.104:48809";

EndpointDescription[] endpoints = UaTcpStackClient.getEndpoints(endpointUrl).get();

EndpointDescription endpoint = Arrays.stream(endpoints)
            .filter(e -> e.getSecurityPolicyUri().equals(securityPolicy.getSecurityPolicyUri()))
            .findFirst().orElseThrow(() -> new Exception("no desired endpoints returned"));

However value of endpoint.getEndpointUrl() returns opc.tcp://127.0.0.1:4880/ which results failure in connection.

I have no idea why my OPC URL gets changed?

like image 639
Harshal Bhavsar Avatar asked Nov 11 '16 18:11

Harshal Bhavsar


1 Answers

This is a pretty common problem when implementing a UA client.

The server is ultimately responsible for the contents of the endpoints you get back, and the one you're connecting to is (mis)configured to return 127.0.0.1 in the endpoint URLs, apparently.

You need to check the endpoints you get from the server and then depending on the nature of your application either just replace them right away with new copied EndpointDescriptions containing URLs that you've modified or let the user know and ask them for permission first.

Either way, you need to create a new set of EndpointDescriptions in which you've corrected the URL before you go on to create the OpcUaClient.

Alternatively... you could figure out how to get your server configured properly so it returns endpoints containing a publicly reachable hostname or IP address.

Update 2:

Since v0.2.2 there has been EndpointUtil.updateUrl that can be used to modify EndpointDescriptions.

Update:

The code to replace the endpoint URL could be some variation of this:

private static EndpointDescription updateEndpointUrl(
    EndpointDescription original, String hostname) throws URISyntaxException {

    URI uri = new URI(original.getEndpointUrl()).parseServerAuthority();

    String endpointUrl = String.format(
        "%s://%s:%s%s",
        uri.getScheme(),
        hostname,
        uri.getPort(),
        uri.getPath()
    );

    return new EndpointDescription(
        endpointUrl,
        original.getServer(),
        original.getServerCertificate(),
        original.getSecurityMode(),
        original.getSecurityPolicyUri(),
        original.getUserIdentityTokens(),
        original.getTransportProfileUri(),
        original.getSecurityLevel()
    );
}

Caveat: this works in most cases, but one notable case it does not work is when the remote endpoint URL contains characters that aren't allowed in a URL hostname (according to the RFC), such as underscore (a '_'), which unfortunately IS allowed in e.g. the hostname of a Windows machine. So you may need to use some other method of parsing the endpoint URL rather than relying on the URI class to do it.

like image 90
Kevin Herron Avatar answered Oct 08 '22 04:10

Kevin Herron