Open62541 Building a Simple Server

I just downloaded the open62541 pkg version 1.3.9 on FreeBSD 14 so that I can learn how to use it. Unfortuately there is no documentation specific for it FreeBSD Could someone provide me an example of how I can create a open62541 server using it.
 
The include headers and libraries are in the obvious places (/usr/local/include/ and /usr/local/lib/).

If you do pkg info -l open62541 you can see which files the package installed and where.
 
Why do you think the documentation has to be specific for FreeBSD?


This seems appropriate: https://www.open62541.org/doc/1.3/tutorial_server_firststeps.html
In the link you sent me there is a section that describes how to build open62541 for OpenBSD
The procedure below works on OpenBSD 5.8 with gcc version 4.8.4, cmake version 3.2.3 and Python version 2.7.10.
Install a recent gcc, python and cmake:​
pkg_add gcc python cmake​

Tell the system to actually use the recent gcc (it gets installed as egcc on OpenBSD):​
export CC=egcc CXX=eg++​

Now procede as described for Ubuntu/Debian:​
cd open62541​
mkdir build​
cd build​
cmake ..​
make​


Regarding the above instructions I do not know if I even need to build anything at all having downlaaded the open62541 pkg. Then the build instructions are for OpenBSD. So what must I do to generate or access the open62541.c/.h files from the open62541 pkg I installed to create the following file?

myServer.c

#include <open62541/plugin/log_stdout.h>​
#include <open62541/server.h>​
#include <open62541/server_config_default.h>​
#include <signal.h>​
#include <stdlib.h>​
static volatile UA_Boolean running = true;​
static void stopHandler(int sig) {​
UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "received ctrl-c");​
running = false;​
}​
int main(void) {​
signal(SIGINT, stopHandler);​
signal(SIGTERM, stopHandler);​
UA_Server *server = UA_Server_new();​
UA_ServerConfig_setDefault(UA_Server_getConfig(server));​
UA_StatusCode retval = UA_Server_run(server, &running);​
UA_Server_delete(server);​
return retval == UA_STATUSCODE_GOOD ? EXIT_SUCCESS : EXIT_FAILURE;​
}​
 
In the link you sent me there is a section that describes how to build open62541 for OpenBSD
There is nothing you need to build, pkg install open62541 will install everything already.
 
There is nothing you need to build, pkg install open62541 will install everything already.

Code:
pkg install open62541
installs the binary already built package to your FreeBSD operating system. You probably have to make some configuration files and then initiate that user webserver service. OpenBSD is very security concious and there has user build from sources, rather than install some binary package. Wish you good luck, write notes down, create a HowTo Open62541 document, and export a PDF file to share with others. Abiword is a good small document editor, Use Screen shots in PNG format, and a DIA the diagram editor, for creating your document if you wish to.
 
Hi FreeBSD Forum members,
I'm trying to compile and run the open62541 myServer.c located at under this URL https://www.open62541.org/doc/1.3/tutorial_server_firststeps.html
To do this i created the directory /home/aperri/open62541Learning and placed the myServer.c file there as shown in the attached files. You will note in the file that I directed the includes to where the *.h files are located for open62541 on my FreeBSD computer.
Then I went about trying to compile it using the command line instruction as indicated in the URL and shown below
Code:
$ gcc -std=c99 open62541.c myServer.c -o myServer
but leaving out the [B]myServer.c [/B]file because I don't where to find it or generate it
   [B] [aperri@freebsd ~/open62541Learning]$ gcc -std=c99  myServer.c -o myServer [/B]
In compiling it the compiler spews out the following information
    [aperri@freebsd ~/open62541Learning]$ gcc -std=c99  myServer.c -o myServer
    /usr/local/bin/ld: /tmp//cc5GU1QC.o: in function `UA_ServerConfig_setMinimal':
    myServer.c:(.text+0x10b): undefined reference to `UA_ServerConfig_setMinimalCustomBuffer'
    /usr/local/bin/ld: /tmp//cc5GU1QC.o: in function `stopHandler':
    myServer.c:(.text+0x143): undefined reference to `UA_Log_Stdout'
    /usr/local/bin/ld: /tmp//cc5GU1QC.o: in function `main':
    myServer.c:(.text+0x18f): undefined reference to `UA_Server_new'
    /usr/local/bin/ld: myServer.c:(.text+0x19f): undefined reference to `UA_Server_getConfig'
    /usr/local/bin/ld: myServer.c:(.text+0x1b8): undefined reference to `UA_Server_run'
    /usr/local/bin/ld: myServer.c:(.text+0x1c7): undefined reference to `UA_Server_delete'
    collect2: error: ld returned 1 exit status

As I am trying to get familiar with the open62541 protocol step-by-step, could anyone explain to me what I need to do to compile the myServer.c file.
Thank you in advance
 

Attachments

  • myServer.zip
    572 bytes · Views: 19
ld is the linker stage, so it cannot find any library that provides those UA_* functions.

But your post is a bit mangled - I'm not sure what are input/output messages and what is your typing (e.g. is the bit about leaving out myServer.c your typing or output from something?)
 
Their instructions are a little jacked.
  1. Download the open62541.h and open62541.c files from the release page and put them in your open62541Learning directory.
  2. You'll have to add these 4 lines to open62541.h
    Code:
    #ifdef __FreeBSD__
    #define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP
    #define IPV6_DROP_MEMBERSHIP    IPV6_LEAVE_GROUP
    #endif
  3. The myServer.c source they suggest is slightly off. Try this
    Code:
    #include "open62541.h"
    #include <signal.h>
    #include <stdlib.h>
    
    static volatile UA_Boolean running = true;
    static void stopHandler(int sig) {
        UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "received ctrl-c");
        running = false;
    }
    int main(void) {
        signal(SIGINT, stopHandler);
        signal(SIGTERM, stopHandler);
        UA_Server *server = UA_Server_new();
        UA_ServerConfig_setDefault(UA_Server_getConfig(server));
        UA_StatusCode retval = UA_Server_run(server, &running);
        UA_Server_delete(server);
        return retval == UA_STATUSCODE_GOOD ? EXIT_SUCCESS : EXIT_FAILURE;
    }
  4. I don't have gcc installed, so I compiled it with clang like this
    Code:
    clang -D __BSD_VISIBLE myServer.c open62541.c -o myServer
This should yield you a working binary in the current directory.
Code:
 $ ./myServer
[2024-04-18 18:08:24.454 (UTC-0700)] info/session    SecureChannel 0 | Session "Administrator" | AddNode (i=15303): No TypeDefinition. Use the default TypeDefinition for the Variable/Object
[2024-04-18 18:08:24.458 (UTC-0700)] warn/server    AccessControl: Unconfigured AccessControl. Users have all permissions.
[2024-04-18 18:08:24.458 (UTC-0700)] info/server    AccessControl: Anonymous login is enabled
[2024-04-18 18:08:24.458 (UTC-0700)] info/server    AccessControl: x509 certificate user authentication is enabled
[2024-04-18 18:08:24.458 (UTC-0700)] warn/server    Username/Password Authentication configured, but no encrypting SecurityPolicy. This can leak credentials on the network.
[2024-04-18 18:08:24.458 (UTC-0700)] warn/userland    AcceptAll Certificate Verification. Any remote certificate will be accepted.
[2024-04-18 18:08:24.458 (UTC-0700)] info/network    TCP network layer listening on opc.tcp://squeeg:4840/
^C[2024-04-18 18:08:25.672 (UTC-0700)] info/userland    received ctrl-c
[2024-04-18 18:08:25.672 (UTC-0700)] info/network    Shutting down the TCP network layer
[2024-04-18 18:08:25.672 (UTC-0700)] info/server    PubSub cleanup was called.
 
Their instructions are a little jacked.
  1. Download the open62541.h and open62541.c files from the release page and put them in your open62541Learning directory.
  2. You'll have to add these 4 lines to open62541.h
    Code:
    #ifdef __FreeBSD__
    #define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP
    #define IPV6_DROP_MEMBERSHIP    IPV6_LEAVE_GROUP
    #endif
  3. The myServer.c source they suggest is slightly off. Try this
    Code:
    #include "open62541.h"
    #include <signal.h>
    #include <stdlib.h>
    
    static volatile UA_Boolean running = true;
    static void stopHandler(int sig) {
        UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "received ctrl-c");
        running = false;
    }
    int main(void) {
        signal(SIGINT, stopHandler);
        signal(SIGTERM, stopHandler);
        UA_Server *server = UA_Server_new();
        UA_ServerConfig_setDefault(UA_Server_getConfig(server));
        UA_StatusCode retval = UA_Server_run(server, &running);
        UA_Server_delete(server);
        return retval == UA_STATUSCODE_GOOD ? EXIT_SUCCESS : EXIT_FAILURE;
    }
  4. I don't have gcc installed, so I compiled it with clang like this
    Code:
    clang -D __BSD_VISIBLE myServer.c open62541.c -o myServer
