ua_client.c 54 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295
  1. #include "ua_util.h"
  2. #include "ua_client.h"
  3. #include "ua_types_generated.h"
  4. #include "ua_nodeids.h"
  5. #include "ua_securechannel.h"
  6. #include "ua_types_encoding_binary.h"
  7. #include "ua_transport_generated.h"
  8. #include "ua_types_generated_encoding_binary.h"
  9. #include "ua_transport_generated_encoding_binary.h"
  10. #include "ua_client_internal.h"
  11. typedef enum {
  12. UA_CLIENTSTATE_READY,
  13. UA_CLIENTSTATE_CONNECTED,
  14. UA_CLIENTSTATE_ERRORED
  15. } UA_Client_State;
  16. struct UA_Client {
  17. /* State */ //maybe it should be visible to user
  18. UA_Client_State state;
  19. /* Connection */
  20. UA_Connection connection;
  21. UA_SecureChannel channel;
  22. UA_String endpointUrl;
  23. UA_UInt32 requestId;
  24. /* Session */
  25. UA_UserTokenPolicy token;
  26. UA_NodeId sessionId;
  27. UA_NodeId authenticationToken;
  28. UA_UInt32 requestHandle;
  29. #ifdef ENABLE_SUBSCRIPTIONS
  30. UA_Int32 monitoredItemHandles;
  31. LIST_HEAD(UA_ListOfUnacknowledgedNotificationNumbers, UA_Client_NotificationsAckNumber_s) pendingNotificationsAcks;
  32. LIST_HEAD(UA_ListOfClientSubscriptionItems, UA_Client_Subscription_s) subscriptions;
  33. #endif
  34. /* Config */
  35. UA_Logger logger;
  36. UA_ClientConfig config;
  37. UA_DateTime scExpiresAt;
  38. };
  39. const UA_EXPORT UA_ClientConfig UA_ClientConfig_standard =
  40. { .timeout = 5 /* ms receive timout */, .secureChannelLifeTime = 30000, .timeToRenewSecureChannel = 2000,
  41. {.protocolVersion = 0, .sendBufferSize = 65536, .recvBufferSize = 65536,
  42. .maxMessageSize = 65536, .maxChunkCount = 1}};
  43. UA_Client * UA_Client_new(UA_ClientConfig config, UA_Logger logger) {
  44. UA_Client *client = UA_calloc(1, sizeof(UA_Client));
  45. if(!client)
  46. return UA_NULL;
  47. UA_Client_init(client, config, logger);
  48. return client;
  49. }
  50. void UA_Client_reset(UA_Client* client){
  51. UA_Client_deleteMembers(client);
  52. UA_Client_init(client, client->config, client->logger);
  53. }
  54. void UA_Client_init(UA_Client* client, UA_ClientConfig config, UA_Logger logger){
  55. client->state = UA_CLIENTSTATE_READY;
  56. UA_Connection_init(&client->connection);
  57. UA_SecureChannel_init(&client->channel);
  58. client->channel.connection = &client->connection;
  59. UA_String_init(&client->endpointUrl);
  60. client->requestId = 0;
  61. UA_NodeId_init(&client->authenticationToken);
  62. client->requestHandle = 0;
  63. client->logger = logger;
  64. client->config = config;
  65. client->scExpiresAt = 0;
  66. #ifdef ENABLE_SUBSCRIPTIONS
  67. client->monitoredItemHandles = 0;
  68. LIST_INIT(&client->pendingNotificationsAcks);
  69. LIST_INIT(&client->subscriptions);
  70. #endif
  71. }
  72. void UA_Client_deleteMembers(UA_Client* client){
  73. if(client->state == UA_CLIENTSTATE_READY) //initialized client has no dynamic memory allocated
  74. return;
  75. UA_Connection_deleteMembers(&client->connection);
  76. UA_SecureChannel_deleteMembersCleanup(&client->channel);
  77. if(client->endpointUrl.data)
  78. UA_String_deleteMembers(&client->endpointUrl);
  79. UA_UserTokenPolicy_deleteMembers(&client->token);
  80. }
  81. void UA_Client_delete(UA_Client* client){
  82. if(client->state != UA_CLIENTSTATE_READY)
  83. UA_Client_deleteMembers(client);
  84. UA_free(client);
  85. }
  86. static UA_StatusCode HelAckHandshake(UA_Client *c) {
  87. UA_TcpMessageHeader messageHeader;
  88. messageHeader.messageTypeAndFinal = UA_MESSAGETYPEANDFINAL_HELF;
  89. UA_TcpHelloMessage hello;
  90. UA_String_copy(&c->endpointUrl, &hello.endpointUrl); /* must be less than 4096 bytes */
  91. UA_Connection *conn = &c->connection;
  92. hello.maxChunkCount = conn->localConf.maxChunkCount;
  93. hello.maxMessageSize = conn->localConf.maxMessageSize;
  94. hello.protocolVersion = conn->localConf.protocolVersion;
  95. hello.receiveBufferSize = conn->localConf.recvBufferSize;
  96. hello.sendBufferSize = conn->localConf.sendBufferSize;
  97. UA_ByteString message;
  98. UA_StatusCode retval = c->connection.getSendBuffer(&c->connection, c->connection.remoteConf.recvBufferSize, &message);
  99. if(retval != UA_STATUSCODE_GOOD)
  100. return retval;
  101. size_t offset = 8;
  102. retval |= UA_TcpHelloMessage_encodeBinary(&hello, &message, &offset);
  103. messageHeader.messageSize = offset;
  104. offset = 0;
  105. retval |= UA_TcpMessageHeader_encodeBinary(&messageHeader, &message, &offset);
  106. UA_TcpHelloMessage_deleteMembers(&hello);
  107. if(retval != UA_STATUSCODE_GOOD) {
  108. c->connection.releaseSendBuffer(&c->connection, &message);
  109. return retval;
  110. }
  111. message.length = messageHeader.messageSize;
  112. retval = c->connection.send(&c->connection, &message);
  113. if(retval != UA_STATUSCODE_GOOD)
  114. return retval;
  115. UA_ByteString reply;
  116. UA_ByteString_init(&reply);
  117. do {
  118. retval = c->connection.recv(&c->connection, &reply, c->config.timeout);
  119. if(retval != UA_STATUSCODE_GOOD)
  120. return retval;
  121. } while(!reply.data);
  122. offset = 0;
  123. UA_TcpMessageHeader_decodeBinary(&reply, &offset, &messageHeader);
  124. UA_TcpAcknowledgeMessage ackMessage;
  125. retval = UA_TcpAcknowledgeMessage_decodeBinary(&reply, &offset, &ackMessage);
  126. UA_ByteString_deleteMembers(&reply);
  127. if(retval != UA_STATUSCODE_GOOD)
  128. return retval;
  129. conn->remoteConf.maxChunkCount = ackMessage.maxChunkCount;
  130. conn->remoteConf.maxMessageSize = ackMessage.maxMessageSize;
  131. conn->remoteConf.protocolVersion = ackMessage.protocolVersion;
  132. conn->remoteConf.recvBufferSize = ackMessage.receiveBufferSize;
  133. conn->remoteConf.sendBufferSize = ackMessage.sendBufferSize;
  134. conn->state = UA_CONNECTION_ESTABLISHED;
  135. return UA_STATUSCODE_GOOD;
  136. }
  137. static UA_StatusCode SecureChannelHandshake(UA_Client *client, UA_Boolean renew) {
  138. /* Check if sc is still valid */
  139. if(renew && client->scExpiresAt - UA_DateTime_now() > client->config.timeToRenewSecureChannel * 10000 ){
  140. return UA_STATUSCODE_GOOD;
  141. }
  142. UA_SecureConversationMessageHeader messageHeader;
  143. messageHeader.messageHeader.messageTypeAndFinal = UA_MESSAGETYPEANDFINAL_OPNF;
  144. messageHeader.secureChannelId = 0;
  145. UA_SequenceHeader seqHeader;
  146. seqHeader.sequenceNumber = ++client->channel.sequenceNumber;
  147. seqHeader.requestId = ++client->requestId;
  148. UA_AsymmetricAlgorithmSecurityHeader asymHeader;
  149. UA_AsymmetricAlgorithmSecurityHeader_init(&asymHeader);
  150. asymHeader.securityPolicyUri = UA_STRING_ALLOC("http://opcfoundation.org/UA/SecurityPolicy#None");
  151. /* id of opensecurechannelrequest */
  152. UA_NodeId requestType = UA_NODEID_NUMERIC(0, UA_NS0ID_OPENSECURECHANNELREQUEST + UA_ENCODINGOFFSET_BINARY);
  153. UA_OpenSecureChannelRequest opnSecRq;
  154. UA_OpenSecureChannelRequest_init(&opnSecRq);
  155. opnSecRq.requestHeader.timestamp = UA_DateTime_now();
  156. opnSecRq.requestHeader.authenticationToken = client->authenticationToken;
  157. opnSecRq.requestedLifetime = client->config.secureChannelLifeTime;
  158. if(renew) {
  159. opnSecRq.requestType = UA_SECURITYTOKENREQUESTTYPE_RENEW;
  160. } else {
  161. opnSecRq.requestType = UA_SECURITYTOKENREQUESTTYPE_ISSUE;
  162. UA_ByteString_init(&client->channel.clientNonce);
  163. UA_ByteString_copy(&client->channel.clientNonce, &opnSecRq.clientNonce);
  164. opnSecRq.securityMode = UA_MESSAGESECURITYMODE_NONE;
  165. }
  166. UA_ByteString message;
  167. UA_Connection *c = &client->connection;
  168. UA_StatusCode retval = c->getSendBuffer(c, c->remoteConf.recvBufferSize, &message);
  169. if(retval != UA_STATUSCODE_GOOD) {
  170. UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&asymHeader);
  171. UA_OpenSecureChannelRequest_deleteMembers(&opnSecRq);
  172. return retval;
  173. }
  174. size_t offset = 12;
  175. retval = UA_AsymmetricAlgorithmSecurityHeader_encodeBinary(&asymHeader, &message, &offset);
  176. retval |= UA_SequenceHeader_encodeBinary(&seqHeader, &message, &offset);
  177. retval |= UA_NodeId_encodeBinary(&requestType, &message, &offset);
  178. retval |= UA_OpenSecureChannelRequest_encodeBinary(&opnSecRq, &message, &offset);
  179. messageHeader.messageHeader.messageSize = offset;
  180. offset = 0;
  181. retval |= UA_SecureConversationMessageHeader_encodeBinary(&messageHeader, &message, &offset);
  182. UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&asymHeader);
  183. UA_OpenSecureChannelRequest_deleteMembers(&opnSecRq);
  184. if(retval != UA_STATUSCODE_GOOD) {
  185. client->connection.releaseSendBuffer(&client->connection, &message);
  186. return retval;
  187. }
  188. message.length = messageHeader.messageHeader.messageSize;
  189. retval = client->connection.send(&client->connection, &message);
  190. if(retval != UA_STATUSCODE_GOOD)
  191. return retval;
  192. UA_ByteString reply;
  193. UA_ByteString_init(&reply);
  194. do {
  195. retval = client->connection.recv(&client->connection, &reply, client->config.timeout);
  196. if(retval != UA_STATUSCODE_GOOD)
  197. return retval;
  198. } while(!reply.data);
  199. offset = 0;
  200. UA_SecureConversationMessageHeader_decodeBinary(&reply, &offset, &messageHeader);
  201. UA_AsymmetricAlgorithmSecurityHeader_decodeBinary(&reply, &offset, &asymHeader);
  202. UA_SequenceHeader_decodeBinary(&reply, &offset, &seqHeader);
  203. UA_NodeId_decodeBinary(&reply, &offset, &requestType);
  204. UA_NodeId expectedRequest = UA_NODEID_NUMERIC(0, UA_NS0ID_OPENSECURECHANNELRESPONSE +
  205. UA_ENCODINGOFFSET_BINARY);
  206. if(!UA_NodeId_equal(&requestType, &expectedRequest)) {
  207. UA_ByteString_deleteMembers(&reply);
  208. UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&asymHeader);
  209. UA_NodeId_deleteMembers(&requestType);
  210. UA_LOG_ERROR(client->logger, UA_LOGCATEGORY_CLIENT,
  211. "Reply answers the wrong request. Expected OpenSecureChannelResponse.");
  212. return UA_STATUSCODE_BADINTERNALERROR;
  213. }
  214. UA_OpenSecureChannelResponse response;
  215. UA_OpenSecureChannelResponse_decodeBinary(&reply, &offset, &response);
  216. client->scExpiresAt = UA_DateTime_now() + response.securityToken.revisedLifetime * 10000;
  217. UA_ByteString_deleteMembers(&reply);
  218. retval = response.responseHeader.serviceResult;
  219. if(!renew && retval == UA_STATUSCODE_GOOD) {
  220. UA_ChannelSecurityToken_copy(&response.securityToken, &client->channel.securityToken);
  221. UA_ByteString_deleteMembers(&client->channel.serverNonce); // if the handshake is repeated
  222. UA_ByteString_copy(&response.serverNonce, &client->channel.serverNonce);
  223. }
  224. UA_OpenSecureChannelResponse_deleteMembers(&response);
  225. UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&asymHeader);
  226. return retval;
  227. }
  228. /** If the request fails, then the response is cast to UA_ResponseHeader (at the beginning of every
  229. response) and filled with the appropriate error code */
  230. static void synchronousRequest(UA_Client *client, void *request, const UA_DataType *requestType,
  231. void *response, const UA_DataType *responseType) {
  232. UA_StatusCode retval = UA_STATUSCODE_GOOD;
  233. if(!response)
  234. return;
  235. UA_init(response, responseType);
  236. UA_ResponseHeader *respHeader = (UA_ResponseHeader*)response;
  237. //make sure we have a valid session
  238. retval = UA_Client_renewSecureChannel(client);
  239. if(retval != UA_STATUSCODE_GOOD) {
  240. respHeader->serviceResult = retval;
  241. client->state = UA_CLIENTSTATE_ERRORED;
  242. return;
  243. }
  244. /* HANDLING REQUEST HEADER PARAMETERS */
  245. typedef struct {
  246. UA_RequestHeader requestHeader;
  247. } headerOnlyRequest;
  248. /* The cast is valid, since all requests start with a requestHeader */
  249. /* Copy authenticationToken token to request header */
  250. UA_NodeId_copy(&client->authenticationToken, &((headerOnlyRequest*)request)->requestHeader.authenticationToken);
  251. ((headerOnlyRequest*)request)->requestHeader.timestamp = UA_DateTime_now();
  252. ((headerOnlyRequest*)request)->requestHeader.requestHandle = ++client->requestHandle;
  253. /*/HANDLING REQUEST HEADER PARAMETERS */
  254. /* Send the request */
  255. UA_UInt32 requestId = ++client->requestId;
  256. retval = UA_SecureChannel_sendBinaryMessage(&client->channel, requestId,
  257. request, requestType);
  258. if(retval) {
  259. if(retval == UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED)
  260. respHeader->serviceResult = UA_STATUSCODE_BADREQUESTTOOLARGE;
  261. else
  262. respHeader->serviceResult = retval;
  263. client->state = UA_CLIENTSTATE_ERRORED;
  264. return;
  265. }
  266. /* Retrieve the response */
  267. // Todo: push this into the generic securechannel implementation for client and server
  268. UA_ByteString reply;
  269. UA_ByteString_init(&reply);
  270. do {
  271. retval = client->connection.recv(&client->connection, &reply, client->config.timeout);
  272. if(retval != UA_STATUSCODE_GOOD) {
  273. respHeader->serviceResult = retval;
  274. client->state = UA_CLIENTSTATE_ERRORED;
  275. return;
  276. }
  277. } while(!reply.data);
  278. size_t offset = 0;
  279. UA_SecureConversationMessageHeader msgHeader;
  280. retval |= UA_SecureConversationMessageHeader_decodeBinary(&reply, &offset, &msgHeader);
  281. UA_SymmetricAlgorithmSecurityHeader symHeader;
  282. retval |= UA_SymmetricAlgorithmSecurityHeader_decodeBinary(&reply, &offset, &symHeader);
  283. UA_SequenceHeader seqHeader;
  284. retval |= UA_SequenceHeader_decodeBinary(&reply, &offset, &seqHeader);
  285. UA_NodeId responseId;
  286. retval |= UA_NodeId_decodeBinary(&reply, &offset, &responseId);
  287. UA_NodeId expectedNodeId = UA_NODEID_NUMERIC(0, responseType->typeId.identifier.numeric +
  288. UA_ENCODINGOFFSET_BINARY);
  289. if(retval != UA_STATUSCODE_GOOD)
  290. goto finish;
  291. /* Todo: we need to demux responses since a publish responses may come at any time */
  292. if(!UA_NodeId_equal(&responseId, &expectedNodeId) || seqHeader.requestId != requestId) {
  293. if(responseId.identifier.numeric != UA_NS0ID_SERVICEFAULT + UA_ENCODINGOFFSET_BINARY) {
  294. UA_LOG_ERROR(client->logger, UA_LOGCATEGORY_CLIENT,
  295. "Reply answers the wrong request. Expected ns=%i,i=%i. But retrieved ns=%i,i=%i",
  296. expectedNodeId.namespaceIndex, expectedNodeId.identifier.numeric,
  297. responseId.namespaceIndex, responseId.identifier.numeric);
  298. respHeader->serviceResult = UA_STATUSCODE_BADINTERNALERROR;
  299. } else
  300. retval = UA_decodeBinary(&reply, &offset, respHeader, &UA_TYPES[UA_TYPES_SERVICEFAULT]);
  301. goto finish;
  302. }
  303. retval = UA_decodeBinary(&reply, &offset, response, responseType);
  304. if(retval == UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED)
  305. retval = UA_STATUSCODE_BADRESPONSETOOLARGE;
  306. finish:
  307. UA_SymmetricAlgorithmSecurityHeader_deleteMembers(&symHeader);
  308. UA_ByteString_deleteMembers(&reply);
  309. if(retval != UA_STATUSCODE_GOOD){
  310. client->state = UA_CLIENTSTATE_ERRORED;
  311. respHeader->serviceResult = retval;
  312. }
  313. }
  314. static UA_StatusCode ActivateSession(UA_Client *client) {
  315. UA_ActivateSessionRequest request;
  316. UA_ActivateSessionRequest_init(&request);
  317. request.requestHeader.requestHandle = 2; //TODO: is it a magic number?
  318. request.requestHeader.authenticationToken = client->authenticationToken;
  319. request.requestHeader.timestamp = UA_DateTime_now();
  320. request.requestHeader.timeoutHint = 10000;
  321. UA_AnonymousIdentityToken identityToken;
  322. UA_AnonymousIdentityToken_init(&identityToken);
  323. UA_String_copy(&client->token.policyId, &identityToken.policyId);
  324. //manual ExtensionObject encoding of the identityToken
  325. request.userIdentityToken.encoding = UA_EXTENSIONOBJECT_ENCODINGMASK_BODYISBYTESTRING;
  326. request.userIdentityToken.typeId = UA_TYPES[UA_TYPES_ANONYMOUSIDENTITYTOKEN].typeId;
  327. request.userIdentityToken.typeId.identifier.numeric+=UA_ENCODINGOFFSET_BINARY;
  328. if (identityToken.policyId.length >= 0)
  329. UA_ByteString_newMembers(&request.userIdentityToken.body, identityToken.policyId.length+4);
  330. else {
  331. identityToken.policyId.length = -1;
  332. UA_ByteString_newMembers(&request.userIdentityToken.body, 4);
  333. }
  334. size_t offset = 0;
  335. UA_ByteString_encodeBinary(&identityToken.policyId,&request.userIdentityToken.body,&offset);
  336. UA_ActivateSessionResponse response;
  337. synchronousRequest(client, &request, &UA_TYPES[UA_TYPES_ACTIVATESESSIONREQUEST],
  338. &response, &UA_TYPES[UA_TYPES_ACTIVATESESSIONRESPONSE]);
  339. UA_AnonymousIdentityToken_deleteMembers(&identityToken);
  340. UA_ActivateSessionRequest_deleteMembers(&request);
  341. UA_ActivateSessionResponse_deleteMembers(&response);
  342. return response.responseHeader.serviceResult; // not deleted
  343. }
  344. static UA_StatusCode EndpointsHandshake(UA_Client *client) {
  345. UA_GetEndpointsRequest request;
  346. UA_GetEndpointsRequest_init(&request);
  347. UA_NodeId_copy(&client->authenticationToken, &request.requestHeader.authenticationToken);
  348. request.requestHeader.timestamp = UA_DateTime_now();
  349. request.requestHeader.timeoutHint = 10000;
  350. UA_String_copy(&client->endpointUrl, &request.endpointUrl);
  351. request.profileUrisSize = 1;
  352. request.profileUris = UA_Array_new(&UA_TYPES[UA_TYPES_STRING], request.profileUrisSize);
  353. *request.profileUris = UA_STRING_ALLOC("http://opcfoundation.org/UA-Profile/Transport/uatcp-uasc-uabinary");
  354. UA_GetEndpointsResponse response;
  355. UA_GetEndpointsResponse_init(&response);
  356. synchronousRequest(client, &request, &UA_TYPES[UA_TYPES_GETENDPOINTSREQUEST],
  357. &response, &UA_TYPES[UA_TYPES_GETENDPOINTSRESPONSE]);
  358. UA_Boolean endpointFound = UA_FALSE;
  359. UA_Boolean tokenFound = UA_FALSE;
  360. for(UA_Int32 i=0; i<response.endpointsSize; ++i){
  361. UA_EndpointDescription* endpoint = &response.endpoints[i];
  362. /* look out for an endpoint without security */
  363. if(!UA_String_equal(&endpoint->securityPolicyUri,
  364. &UA_STRING("http://opcfoundation.org/UA/SecurityPolicy#None")))
  365. continue;
  366. endpointFound = UA_TRUE;
  367. /* endpoint with no security found */
  368. /* look for a user token policy with an anonymous token */
  369. for(UA_Int32 j=0; j<endpoint->userIdentityTokensSize; ++j) {
  370. UA_UserTokenPolicy* userToken = &endpoint->userIdentityTokens[j];
  371. if(userToken->tokenType != UA_USERTOKENTYPE_ANONYMOUS)
  372. continue;
  373. tokenFound = UA_TRUE;
  374. UA_UserTokenPolicy_copy(userToken, &client->token);
  375. break;
  376. }
  377. }
  378. UA_GetEndpointsRequest_deleteMembers(&request);
  379. UA_GetEndpointsResponse_deleteMembers(&response);
  380. if(!endpointFound){
  381. UA_LOG_ERROR(client->logger, UA_LOGCATEGORY_CLIENT, "No suitable endpoint found");
  382. return UA_STATUSCODE_BADINTERNALERROR;
  383. }
  384. if(!tokenFound){
  385. UA_LOG_ERROR(client->logger, UA_LOGCATEGORY_CLIENT, "No anonymous token found");
  386. return UA_STATUSCODE_BADINTERNALERROR;
  387. }
  388. return response.responseHeader.serviceResult;
  389. }
  390. static UA_StatusCode SessionHandshake(UA_Client *client) {
  391. UA_CreateSessionRequest request;
  392. UA_CreateSessionRequest_init(&request);
  393. // todo: is this needed for all requests?
  394. UA_NodeId_copy(&client->authenticationToken, &request.requestHeader.authenticationToken);
  395. request.requestHeader.timestamp = UA_DateTime_now();
  396. request.requestHeader.timeoutHint = 10000;
  397. UA_ByteString_copy(&client->channel.clientNonce, &request.clientNonce);
  398. request.requestedSessionTimeout = 1200000;
  399. request.maxResponseMessageSize = UA_INT32_MAX;
  400. UA_CreateSessionResponse response;
  401. UA_CreateSessionResponse_init(&response);
  402. synchronousRequest(client, &request, &UA_TYPES[UA_TYPES_CREATESESSIONREQUEST],
  403. &response, &UA_TYPES[UA_TYPES_CREATESESSIONRESPONSE]);
  404. UA_NodeId_copy(&response.authenticationToken, &client->authenticationToken);
  405. UA_CreateSessionRequest_deleteMembers(&request);
  406. UA_CreateSessionResponse_deleteMembers(&response);
  407. return response.responseHeader.serviceResult; // not deleted
  408. }
  409. static UA_StatusCode CloseSession(UA_Client *client) {
  410. UA_CloseSessionRequest request;
  411. UA_CloseSessionRequest_init(&request);
  412. request.requestHeader.timestamp = UA_DateTime_now();
  413. request.requestHeader.timeoutHint = 10000;
  414. request.deleteSubscriptions = UA_TRUE;
  415. UA_NodeId_copy(&client->authenticationToken, &request.requestHeader.authenticationToken);
  416. UA_CloseSessionResponse response;
  417. synchronousRequest(client, &request, &UA_TYPES[UA_TYPES_CLOSESESSIONREQUEST],
  418. &response, &UA_TYPES[UA_TYPES_CLOSESESSIONRESPONSE]);
  419. UA_CloseSessionRequest_deleteMembers(&request);
  420. UA_CloseSessionResponse_deleteMembers(&response);
  421. return response.responseHeader.serviceResult; // not deleted
  422. }
  423. static UA_StatusCode CloseSecureChannel(UA_Client *client) {
  424. UA_SecureChannel *channel = &client->channel;
  425. UA_CloseSecureChannelRequest request;
  426. UA_CloseSecureChannelRequest_init(&request);
  427. request.requestHeader.requestHandle = 1; //TODO: magic number?
  428. request.requestHeader.timestamp = UA_DateTime_now();
  429. request.requestHeader.timeoutHint = 10000;
  430. request.requestHeader.authenticationToken = client->authenticationToken;
  431. UA_SecureConversationMessageHeader msgHeader;
  432. msgHeader.messageHeader.messageTypeAndFinal = UA_MESSAGETYPEANDFINAL_CLOF;
  433. msgHeader.secureChannelId = client->channel.securityToken.channelId;
  434. UA_SymmetricAlgorithmSecurityHeader symHeader;
  435. symHeader.tokenId = channel->securityToken.tokenId;
  436. UA_SequenceHeader seqHeader;
  437. seqHeader.sequenceNumber = ++channel->sequenceNumber;
  438. seqHeader.requestId = ++client->requestId;
  439. UA_NodeId typeId = UA_NODEID_NUMERIC(0, UA_NS0ID_CLOSESECURECHANNELREQUEST + UA_ENCODINGOFFSET_BINARY);
  440. UA_ByteString message;
  441. UA_Connection *c = &client->connection;
  442. UA_StatusCode retval = c->getSendBuffer(c, c->remoteConf.recvBufferSize, &message);
  443. if(retval != UA_STATUSCODE_GOOD)
  444. return retval;
  445. size_t offset = 12;
  446. retval |= UA_SymmetricAlgorithmSecurityHeader_encodeBinary(&symHeader, &message, &offset);
  447. retval |= UA_SequenceHeader_encodeBinary(&seqHeader, &message, &offset);
  448. retval |= UA_NodeId_encodeBinary(&typeId, &message, &offset);
  449. retval |= UA_encodeBinary(&request, &UA_TYPES[UA_TYPES_CLOSESECURECHANNELREQUEST], &message, &offset);
  450. msgHeader.messageHeader.messageSize = offset;
  451. offset = 0;
  452. retval |= UA_SecureConversationMessageHeader_encodeBinary(&msgHeader, &message, &offset);
  453. if(retval != UA_STATUSCODE_GOOD) {
  454. client->connection.releaseSendBuffer(&client->connection, &message);
  455. return retval;
  456. }
  457. message.length = msgHeader.messageHeader.messageSize;
  458. retval = client->connection.send(&client->connection, &message);
  459. return retval;
  460. }
  461. /*************************/
  462. /* User-Facing Functions */
  463. /*************************/
  464. UA_StatusCode UA_Client_connect(UA_Client *client, UA_ConnectClientConnection connectFunc, char *endpointUrl) {
  465. UA_StatusCode retval = UA_STATUSCODE_GOOD;
  466. /** make the function more convenient to the end-user **/
  467. if(client->state == UA_CLIENTSTATE_CONNECTED){
  468. UA_Client_disconnect(client);
  469. }
  470. if(client->state == UA_CLIENTSTATE_ERRORED){
  471. UA_Client_reset(client);
  472. }
  473. client->connection = connectFunc(UA_ConnectionConfig_standard, endpointUrl, client->logger);
  474. if(client->connection.state != UA_CONNECTION_OPENING){
  475. retval = UA_STATUSCODE_BADCONNECTIONCLOSED;
  476. goto cleanup;
  477. }
  478. client->endpointUrl = UA_STRING_ALLOC(endpointUrl);
  479. if(client->endpointUrl.length < 0){
  480. retval = UA_STATUSCODE_BADOUTOFMEMORY;
  481. goto cleanup;
  482. }
  483. client->connection.localConf = client->config.localConnectionConfig;
  484. retval = HelAckHandshake(client);
  485. if(retval == UA_STATUSCODE_GOOD)
  486. retval = SecureChannelHandshake(client, UA_FALSE);
  487. if(retval == UA_STATUSCODE_GOOD)
  488. retval = EndpointsHandshake(client);
  489. if(retval == UA_STATUSCODE_GOOD)
  490. retval = SessionHandshake(client);
  491. if(retval == UA_STATUSCODE_GOOD)
  492. retval = ActivateSession(client);
  493. if(retval == UA_STATUSCODE_GOOD){
  494. client->connection.state = UA_CONNECTION_ESTABLISHED;
  495. client->state = UA_CLIENTSTATE_CONNECTED;
  496. }else{
  497. goto cleanup;
  498. }
  499. return retval;
  500. cleanup:
  501. client->state = UA_CLIENTSTATE_ERRORED;
  502. UA_Client_reset(client);
  503. return retval;
  504. }
  505. UA_StatusCode UA_Client_disconnect(UA_Client *client) {
  506. UA_StatusCode retval = UA_STATUSCODE_GOOD;
  507. if(client->channel.connection->state == UA_CONNECTION_ESTABLISHED){
  508. retval = CloseSession(client);
  509. if(retval == UA_STATUSCODE_GOOD)
  510. retval = CloseSecureChannel(client);
  511. }
  512. UA_Client_reset(client);
  513. return retval;
  514. }
  515. UA_StatusCode UA_Client_renewSecureChannel(UA_Client *client) {
  516. return SecureChannelHandshake(client, UA_TRUE);
  517. }
  518. UA_ReadResponse UA_Client_read(UA_Client *client, UA_ReadRequest *request) {
  519. UA_ReadResponse response;
  520. synchronousRequest(client, request, &UA_TYPES[UA_TYPES_READREQUEST], &response,
  521. &UA_TYPES[UA_TYPES_READRESPONSE]);
  522. return response;
  523. }
  524. UA_WriteResponse UA_Client_write(UA_Client *client, UA_WriteRequest *request) {
  525. UA_WriteResponse response;
  526. synchronousRequest(client, request, &UA_TYPES[UA_TYPES_WRITEREQUEST], &response,
  527. &UA_TYPES[UA_TYPES_WRITERESPONSE]);
  528. return response;
  529. }
  530. UA_BrowseResponse UA_Client_browse(UA_Client *client, UA_BrowseRequest *request) {
  531. UA_BrowseResponse response;
  532. synchronousRequest(client, request, &UA_TYPES[UA_TYPES_BROWSEREQUEST], &response,
  533. &UA_TYPES[UA_TYPES_BROWSERESPONSE]);
  534. return response;
  535. }
  536. UA_StatusCode UA_Client_NamespaceGetIndex(UA_Client *client, UA_String *namespaceUri, UA_UInt16 *namespaceIndex){
  537. UA_ReadRequest ReadRequest;
  538. UA_ReadResponse ReadResponse;
  539. UA_StatusCode retval = UA_STATUSCODE_BADUNEXPECTEDERROR;
  540. UA_ReadRequest_init(&ReadRequest);
  541. ReadRequest.nodesToRead = UA_ReadValueId_new();
  542. ReadRequest.nodesToReadSize = 1;
  543. ReadRequest.nodesToRead[0].attributeId = UA_ATTRIBUTEID_VALUE;
  544. ReadRequest.nodesToRead[0].nodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_NAMESPACEARRAY);
  545. ReadResponse = UA_Client_read(client, &ReadRequest);
  546. UA_ReadRequest_deleteMembers(&ReadRequest);
  547. if(ReadResponse.responseHeader.serviceResult != UA_STATUSCODE_GOOD){
  548. retval = ReadResponse.responseHeader.serviceResult;
  549. goto cleanup;
  550. }
  551. if(ReadResponse.resultsSize != 1 || !ReadResponse.results[0].hasValue){
  552. retval = UA_STATUSCODE_BADNODEATTRIBUTESINVALID;
  553. goto cleanup;
  554. }
  555. if(ReadResponse.results[0].value.type != &UA_TYPES[UA_TYPES_STRING]){
  556. retval = UA_STATUSCODE_BADTYPEMISMATCH;
  557. goto cleanup;
  558. }
  559. retval = UA_STATUSCODE_BADNOTFOUND;
  560. for(UA_UInt16 iterator = 0; iterator < ReadResponse.results[0].value.arrayLength; iterator++){
  561. if(UA_String_equal(namespaceUri, &((UA_String*)ReadResponse.results[0].value.data)[iterator] )){
  562. *namespaceIndex = iterator;
  563. retval = UA_STATUSCODE_GOOD;
  564. break;
  565. }
  566. }
  567. cleanup:
  568. UA_ReadResponse_deleteMembers(&ReadResponse);
  569. return retval;
  570. }
  571. UA_BrowseNextResponse UA_Client_browseNext(UA_Client *client, UA_BrowseNextRequest *request) {
  572. UA_BrowseNextResponse response;
  573. synchronousRequest(client, request, &UA_TYPES[UA_TYPES_BROWSENEXTREQUEST], &response,
  574. &UA_TYPES[UA_TYPES_BROWSENEXTRESPONSE]);
  575. return response;
  576. }
  577. UA_TranslateBrowsePathsToNodeIdsResponse
  578. UA_Client_translateTranslateBrowsePathsToNodeIds(UA_Client *client,
  579. UA_TranslateBrowsePathsToNodeIdsRequest *request) {
  580. UA_TranslateBrowsePathsToNodeIdsResponse response;
  581. synchronousRequest(client, request, &UA_TYPES[UA_TYPES_TRANSLATEBROWSEPATHSTONODEIDSREQUEST],
  582. &response, &UA_TYPES[UA_TYPES_TRANSLATEBROWSEPATHSTONODEIDSRESPONSE]);
  583. return response;
  584. }
  585. UA_AddNodesResponse UA_Client_addNodes(UA_Client *client, UA_AddNodesRequest *request) {
  586. UA_AddNodesResponse response;
  587. synchronousRequest(client, request, &UA_TYPES[UA_TYPES_ADDNODESREQUEST],
  588. &response, &UA_TYPES[UA_TYPES_ADDNODESRESPONSE]);
  589. return response;
  590. }
  591. UA_AddReferencesResponse UA_Client_addReferences(UA_Client *client, UA_AddReferencesRequest *request) {
  592. UA_AddReferencesResponse response;
  593. synchronousRequest(client, request, &UA_TYPES[UA_TYPES_ADDREFERENCESREQUEST],
  594. &response, &UA_TYPES[UA_TYPES_ADDREFERENCESRESPONSE]);
  595. return response;
  596. }
  597. UA_DeleteNodesResponse UA_Client_deleteNodes(UA_Client *client, UA_DeleteNodesRequest *request) {
  598. UA_DeleteNodesResponse response;
  599. synchronousRequest(client, request, &UA_TYPES[UA_TYPES_DELETENODESREQUEST],
  600. &response, &UA_TYPES[UA_TYPES_DELETENODESRESPONSE]);
  601. return response;
  602. }
  603. UA_DeleteReferencesResponse UA_Client_deleteReferences(UA_Client *client, UA_DeleteReferencesRequest *request) {
  604. UA_DeleteReferencesResponse response;
  605. synchronousRequest(client, request, &UA_TYPES[UA_TYPES_DELETEREFERENCESREQUEST],
  606. &response, &UA_TYPES[UA_TYPES_DELETEREFERENCESRESPONSE]);
  607. return response;
  608. }
  609. #ifdef ENABLE_SUBSCRIPTIONS
  610. UA_CreateSubscriptionResponse UA_Client_createSubscription(UA_Client *client, UA_CreateSubscriptionRequest *request) {
  611. UA_CreateSubscriptionResponse response;
  612. synchronousRequest(client, request, &UA_TYPES[UA_TYPES_CREATESUBSCRIPTIONREQUEST],
  613. &response, &UA_TYPES[UA_TYPES_CREATESUBSCRIPTIONRESPONSE]);
  614. return response;
  615. }
  616. UA_DeleteSubscriptionsResponse UA_Client_deleteSubscriptions(UA_Client *client, UA_DeleteSubscriptionsRequest *request) {
  617. UA_DeleteSubscriptionsResponse response;
  618. synchronousRequest(client, request, &UA_TYPES[UA_TYPES_DELETESUBSCRIPTIONSREQUEST],
  619. &response, &UA_TYPES[UA_TYPES_DELETESUBSCRIPTIONSRESPONSE]);
  620. return response;
  621. }
  622. UA_ModifySubscriptionResponse UA_Client_modifySubscription(UA_Client *client, UA_ModifySubscriptionRequest *request) {
  623. UA_ModifySubscriptionResponse response;
  624. synchronousRequest(client, request, &UA_TYPES[UA_TYPES_MODIFYSUBSCRIPTIONREQUEST],
  625. &response, &UA_TYPES[UA_TYPES_MODIFYSUBSCRIPTIONRESPONSE]);
  626. return response;
  627. }
  628. UA_CreateMonitoredItemsResponse UA_Client_createMonitoredItems(UA_Client *client, UA_CreateMonitoredItemsRequest *request) {
  629. UA_CreateMonitoredItemsResponse response;
  630. synchronousRequest(client, request, &UA_TYPES[UA_TYPES_CREATEMONITOREDITEMSREQUEST],
  631. &response, &UA_TYPES[UA_TYPES_CREATEMONITOREDITEMSRESPONSE]);
  632. return response;
  633. }
  634. UA_DeleteMonitoredItemsResponse UA_Client_deleteMonitoredItems(UA_Client *client, UA_DeleteMonitoredItemsRequest *request) {
  635. UA_DeleteMonitoredItemsResponse response;
  636. synchronousRequest(client, request, &UA_TYPES[UA_TYPES_DELETEMONITOREDITEMSREQUEST],
  637. &response, &UA_TYPES[UA_TYPES_DELETEMONITOREDITEMSRESPONSE]);
  638. return response;
  639. }
  640. UA_PublishResponse UA_Client_publish(UA_Client *client, UA_PublishRequest *request) {
  641. UA_PublishResponse response;
  642. synchronousRequest(client, request, &UA_TYPES[UA_TYPES_PUBLISHREQUEST],
  643. &response, &UA_TYPES[UA_TYPES_PUBLISHRESPONSE]);
  644. return response;
  645. }
  646. UA_Int32 UA_Client_newSubscription(UA_Client *client, UA_Int32 publishInterval) {
  647. UA_Int32 retval;
  648. UA_CreateSubscriptionRequest aReq;
  649. UA_CreateSubscriptionResponse aRes;
  650. UA_CreateSubscriptionRequest_init(&aReq);
  651. UA_CreateSubscriptionResponse_init(&aRes);
  652. aReq.maxNotificationsPerPublish = 10;
  653. aReq.priority = 0;
  654. aReq.publishingEnabled = UA_TRUE;
  655. aReq.requestedLifetimeCount = 100;
  656. aReq.requestedMaxKeepAliveCount = 10;
  657. aReq.requestedPublishingInterval = publishInterval;
  658. aRes = UA_Client_createSubscription(client, &aReq);
  659. if (aRes.responseHeader.serviceResult == UA_STATUSCODE_GOOD) {
  660. UA_Client_Subscription *newSub = UA_malloc(sizeof(UA_Client_Subscription));
  661. LIST_INIT(&newSub->MonitoredItems);
  662. newSub->LifeTime = aRes.revisedLifetimeCount;
  663. newSub->KeepAliveCount = aRes.revisedMaxKeepAliveCount;
  664. newSub->PublishingInterval = aRes.revisedPublishingInterval;
  665. newSub->SubscriptionID = aRes.subscriptionId;
  666. newSub->NotificationsPerPublish = aReq.maxNotificationsPerPublish;
  667. newSub->Priority = aReq.priority;
  668. retval = newSub->SubscriptionID;
  669. LIST_INSERT_HEAD(&(client->subscriptions), newSub, listEntry);
  670. } else
  671. retval = 0;
  672. UA_CreateSubscriptionResponse_deleteMembers(&aRes);
  673. UA_CreateSubscriptionRequest_deleteMembers(&aReq);
  674. return retval;
  675. }
  676. UA_StatusCode UA_Client_removeSubscription(UA_Client *client, UA_UInt32 subscriptionId) {
  677. UA_Client_Subscription *sub;
  678. UA_StatusCode retval = UA_STATUSCODE_GOOD;
  679. LIST_FOREACH(sub, &(client->subscriptions), listEntry) {
  680. if (sub->SubscriptionID == subscriptionId)
  681. break;
  682. }
  683. // Problem? We do not have this subscription registeres. Maybe the server should
  684. // be consulted at this point?
  685. if (sub == NULL)
  686. return UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID;
  687. UA_DeleteSubscriptionsRequest request;
  688. UA_DeleteSubscriptionsResponse response;
  689. UA_DeleteSubscriptionsRequest_init(&request);
  690. UA_DeleteSubscriptionsResponse_init(&response);
  691. request.subscriptionIdsSize=1;
  692. request.subscriptionIds = (UA_UInt32 *) UA_malloc(sizeof(UA_UInt32));
  693. *(request.subscriptionIds) = sub->SubscriptionID;
  694. UA_Client_MonitoredItem *mon, *tmpmon;
  695. LIST_FOREACH_SAFE(mon, &(sub->MonitoredItems), listEntry, tmpmon) {
  696. retval |= UA_Client_unMonitorItemChanges(client, sub->SubscriptionID, mon->MonitoredItemId);
  697. }
  698. if (retval != UA_STATUSCODE_GOOD){
  699. UA_DeleteSubscriptionsRequest_deleteMembers(&request);
  700. return retval;
  701. }
  702. response = UA_Client_deleteSubscriptions(client, &request);
  703. if (response.resultsSize > 0)
  704. retval = response.results[0];
  705. else
  706. retval = response.responseHeader.serviceResult;
  707. if (retval == UA_STATUSCODE_GOOD) {
  708. LIST_REMOVE(sub, listEntry);
  709. UA_free(sub);
  710. }
  711. UA_DeleteSubscriptionsRequest_deleteMembers(&request);
  712. UA_DeleteSubscriptionsResponse_deleteMembers(&response);
  713. return retval;
  714. }
  715. UA_UInt32 UA_Client_monitorItemChanges(UA_Client *client, UA_UInt32 subscriptionId,
  716. UA_NodeId nodeId, UA_UInt32 attributeID, void *handlingFunction) {
  717. UA_Client_Subscription *sub;
  718. UA_StatusCode retval = 0;
  719. LIST_FOREACH(sub, &(client->subscriptions), listEntry) {
  720. if (sub->SubscriptionID == subscriptionId)
  721. break;
  722. }
  723. // Maybe the same problem as in DeleteSubscription... ask the server?
  724. if (sub == NULL)
  725. return UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID;
  726. UA_CreateMonitoredItemsRequest request;
  727. UA_CreateMonitoredItemsResponse response;
  728. UA_CreateMonitoredItemsRequest_init(&request);
  729. UA_CreateMonitoredItemsResponse_init(&response);
  730. request.subscriptionId = subscriptionId;
  731. request.itemsToCreateSize = 1;
  732. request.itemsToCreate = UA_MonitoredItemCreateRequest_new();
  733. UA_NodeId_copy(&nodeId, &((request.itemsToCreate[0]).itemToMonitor.nodeId));
  734. (request.itemsToCreate[0]).itemToMonitor.attributeId = attributeID;
  735. (request.itemsToCreate[0]).monitoringMode = UA_MONITORINGMODE_REPORTING;
  736. (request.itemsToCreate[0]).requestedParameters.clientHandle = ++(client->monitoredItemHandles);
  737. (request.itemsToCreate[0]).requestedParameters.samplingInterval = sub->PublishingInterval;
  738. (request.itemsToCreate[0]).requestedParameters.discardOldest = UA_TRUE;
  739. (request.itemsToCreate[0]).requestedParameters.queueSize = 1;
  740. // Filter can be left void for now, only changes are supported (UA_Expert does the same with changeItems)
  741. response = UA_Client_createMonitoredItems(client, &request);
  742. // slight misuse of retval here to check if the deletion was successfull.
  743. if (response.resultsSize == 0)
  744. retval = response.responseHeader.serviceResult;
  745. else
  746. retval = response.results[0].statusCode;
  747. if (retval == UA_STATUSCODE_GOOD) {
  748. UA_Client_MonitoredItem *newMon = (UA_Client_MonitoredItem *) UA_malloc(sizeof(UA_Client_MonitoredItem));
  749. newMon->MonitoringMode = UA_MONITORINGMODE_REPORTING;
  750. UA_NodeId_copy(&nodeId, &(newMon->monitoredNodeId));
  751. newMon->AttributeID = attributeID;
  752. newMon->ClientHandle = client->monitoredItemHandles;
  753. newMon->SamplingInterval = sub->PublishingInterval;
  754. newMon->QueueSize = 1;
  755. newMon->DiscardOldest = UA_TRUE;
  756. newMon->handler = handlingFunction;
  757. newMon->MonitoredItemId = response.results[0].monitoredItemId;
  758. LIST_INSERT_HEAD(&(sub->MonitoredItems), newMon, listEntry);
  759. retval = newMon->MonitoredItemId ;
  760. }
  761. else {
  762. retval = 0;
  763. }
  764. UA_CreateMonitoredItemsRequest_deleteMembers(&request);
  765. UA_CreateMonitoredItemsResponse_deleteMembers(&response);
  766. return retval;
  767. }
  768. UA_StatusCode UA_Client_unMonitorItemChanges(UA_Client *client, UA_UInt32 subscriptionId, UA_UInt32 monitoredItemId ) {
  769. UA_Client_Subscription *sub;
  770. UA_StatusCode retval = 0;
  771. LIST_FOREACH(sub, &(client->subscriptions), listEntry) {
  772. if (sub->SubscriptionID == subscriptionId)
  773. break;
  774. }
  775. // Maybe the same problem as in DeleteSubscription... ask the server?
  776. if (sub == NULL)
  777. return UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID;
  778. UA_Client_MonitoredItem *mon, *tmpmon;
  779. LIST_FOREACH_SAFE(mon, &(sub->MonitoredItems), listEntry, tmpmon) {
  780. if (mon->MonitoredItemId == monitoredItemId)
  781. break;
  782. }
  783. // Also... ask the server?
  784. if(mon==NULL) {
  785. return UA_STATUSCODE_BADMONITOREDITEMIDINVALID;
  786. }
  787. UA_DeleteMonitoredItemsRequest request;
  788. UA_DeleteMonitoredItemsResponse response;
  789. UA_DeleteMonitoredItemsRequest_init(&request);
  790. UA_DeleteMonitoredItemsResponse_init(&response);
  791. request.subscriptionId = sub->SubscriptionID;
  792. request.monitoredItemIdsSize = 1;
  793. request.monitoredItemIds = (UA_UInt32 *) UA_malloc(sizeof(UA_UInt32));
  794. request.monitoredItemIds[0] = mon->MonitoredItemId;
  795. response = UA_Client_deleteMonitoredItems(client, &request);
  796. if (response.resultsSize > 1)
  797. retval = response.results[0];
  798. else
  799. retval = response.responseHeader.serviceResult;
  800. if (retval == 0) {
  801. LIST_REMOVE(mon, listEntry);
  802. UA_NodeId_deleteMembers(&mon->monitoredNodeId);
  803. UA_free(mon);
  804. }
  805. UA_DeleteMonitoredItemsRequest_deleteMembers(&request);
  806. UA_DeleteMonitoredItemsResponse_deleteMembers(&response);
  807. return retval;
  808. }
  809. UA_Boolean UA_Client_processPublishRx(UA_Client *client, UA_PublishResponse response) {
  810. UA_Client_Subscription *sub;
  811. UA_Client_MonitoredItem *mon;
  812. UA_StatusCode retval = UA_STATUSCODE_GOOD;
  813. if(response.responseHeader.serviceResult != UA_STATUSCODE_GOOD)
  814. return UA_FALSE;
  815. // Check if the server has acknowledged any of our ACKS
  816. // Note that a list of serverside status codes may be send without valid publish data, i.e.
  817. // during keepalives or no data availability
  818. UA_Client_NotificationsAckNumber *tmpAck = client->pendingNotificationsAcks.lh_first;
  819. UA_Client_NotificationsAckNumber *nxtAck = tmpAck;
  820. for(int i=0; i<response.resultsSize && nxtAck != NULL; i++) {
  821. tmpAck = nxtAck;
  822. nxtAck = tmpAck->listEntry.le_next;
  823. if (response.results[i] == UA_STATUSCODE_GOOD || response.results[i] == UA_STATUSCODE_BADSEQUENCENUMBERINVALID) {
  824. LIST_REMOVE(tmpAck, listEntry);
  825. UA_free(tmpAck);
  826. }
  827. }
  828. if(response.subscriptionId == 0)
  829. return UA_FALSE;
  830. LIST_FOREACH(sub, &(client->subscriptions), listEntry) {
  831. if (sub->SubscriptionID == response.subscriptionId)
  832. break;
  833. }
  834. if (sub == NULL)
  835. return UA_FALSE;
  836. UA_NotificationMessage msg = response.notificationMessage;
  837. UA_DataChangeNotification dataChangeNotification;
  838. size_t decodingOffset = 0;
  839. for (int k=0; k<msg.notificationDataSize; k++) {
  840. if (msg.notificationData[k].encoding == UA_EXTENSIONOBJECT_ENCODINGMASK_BODYISBYTESTRING) {
  841. if (msg.notificationData[k].typeId.namespaceIndex == 0 && msg.notificationData[k].typeId.identifier.numeric == 811 ) {
  842. // This is a dataChangeNotification
  843. retval |= UA_DataChangeNotification_decodeBinary(&(msg.notificationData[k].body), &decodingOffset, &dataChangeNotification);
  844. UA_MonitoredItemNotification *mitemNot;
  845. for(int i=0; i<dataChangeNotification.monitoredItemsSize; i++) {
  846. mitemNot = &dataChangeNotification.monitoredItems[i];
  847. // find this client handle
  848. LIST_FOREACH(mon, &(sub->MonitoredItems), listEntry) {
  849. if (mon->ClientHandle == mitemNot->clientHandle) {
  850. mon->handler(mitemNot->clientHandle, &(mitemNot->value));
  851. break;
  852. }
  853. }
  854. }
  855. UA_DataChangeNotification_deleteMembers(&dataChangeNotification);
  856. }
  857. else if (msg.notificationData[k].typeId.namespaceIndex == 0 && msg.notificationData[k].typeId.identifier.numeric == 820 ) {
  858. //FIXME: This is a statusChangeNotification (not supported yet)
  859. continue;
  860. }
  861. else if (msg.notificationData[k].typeId.namespaceIndex == 0 && msg.notificationData[k].typeId.identifier.numeric == 916 ) {
  862. //FIXME: This is an EventNotification
  863. continue;
  864. }
  865. }
  866. }
  867. // We processed this message, add it to the list of pending acks (but make sure it's not in the list first)
  868. LIST_FOREACH(tmpAck, &(client->pendingNotificationsAcks), listEntry) {
  869. if (tmpAck->subAck.sequenceNumber == msg.sequenceNumber &&
  870. tmpAck->subAck.subscriptionId == response.subscriptionId)
  871. break;
  872. }
  873. if (tmpAck == NULL ){
  874. tmpAck = (UA_Client_NotificationsAckNumber *) UA_malloc(sizeof(UA_Client_NotificationsAckNumber));
  875. tmpAck->subAck.sequenceNumber = msg.sequenceNumber;
  876. tmpAck->subAck.subscriptionId = sub->SubscriptionID;
  877. tmpAck->listEntry.le_next = UA_NULL;
  878. tmpAck->listEntry.le_prev = UA_NULL;
  879. LIST_INSERT_HEAD(&(client->pendingNotificationsAcks), tmpAck, listEntry);
  880. }
  881. return response.moreNotifications;
  882. }
  883. void UA_Client_doPublish(UA_Client *client) {
  884. UA_PublishRequest request;
  885. UA_PublishResponse response;
  886. UA_Client_NotificationsAckNumber *ack;
  887. UA_Boolean moreNotifications = UA_TRUE;
  888. int index = 0 ;
  889. do {
  890. UA_PublishRequest_init(&request);
  891. UA_PublishResponse_init(&response);
  892. request.subscriptionAcknowledgementsSize = 0;
  893. LIST_FOREACH(ack, &(client->pendingNotificationsAcks), listEntry) {
  894. request.subscriptionAcknowledgementsSize++;
  895. }
  896. request.subscriptionAcknowledgements = (UA_SubscriptionAcknowledgement *) UA_malloc(sizeof(UA_SubscriptionAcknowledgement)*request.subscriptionAcknowledgementsSize);
  897. index = 0;
  898. LIST_FOREACH(ack, &(client->pendingNotificationsAcks), listEntry) {
  899. request.subscriptionAcknowledgements[index].sequenceNumber = ack->subAck.sequenceNumber;
  900. request.subscriptionAcknowledgements[index].subscriptionId = ack->subAck.subscriptionId;
  901. index++;
  902. }
  903. response = UA_Client_publish(client, &request);
  904. if (response.responseHeader.serviceResult == UA_STATUSCODE_GOOD)
  905. moreNotifications = UA_Client_processPublishRx(client, response);
  906. else
  907. moreNotifications = UA_FALSE;
  908. UA_PublishResponse_deleteMembers(&response);
  909. UA_PublishRequest_deleteMembers(&request);
  910. } while(moreNotifications == UA_TRUE);
  911. return;
  912. }
  913. #endif
  914. /**********************************/
  915. /* User-Facing Macros-Function */
  916. /**********************************/
  917. #ifdef ENABLE_METHODCALLS
  918. UA_CallResponse UA_Client_call(UA_Client *client, UA_CallRequest *request) {
  919. UA_CallResponse response;
  920. synchronousRequest(client, request, &UA_TYPES[UA_TYPES_CALLREQUEST],
  921. &response, &UA_TYPES[UA_TYPES_CALLRESPONSE]);
  922. return response;
  923. }
  924. UA_StatusCode UA_Client_CallServerMethod(UA_Client *client, UA_NodeId objectNodeId, UA_NodeId methodNodeId,
  925. UA_Int32 inputSize, const UA_Variant *input,
  926. UA_Int32 *outputSize, UA_Variant **output) {
  927. UA_CallRequest request;
  928. UA_CallRequest_init(&request);
  929. request.methodsToCallSize = 1;
  930. request.methodsToCall = UA_CallMethodRequest_new();
  931. if(!request.methodsToCall)
  932. return UA_STATUSCODE_BADOUTOFMEMORY;
  933. UA_CallMethodRequest *rq = &request.methodsToCall[0];
  934. UA_NodeId_copy(&methodNodeId, &rq->methodId);
  935. UA_NodeId_copy(&objectNodeId, &rq->objectId);
  936. rq->inputArguments = (void*)(uintptr_t)input; // cast const...
  937. rq->inputArgumentsSize = inputSize;
  938. UA_CallResponse response;
  939. response = UA_Client_call(client, &request);
  940. rq->inputArguments = UA_NULL;
  941. rq->inputArgumentsSize = -1;
  942. UA_CallRequest_deleteMembers(&request);
  943. UA_StatusCode retval = response.responseHeader.serviceResult;
  944. if(response.resultsSize > 0){
  945. retval |= response.results[0].statusCode;
  946. if(retval == UA_STATUSCODE_GOOD) {
  947. *output = response.results[0].outputArguments;
  948. *outputSize = response.results[0].outputArgumentsSize;
  949. response.results[0].outputArguments = UA_NULL;
  950. response.results[0].outputArgumentsSize = -1;
  951. }
  952. }
  953. UA_CallResponse_deleteMembers(&response);
  954. return retval;
  955. }
  956. #endif
  957. #define ADDNODES_COPYDEFAULTATTRIBUTES(REQUEST,ATTRIBUTES) do { \
  958. ATTRIBUTES.specifiedAttributes = 0; \
  959. if(! UA_LocalizedText_copy(&description, &(ATTRIBUTES.description))) \
  960. ATTRIBUTES.specifiedAttributes |= UA_NODEATTRIBUTESMASK_DESCRIPTION; \
  961. if(! UA_LocalizedText_copy(&displayName, &(ATTRIBUTES.displayName))) \
  962. ATTRIBUTES.specifiedAttributes |= UA_NODEATTRIBUTESMASK_DISPLAYNAME; \
  963. ATTRIBUTES.userWriteMask = userWriteMask; \
  964. ATTRIBUTES.specifiedAttributes |= UA_NODEATTRIBUTESMASK_USERWRITEMASK; \
  965. ATTRIBUTES.writeMask = writeMask; \
  966. ATTRIBUTES.specifiedAttributes |= UA_NODEATTRIBUTESMASK_WRITEMASK; \
  967. UA_QualifiedName_copy(&browseName, &(REQUEST.nodesToAdd[0].browseName)); \
  968. UA_ExpandedNodeId_copy(&parentNodeId, &(REQUEST.nodesToAdd[0].parentNodeId)); \
  969. UA_NodeId_copy(&referenceTypeId, &(REQUEST.nodesToAdd[0].referenceTypeId)); \
  970. UA_ExpandedNodeId_copy(&typeDefinition, &(REQUEST.nodesToAdd[0].typeDefinition)); \
  971. UA_ExpandedNodeId_copy(&reqId, &(REQUEST.nodesToAdd[0].requestedNewNodeId )); \
  972. REQUEST.nodesToAddSize = 1; \
  973. } while(0)
  974. #define ADDNODES_PACK_AND_SEND(PREQUEST,PATTRIBUTES,PNODETYPE) do { \
  975. PREQUEST.nodesToAdd[0].nodeAttributes.encoding = UA_EXTENSIONOBJECT_ENCODINGMASK_BODYISBYTESTRING; \
  976. PREQUEST.nodesToAdd[0].nodeAttributes.typeId = UA_NODEID_NUMERIC(0, UA_NS0ID_##PNODETYPE##ATTRIBUTES + UA_ENCODINGOFFSET_BINARY); \
  977. size_t encOffset = 0; \
  978. UA_ByteString_newMembers(&PREQUEST.nodesToAdd[0].nodeAttributes.body, client->connection.remoteConf.maxMessageSize); \
  979. UA_encodeBinary(&PATTRIBUTES,&UA_TYPES[UA_TYPES_##PNODETYPE##ATTRIBUTES], &(PREQUEST.nodesToAdd[0].nodeAttributes.body), &encOffset); \
  980. PREQUEST.nodesToAdd[0].nodeAttributes.body.length = encOffset; \
  981. *(adRes) = UA_Client_addNodes(client, &PREQUEST); \
  982. UA_AddNodesRequest_deleteMembers(&PREQUEST); \
  983. } while(0)
  984. /* NodeManagement */
  985. UA_AddNodesResponse *UA_Client_createObjectNode(UA_Client *client, UA_ExpandedNodeId reqId, UA_QualifiedName browseName, UA_LocalizedText displayName,
  986. UA_LocalizedText description, UA_ExpandedNodeId parentNodeId, UA_NodeId referenceTypeId,
  987. UA_UInt32 userWriteMask, UA_UInt32 writeMask, UA_ExpandedNodeId typeDefinition ) {
  988. UA_AddNodesRequest adReq;
  989. UA_AddNodesRequest_init(&adReq);
  990. UA_AddNodesResponse *adRes;
  991. adRes = UA_AddNodesResponse_new();
  992. UA_AddNodesResponse_init(adRes);
  993. UA_ObjectAttributes vAtt;
  994. UA_ObjectAttributes_init(&vAtt);
  995. adReq.nodesToAdd = (UA_AddNodesItem *) UA_AddNodesItem_new();
  996. UA_AddNodesItem_init(adReq.nodesToAdd);
  997. // Default node properties and attributes
  998. ADDNODES_COPYDEFAULTATTRIBUTES(adReq, vAtt);
  999. // Specific to objects
  1000. adReq.nodesToAdd[0].nodeClass = UA_NODECLASS_OBJECT;
  1001. vAtt.eventNotifier = 0;
  1002. vAtt.specifiedAttributes |= UA_NODEATTRIBUTESMASK_EVENTNOTIFIER;
  1003. ADDNODES_PACK_AND_SEND(adReq,vAtt,OBJECT);
  1004. return adRes;
  1005. }
  1006. UA_AddNodesResponse *UA_Client_createVariableNode(UA_Client *client, UA_ExpandedNodeId reqId, UA_QualifiedName browseName, UA_LocalizedText displayName,
  1007. UA_LocalizedText description, UA_ExpandedNodeId parentNodeId, UA_NodeId referenceTypeId,
  1008. UA_UInt32 userWriteMask, UA_UInt32 writeMask, UA_ExpandedNodeId typeDefinition,
  1009. UA_NodeId dataType, UA_Variant *value) {
  1010. UA_AddNodesRequest adReq;
  1011. UA_AddNodesRequest_init(&adReq);
  1012. UA_AddNodesResponse *adRes;
  1013. adRes = UA_AddNodesResponse_new();
  1014. UA_AddNodesResponse_init(adRes);
  1015. UA_VariableAttributes vAtt;
  1016. UA_VariableAttributes_init(&vAtt);
  1017. adReq.nodesToAdd = (UA_AddNodesItem *) UA_AddNodesItem_new();
  1018. UA_AddNodesItem_init(adReq.nodesToAdd);
  1019. // Default node properties and attributes
  1020. ADDNODES_COPYDEFAULTATTRIBUTES(adReq, vAtt);
  1021. // Specific to variables
  1022. adReq.nodesToAdd[0].nodeClass = UA_NODECLASS_VARIABLE;
  1023. vAtt.accessLevel = 0;
  1024. vAtt.specifiedAttributes |= UA_NODEATTRIBUTESMASK_ACCESSLEVEL;
  1025. vAtt.userAccessLevel = 0;
  1026. vAtt.specifiedAttributes |= UA_NODEATTRIBUTESMASK_USERACCESSLEVEL;
  1027. vAtt.minimumSamplingInterval = 100;
  1028. vAtt.specifiedAttributes |= UA_NODEATTRIBUTESMASK_MINIMUMSAMPLINGINTERVAL;
  1029. vAtt.historizing = UA_FALSE;
  1030. vAtt.specifiedAttributes |= UA_NODEATTRIBUTESMASK_HISTORIZING;
  1031. if (value != NULL) {
  1032. UA_Variant_copy(value, &(vAtt.value));
  1033. vAtt.specifiedAttributes |= UA_NODEATTRIBUTESMASK_VALUE;
  1034. vAtt.valueRank = -2;
  1035. vAtt.specifiedAttributes |= UA_NODEATTRIBUTESMASK_VALUERANK;
  1036. // These are defined by the variant
  1037. //vAtt.arrayDimensionsSize = value->arrayDimensionsSize;
  1038. //vAtt.arrayDimensions = NULL;
  1039. }
  1040. UA_NodeId_copy(&dataType, &(vAtt.dataType));
  1041. ADDNODES_PACK_AND_SEND(adReq,vAtt,VARIABLE);
  1042. return adRes;
  1043. }
  1044. UA_AddNodesResponse *UA_Client_createReferenceTypeNode(UA_Client *client, UA_ExpandedNodeId reqId, UA_QualifiedName browseName, UA_LocalizedText displayName,
  1045. UA_LocalizedText description, UA_ExpandedNodeId parentNodeId, UA_NodeId referenceTypeId,
  1046. UA_UInt32 userWriteMask, UA_UInt32 writeMask, UA_ExpandedNodeId typeDefinition,
  1047. UA_LocalizedText inverseName ) {
  1048. UA_AddNodesRequest adReq;
  1049. UA_AddNodesRequest_init(&adReq);
  1050. UA_AddNodesResponse *adRes;
  1051. adRes = UA_AddNodesResponse_new();
  1052. UA_AddNodesResponse_init(adRes);
  1053. UA_ReferenceTypeAttributes vAtt;
  1054. UA_ReferenceTypeAttributes_init(&vAtt);
  1055. adReq.nodesToAdd = (UA_AddNodesItem *) UA_AddNodesItem_new();
  1056. UA_AddNodesItem_init(adReq.nodesToAdd);
  1057. // Default node properties and attributes
  1058. ADDNODES_COPYDEFAULTATTRIBUTES(adReq, vAtt);
  1059. // Specific to referencetypes
  1060. adReq.nodesToAdd[0].nodeClass = UA_NODECLASS_REFERENCETYPE;
  1061. UA_LocalizedText_copy(&inverseName, &(vAtt.inverseName));
  1062. vAtt.specifiedAttributes |= UA_NODEATTRIBUTESMASK_INVERSENAME;
  1063. vAtt.symmetric = UA_FALSE;
  1064. vAtt.specifiedAttributes |= UA_NODEATTRIBUTESMASK_SYMMETRIC;
  1065. vAtt.isAbstract = UA_FALSE;
  1066. vAtt.specifiedAttributes |= UA_NODEATTRIBUTESMASK_ISABSTRACT;
  1067. ADDNODES_PACK_AND_SEND(adReq,vAtt,REFERENCETYPE);
  1068. return adRes;
  1069. }
  1070. UA_AddNodesResponse *UA_Client_createObjectTypeNode(UA_Client *client, UA_ExpandedNodeId reqId, UA_QualifiedName browseName, UA_LocalizedText displayName,
  1071. UA_LocalizedText description, UA_ExpandedNodeId parentNodeId, UA_NodeId referenceTypeId,
  1072. UA_UInt32 userWriteMask, UA_UInt32 writeMask, UA_ExpandedNodeId typeDefinition) {
  1073. UA_AddNodesRequest adReq;
  1074. UA_AddNodesRequest_init(&adReq);
  1075. UA_AddNodesResponse *adRes;
  1076. adRes = UA_AddNodesResponse_new();
  1077. UA_AddNodesResponse_init(adRes);
  1078. UA_ObjectTypeAttributes vAtt;
  1079. UA_ObjectTypeAttributes_init(&vAtt);
  1080. adReq.nodesToAdd = (UA_AddNodesItem *) UA_AddNodesItem_new();
  1081. UA_AddNodesItem_init(adReq.nodesToAdd);
  1082. // Default node properties and attributes
  1083. ADDNODES_COPYDEFAULTATTRIBUTES(adReq, vAtt);
  1084. // Specific to referencetypes
  1085. adReq.nodesToAdd[0].nodeClass = UA_NODECLASS_OBJECTTYPE;
  1086. vAtt.isAbstract = UA_FALSE;
  1087. vAtt.specifiedAttributes |= UA_NODEATTRIBUTESMASK_ISABSTRACT;
  1088. ADDNODES_PACK_AND_SEND(adReq,vAtt,OBJECTTYPE);
  1089. return adRes;
  1090. }