CreateServerSocket using hostname fails!

Questions regarding the use of the C++ SDK for Server or Client development or integration into customer products ...

Moderator: uasdkcpp

Post Reply
tommys
Hero Member
Hero Member
Posts: 33
Joined: 03 Oct 2023, 16:42

CreateServerSocket using hostname fails!

Post by tommys »

Hi,

in our OPCUA C++ Server we set the endpoint URL:

Code: Select all

pEndpoint->setEndpointUrl(UaString("opc.tcp://%1:%2").arg(szHostname).arg(m_serverPort), OpcUa_True);
However, the server is not able to create the server socket! (the call to socket() fails with errno 97)
The problem seems to be that it tries to create an IPv6 server socket - but we do not want nor support IPv6!

My hack to solve this is to add one line:

Code: Select all

iFamily = OPCUA_P_AF_INET4;
for the case when OpcUa_P_ParseUrl has detected that it is a hostname.
This results in a IPv4 server socket using the hostname is created, which is exactly what we want. But this is a hack... Can I configure the server to always use IPv4 and never use IPv6? Or something similar?

Regards,
/Tommy

User avatar
Support Team
Hero Member
Hero Member
Posts: 3174
Joined: 18 Mar 2011, 15:09

Re: CreateServerSocket using hostname fails!

Post by Support Team »

Hi,

the "hack" is good as is.

On many OS running a dual stack (TCP stack that is capable of both IP4 and IP6) you can hardly predict what is retured, but typically IPv6 is "prefered". That said, you could either disable the IP6 completely, however would be global setting for the OS in general, or you manually enter IP4 in the "hosts" list file in the OS.

From an OPC UA Endpoint perspective you can either set the "hostname" which results in bind to the "any"-address, OR you can explicitely bind to only one IP (in case you have multiple NICs and multiple IPs). However, for the "explicite bind" you must "know" the IP (4 or 6) and set/configure it in the UA server's configuration file (which in case of DHCP might be difficult to predict).
Best regards
Unified Automation Support Team

tommys
Hero Member
Hero Member
Posts: 33
Joined: 03 Oct 2023, 16:42

Re: CreateServerSocket using hostname fails!

Post by tommys »

So, I do not have IPv6 on my target machine but still the server tries to create an IPv6 server, which of course fails.
My hack to work around this, as described above, does not feel right. I do not want to an intrusive hack requiring me to modify UA sources.

Instead, I created a non-intrusive work-around, which is a better solution that I share for others having the same problem.
Internally, there is a variable default initialized to prefer IPv6. Fortunately there is a macro definition OPCUA_P_SERVER_PREFER_INET6 (that is default set to !0) that one can change to 0, which causes the internal variable to not prefer IPv6. This will select IPv4 over IPv6 and that allows the server socket to be created as an IPv4 socket using our hostname as endpointUrl.

In our CMake-file I simply added (after the add_library(uastack) has been created of course):

Code: Select all

target_compile_definitions(uastack PRIVATE OPCUA_P_SERVER_PREFER_INET6=0)
Actually, I created a CMake option that checks whether IPv6 is to be disabled or not and then, in an if-statement, I set the uastack target's compile definition to OPCUA_P_SERVER_PREFER_INET6=0.

I think the current UA implementation, which tries to create an IPv6 server despite IPv6 is not available, is a bug.
Also I think it would be nice to have a well-documented way to enable or disable IPv6 (and IPv4).

Regards,
/Tommy

User avatar
Support Team
Hero Member
Hero Member
Posts: 3174
Joined: 18 Mar 2011, 15:09

Re: CreateServerSocket using hostname fails!

Post by Support Team »

Hi,

we disagree with your solution of hardly defining the IP6 or IP4 at compile time being a good "general" solution. It might be good in your (narrowed) scope of having IP4 capabilities on the device or in the network only. However our API design has a more "flexible" approach, which we think is more preferable for the majority of customers (and maybe even end users), hence we have separate configuration settings for the endpoint and (optional) for the stack (see config.xml for details).

But if you desperately want to set this in code there is a possibility you can try based on your code snippet:

Code: Select all

 
 pEndpoint->setEndpointUrl(UaString("opc.tcp://%1:%2").arg(szHostname).arg(m_serverPort), OpcUa_False);
 pEndpoint->setStackEndpointUrl(UaString("opc.tcp://0.0.0.0:%2").arg(m_serverPort));
whereas the in the first line you select that you want to configure the stack bind separately. And in second line setting stack bind to the IP4-Any. But again, this is available through configuration as well.
Best regards
Unified Automation Support Team

Post Reply