This should yield you a working binary in the current directory.
Code:
 $ ./myServer
[2024-04-18 18:08:24.454 (UTC-0700)] info/session    SecureChannel 0 | Session "Administrator" | AddNode (i=15303): No TypeDefinition. Use the default TypeDefinition for the Variable/Object
[2024-04-18 18:08:24.458 (UTC-0700)] warn/server    AccessControl: Unconfigured AccessControl. Users have all permissions.
[2024-04-18 18:08:24.458 (UTC-0700)] info/server    AccessControl: Anonymous login is enabled
[2024-04-18 18:08:24.458 (UTC-0700)] info/server    AccessControl: x509 certificate user authentication is enabled
[2024-04-18 18:08:24.458 (UTC-0700)] warn/server    Username/Password Authentication configured, but no encrypting SecurityPolicy. This can leak credentials on the network.
[2024-04-18 18:08:24.458 (UTC-0700)] warn/userland    AcceptAll Certificate Verification. Any remote certificate will be accepted.
[2024-04-18 18:08:24.458 (UTC-0700)] info/network    TCP network layer listening on opc.tcp://squeeg:4840/
^C[2024-04-18 18:08:25.672 (UTC-0700)] info/userland    received ctrl-c
[2024-04-18 18:08:25.672 (UTC-0700)] info/network    Shutting down the TCP network layer
[2024-04-18 18:08:25.672 (UTC-0700)] info/server    PubSub cleanup was called.
Hi Jose, in an earlier thread wb7odyfred (freebsd forum participant) said downloading

pkg install open62541

installs the binary already built package to your FreeBSD operating system. You probably have to make some configuration files and then initiate that user webserver service. OpenBSD is very security concious and there has user build from sources, rather than install some binary package. Wish you good luck, write notes down, create a HowTo Open62541 document, and export a PDF file to share with others. Abiword is a good small document editor, Use Screen shots in PNG format, and a DIA the diagram editor, for creating your document if you wish to.

Then SirDice also (freebsd forum participant) pointed out The include headers and libraries are in the obvious places (/usr/local/include/ and /usr/local/lib/). If you do

pkg info -l open62541

you can see which files the package installed and where.

So based on that information I was convinced I had all the include files to run the myServer.c as stated in the https://www.open62541.org/doc/1.3/tutorial_server_firststeps.html. However you pointed out that I need to download the open62541.h and open62541.c files from the release page and put them into my open62541Learning directory.

I have gone to the extent of comparing the open62541.h against the /usr/local/include/open62541/types.h and the /usr/local/include/open62541/server.h to note that they contain the same typdefs and defines and that the open62541.c contains implementations of functions included in the /usr/local/include/open62541/server.h.

Since I installed the open62541 package for freebsd 14, shouldn't I be using these installed files, instead of installing files from some other website?
 
Why do you think the documentation has to be specific for FreeBSD?


This seems appropriate: https://www.open62541.org/doc/1.3/tutorial_server_firststeps.html
SirDice, thank you for trying to get me straight in how to start leaning about open62541, but I'm still groping in the dark. In the link you sent to compile the myServer.c example listed there assume that I have the open62541.c/.h files in the same folder I have myServer.c in. For not knowing any better I downloaded these files from the following link https://github.com/open62541/open62541/releases/tag/v1.3.6 to determine how to build my own "myServer.c" file based on the (/usr/local/include/ and /usr/local/lib/) on my computer after installing the open62541 pkg. I'm running in circles regarding this endeavor. Could you help me out with this please. I've attached the beginnings of myServer.c file showing my attempt so far.
 

Attachments

  • myServer.zip
    572 bytes · Views: 11
SirDice, thank you for trying to get me straight in how to start leaning about open62541, but I'm still groping in the dark. In the link you sent to compile the myServer.c example listed there assume that I have the open62541.c/.h files in the same folder I have myServer.c in. For not knowing any better I downloaded these files from the following link https://github.com/open62541/open62541/releases/tag/v1.3.6 to determine how to build my own "myServer.c" file based on the (/usr/local/include/ and /usr/local/lib/) on my computer after installing the open62541 pkg. I'm running in circles regarding this endeavor. Could you help me out with this please. I've attached the beginnings of myServer.c file showing my attempt so far.
I suspect those open62541.c/.h files are not properly patched for FreeBSD...

I went through the same steps as OP (except that I compiled the port, which is at v. 1.3.7 on my system), fetched the files from the page OP linked to, created myServer.c according to instructions, but then got compilation errors, and no binary got produced...

Code:
% mkdir open62541
% cd open62541
% (fetch open62541.c/.h files in the same folder I have myServer.c in )
% gcc -std=c99 open62541.c myServer.c -o myServer
% (Got compilation errors, mostly related to networking)

The errors.txt file that I attached will show the compilation errors I got. There's not very many, and most are easy to fix, but some do require FreeBSD-specific knowledge of C programming...
 

Attachments

  • errors.txt
    5.6 KB · Views: 11
Since I installed the open62541 package for freebsd 14, shouldn't I be using these installed files, instead of installing files from some other website?
You started this thread asking for help compiling something and that’s what has been provided.

But looks like there’s a bit of a back story?

Yes you are better off using a package.

Maybe your compilation question was more to do with using headers and libraries provided by the package?

You probably need to look at the compiler’s -I (i for include) and -L flags - these tell it where to look for include files and link library files.
 
Oh, there are two threads running on this:

 
I suspect those open62541.c/.h files are not properly patched for FreeBSD...

I went through the same steps as OP (except that I compiled the port, which is at v. 1.3.7 on my system), fetched the files from the page OP linked to, created myServer.c according to instructions, but then got compilation errors, and no binary got produced...

Code:
% mkdir open62541
% cd open62541
% (fetch open62541.c/.h files in the same folder I have myServer.c in )
% gcc -std=c99 open62541.c myServer.c -o myServer
% (Got compilation errors, mostly related to networking)

The errors.txt file that I attached will show the compilation errors I got. There's not very many, and most are easy to fix, but some do require FreeBSD-specific knowledge of C programming...

Hi astyle, if you compare the open62541.c/.h files to the (/usr/local/include/ and /usr/local/lib/) files made available through the open62541 pkg installation, you will find that there is a lot of overlap between them. So the mySever.c file should be made up from the installed files, and not the ones downloaded from https://github.com/open62541/open62541/releases/tag/v1.3.6. Could you provide a small road-map how one can go about doing this?
 
