Inclusion of custom server bind address

The custom opcua server bind option is added and it can be
parced with command line option -a or server_ip_address=.
If no ip address is mentioned, then server is listening on all interfaces

modified:   cli.h
modified:   keep_alive_publisher.h
modified:   keep_alive_subscriber.h
modified:   server.c

Test: Program is tested
parent 7bf2d914
...@@ -7,6 +7,7 @@ static char doc[] = "OPC-UA server which controls MOD-IO's relays' state over OP ...@@ -7,6 +7,7 @@ static char doc[] = "OPC-UA server which controls MOD-IO's relays' state over OP
static char args_doc[] = "..."; static char args_doc[] = "...";
static struct argp_option options[] = { static struct argp_option options[] = {
{"port", 'p', "4840", 0, "Port to bind to."}, {"port", 'p', "4840", 0, "Port to bind to."},
{"server-ip-address", 'a', "", 0, "Server address to bind to."},
{"device", 'd', "/dev/i2c-1", 0, "Linux block device path."}, {"device", 'd', "/dev/i2c-1", 0, "Linux block device path."},
{"slave-address-list", 's', "0x58", 0, "Comma separated list of slave I2C addresses."}, {"slave-address-list", 's', "0x58", 0, "Comma separated list of slave I2C addresses."},
{"mode", 'm', "0", 0, "Set different modes of operation of coupler. Default (0) is set attached \ {"mode", 'm', "0", 0, "Set different modes of operation of coupler. Default (0) is set attached \
...@@ -30,6 +31,7 @@ struct arguments ...@@ -30,6 +31,7 @@ struct arguments
{ {
int mode; int mode;
int port; int port;
char *server_ip_address;
char *device; char *device;
char *slave_address_list; char *slave_address_list;
char *username; char *username;
...@@ -51,6 +53,9 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state) ...@@ -51,6 +53,9 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state)
case 'p': case 'p':
arguments->port = arg ? atoi (arg) : DEFAULT_OPC_UA_PORT; arguments->port = arg ? atoi (arg) : DEFAULT_OPC_UA_PORT;
break; break;
case 'a':
arguments->server_ip_address = arg;
break;
case 'd': case 'd':
arguments->device = arg; arguments->device = arg;
break; break;
...@@ -110,6 +115,7 @@ void handleCLI(int argc, char **argv) { ...@@ -110,6 +115,7 @@ void handleCLI(int argc, char **argv) {
struct arguments arguments; struct arguments arguments;
arguments.port = DEFAULT_OPC_UA_PORT; arguments.port = DEFAULT_OPC_UA_PORT;
arguments.server_ip_address = "";
arguments.mode = DEFAULT_MODE; arguments.mode = DEFAULT_MODE;
arguments.device = DEFAULT_I2C_BLOCK_DEVICE_NAME; arguments.device = DEFAULT_I2C_BLOCK_DEVICE_NAME;
arguments.slave_address_list = DEFAULT_I2C_0_ADDR; arguments.slave_address_list = DEFAULT_I2C_0_ADDR;
...@@ -126,6 +132,7 @@ void handleCLI(int argc, char **argv) { ...@@ -126,6 +132,7 @@ void handleCLI(int argc, char **argv) {
printf("Mode=%d\n", arguments.mode); printf("Mode=%d\n", arguments.mode);
printf("Listening port=%d\n", arguments.port); printf("Listening port=%d\n", arguments.port);
printf("server_ip_address=%s\n", arguments.server_ip_address);
printf("Block device=%s\n", arguments.device); printf("Block device=%s\n", arguments.device);
printf("Slave address list=%s\n", arguments.slave_address_list); printf("Slave address list=%s\n", arguments.slave_address_list);
printf("Key=%s\n", arguments.key); printf("Key=%s\n", arguments.key);
...@@ -147,6 +154,7 @@ void handleCLI(int argc, char **argv) { ...@@ -147,6 +154,7 @@ void handleCLI(int argc, char **argv) {
USERNAME = arguments.username; USERNAME = arguments.username;
PASSWORD = arguments.password; PASSWORD = arguments.password;
OPC_UA_PORT = arguments.port; OPC_UA_PORT = arguments.port;
OPC_UA_ADDRESS = arguments.server_ip_address;
ENABLE_X509 = strlen(arguments.key) > 0 && strlen(arguments.certificate); ENABLE_X509 = strlen(arguments.key) > 0 && strlen(arguments.certificate);
ENABLE_USERNAME_PASSWORD_AUTHENTICATION = strlen(arguments.username) > 0 && strlen(arguments.password) > 0; ENABLE_USERNAME_PASSWORD_AUTHENTICATION = strlen(arguments.username) > 0 && strlen(arguments.password) > 0;
ENABLE_HEART_BEAT = arguments.heart_beat; ENABLE_HEART_BEAT = arguments.heart_beat;
......
...@@ -19,7 +19,7 @@ static void addPubSubConnection(UA_Server *server, UA_String *transportProfile, ...@@ -19,7 +19,7 @@ static void addPubSubConnection(UA_Server *server, UA_String *transportProfile,
&UA_TYPES[UA_TYPES_NETWORKADDRESSURLDATATYPE]); &UA_TYPES[UA_TYPES_NETWORKADDRESSURLDATATYPE]);
/* Changed to static publisherId from random generation to identify /* Changed to static publisherId from random generation to identify
* the publisher on Subscriber side */ * the publisher on Subscriber side */
connectionConfig.publisherId.numeric = PUBLISHER_ID; connectionConfig.publisherId.uint32 = PUBLISHER_ID;
UA_Server_addPubSubConnection(server, &connectionConfig, &connectionIdent); UA_Server_addPubSubConnection(server, &connectionConfig, &connectionIdent);
} }
......
...@@ -72,7 +72,7 @@ static UA_StatusCode addPubSubConnectionSubscriber(UA_Server *server, UA_String ...@@ -72,7 +72,7 @@ static UA_StatusCode addPubSubConnectionSubscriber(UA_Server *server, UA_String
connectionConfig.enabled = UA_TRUE; connectionConfig.enabled = UA_TRUE;
UA_Variant_setScalar(&connectionConfig.address, networkAddressUrl, UA_Variant_setScalar(&connectionConfig.address, networkAddressUrl,
&UA_TYPES[UA_TYPES_NETWORKADDRESSURLDATATYPE]); &UA_TYPES[UA_TYPES_NETWORKADDRESSURLDATATYPE]);
connectionConfig.publisherId.numeric = UA_UInt32_random (); connectionConfig.publisherId.uint32 = UA_UInt32_random ();
retval |= UA_Server_addPubSubConnection (server, &connectionConfig, &connectionIdentifier); retval |= UA_Server_addPubSubConnection (server, &connectionConfig, &connectionIdentifier);
if (retval != UA_STATUSCODE_GOOD) { if (retval != UA_STATUSCODE_GOOD) {
return retval; return retval;
......
...@@ -48,6 +48,7 @@ const int DEFAULT_MODE = 0; ...@@ -48,6 +48,7 @@ const int DEFAULT_MODE = 0;
const int DEFAULT_COUPLER_ID = 0; const int DEFAULT_COUPLER_ID = 0;
int OPC_UA_PORT; int OPC_UA_PORT;
char *OPC_UA_ADDRESS;
bool ENABLE_HEART_BEAT = false; bool ENABLE_HEART_BEAT = false;
bool ENABLE_HEART_BEAT_CHECK = false; bool ENABLE_HEART_BEAT_CHECK = false;
bool ENABLE_X509 = false; bool ENABLE_X509 = false;
...@@ -72,86 +73,113 @@ static void stopHandler(int sign) ...@@ -72,86 +73,113 @@ static void stopHandler(int sign)
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
// init dictionary only once$ // init dictionary only once$
if (SUBSCRIBER_DICT==NULL){ if (SUBSCRIBER_DICT==NULL){
SUBSCRIBER_DICT = *dictAlloc(); SUBSCRIBER_DICT = *dictAlloc();
}
// parse CLI
handleCLI(argc, argv);
// always start attached slaves from a know safe shutdown state
safeShutdownI2CSlaveList();
signal(SIGINT, stopHandler);
signal(SIGTERM, stopHandler);
UA_String serverUrls[1];
size_t serverUrlsSize = 0;
char serverUrlBuffer[1][512];
server = UA_Server_new();
UA_ServerConfig_setMinimal(UA_Server_getConfig(server), OPC_UA_PORT, NULL);
UA_ServerConfig *config = UA_Server_getConfig(server);
// opc_ua server is listening to user input address else on all interfaces
// user input ip address should be added to any of the interface else no server socket will be created
if(OPC_UA_ADDRESS!= NULL){
// check whether the default url is already set
if(config->serverUrlsSize > 0) {
UA_LOG_WARNING(&config->logger, UA_LOGCATEGORY_USERLAND, "ServerUrls already set. Overriding.");
UA_Array_delete(config->serverUrls, config->serverUrlsSize, &UA_TYPES[UA_TYPES_STRING]);
config->serverUrls = NULL;
config->serverUrlsSize = 0;
} }
// parse CLI // construct opc_ua server url based on input ip address
handleCLI(argc, argv); UA_snprintf(serverUrlBuffer[0], sizeof(serverUrlBuffer[0]), "opc.tcp://%s:%u", OPC_UA_ADDRESS, OPC_UA_PORT);
serverUrls[serverUrlsSize] = UA_STRING(serverUrlBuffer[0]);
// always start attached slaves from a know safe shutdown state serverUrlsSize++;
safeShutdownI2CSlaveList();
// add the url into the config
signal(SIGINT, stopHandler); UA_StatusCode ret_val = UA_Array_copy(serverUrls, serverUrlsSize, (void**)&config->serverUrls, &UA_TYPES[UA_TYPES_STRING]);
signal(SIGTERM, stopHandler); if(ret_val != UA_STATUSCODE_GOOD){
return ret_val;
server = UA_Server_new();
UA_ServerConfig_setMinimal(UA_Server_getConfig(server), OPC_UA_PORT, NULL);
UA_ServerConfig *config = UA_Server_getConfig(server);
config->verifyRequestTimestamp = UA_RULEHANDLING_ACCEPT;
// add variables representing physical relays / inputs, etc
addVariable(server);
addValueCallbackToCurrentTimeVariable(server);
/* Disable anonymous logins, enable two user/password logins */
if (ENABLE_USERNAME_PASSWORD_AUTHENTICATION){
UA_UsernamePasswordLogin logins[1] = {
{UA_STRING(USERNAME), UA_STRING(PASSWORD)},
};
config->accessControl.clear(&config->accessControl);
UA_StatusCode retval1 = UA_AccessControl_default(config, false, NULL,
&config->securityPolicies[config->securityPoliciesSize-1].policyUri, 1, logins);
} }
config->serverUrlsSize = serverUrlsSize;
/* Enable x509 */ }
#ifdef UA_ENABLE_ENCRYPTION config->verifyRequestTimestamp = UA_RULEHANDLING_ACCEPT;
if (ENABLE_X509){
/* Load certificate and private key */ // add variables representing physical relays / inputs, etc
UA_ByteString certificate = loadFile(X509_CERTIFICATE_FILENAME); addVariable(server);
UA_ByteString privateKey = loadFile(X509_KEY_FILENAME); addValueCallbackToCurrentTimeVariable(server);
/* Load the trustlist - not used thus 0 */ /* Disable anonymous logins, enable two user/password logins */
size_t trustListSize = 0; if (ENABLE_USERNAME_PASSWORD_AUTHENTICATION){
UA_STACKARRAY(UA_ByteString, trustList, trustListSize); UA_UsernamePasswordLogin logins[1] = {
{UA_STRING(USERNAME), UA_STRING(PASSWORD)},
/* Loading of a issuer list, not used in this application */ };
size_t issuerListSize = 0;
UA_ByteString *issuerList = NULL; config->accessControl.clear(&config->accessControl);
UA_StatusCode retval1 = UA_AccessControl_default(config, false, NULL,
/* Loading of a revocation list currently unsupported */ &config->securityPolicies[config->securityPoliciesSize-1].policyUri, 1, logins);
UA_ByteString *revocationList = NULL; }
size_t revocationListSize = 0;
UA_StatusCode retval = /* Enable x509 */
UA_ServerConfig_setDefaultWithSecurityPolicies(config, 4841, // XXX: why not use 4840 ? #ifdef UA_ENABLE_ENCRYPTION
&certificate, &privateKey, if (ENABLE_X509){
trustList, trustListSize, /* Load certificate and private key */
issuerList, issuerListSize, UA_ByteString certificate = loadFile(X509_CERTIFICATE_FILENAME);
revocationList, revocationListSize); UA_ByteString privateKey = loadFile(X509_KEY_FILENAME);
//The place to fill the hole is very important
config->applicationDescription.applicationUri = UA_STRING_ALLOC("urn:open62541.server.application"); /* Load the trustlist - not used thus 0 */
} size_t trustListSize = 0;
#endif UA_STACKARRAY(UA_ByteString, trustList, trustListSize);
// enable protocol for Pub/Sub /* Loading of a issuer list, not used in this application */
UA_ServerConfig_addPubSubTransportLayer(config, UA_PubSubTransportLayerUDPMP()); size_t issuerListSize = 0;
UA_ByteString *issuerList = NULL;
// enable publish keep-alive messages
if (ENABLE_HEART_BEAT) { /* Loading of a revocation list currently unsupported */
enablePublishHeartBeat(server, config); UA_ByteString *revocationList = NULL;
} size_t revocationListSize = 0;
UA_StatusCode retval =
// enable subscribe to keep-alive messages UA_ServerConfig_setDefaultWithSecurityPolicies(config, 4841, // XXX: why not use 4840 ?
enableSubscribeToHeartBeat(server, config); &certificate, &privateKey,
trustList, trustListSize,
// run server issuerList, issuerListSize,
UA_StatusCode retval = UA_Server_run(server, &running); revocationList, revocationListSize);
UA_Server_delete(server); //The place to fill the hole is very important
config->applicationDescription.applicationUri = UA_STRING_ALLOC("urn:open62541.server.application");
// always leave attached slaves to a known safe shutdown state }
safeShutdownI2CSlaveList(); #endif
return retval == UA_STATUSCODE_GOOD ? EXIT_SUCCESS : EXIT_FAILURE; // enable protocol for Pub/Sub
UA_ServerConfig_addPubSubTransportLayer(config, UA_PubSubTransportLayerUDPMP());
// enable publish keep-alive messages
if (ENABLE_HEART_BEAT) {
enablePublishHeartBeat(server, config);
}
// enable subscribe to keep-alive messages
enableSubscribeToHeartBeat(server, config);
// run server
UA_StatusCode retval = UA_Server_run(server, &running);
UA_Server_delete(server);
// always leave attached slaves to a known safe shutdown state
safeShutdownI2CSlaveList();
return retval == UA_STATUSCODE_GOOD ? EXIT_SUCCESS : EXIT_FAILURE;
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment