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
static char args_doc[] = "...";
static struct argp_option options[] = {
{"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."},
{"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 \
......@@ -30,6 +31,7 @@ struct arguments
{
int mode;
int port;
char *server_ip_address;
char *device;
char *slave_address_list;
char *username;
......@@ -51,6 +53,9 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state)
case 'p':
arguments->port = arg ? atoi (arg) : DEFAULT_OPC_UA_PORT;
break;
case 'a':
arguments->server_ip_address = arg;
break;
case 'd':
arguments->device = arg;
break;
......@@ -110,6 +115,7 @@ void handleCLI(int argc, char **argv) {
struct arguments arguments;
arguments.port = DEFAULT_OPC_UA_PORT;
arguments.server_ip_address = "";
arguments.mode = DEFAULT_MODE;
arguments.device = DEFAULT_I2C_BLOCK_DEVICE_NAME;
arguments.slave_address_list = DEFAULT_I2C_0_ADDR;
......@@ -126,6 +132,7 @@ void handleCLI(int argc, char **argv) {
printf("Mode=%d\n", arguments.mode);
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("Slave address list=%s\n", arguments.slave_address_list);
printf("Key=%s\n", arguments.key);
......@@ -147,6 +154,7 @@ void handleCLI(int argc, char **argv) {
USERNAME = arguments.username;
PASSWORD = arguments.password;
OPC_UA_PORT = arguments.port;
OPC_UA_ADDRESS = arguments.server_ip_address;
ENABLE_X509 = strlen(arguments.key) > 0 && strlen(arguments.certificate);
ENABLE_USERNAME_PASSWORD_AUTHENTICATION = strlen(arguments.username) > 0 && strlen(arguments.password) > 0;
ENABLE_HEART_BEAT = arguments.heart_beat;
......
......@@ -19,7 +19,7 @@ static void addPubSubConnection(UA_Server *server, UA_String *transportProfile,
&UA_TYPES[UA_TYPES_NETWORKADDRESSURLDATATYPE]);
/* Changed to static publisherId from random generation to identify
* the publisher on Subscriber side */
connectionConfig.publisherId.numeric = PUBLISHER_ID;
connectionConfig.publisherId.uint32 = PUBLISHER_ID;
UA_Server_addPubSubConnection(server, &connectionConfig, &connectionIdent);
}
......
......@@ -72,7 +72,7 @@ static UA_StatusCode addPubSubConnectionSubscriber(UA_Server *server, UA_String
connectionConfig.enabled = UA_TRUE;
UA_Variant_setScalar(&connectionConfig.address, networkAddressUrl,
&UA_TYPES[UA_TYPES_NETWORKADDRESSURLDATATYPE]);
connectionConfig.publisherId.numeric = UA_UInt32_random ();
connectionConfig.publisherId.uint32 = UA_UInt32_random ();
retval |= UA_Server_addPubSubConnection (server, &connectionConfig, &connectionIdentifier);
if (retval != UA_STATUSCODE_GOOD) {
return retval;
......
......@@ -48,6 +48,7 @@ const int DEFAULT_MODE = 0;
const int DEFAULT_COUPLER_ID = 0;
int OPC_UA_PORT;
char *OPC_UA_ADDRESS;
bool ENABLE_HEART_BEAT = false;
bool ENABLE_HEART_BEAT_CHECK = false;
bool ENABLE_X509 = false;
......@@ -72,86 +73,113 @@ static void stopHandler(int sign)
int main(int argc, char **argv)
{
// init dictionary only once$
if (SUBSCRIBER_DICT==NULL){
SUBSCRIBER_DICT = *dictAlloc();
// init dictionary only once$
if (SUBSCRIBER_DICT==NULL){
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
handleCLI(argc, argv);
// always start attached slaves from a know safe shutdown state
safeShutdownI2CSlaveList();
signal(SIGINT, stopHandler);
signal(SIGTERM, stopHandler);
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);
// construct opc_ua server url based on input ip address
UA_snprintf(serverUrlBuffer[0], sizeof(serverUrlBuffer[0]), "opc.tcp://%s:%u", OPC_UA_ADDRESS, OPC_UA_PORT);
serverUrls[serverUrlsSize] = UA_STRING(serverUrlBuffer[0]);
serverUrlsSize++;
// add the url into the config
UA_StatusCode ret_val = UA_Array_copy(serverUrls, serverUrlsSize, (void**)&config->serverUrls, &UA_TYPES[UA_TYPES_STRING]);
if(ret_val != UA_STATUSCODE_GOOD){
return ret_val;
}
/* Enable x509 */
#ifdef UA_ENABLE_ENCRYPTION
if (ENABLE_X509){
/* Load certificate and private key */
UA_ByteString certificate = loadFile(X509_CERTIFICATE_FILENAME);
UA_ByteString privateKey = loadFile(X509_KEY_FILENAME);
/* Load the trustlist - not used thus 0 */
size_t trustListSize = 0;
UA_STACKARRAY(UA_ByteString, trustList, trustListSize);
/* Loading of a issuer list, not used in this application */
size_t issuerListSize = 0;
UA_ByteString *issuerList = NULL;
/* Loading of a revocation list currently unsupported */
UA_ByteString *revocationList = NULL;
size_t revocationListSize = 0;
UA_StatusCode retval =
UA_ServerConfig_setDefaultWithSecurityPolicies(config, 4841, // XXX: why not use 4840 ?
&certificate, &privateKey,
trustList, trustListSize,
issuerList, issuerListSize,
revocationList, revocationListSize);
//The place to fill the hole is very important
config->applicationDescription.applicationUri = UA_STRING_ALLOC("urn:open62541.server.application");
}
#endif
// 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;
config->serverUrlsSize = serverUrlsSize;
}
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);
}
/* Enable x509 */
#ifdef UA_ENABLE_ENCRYPTION
if (ENABLE_X509){
/* Load certificate and private key */
UA_ByteString certificate = loadFile(X509_CERTIFICATE_FILENAME);
UA_ByteString privateKey = loadFile(X509_KEY_FILENAME);
/* Load the trustlist - not used thus 0 */
size_t trustListSize = 0;
UA_STACKARRAY(UA_ByteString, trustList, trustListSize);
/* Loading of a issuer list, not used in this application */
size_t issuerListSize = 0;
UA_ByteString *issuerList = NULL;
/* Loading of a revocation list currently unsupported */
UA_ByteString *revocationList = NULL;
size_t revocationListSize = 0;
UA_StatusCode retval =
UA_ServerConfig_setDefaultWithSecurityPolicies(config, 4841, // XXX: why not use 4840 ?
&certificate, &privateKey,
trustList, trustListSize,
issuerList, issuerListSize,
revocationList, revocationListSize);
//The place to fill the hole is very important
config->applicationDescription.applicationUri = UA_STRING_ALLOC("urn:open62541.server.application");
}
#endif
// 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