Hi astyle, if you compare the open62541.c/.h files to the (/usr/local/include/ and /usr/local/lib/) files made available through the open62541 pkg installation, you will find that there is a lot of overlap between them. So the mySever.c file should be made up from the installed files, and not the ones downloaded from https://github.com/open62541/open62541/releases/tag/v1.3.6. Could you provide a small road-map how one can go about doing this?
Seems like the compiler line that you got from the instructions (linked to by SirDice ) wants those files to be in the same directory as myServer.c... When I installed the open62541 port, I ran updatedb as root. (On FreeBSD, it's a symlink to /usr/libexec/locate.updatedb that you have to make yourself). Doing it as root picks up ALL files on the system, so there are reasons to avoid running it as root.

After that updatedb as root, you should be able to use locate to find the files in question. In my case, I discovered that the usual locations (/usr/local/include/ and /usr/local/lib/ ) actually don't have the open62541.c/.h files... Not only that, they were not present on the system at all, which is why I had to download them.

Well, the very fact that for me, those open62541.c/.h files were NOT available in the locations where FreeBSD normally puts such files - that has me thinking that maybe the port is not that well-done. You can install the package, and FreeBSD will report it as installed, but with important files missing from the install package, compiling myServer.c is problematic, to the point that there's no output from the compiler.

But I agree, those files really should match the installed version of open62541, and be available in the package itself. Well, if you want, there's several ways to deal with it. You can write a Makefile that helps make look in the standard locations, or your can modify the include lines in myServer.c to look in the standard locations (provided the standard locations actually have the open62541.c/.h files that are needed). Or you can just go along with instructions and have those files in the same directory as myServer.c...

Well, there's also the option of modifying the port itself, but then you'll need to read the FreeBSD Porter's Handbook...
 
Seems like the compiler line that you got from the instructions (linked to by SirDice ) wants those files to be in the same directory as myServer.c... When I installed the open62541 port, I ran updatedb as root. (On FreeBSD, it's a symlink to /usr/libexec/locate.updatedb that you have to make yourself). Doing it as root picks up ALL files on the system, so there are reasons to avoid running it as root.

After that updatedb as root, you should be able to use locate to find the files in question. In my case, I discovered that the usual locations (/usr/local/include/ and /usr/local/lib/ ) actually don't have the open62541.c/.h files... Not only that, they were not present on the system at all, which is why I had to download them.

Well, the very fact that for me, those open62541.c/.h files were NOT available in the locations where FreeBSD normally puts such files - that has me thinking that maybe the port is not that well-done. You can install the package, and FreeBSD will report it as installed, but with important files missing from the install package, compiling myServer.c is problematic, to the point that there's no output from the compiler.

But I agree, those files really should match the installed version of open62541, and be available in the package itself. Well, if you want, there's several ways to deal with it. You can write a Makefile that helps make look in the standard locations, or your can modify the include lines in myServer.c to look in the standard locations (provided the standard locations actually have the open62541.c/.h files that are needed). Or you can just go along with instructions and have those files in the same directory as myServer.c...

Well, there's also the option of modifying the port itself, but then you'll need to read the FreeBSD Porter's Handbook...
The open62541.c/.h that you downloaded are a subset of the open62541 pkg files you install for FreeBSD.

The open62541.h file contains files such as /usr/local/include/open62541/config.h, /usr/local/include/open62541/types.h and so on.​
And the open62541.c file defines the #undef from the "/usr/local/include/open62541/posix/ua_architecture.h".​

So there is nothing wrong with the pkg one installs. It requires that one has sufficient knowledge of OPC-UA architecture to build their own open62541.c/.h files.

For a beginner like me that will certainly take quite some time. So I hope someone out there, savvy enough with the OPC-UA architecture, can minimally create open62541.c/.h files as well as myServer.c file and a myClient.c files for FreeBSD 14, to help one get started.
 
The open62541.c/.h that you downloaded are a subset of the open62541 pkg files you install for FreeBSD.
If that were the case, locate would find those files (provided you ran updatedb beforehand). And yeah, presence of actual files is important to pay attention to when compiling, no matter the platform. Sometimes, though, an OS-specific package is not very well crafted, and trying to install it, one discovers that there are parts missing. Unfortunate, but to be expected when dealing with Open Source software.

The open62541.h file contains files such as /usr/local/include/open62541/config.h, /usr/local/include/open62541/types.h and so on.
The file open62541.h or the open62541.c does NOT 'contain' header files. It will have # include lines that refer to those files. Yes, there is a difference, and it is important to pay attention to it when compiling anything.

Code:
$ locate config.h | grep 62541
/usr/home/user/open62541/open62541-1.3.7/include/open62541/config.h.in
/usr/home/user/open62541/open62541-1.3.7/src/pubsub/ua_pubsub_config.h
/usr/home/user/open62541/open62541-1.3.7/tests/pubsub/ethernet_config.h
/usr/local/include/open62541/config.h
/usr/ports/devel/open62541/work/.build/src_generated/open62541/config.h
/usr/ports/devel/open62541/work/open62541-1.3.7/include/open62541/config.h.in
/usr/ports/devel/open62541/work/open62541-1.3.7/src/pubsub/ua_pubsub_config.h
/usr/ports/devel/open62541/work/open62541-1.3.7/tests/pubsub/ethernet_config.h
/usr/ports/devel/open62541/work/stage/usr/local/include/open62541/config.h

Those 3 files (open62541.h, open62541.c, myServer.c) do need to be present in the same directory when you compile stuff. Yeah, you'll get compiler errors - but at least you'll know that the compiler is finding everything it needs, and the issue is in those 3 files.

You can treat those 3 files as a template for getting started - that's a very standard roadmap for most compilations, most people start out by successfully compiling a template. After that, you can try running the stuff that was successfully compiled. The OPC-UA architecture specs will tell you what to expect when you run the stuff that you successfully compiled.
 
Hi Jose, in an earlier thread wb7odyfred (freebsd forum participant) said downloading
Please don't start multiple threads on the same subject. (Thanks to SirDice for merging them.)

So based on that information I was convinced I had all the include files to run the myServer.c as stated in the https://www.open62541.org/doc/1.3/tutorial_server_firststeps.html. However you pointed out that I need to download the open62541.h and open62541.c files from the release page and put them into my open62541Learning directory.
I find what that tutorial asks you to do to be really confusing. On the one hand they instruct you to download the "amalgamated" release file (open62541.c), but also mention that you'll wind up with the open62541.h file in your work directory.
To get started, downdload the open62541 single-file release from http://open62541.org or generate it according to the build instructions with the “amalgamation” option enabled. From now on, we assume you have the open62541.c/.h files in the current folder.

Now their sample source ignores open62541.h and assumes you've installed the header files in a location that's standard for most unix-like operating systems
Code:
#include <open62541/plugin/log_stdout.h>
#include <open62541/server.h>
#include <open62541/server_config_default.h>

I didn't want to install that package on my system, because I'm not all that interested in it, so I just downloaded the single-file amalgamated headers file and used it.

However, two problems remained. Somehow __BSD_VISIBLE is not getting defined. This undefines a bunch of stuff in socket.h that the sample code needs. There's probably a standard way to solve this. I chose the easy way out and just defined __BSD_VISIBLE on the command line.

The next problem was that their source is lacking definitions for a couple of IPV6 macros that apparently are slightly different in FreeBSD. Hence the
Code:
#ifdef __FreeBSD__
#define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP
#define IPV6_DROP_MEMBERSHIP    IPV6_LEAVE_GROUP
#endif
 
To get rid of the following errors displayed when I compile the myServer.c file

[aperri@freebsd ~/open62541Learning]$ gcc -std=c99 open62541.c myServer.c -o myServer​
open62541.c: In function 'UA_PubSubChannelUDPMC_open':​
open62541.c:80475:50: error: 'PF_INET6' undeclared (first use in this function); did you mean 'AF_INET6'?​
80475 | requestResult->ai_family == PF_INET6 ? IPPROTO_IPV6 : IPPROTO_IP,​
| ^~~~~~~~​
| AF_INET6​
open62541.c:80475:50: note: each undeclared identifier is reported only once for each function it appears in​
open62541.c:80476:83: error: 'IP_MULTICAST_TTL' undeclared (first use in this function); did you mean 'IPV6_MULTICAST_IF'?​
80476 | requestResult->ai_family == PF_INET6 ? IPV6_MULTICAST_HOPS : IP_MULTICAST_TTL,​
| ^~~~~~~~~~~~~~~~​
| IPV6_MULTICAST_IF​
open62541.c:80516:24: error: field 'ipv4' has incomplete type​
80516 | struct ip_mreq ipv4;​
| ^~~~​
open62541.c:80573:70: error: 'IP_MULTICAST_IF' undeclared (first use in this function); did you mean 'IPV6_MULTICAST_IF'?​
80573 | requestResult->ai_family == PF_INET6 ? IPV6_MULTICAST_IF : IP_MULTICAST_IF,​
| ^~~~~~~~~~~~~~~​
| IPV6_MULTICAST_IF​
open62541.c:80590:36: error: 'PF_INET' undeclared (first use in this function); did you mean 'AF_INET'?​
80590 | if(requestResult->ai_family == PF_INET){//IPv4 handling​
| ^~~~~~~​
| AF_INET​
open62541.c: In function 'UA_PubSubChannelUDPMC_regist':​
open62541.c:80665:20: error: storage size of 'groupV4' isn't known​
80665 | struct ip_mreq groupV4;​
| ^~~~~~~​
open62541.c:80666:32: error: invalid application of 'sizeof' to incomplete type 'struct ip_mreq'​
80666 | memset(&groupV4, 0, sizeof(struct ip_mreq));​
| ^~~~~~​
open62541.c:80681:44: error: 'PF_INET6' undeclared (first use in this function); did you mean 'AF_INET6'?​
80681 | connectionConfig->ai_family == PF_INET6 ? IPPROTO_IPV6 : IPPROTO_IP,​
| ^~~~~~~~​
| AF_INET6​
open62541.c:80682:77: error: 'IP_ADD_MEMBERSHIP' undeclared (first use in this function); did you mean 'IPV6_ADD_MEMBERSHIP'?​
80682 | connectionConfig->ai_family == PF_INET6 ? IPV6_ADD_MEMBERSHIP : IP_ADD_MEMBERSHIP,​
| ^~~~~~~~~~~~~~~~~​
| IPV6_ADD_MEMBERSHIP​
open62541.c: In function 'UA_PubSubChannelUDPMC_unregist':​
open62541.c:80750:2: error: #endif without #if​
80750 | #endif​

I added these #defines to the open62541. h file

#define PF_INET6 AF_INET6​
#define IP_MULTICAST_IF IPV6_MULTICAST_IF​
#define IP_MULTICAST_TTL IP_MULTICAST_IF​
#define IP_ADD_MEMBERSHIP IPV6_ADD_MEMBERSHIP​
#define PF_INET PF_INET6​

As well as what Jose suggested

#ifdef __FreeBSD__​
#define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP​
#define IPV6_DROP_MEMBERSHIP IPV6_LEAVE_GROUP​
#endif​

And then compiled the myServer.c file shown below using


gcc -std=c99 open62541.c myServer.c -o myServer


Code:
#include "open62541.h"
#include <signal.h>
#include <stdlib.h>

static volatile UA_Boolean running = true;
static void stopHandler(int sig) {
    UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "received ctrl-c");
    running = false;
}
int main(void) {
    signal(SIGINT, stopHandler);
    signal(SIGTERM, stopHandler);
    UA_Server *server = UA_Server_new();
    UA_ServerConfig_setDefault(UA_Server_getConfig(server));
    UA_StatusCode retval = UA_Server_run(server, &running);
    UA_Server_delete(server);
    return retval == UA_STATUSCODE_GOOD ? EXIT_SUCCESS : EXIT_FAILURE;
}

And got the following results

[aperri@freebsd ~/open62541Learning]$ gcc -std=c99 open62541.c myServer.c -o myServer​
open62541.c: In function 'UA_PubSubChannelUDPMC_open':​
open62541.c:80516:24: error: field 'ipv4' has incomplete type​
80516 | struct ip_mreq ipv4;​
| ^~~~​
open62541.c: In function 'UA_PubSubChannelUDPMC_regist':​
open62541.c:80665:20: error: storage size of 'groupV4' isn't known​
80665 | struct ip_mreq groupV4;​
| ^~~~~~~​
open62541.c:80666:32: error: invalid application of 'sizeof' to incomplete type 'struct ip_mreq'​
80666 | memset(&groupV4, 0, sizeof(struct ip_mreq));​
| ^~~~~~​
open62541.c: In function 'UA_PubSubChannelUDPMC_unregist':​
open62541.c:80750:2: error: #endif without #if​
80750 | #endif​

Can someone explain what adjustments I have to make to compile the myServer.c file?
 
open62541.c: In function 'UA_PubSubChannelUDPMC_unregist': open62541.c:80750:2: error: #endif without #if 80750 | #endif
^ This one should be easy to correct.

But the rest - study the OPC-UA architecture specs and the 62541 tutorials.
 
^ This one should be easy to correct.

But the rest - study the OPC-UA architecture specs and the 62541 tutorials.
Hi astyle,

here is the original function

Code:
static UA_StatusCode
UA_PubSubChannelUDPMC_unregist(UA_PubSubChannel *channel, UA_ExtensionObject *transportSettings) {
    if(!(channel->state == UA_PUBSUB_CHANNEL_PUB_SUB || channel->state == UA_PUBSUB_CHANNEL_SUB)){
        UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "PubSub Connection unregist failed.");
        return UA_STATUSCODE_BADINTERNALERROR;
    }
    UA_PubSubChannelDataUDPMC * connectionConfig = (UA_PubSubChannelDataUDPMC *) channel->handle;
    if(connectionConfig->ai_family == PF_INET){//IPv4 handling
        struct ip_mreq groupV4 = { 0 };

        memcpy(&groupV4.imr_multiaddr,
               &((const struct sockaddr_in *) &connectionConfig->ai_addr)->sin_addr,
               sizeof(struct in_addr));
        groupV4.imr_interface.s_addr = UA_htonl(INADDR_ANY);

        if(UA_setsockopt(channel->sockfd, IPPROTO_IP, IP_DROP_MEMBERSHIP,
                         (char *) &groupV4, sizeof(groupV4)) != 0){
            UA_LOG_SOCKET_ERRNO_WRAP(
                UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_NETWORK,
                             "PubSub Connection unregist failed. IP membership setup failed: "
                             "Cannot set socket option IP_DROP_MEMBERSHIP. Error: %s",
                             errno_str));
            return UA_STATUSCODE_BADINTERNALERROR;
        }
#if UA_IPV6
    } else if (connectionConfig->ai_family == PF_INET6) {//IPv6 handling
        struct ipv6_mreq groupV6 = { 0 };

        memcpy(&groupV6.ipv6mr_multiaddr,
               &((const struct sockaddr_in6 *) &connectionConfig->ai_addr)->sin6_addr,
               sizeof(struct in6_addr));

        if(UA_setsockopt(channel->sockfd, IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP,
                         (char *) &groupV6, sizeof(groupV6)) != 0){
            UA_LOG_SOCKET_ERRNO_WRAP(
                UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_NETWORK,
                             "PubSub Connection unregist failed. IP membership setup failed: "
                             "Cannot set socket option IPV6_DROP_MEMBERSHIP. Error: %s",
                             errno_str));
            return UA_STATUSCODE_BADINTERNALERROR;
        }
#endif
    } else {
        UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "PubSub Connection unregist failed.");
        return UA_STATUSCODE_BADINTERNALERROR;
    }
    return UA_STATUSCODE_GOOD;
}

