static void setup_lds(void) { // start LDS server running_lds = UA_Boolean_new(); *running_lds = true; config_lds = UA_ServerConfig_new_default(); config_lds->applicationDescription.applicationType = UA_APPLICATIONTYPE_DISCOVERYSERVER; UA_String_deleteMembers(&config_lds->applicationDescription.applicationUri); config_lds->applicationDescription.applicationUri = UA_STRING_ALLOC("urn:open62541.test.local_discovery_server"); UA_LocalizedText_deleteMembers(&config_lds->applicationDescription.applicationName); config_lds->applicationDescription.applicationName = UA_LOCALIZEDTEXT_ALLOC("en", "LDS Server"); config_lds->mdnsServerName = UA_String_fromChars("LDS_test"); config_lds->serverCapabilitiesSize = 1; UA_String *caps = UA_String_new(); *caps = UA_String_fromChars("LDS"); config_lds->serverCapabilities = caps; config_lds->discoveryCleanupTimeout = registerTimeout; server_lds = UA_Server_new(config_lds); UA_Server_run_startup(server_lds); pthread_create(&server_thread_lds, NULL, serverloop_lds, NULL); // wait until LDS started UA_sleep(1000); sleep(1); }
static void GetEndpointsAndCheck(const char* discoveryUrl, const char* filterTransportProfileUri, const UA_String expectedEndpointUrls[], size_t expectedEndpointUrlsSize) { UA_Client *client = UA_Client_new(); UA_ClientConfig_setDefault(UA_Client_getConfig(client)); ck_assert_uint_eq(UA_Client_connect(client, discoveryUrl), UA_STATUSCODE_GOOD); UA_EndpointDescription* endpointArray = NULL; size_t endpointArraySize = 0; UA_String discoveryUrlUA = UA_String_fromChars(discoveryUrl); UA_StatusCode retval = GetEndpoints(client, &discoveryUrlUA, &endpointArraySize, &endpointArray, filterTransportProfileUri); ck_assert_uint_eq(retval, UA_STATUSCODE_GOOD); UA_String_deleteMembers(&discoveryUrlUA); ck_assert_uint_eq(endpointArraySize , expectedEndpointUrlsSize); for(size_t j = 0; j < endpointArraySize && j < expectedEndpointUrlsSize; j++) { UA_EndpointDescription* endpoint = &endpointArray[j]; ck_assert(UA_String_equal(&endpoint->endpointUrl, &expectedEndpointUrls[j])); } UA_Array_delete(endpointArray, endpointArraySize, &UA_TYPES[UA_TYPES_ENDPOINTDESCRIPTION]); UA_Client_delete(client); }
static void UA_Client_deleteMembers(UA_Client* client){ UA_Client_disconnect(client); UA_Connection_deleteMembers(&client->connection); UA_SecureChannel_deleteMembersCleanup(&client->channel); if(client->endpointUrl.data) UA_String_deleteMembers(&client->endpointUrl); UA_UserTokenPolicy_deleteMembers(&client->token); }
static void variables_basic(void) { /* Int32 */ UA_Int32 i = 5; UA_Int32 j; UA_Int32_copy(&i, &j); UA_Int32 *ip = UA_Int32_new(); UA_Int32_copy(&i, ip); UA_Int32_delete(ip); /* String */ UA_String s; UA_String_init(&s); /* _init zeroes out the entire memory of the datatype */ char *test = "test"; s.length = strlen(test); s.data = (UA_Byte*)test; UA_String s2; UA_String_copy(&s, &s2); UA_String_deleteMembers(&s2); /* Copying heap-allocated the dynamic content */ UA_String s3 = UA_STRING("test2"); UA_String s4 = UA_STRING_ALLOC("test2"); /* Copies the content to the heap */ UA_Boolean eq = UA_String_equal(&s3, &s4); UA_String_deleteMembers(&s4); if(!eq) return; /* Structured Type */ UA_ReadRequest rr; UA_init(&rr, &UA_TYPES[UA_TYPES_READREQUEST]); /* Generic method */ UA_ReadRequest_init(&rr); /* Shorthand for the previous line */ rr.requestHeader.timestamp = UA_DateTime_now(); /* Members of a structure */ rr.nodesToRead = (UA_ReadValueId *)UA_Array_new(5, &UA_TYPES[UA_TYPES_READVALUEID]); rr.nodesToReadSize = 5; /* Array size needs to be made known */ UA_ReadRequest *rr2 = UA_ReadRequest_new(); UA_copy(&rr, rr2, &UA_TYPES[UA_TYPES_READREQUEST]); UA_ReadRequest_deleteMembers(&rr); UA_ReadRequest_delete(rr2); }
static void setup_server(void) { // start server running_translate_browse = UA_Boolean_new(); *running_translate_browse = true; server_translate_config = UA_ServerConfig_new_default(); UA_String_deleteMembers(&server_translate_config->applicationDescription.applicationUri); server_translate_config->applicationDescription.applicationUri = UA_String_fromChars("urn:open62541.test.server_translate_browse"); server_translate_browse = UA_Server_new(server_translate_config); UA_Server_run_startup(server_translate_browse); pthread_create(&server_thread_translate_browse, NULL, serverloop_register, NULL); }
int main(void) { signal(SIGINT, stopHandler); /* catches ctrl-c */ UA_ClientConfig config = UA_ClientConfig_default; /* default timeout is 5 seconds. Set it to 1 second here for demo */ config.timeout = 1000; UA_Client *client = UA_Client_new(config); /* Read the value attribute of the node. UA_Client_readValueAttribute is a * wrapper for the raw read service available as UA_Client_Service_read. */ UA_Variant value; /* Variants can hold scalar values and arrays of any type */ UA_Variant_init(&value); /* Endless loop reading the server time */ while (running) { /* if already connected, this will return GOOD and do nothing */ /* if the connection is closed/errored, the connection will be reset and then reconnected */ /* Alternatively you can also use UA_Client_getState to get the current state */ UA_StatusCode retval = UA_Client_connect(client, "opc.tcp://localhost:4840"); if (retval != UA_STATUSCODE_GOOD) { UA_LOG_ERROR(logger, UA_LOGCATEGORY_CLIENT, "Not connected. Retrying to connect in 1 second"); /* The connect may timeout after 1 second (see above) or it may fail immediately on network errors */ /* E.g. name resolution errors or unreachable network. Thus there should be a small sleep here */ UA_sleep_ms(1000); continue; } /* NodeId of the variable holding the current time */ const UA_NodeId nodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_CURRENTTIME); retval = UA_Client_readValueAttribute(client, nodeId, &value); if (retval == UA_STATUSCODE_BADCONNECTIONCLOSED) { UA_LOG_ERROR(logger, UA_LOGCATEGORY_CLIENT, "Connection was closed. Reconnecting ..."); continue; } if (retval == UA_STATUSCODE_GOOD && UA_Variant_hasScalarType(&value, &UA_TYPES[UA_TYPES_DATETIME])) { UA_DateTime raw_date = *(UA_DateTime *) value.data; UA_String string_date = UA_DateTime_toString(raw_date); UA_LOG_INFO(logger, UA_LOGCATEGORY_CLIENT, "string date is: %.*s", (int) string_date.length, string_date.data); UA_String_deleteMembers(&string_date); } UA_sleep_ms(1000); }; /* Clean up */ UA_Variant_deleteMembers(&value); UA_Client_delete(client); /* Disconnects the client internally */ return UA_STATUSCODE_GOOD; }
static UA_StatusCode helloWorldMethod(const UA_NodeId objectId, const UA_Variant *input, UA_Variant *output, void *handle) { UA_String *inputStr = (UA_String*)input->data; UA_String tmp = UA_STRING_ALLOC("Hello "); if(inputStr->length > 0) { tmp.data = realloc(tmp.data, tmp.length + inputStr->length); memcpy(&tmp.data[tmp.length], inputStr->data, inputStr->length); tmp.length += inputStr->length; } UA_Variant_setScalarCopy(output, &tmp, &UA_TYPES[UA_TYPES_STRING]); UA_String_deleteMembers(&tmp); UA_LOG_INFO(logger, UA_LOGCATEGORY_SERVER, "Hello World was called"); return UA_STATUSCODE_GOOD; }
static void setup_register(void) { // start register server running_register = UA_Boolean_new(); *running_register = true; config_register = UA_ServerConfig_new_minimal(16664, NULL); UA_String_deleteMembers(&config_register->applicationDescription.applicationUri); config_register->applicationDescription.applicationUri = UA_String_fromChars("urn:open62541.test.server_register"); UA_LocalizedText_deleteMembers(&config_register->applicationDescription.applicationName); config_register->applicationDescription.applicationName = UA_LOCALIZEDTEXT_ALLOC("de", "Anmeldungsserver"); config_register->mdnsServerName = UA_String_fromChars("Register_test"); server_register = UA_Server_new(config_register); UA_Server_run_startup(server_register); pthread_create(&server_thread_register, NULL, serverloop_register, NULL); }
/* Example 3 */ static UA_StatusCode fooBarMethod(void *handle, const UA_NodeId objectId, size_t inputSize, const UA_Variant *input, size_t outputSize, UA_Variant *output) { /* the same as helloWorld, but returns foobar */ UA_String *inputStr = (UA_String*)input->data; UA_String tmp = UA_STRING_ALLOC("FooBar! "); if(inputStr->length > 0) { tmp.data = realloc(tmp.data, tmp.length + inputStr->length); memcpy(&tmp.data[tmp.length], inputStr->data, inputStr->length); tmp.length += inputStr->length; } UA_Variant_setScalarCopy(output, &tmp, &UA_TYPES[UA_TYPES_STRING]); UA_String_deleteMembers(&tmp); UA_LOG_INFO(logger, UA_LOGCATEGORY_SERVER, "FooBar was called"); return UA_STATUSCODE_GOOD; }
static UA_StatusCode helloWorld(UA_Server *server, const UA_NodeId *sessionId, void *sessionContext, const UA_NodeId *methodId, void *methodContext, const UA_NodeId *objectId, void *objectContext, size_t inputSize, const UA_Variant *input, size_t outputSize, UA_Variant *output) { /* input is a scalar string (checked by the server) */ UA_String *name = (UA_String *)input[0].data; UA_String hello = UA_STRING("Hello "); UA_String greet; greet.length = hello.length + name->length; greet.data = (UA_Byte *)UA_malloc(greet.length); memcpy(greet.data, hello.data, hello.length); memcpy(greet.data + hello.length, name->data, name->length); UA_Variant_setScalarCopy(output, &greet, &UA_TYPES[UA_TYPES_STRING]); UA_String_deleteMembers(&greet); return UA_STATUSCODE_GOOD; }
static void configure_lds_server(UA_Server *pServer) { UA_ServerConfig *config_lds = UA_Server_getConfig(pServer); UA_ServerConfig_setDefault(config_lds); config_lds->applicationDescription.applicationType = UA_APPLICATIONTYPE_DISCOVERYSERVER; UA_String_deleteMembers(&config_lds->applicationDescription.applicationUri); config_lds->applicationDescription.applicationUri = UA_STRING_ALLOC("urn:open62541.test.local_discovery_server"); UA_LocalizedText_deleteMembers(&config_lds->applicationDescription.applicationName); config_lds->applicationDescription.applicationName = UA_LOCALIZEDTEXT_ALLOC("en", "LDS Server"); config_lds->discovery.mdnsEnable = true; #ifdef UA_ENABLE_DISCOVERY_MULTICAST config_lds->discovery.mdns.mdnsServerName = UA_String_fromChars("LDS_test"); config_lds->discovery.mdns.serverCapabilitiesSize = 1; UA_String *caps = UA_String_new(); *caps = UA_String_fromChars("LDS"); config_lds->discovery.mdns.serverCapabilities = caps; #endif config_lds->discovery.cleanupTimeout = registerTimeout; }
static void setup_register(void) { // start register server running_register = UA_Boolean_new(); *running_register = true; server_register = UA_Server_new(); UA_ServerConfig *config_register = UA_Server_getConfig(server_register); UA_ServerConfig_setMinimal(config_register, 16664, NULL); UA_String_deleteMembers(&config_register->applicationDescription.applicationUri); config_register->applicationDescription.applicationUri = UA_String_fromChars("urn:open62541.test.server_register"); UA_LocalizedText_deleteMembers(&config_register->applicationDescription.applicationName); config_register->applicationDescription.applicationName = UA_LOCALIZEDTEXT_ALLOC("de", "Anmeldungsserver"); #ifdef UA_ENABLE_DISCOVERY_MULTICAST config_register->discovery.mdns.mdnsServerName = UA_String_fromChars("Register_test"); #endif UA_Server_run_startup(server_register); THREAD_CREATE(server_thread_register, serverloop_register); }
int main(void) { signal(SIGINT, stopHandler); signal(SIGTERM, stopHandler); UA_ServerConfig config = UA_ServerConfig_standard; config.applicationDescription.applicationType = UA_APPLICATIONTYPE_DISCOVERYSERVER; config.applicationDescription.applicationUri = UA_String_fromChars("open62541.example.local_discovery_server"); // timeout in seconds when to automatically remove a registered server from the list, // if it doesn't re-register within the given time frame. A value of 0 disables automatic removal. // Default is 60 Minutes (60*60). Must be bigger than 10 seconds, because cleanup is only triggered approximately // ervery 10 seconds. // The server will still be removed depending on the state of the semaphore file. // config.discoveryCleanupTimeout = 60*60; UA_ServerNetworkLayer nl = UA_ServerNetworkLayerTCP(UA_ConnectionConfig_standard, 4840); config.networkLayers = &nl; config.networkLayersSize = 1; UA_Server *server = UA_Server_new(config); UA_StatusCode retval = UA_Server_run(server, &running); UA_String_deleteMembers(&config.applicationDescription.applicationUri); UA_Server_delete(server); nl.deleteMembers(&nl); return (int)retval; }
/* run only when the server is stopped */ static void ServerNetworkLayerTCP_deleteMembers(UA_ServerNetworkLayer *nl) { ServerNetworkLayerTCP *layer = nl->handle; free(layer->mappings); free(layer); UA_String_deleteMembers(&nl->discoveryUrl); }
UA_Int32 UA_SecureConversationMessageAbortBody_deleteMembers(UA_SecureConversationMessageAbortBody* p) { UA_Int32 retval = UA_SUCCESS; retval |= UA_String_deleteMembers(&(p->reason)); return retval; }
UA_Int32 UA_OPCUATcpHelloMessage_deleteMembers(UA_OPCUATcpHelloMessage* p) { UA_Int32 retval = UA_SUCCESS; retval |= UA_String_deleteMembers(&(p->endpointUrl)); return retval; }
void Service_CreateSession(UA_Server *server, UA_SecureChannel *channel, const UA_CreateSessionRequest *request, UA_CreateSessionResponse *response) { if(channel->securityToken.channelId == 0) { response->responseHeader.serviceResult = UA_STATUSCODE_BADSECURECHANNELIDINVALID; return; } /* Allocate the response */ response->serverEndpoints = (UA_EndpointDescription*) UA_Array_new(server->config.endpoints.count, &UA_TYPES[UA_TYPES_ENDPOINTDESCRIPTION]); if(!response->serverEndpoints) { response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY; return; } response->serverEndpointsSize = server->config.endpoints.count; /* Copy the server's endpointdescriptions into the response */ for(size_t i = 0; i < server->config.endpoints.count; ++i) response->responseHeader.serviceResult |= UA_EndpointDescription_copy(&server->config.endpoints.endpoints[0].endpointDescription, &response->serverEndpoints[i]); /* Mirror back the endpointUrl */ for(size_t i = 0; i < response->serverEndpointsSize; ++i) { UA_String_deleteMembers(&response->serverEndpoints[i].endpointUrl); UA_String_copy(&request->endpointUrl, &response->serverEndpoints[i].endpointUrl); } UA_Session *newSession; response->responseHeader.serviceResult = UA_SessionManager_createSession(&server->sessionManager, channel, request, &newSession); if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) { UA_LOG_DEBUG_CHANNEL(server->config.logger, channel, "Processing CreateSessionRequest failed"); return; } /* Fill the session with more information */ newSession->maxResponseMessageSize = request->maxResponseMessageSize; newSession->maxRequestMessageSize = channel->connection->localConf.maxMessageSize; response->responseHeader.serviceResult |= UA_ApplicationDescription_copy(&request->clientDescription, &newSession->clientDescription); /* Prepare the response */ response->sessionId = newSession->sessionId; response->revisedSessionTimeout = (UA_Double)newSession->timeout; response->authenticationToken = newSession->authenticationToken; response->responseHeader.serviceResult = UA_String_copy(&request->sessionName, &newSession->sessionName); if(server->config.endpoints.count > 0) response->responseHeader.serviceResult |= UA_ByteString_copy(&server->config.endpoints.endpoints[0].endpointDescription.serverCertificate, &response->serverCertificate); /* Failure -> remove the session */ if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) { UA_SessionManager_removeSession(&server->sessionManager, &newSession->authenticationToken); return; } UA_LOG_DEBUG_CHANNEL(server->config.logger, channel, "Session " UA_PRINTF_GUID_FORMAT " created", UA_PRINTF_GUID_DATA(newSession->sessionId.identifier.guid)); }
UA_StatusCode UA_Client_connect_async(UA_Client *client, const char *endpointUrl, UA_ClientAsyncServiceCallback callback, void *userdata) { UA_LOG_TRACE(&client->config.logger, UA_LOGCATEGORY_CLIENT, "Client internal async"); if(client->state >= UA_CLIENTSTATE_WAITING_FOR_ACK) return UA_STATUSCODE_GOOD; UA_ChannelSecurityToken_init(&client->channel.securityToken); client->channel.state = UA_SECURECHANNELSTATE_FRESH; client->endpointsHandshake = true; client->channel.sendSequenceNumber = 0; client->requestId = 0; UA_String_deleteMembers(&client->endpointUrl); client->endpointUrl = UA_STRING_ALLOC(endpointUrl); UA_StatusCode retval = UA_STATUSCODE_GOOD; client->connection = client->config.initConnectionFunc(client->config.localConnectionConfig, client->endpointUrl, client->config.timeout, &client->config.logger); if(client->connection.state != UA_CONNECTION_OPENING) { UA_LOG_TRACE(&client->config.logger, UA_LOGCATEGORY_CLIENT, "Could not init async connection"); retval = UA_STATUSCODE_BADCONNECTIONCLOSED; goto cleanup; } /* Set the channel SecurityMode if not done so far */ if(client->channel.securityMode == UA_MESSAGESECURITYMODE_INVALID) client->channel.securityMode = UA_MESSAGESECURITYMODE_NONE; /* Set the channel SecurityPolicy if not done so far */ if(!client->channel.securityPolicy) { UA_SecurityPolicy *sp = getSecurityPolicy(client, UA_STRING("http://opcfoundation.org/UA/SecurityPolicy#None")); if(!sp) { retval = UA_STATUSCODE_BADINTERNALERROR; goto cleanup; } UA_ByteString remoteCertificate = UA_BYTESTRING_NULL; retval = UA_SecureChannel_setSecurityPolicy(&client->channel, sp, &remoteCertificate); if(retval != UA_STATUSCODE_GOOD) goto cleanup; } client->asyncConnectCall.callback = callback; client->asyncConnectCall.userdata = userdata; if(!client->connection.connectCallbackID) { UA_LOG_TRACE(&client->config.logger, UA_LOGCATEGORY_CLIENT, "Adding async connection callback"); retval = UA_Client_addRepeatedCallback( client, client->config.pollConnectionFunc, &client->connection, 100.0, &client->connection.connectCallbackID); if(retval != UA_STATUSCODE_GOOD) goto cleanup; } retval = UA_SecureChannel_generateLocalNonce(&client->channel); if(retval != UA_STATUSCODE_GOOD) goto cleanup; /* Delete async service. TODO: Move this from connect to the disconnect/cleanup phase */ UA_Client_AsyncService_removeAll(client, UA_STATUSCODE_BADSHUTDOWN); #ifdef UA_ENABLE_SUBSCRIPTIONS client->currentlyOutStandingPublishRequests = 0; #endif UA_NodeId_deleteMembers(&client->authenticationToken); /* Generate new local and remote key */ retval = UA_SecureChannel_generateNewKeys(&client->channel); if(retval != UA_STATUSCODE_GOOD) goto cleanup; return retval; cleanup: UA_LOG_TRACE(&client->config.logger, UA_LOGCATEGORY_CLIENT, "Failure during async connect"); UA_Client_disconnect(client); return retval; }
UA_StatusCode UA_NodeId_toString(const UA_NodeId *nodeId, UA_String *nodeIdStr) { if (nodeIdStr->length != 0) { UA_free(nodeIdStr->data); nodeIdStr->data = NULL; nodeIdStr->length = 0; } if (nodeId == NULL) return UA_STATUSCODE_GOOD; char *nsStr = NULL; long snprintfLen = 0; size_t nsLen = 0; if (nodeId->namespaceIndex != 0) { nsStr = (char*)UA_malloc(9+1); // strlen("ns=XXXXX;") = 9 + Nullbyte snprintfLen = UA_snprintf(nsStr, 10, "ns=%d;", nodeId->namespaceIndex); if (snprintfLen < 0 || snprintfLen >= 10) { UA_free(nsStr); return UA_STATUSCODE_BADINTERNALERROR; } nsLen = (size_t)(snprintfLen); } UA_ByteString byteStr = UA_BYTESTRING_NULL; switch (nodeId->identifierType) { case UA_NODEIDTYPE_NUMERIC: /* ns (2 byte, 65535) = 5 chars, numeric (4 byte, 4294967295) = 10 chars, delim = 1 , nullbyte = 1-> 17 chars */ nodeIdStr->length = nsLen + 2 + 10 + 1; nodeIdStr->data = (UA_Byte*)UA_malloc(nodeIdStr->length); if (nodeIdStr->data == NULL) { nodeIdStr->length = 0; UA_free(nsStr); return UA_STATUSCODE_BADOUTOFMEMORY; } snprintfLen =UA_snprintf((char*)nodeIdStr->data, nodeIdStr->length, "%si=%lu", nsLen > 0 ? nsStr : "", (unsigned long )nodeId->identifier.numeric); break; case UA_NODEIDTYPE_STRING: /* ns (16bit) = 5 chars, strlen + nullbyte */ nodeIdStr->length = nsLen + 2 + nodeId->identifier.string.length + 1; nodeIdStr->data = (UA_Byte*)UA_malloc(nodeIdStr->length); if (nodeIdStr->data == NULL) { nodeIdStr->length = 0; UA_free(nsStr); return UA_STATUSCODE_BADOUTOFMEMORY; } snprintfLen =UA_snprintf((char*)nodeIdStr->data, nodeIdStr->length, "%ss=%.*s", nsLen > 0 ? nsStr : "", (int)nodeId->identifier.string.length, nodeId->identifier.string.data); break; case UA_NODEIDTYPE_GUID: /* ns (16bit) = 5 chars + strlen(A123456C-0ABC-1A2B-815F-687212AAEE1B)=36 + nullbyte */ nodeIdStr->length = nsLen + 2 + 36 + 1; nodeIdStr->data = (UA_Byte*)UA_malloc(nodeIdStr->length); if (nodeIdStr->data == NULL) { nodeIdStr->length = 0; UA_free(nsStr); return UA_STATUSCODE_BADOUTOFMEMORY; } snprintfLen = UA_snprintf((char*)nodeIdStr->data, nodeIdStr->length, "%sg=" UA_PRINTF_GUID_FORMAT, nsLen > 0 ? nsStr : "", UA_PRINTF_GUID_DATA(nodeId->identifier.guid)); break; case UA_NODEIDTYPE_BYTESTRING: UA_ByteString_toBase64String(&nodeId->identifier.byteString, &byteStr); /* ns (16bit) = 5 chars + LEN + nullbyte */ nodeIdStr->length = nsLen + 2 + byteStr.length + 1; nodeIdStr->data = (UA_Byte*)UA_malloc(nodeIdStr->length); if (nodeIdStr->data == NULL) { nodeIdStr->length = 0; UA_String_deleteMembers(&byteStr); UA_free(nsStr); return UA_STATUSCODE_BADOUTOFMEMORY; } snprintfLen = UA_snprintf((char*)nodeIdStr->data, nodeIdStr->length, "%sb=%.*s", nsLen > 0 ? nsStr : "", (int)byteStr.length, byteStr.data); UA_String_deleteMembers(&byteStr); break; } UA_free(nsStr); if (snprintfLen < 0 || snprintfLen >= (long) nodeIdStr->length) { UA_free(nodeIdStr->data); nodeIdStr->data = NULL; nodeIdStr->length = 0; return UA_STATUSCODE_BADINTERNALERROR; } nodeIdStr->length = (size_t)snprintfLen; return UA_STATUSCODE_GOOD; }
int main(int argc, char **argv) { signal(SIGINT, stopHandler); /* catches ctrl-c */ signal(SIGTERM, stopHandler); UA_ServerConfig *config = UA_ServerConfig_new_minimal(16600, NULL); // To enable mDNS discovery, set application type to discovery server. config->applicationDescription.applicationType = UA_APPLICATIONTYPE_DISCOVERYSERVER; UA_String_deleteMembers(&config->applicationDescription.applicationUri); config->applicationDescription.applicationUri = UA_String_fromChars("urn:open62541.example.server_multicast"); config->mdnsServerName = UA_String_fromChars("Sample Multicast Server"); // See http://www.opcfoundation.org/UA/schemas/1.03/ServerCapabilities.csv //config.serverCapabilitiesSize = 1; //UA_String caps = UA_String_fromChars("LDS"); //config.serverCapabilities = ∩︀ UA_Server *server = UA_Server_new(config); self_discovery_url = &config->networkLayers[0].discoveryUrl; /* add a variable node to the address space */ UA_Int32 myInteger = 42; UA_NodeId myIntegerNodeId = UA_NODEID_STRING(1, "the.answer"); UA_QualifiedName myIntegerName = UA_QUALIFIEDNAME(1, "the answer"); UA_DataSource dateDataSource; dateDataSource.read = readInteger; dateDataSource.write = writeInteger; UA_VariableAttributes attr = UA_VariableAttributes_default; attr.description = UA_LOCALIZEDTEXT("en-US", "the answer"); attr.displayName = UA_LOCALIZEDTEXT("en-US", "the answer"); UA_Server_addDataSourceVariableNode(server, myIntegerNodeId, UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), myIntegerName, UA_NODEID_NULL, attr, dateDataSource, &myInteger, NULL); // callback which is called when a new server is detected through mDNS UA_Server_setServerOnNetworkCallback(server, serverOnNetworkCallback, NULL); // Start the server and call iterate to wait for the multicast discovery of the LDS UA_StatusCode retval = UA_Server_run_startup(server); if(retval != UA_STATUSCODE_GOOD) { UA_LOG_ERROR(logger, UA_LOGCATEGORY_SERVER, "Could not start the server. StatusCode %s", UA_StatusCode_name(retval)); UA_Server_delete(server); UA_ServerConfig_delete(config); UA_free(discovery_url); return 1; } UA_LOG_INFO(logger, UA_LOGCATEGORY_SERVER, "Server started. Waiting for announce of LDS Server."); while (running && discovery_url == NULL) UA_Server_run_iterate(server, true); if(!running) { UA_Server_delete(server); UA_ServerConfig_delete(config); UA_free(discovery_url); return 1; } UA_LOG_INFO(logger, UA_LOGCATEGORY_SERVER, "LDS-ME server found on %s", discovery_url); /* Check if the server supports sign and encrypt. OPC Foundation LDS requires an encrypted session for * RegisterServer call, our server currently uses encrpytion optionally */ UA_EndpointDescription *endpointRegister = getRegisterEndpointFromServer(discovery_url); UA_free(discovery_url); if (endpointRegister == NULL || endpointRegister->securityMode == UA_MESSAGESECURITYMODE_INVALID) { UA_LOG_ERROR(logger, UA_LOGCATEGORY_SERVER, "Could not find any suitable endpoints on discovery server"); UA_Server_delete(server); UA_ServerConfig_delete(config); return 1; } UA_Client *clientRegister = getRegisterClient(endpointRegister, argc, argv); if (!clientRegister) { UA_LOG_FATAL(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "Could not create the client for remote registering"); UA_Server_delete(server); UA_ServerConfig_delete(config); return 1; } /* Connect the client */ char *endpointUrl = (char*)UA_malloc(endpointRegister->endpointUrl.length + 1); memcpy(endpointUrl, endpointRegister->endpointUrl.data, endpointRegister->endpointUrl.length); endpointUrl[endpointRegister->endpointUrl.length] = 0; retval = UA_Server_addPeriodicServerRegisterCallback(server, clientRegister, endpointUrl, 10 * 60 * 1000, 500, NULL); if(retval != UA_STATUSCODE_GOOD) { UA_LOG_ERROR(logger, UA_LOGCATEGORY_SERVER, "Could not create periodic job for server register. StatusCode %s", UA_StatusCode_name(retval)); UA_free(endpointUrl); UA_Client_disconnect(clientRegister); UA_Client_delete(clientRegister); UA_Server_delete(server); UA_ServerConfig_delete(config); return 1; } while (running) UA_Server_run_iterate(server, true); UA_Server_run_shutdown(server); // UNregister the server from the discovery server. retval = UA_Server_unregister_discovery(server, clientRegister); if (retval != UA_STATUSCODE_GOOD) UA_LOG_ERROR(logger, UA_LOGCATEGORY_SERVER, "Could not unregister server from discovery server. " "StatusCode %s", UA_StatusCode_name(retval)); UA_free(endpointUrl); UA_Client_disconnect(clientRegister); UA_Client_delete(clientRegister); UA_Server_delete(server); UA_ServerConfig_delete(config); return (int)retval; }
int main(int argc, char **argv) { signal(SIGINT, stopHandler); /* catches ctrl-c */ signal(SIGTERM, stopHandler); UA_ServerConfig *config = UA_ServerConfig_new_default(); UA_String_deleteMembers(&config->applicationDescription.applicationUri); config->applicationDescription.applicationUri = UA_String_fromChars("urn:open62541.example.server_register"); config->mdnsServerName = UA_String_fromChars("Sample Server"); // See http://www.opcfoundation.org/UA/schemas/1.03/ServerCapabilities.csv //config.serverCapabilitiesSize = 1; //UA_String caps = UA_String_fromChars("LDS"); //config.serverCapabilities = ∩︀ UA_Server *server = UA_Server_new(config); /* add a variable node to the address space */ UA_Int32 myInteger = 42; UA_NodeId myIntegerNodeId = UA_NODEID_STRING(1, "the.answer"); UA_QualifiedName myIntegerName = UA_QUALIFIEDNAME(1, "the answer"); UA_DataSource dateDataSource; dateDataSource.read = readInteger; dateDataSource.write = writeInteger; UA_VariableAttributes attr = UA_VariableAttributes_default; attr.description = UA_LOCALIZEDTEXT("en-US", "the answer"); attr.displayName = UA_LOCALIZEDTEXT("en-US", "the answer"); UA_Server_addDataSourceVariableNode(server, myIntegerNodeId, UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), myIntegerName, UA_NODEID_NULL, attr, dateDataSource, &myInteger, NULL); // periodic server register after 10 Minutes, delay first register for 500ms UA_StatusCode retval = UA_Server_addPeriodicServerRegisterCallback(server, DISCOVERY_SERVER_ENDPOINT, 10 * 60 * 1000, 500, NULL); // UA_StatusCode retval = UA_Server_addPeriodicServerRegisterJob(server, // "opc.tcp://localhost:4840", 10*60*1000, 500, NULL); if (retval != UA_STATUSCODE_GOOD) { UA_LOG_ERROR(logger, UA_LOGCATEGORY_SERVER, "Could not create periodic job for server register. StatusCode %s", UA_StatusCode_name(retval)); UA_Server_delete(server); UA_ServerConfig_delete(config); return (int)retval; } retval = UA_Server_run(server, &running); if (retval != UA_STATUSCODE_GOOD) { UA_LOG_ERROR(logger, UA_LOGCATEGORY_SERVER, "Could not start the server. StatusCode %s", UA_StatusCode_name(retval)); UA_Server_delete(server); UA_ServerConfig_delete(config); return (int)retval; } // UNregister the server from the discovery server. retval = UA_Server_unregister_discovery(server, DISCOVERY_SERVER_ENDPOINT); //retval = UA_Server_unregister_discovery(server, "opc.tcp://localhost:4840" ); if(retval != UA_STATUSCODE_GOOD) UA_LOG_ERROR(logger, UA_LOGCATEGORY_SERVER, "Could not unregister server from discovery server. StatusCode %s", UA_StatusCode_name(retval)); UA_Server_delete(server); UA_ServerConfig_delete(config); return (int)retval; }
static int ua_client_connectUA(char* ipaddress,int port, UA_String *endpointUrl, ConnectionInfo *connectionInfo, UA_Boolean stateless, UA_Boolean udp) { UA_ByteString reply; UA_ByteString_newMembers(&reply, 65536); int sock; struct sockaddr_in server; //Create socket if(udp==UA_TRUE){ sock = socket(AF_INET, SOCK_DGRAM, 0); }else{ sock = socket(AF_INET, SOCK_STREAM, 0); } if(sock == -1) { printf("Could not create socket"); return 1; } server.sin_addr.s_addr = inet_addr(ipaddress); server.sin_family = AF_INET; server.sin_port = htons(port); if(connect(sock, (struct sockaddr *) &server, sizeof(server)) < 0) { perror("connect failed. Error"); return 1; } connectionInfo->socket = sock; if(stateless){ UA_NodeId_init(&connectionInfo->authenticationToken); connectionInfo->channelId=0; UA_SequenceHeader_init(&connectionInfo->sequenceHdr); connectionInfo->tokenId=0; return 0; }else{ sendHello(sock, endpointUrl); recv(sock, reply.data, reply.length, 0); sendOpenSecureChannel(sock); recv(sock, reply.data, reply.length, 0); size_t recvOffset = 0; UA_TcpMessageHeader msghdr; UA_TcpMessageHeader_decodeBinary(&reply, &recvOffset, &msghdr); UA_AsymmetricAlgorithmSecurityHeader asymHeader; UA_NodeId rspType; UA_OpenSecureChannelResponse openSecChannelRsp; UA_UInt32_decodeBinary(&reply, &recvOffset, &connectionInfo->channelId); UA_AsymmetricAlgorithmSecurityHeader_decodeBinary(&reply,&recvOffset,&asymHeader); UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&asymHeader); UA_SequenceHeader_decodeBinary(&reply,&recvOffset,&connectionInfo->sequenceHdr); UA_NodeId_decodeBinary(&reply,&recvOffset,&rspType); UA_OpenSecureChannelResponse_decodeBinary(&reply,&recvOffset,&openSecChannelRsp); connectionInfo->tokenId = openSecChannelRsp.securityToken.tokenId; sendCreateSession(sock, connectionInfo->channelId, openSecChannelRsp.securityToken.tokenId, 52, 2, endpointUrl); recv(sock, reply.data, reply.length, 0); UA_NodeId messageType; recvOffset = 24; UA_NodeId_decodeBinary(&reply,&recvOffset,&messageType); UA_CreateSessionResponse createSessionResponse; UA_CreateSessionResponse_decodeBinary(&reply,&recvOffset,&createSessionResponse); connectionInfo->authenticationToken = createSessionResponse.authenticationToken; sendActivateSession(sock, connectionInfo->channelId, connectionInfo->tokenId, 53, 3, connectionInfo->authenticationToken); recv(sock, reply.data, reply.length, 0); UA_OpenSecureChannelResponse_deleteMembers(&openSecChannelRsp); UA_String_deleteMembers(&reply); UA_CreateSessionResponse_deleteMembers(&createSessionResponse); return 0; } }
int main(int argc, char *argv[]) { int defaultParams = argc < 8; //start parameters if(defaultParams) { printf("1st parameter: number of nodes to read \n"); printf("2nd parameter: number of read-tries \n"); printf("3rd parameter: name of the file to save measurement data \n"); printf("4th parameter: 1 = read same node, 0 = read different nodes \n"); printf("5th parameter: ip adress \n"); printf("6th parameter: port \n"); printf("7th parameter: 0=stateful, 1=stateless\n"); printf("8th parameter: 0=tcp, 1=udp (only with stateless calls)\n"); printf("\nUsing default parameters. \n"); } UA_UInt32 nodesToReadSize; UA_UInt32 tries; UA_Boolean alwaysSameNode; UA_ByteString reply; UA_ByteString_newMembers(&reply, 65536); UA_Boolean stateless; UA_Boolean udp; if(defaultParams) nodesToReadSize = 1; else nodesToReadSize = atoi(argv[1]); if(defaultParams) tries= 2; else tries = (UA_UInt32) atoi(argv[2]); if(defaultParams){ alwaysSameNode = UA_TRUE; }else{ if(atoi(argv[4]) != 0) alwaysSameNode = UA_TRUE; else alwaysSameNode = UA_FALSE; } if(defaultParams){ stateless = UA_FALSE; }else{ if(atoi(argv[7]) != 0) stateless = UA_TRUE; else stateless = UA_FALSE; } if(defaultParams){ udp = UA_FALSE; }else{ if(atoi(argv[8]) != 0) udp = UA_TRUE; else udp = UA_FALSE; } //Connect to remote server UA_String endpoint; UA_String_copycstring("none",&endpoint); ConnectionInfo connectionInfo; /* REQUEST START*/ UA_NodeId *nodesToRead; nodesToRead = UA_Array_new(&UA_TYPES[UA_TYPES_NODEID], 1); for(UA_UInt32 i = 0; i<1; i++) { if(alwaysSameNode) nodesToRead[i].identifier.numeric = 2253; //ask always the same node else nodesToRead[i].identifier.numeric = 19000 +i; nodesToRead[i].identifierType = UA_NODEIDTYPE_NUMERIC; nodesToRead[i].namespaceIndex = 0; } UA_DateTime tic, toc; UA_Double *timeDiffs; UA_Int32 received; timeDiffs = UA_Array_new(&UA_TYPES[UA_TYPES_DOUBLE], tries); UA_Double sum = 0; tic = UA_DateTime_now(); /** UA_Double duration; UA_UInt32 count = 0; UA_Double start = 0, stop = 0; UA_UInt32 timeToRun = 30; UA_UInt32 timeToStart = 8; UA_UInt32 timeToStop = 22; do{ toc = UA_DateTime_now(); duration = ((UA_Double)toc-(UA_Double)tic)/(UA_Double)1e4; if(duration>=timeToStart*1000 && duration <= timeToStop*1000){ if(start==0.0){ start=UA_DateTime_now(); } } //if(stateless || (!stateless && i==0)){ if(defaultParams){ if(ua_client_connectUA("127.0.0.1",atoi("16664"),&endpoint,&connectionInfo,stateless,udp) != 0){ return 0; } }else{ if(ua_client_connectUA(argv[5],atoi(argv[6]),&endpoint,&connectionInfo,stateless,udp) != 0){ return 0; } } //} sendReadRequest(&connectionInfo,1,nodesToRead); received = recv(connectionInfo.socket, reply.data, 2000, 0); if(duration>=timeToStart*1000 && duration <= timeToStop*1000){ count++; } if(!stateless){ closeSession(&connectionInfo); recv(connectionInfo.socket, reply.data, 2000, 0); closeSecureChannel(&connectionInfo); } //if(stateless || (!stateless && i==tries-1)){ close(connectionInfo.socket); //} if(duration >= timeToStop*1000 && stop==0){ stop=UA_DateTime_now(); printf("%i messages in %f secs, rate %f m/s\n", count, (stop-start)/(UA_Double)1e7, (UA_Double)count/((stop-start)/(UA_Double)1e7)); } }while(duration<timeToRun*1000); exit(0); **/ for(UA_UInt32 i = 0; i < tries; i++) { //if(stateless || (!stateless && i==0)){ tic = UA_DateTime_now(); if(defaultParams){ if(ua_client_connectUA("127.0.0.1",atoi("16664"),&endpoint,&connectionInfo,stateless,udp) != 0){ return 0; } }else{ if(ua_client_connectUA(argv[5],atoi(argv[6]),&endpoint,&connectionInfo,stateless,udp) != 0){ return 0; } } //} for(UA_UInt32 i = 0; i < nodesToReadSize; i++) { sendReadRequest(&connectionInfo,1,nodesToRead); received = recv(connectionInfo.socket, reply.data, 2000, 0); } if(!stateless){ closeSession(&connectionInfo); recv(connectionInfo.socket, reply.data, 2000, 0); closeSecureChannel(&connectionInfo); } //if(stateless || (!stateless && i==tries-1)){ close(connectionInfo.socket); //} toc = UA_DateTime_now() - tic; timeDiffs[i] = (UA_Double)toc/(UA_Double)1e4; sum = sum + timeDiffs[i]; } /* REQUEST END*/ UA_Double mean = sum / tries; printf("mean time for handling request: %16.10f ms \n",mean); if(received>0) printf("received: %i\n",received); // dummy //save to file char data[100]; const char flag = 'a'; FILE* fHandle = UA_NULL; if (defaultParams) { fHandle = fopen("client.log", &flag); }else{ fHandle = fopen(argv[3], &flag); } //header UA_Int32 bytesToWrite = sprintf(data, "measurement %s in ms, nodesToRead %d \n", argv[3], 1); fwrite(data,1,bytesToWrite,fHandle); for(UA_UInt32 i=0;i<tries;i++) { bytesToWrite = sprintf(data,"%16.10f \n",timeDiffs[i]); fwrite(data,1,bytesToWrite,fHandle); } fclose(fHandle); UA_String_deleteMembers(&reply); UA_Array_delete(nodesToRead,&UA_TYPES[UA_TYPES_NODEID], 1); UA_free(timeDiffs); return 0; }
void Service_CreateSession(UA_Server *server, UA_SecureChannel *channel, const UA_CreateSessionRequest *request, UA_CreateSessionResponse *response) { if(channel == NULL) { response->responseHeader.serviceResult = UA_STATUSCODE_BADINTERNALERROR; return; } if(channel->connection == NULL) { response->responseHeader.serviceResult = UA_STATUSCODE_BADINTERNALERROR; return; } UA_LOG_DEBUG_CHANNEL(server->config.logger, channel, "Trying to create session"); if(channel->securityMode == UA_MESSAGESECURITYMODE_SIGN || channel->securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT) { if(!UA_ByteString_equal(&request->clientCertificate, &channel->remoteCertificate)) { response->responseHeader.serviceResult = UA_STATUSCODE_BADCERTIFICATEINVALID; return; } } if(channel->securityToken.channelId == 0) { response->responseHeader.serviceResult = UA_STATUSCODE_BADSECURECHANNELIDINVALID; return; } if(!UA_ByteString_equal(&channel->securityPolicy->policyUri, &UA_SECURITY_POLICY_NONE_URI) && request->clientNonce.length < 32) { response->responseHeader.serviceResult = UA_STATUSCODE_BADNONCEINVALID; return; } ////////////////////// TODO: Compare application URI with certificate uri (decode certificate) /* Allocate the response */ response->serverEndpoints = (UA_EndpointDescription*) UA_Array_new(server->config.endpointsSize, &UA_TYPES[UA_TYPES_ENDPOINTDESCRIPTION]); if(!response->serverEndpoints) { response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY; return; } response->serverEndpointsSize = server->config.endpointsSize; /* Copy the server's endpointdescriptions into the response */ for(size_t i = 0; i < server->config.endpointsSize; ++i) response->responseHeader.serviceResult |= UA_EndpointDescription_copy(&server->config.endpoints[0].endpointDescription, &response->serverEndpoints[i]); if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) return; /* Mirror back the endpointUrl */ for(size_t i = 0; i < response->serverEndpointsSize; ++i) { UA_String_deleteMembers(&response->serverEndpoints[i].endpointUrl); UA_String_copy(&request->endpointUrl, &response->serverEndpoints[i].endpointUrl); } UA_Session *newSession; response->responseHeader.serviceResult = UA_SessionManager_createSession(&server->sessionManager, channel, request, &newSession); if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) { UA_LOG_DEBUG_CHANNEL(server->config.logger, channel, "Processing CreateSessionRequest failed"); return; } /* Fill the session with more information */ newSession->maxResponseMessageSize = request->maxResponseMessageSize; newSession->maxRequestMessageSize = channel->connection->localConf.maxMessageSize; response->responseHeader.serviceResult |= UA_ApplicationDescription_copy(&request->clientDescription, &newSession->clientDescription); /* Prepare the response */ response->sessionId = newSession->sessionId; response->revisedSessionTimeout = (UA_Double)newSession->timeout; response->authenticationToken = newSession->authenticationToken; response->responseHeader.serviceResult = UA_String_copy(&request->sessionName, &newSession->sessionName); if(server->config.endpointsSize > 0) response->responseHeader.serviceResult |= UA_ByteString_copy(&channel->securityPolicy->localCertificate, &response->serverCertificate); /* Create a signed nonce */ response->responseHeader.serviceResult = nonceAndSignCreateSessionResponse(server, channel, newSession, request, response); /* Failure -> remove the session */ if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) { UA_SessionManager_removeSession(&server->sessionManager, &newSession->authenticationToken); return; } UA_LOG_DEBUG_CHANNEL(server->config.logger, channel, "Session " UA_PRINTF_GUID_FORMAT " created", UA_PRINTF_GUID_DATA(newSession->sessionId.identifier.guid)); }
static int sendOpenSecureChannel(UA_Int32 sock) { UA_TcpMessageHeader msghdr; msghdr.messageTypeAndFinal = UA_MESSAGETYPEANDFINAL_OPNF; UA_UInt32 secureChannelId = 0; UA_String securityPolicy; UA_String_copycstring("http://opcfoundation.org/UA/SecurityPolicy#None", &securityPolicy); UA_String senderCert; senderCert.data = UA_NULL; senderCert.length = -1; UA_String receiverCertThumb; receiverCertThumb.data = UA_NULL; receiverCertThumb.length = -1; UA_UInt32 sequenceNumber = 51; UA_UInt32 requestId = 1; UA_NodeId type; type.identifier.numeric = 446; // id of opensecurechannelrequest type.identifierType = UA_NODEIDTYPE_NUMERIC; type.namespaceIndex = 0; UA_OpenSecureChannelRequest opnSecRq; UA_OpenSecureChannelRequest_init(&opnSecRq); opnSecRq.requestHeader.timestamp = UA_DateTime_now(); UA_ByteString_newMembers(&opnSecRq.clientNonce, 1); opnSecRq.clientNonce.data[0] = 0; opnSecRq.clientProtocolVersion = 0; opnSecRq.requestedLifetime = 30000; opnSecRq.securityMode = UA_MESSAGESECURITYMODE_NONE; opnSecRq.requestType = UA_SECURITYTOKENREQUESTTYPE_ISSUE; opnSecRq.requestHeader.authenticationToken.identifier.numeric = 10; opnSecRq.requestHeader.authenticationToken.identifierType = UA_NODEIDTYPE_NUMERIC; opnSecRq.requestHeader.authenticationToken.namespaceIndex = 10; msghdr.messageSize = 135; // todo: compute the message size from the actual content UA_ByteString message; UA_ByteString_newMembers(&message, 1000); size_t offset = 0; UA_TcpMessageHeader_encodeBinary(&msghdr, &message, &offset); UA_UInt32_encodeBinary(&secureChannelId, &message, &offset); UA_String_encodeBinary(&securityPolicy, &message, &offset); UA_String_encodeBinary(&senderCert, &message, &offset); UA_String_encodeBinary(&receiverCertThumb, &message, &offset); UA_UInt32_encodeBinary(&sequenceNumber, &message, &offset); UA_UInt32_encodeBinary(&requestId, &message, &offset); UA_NodeId_encodeBinary(&type, &message, &offset); UA_OpenSecureChannelRequest_encodeBinary(&opnSecRq, &message, &offset); UA_OpenSecureChannelRequest_deleteMembers(&opnSecRq); UA_String_deleteMembers(&securityPolicy); UA_Int32 sendret = send(sock, message.data, offset, 0); UA_ByteString_deleteMembers(&message); if (sendret < 0) { printf("send opensecurechannel failed"); return 1; } return 0; }