And here is what I changed. Did I do this correctly?

Code:
static UA_StatusCode
UA_PubSubChannelUDPMC_unregist(UA_PubSubChannel *channel, UA_ExtensionObject *transportSettings) {
    if(!(channel->state == UA_PUBSUB_CHANNEL_PUB_SUB || channel->state == UA_PUBSUB_CHANNEL_SUB)){
        UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "PubSub Connection unregist failed.");
        return UA_STATUSCODE_BADINTERNALERROR;
    }
    UA_PubSubChannelDataUDPMC * connectionConfig = (UA_PubSubChannelDataUDPMC *) channel->handle;
    if(connectionConfig->ai_family == PF_INET){//IPv4 handling
        struct ip_mreq groupV4 = { 0 };

        memcpy(&groupV4.imr_multiaddr,
               &((const struct sockaddr_in *) &connectionConfig->ai_addr)->sin_addr,
               sizeof(struct in_addr));
        groupV4.imr_interface.s_addr = UA_htonl(INADDR_ANY);

        if(UA_setsockopt(channel->sockfd, IPPROTO_IP, IP_DROP_MEMBERSHIP,
                         (char *) &groupV4, sizeof(groupV4)) != 0){
            UA_LOG_SOCKET_ERRNO_WRAP(
                UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_NETWORK,
                             "PubSub Connection unregist failed. IP membership setup failed: "
                             "Cannot set socket option IP_DROP_MEMBERSHIP. Error: %s",
                             errno_str));
            return UA_STATUSCODE_BADINTERNALERROR;
        }

    }
#if UA_IPV6
    else if (connectionConfig->ai_family == PF_INET6) {//IPv6 handling
        struct ipv6_mreq groupV6 = { 0 };

        memcpy(&groupV6.ipv6mr_multiaddr,
               &((const struct sockaddr_in6 *) &connectionConfig->ai_addr)->sin6_addr,
               sizeof(struct in6_addr));

        if(UA_setsockopt(channel->sockfd, IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP,
                         (char *) &groupV6, sizeof(groupV6)) != 0){
            UA_LOG_SOCKET_ERRNO_WRAP(
                UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_NETWORK,
                             "PubSub Connection unregist failed. IP membership setup failed: "
                             "Cannot set socket option IPV6_DROP_MEMBERSHIP. Error: %s",
                             errno_str));
            return UA_STATUSCODE_BADINTERNALERROR;
        }

    }
#endif
     else {
        UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "PubSub Connection unregist failed.");
        return UA_STATUSCODE_BADINTERNALERROR;
    }
    return UA_STATUSCODE_GOOD;
}
 
Back
Top