ua_client.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603
  1. #include "ua_util.h"
  2. #include "ua_client.h"
  3. #include "ua_client_internal.h"
  4. #include "ua_types_generated.h"
  5. #include "ua_nodeids.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. const UA_EXPORT UA_ClientConfig UA_ClientConfig_standard =
  11. { .timeout = 500 /* ms receive timout */, .secureChannelLifeTime = 30000,
  12. .timeToRenewSecureChannel = 2000,
  13. {.protocolVersion = 0, .sendBufferSize = 65536, .recvBufferSize = 65536,
  14. .maxMessageSize = 65536, .maxChunkCount = 1}};
  15. /*********************/
  16. /* Create and Delete */
  17. /*********************/
  18. static void UA_Client_init(UA_Client* client, UA_ClientConfig config,
  19. UA_Logger logger) {
  20. client->state = UA_CLIENTSTATE_READY;
  21. UA_Connection_init(&client->connection);
  22. UA_SecureChannel_init(&client->channel);
  23. client->channel.connection = &client->connection;
  24. UA_String_init(&client->endpointUrl);
  25. client->requestId = 0;
  26. UA_NodeId_init(&client->authenticationToken);
  27. client->requestHandle = 0;
  28. client->logger = logger;
  29. client->config = config;
  30. client->scExpiresAt = 0;
  31. #ifdef ENABLE_SUBSCRIPTIONS
  32. client->monitoredItemHandles = 0;
  33. LIST_INIT(&client->pendingNotificationsAcks);
  34. LIST_INIT(&client->subscriptions);
  35. #endif
  36. }
  37. UA_Client * UA_Client_new(UA_ClientConfig config, UA_Logger logger) {
  38. UA_Client *client = UA_calloc(1, sizeof(UA_Client));
  39. if(!client)
  40. return NULL;
  41. UA_Client_init(client, config, logger);
  42. return client;
  43. }
  44. static void UA_Client_deleteMembers(UA_Client* client){
  45. UA_Client_disconnect(client);
  46. UA_Connection_deleteMembers(&client->connection);
  47. UA_SecureChannel_deleteMembersCleanup(&client->channel);
  48. if(client->endpointUrl.data)
  49. UA_String_deleteMembers(&client->endpointUrl);
  50. UA_UserTokenPolicy_deleteMembers(&client->token);
  51. }
  52. void UA_Client_reset(UA_Client* client){
  53. UA_Client_deleteMembers(client);
  54. UA_Client_init(client, client->config, client->logger);
  55. }
  56. void UA_Client_delete(UA_Client* client){
  57. if(client->state != UA_CLIENTSTATE_READY)
  58. UA_Client_deleteMembers(client);
  59. UA_free(client);
  60. }
  61. /*************************/
  62. /* Manage the Connection */
  63. /*************************/
  64. static UA_StatusCode HelAckHandshake(UA_Client *c) {
  65. UA_TcpMessageHeader messageHeader;
  66. messageHeader.messageTypeAndFinal = UA_MESSAGETYPEANDFINAL_HELF;
  67. UA_TcpHelloMessage hello;
  68. UA_String_copy(&c->endpointUrl, &hello.endpointUrl); /* must be less than 4096 bytes */
  69. UA_Connection *conn = &c->connection;
  70. hello.maxChunkCount = conn->localConf.maxChunkCount;
  71. hello.maxMessageSize = conn->localConf.maxMessageSize;
  72. hello.protocolVersion = conn->localConf.protocolVersion;
  73. hello.receiveBufferSize = conn->localConf.recvBufferSize;
  74. hello.sendBufferSize = conn->localConf.sendBufferSize;
  75. UA_ByteString message;
  76. UA_StatusCode retval;
  77. retval = c->connection.getSendBuffer(&c->connection, c->connection.remoteConf.recvBufferSize, &message);
  78. if(retval != UA_STATUSCODE_GOOD)
  79. return retval;
  80. size_t offset = 8;
  81. retval |= UA_TcpHelloMessage_encodeBinary(&hello, &message, &offset);
  82. messageHeader.messageSize = offset;
  83. offset = 0;
  84. retval |= UA_TcpMessageHeader_encodeBinary(&messageHeader, &message, &offset);
  85. UA_TcpHelloMessage_deleteMembers(&hello);
  86. if(retval != UA_STATUSCODE_GOOD) {
  87. c->connection.releaseSendBuffer(&c->connection, &message);
  88. return retval;
  89. }
  90. message.length = messageHeader.messageSize;
  91. retval = c->connection.send(&c->connection, &message);
  92. if(retval != UA_STATUSCODE_GOOD) {
  93. UA_LOG_DEBUG(c->logger, UA_LOGCATEGORY_NETWORK, "Sending HEL failed");
  94. return retval;
  95. }
  96. UA_LOG_DEBUG(c->logger, UA_LOGCATEGORY_NETWORK, "Sent HEL message");
  97. UA_ByteString reply;
  98. UA_ByteString_init(&reply);
  99. do {
  100. retval = c->connection.recv(&c->connection, &reply, c->config.timeout);
  101. if(retval != UA_STATUSCODE_GOOD) {
  102. UA_LOG_DEBUG(c->logger, UA_LOGCATEGORY_NETWORK, "Receiving ACK message failed");
  103. return retval;
  104. }
  105. } while(!reply.data);
  106. offset = 0;
  107. UA_TcpMessageHeader_decodeBinary(&reply, &offset, &messageHeader);
  108. UA_TcpAcknowledgeMessage ackMessage;
  109. retval = UA_TcpAcknowledgeMessage_decodeBinary(&reply, &offset, &ackMessage);
  110. UA_ByteString_deleteMembers(&reply);
  111. if(retval != UA_STATUSCODE_GOOD) {
  112. UA_LOG_DEBUG(c->logger, UA_LOGCATEGORY_NETWORK, "Decoding ACK message failed");
  113. return retval;
  114. }
  115. UA_LOG_DEBUG(c->logger, UA_LOGCATEGORY_NETWORK, "Received ACK message");
  116. conn->remoteConf.maxChunkCount = ackMessage.maxChunkCount;
  117. conn->remoteConf.maxMessageSize = ackMessage.maxMessageSize;
  118. conn->remoteConf.protocolVersion = ackMessage.protocolVersion;
  119. conn->remoteConf.recvBufferSize = ackMessage.receiveBufferSize;
  120. conn->remoteConf.sendBufferSize = ackMessage.sendBufferSize;
  121. conn->state = UA_CONNECTION_ESTABLISHED;
  122. return UA_STATUSCODE_GOOD;
  123. }
  124. static UA_StatusCode SecureChannelHandshake(UA_Client *client, UA_Boolean renew) {
  125. /* Check if sc is still valid */
  126. if(renew && client->scExpiresAt - UA_DateTime_now() > client->config.timeToRenewSecureChannel * 10000)
  127. return UA_STATUSCODE_GOOD;
  128. UA_SecureConversationMessageHeader messageHeader;
  129. messageHeader.messageHeader.messageTypeAndFinal = UA_MESSAGETYPEANDFINAL_OPNF;
  130. messageHeader.secureChannelId = 0;
  131. UA_SequenceHeader seqHeader;
  132. seqHeader.sequenceNumber = ++client->channel.sequenceNumber;
  133. seqHeader.requestId = ++client->requestId;
  134. UA_AsymmetricAlgorithmSecurityHeader asymHeader;
  135. UA_AsymmetricAlgorithmSecurityHeader_init(&asymHeader);
  136. asymHeader.securityPolicyUri = UA_STRING_ALLOC("http://opcfoundation.org/UA/SecurityPolicy#None");
  137. /* id of opensecurechannelrequest */
  138. UA_NodeId requestType = UA_NODEID_NUMERIC(0, UA_NS0ID_OPENSECURECHANNELREQUEST + UA_ENCODINGOFFSET_BINARY);
  139. UA_OpenSecureChannelRequest opnSecRq;
  140. UA_OpenSecureChannelRequest_init(&opnSecRq);
  141. opnSecRq.requestHeader.timestamp = UA_DateTime_now();
  142. opnSecRq.requestHeader.authenticationToken = client->authenticationToken;
  143. opnSecRq.requestedLifetime = client->config.secureChannelLifeTime;
  144. if(renew) {
  145. opnSecRq.requestType = UA_SECURITYTOKENREQUESTTYPE_RENEW;
  146. UA_LOG_DEBUG(client->logger, UA_LOGCATEGORY_SECURECHANNEL, "Requesting to renew the SecureChannel");
  147. } else {
  148. opnSecRq.requestType = UA_SECURITYTOKENREQUESTTYPE_ISSUE;
  149. UA_ByteString_init(&client->channel.clientNonce);
  150. UA_ByteString_copy(&client->channel.clientNonce, &opnSecRq.clientNonce);
  151. opnSecRq.securityMode = UA_MESSAGESECURITYMODE_NONE;
  152. UA_LOG_DEBUG(client->logger, UA_LOGCATEGORY_SECURECHANNEL, "Requesting to open a SecureChannel");
  153. }
  154. UA_ByteString message;
  155. UA_Connection *c = &client->connection;
  156. UA_StatusCode retval = c->getSendBuffer(c, c->remoteConf.recvBufferSize, &message);
  157. if(retval != UA_STATUSCODE_GOOD) {
  158. UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&asymHeader);
  159. UA_OpenSecureChannelRequest_deleteMembers(&opnSecRq);
  160. return retval;
  161. }
  162. size_t offset = 12;
  163. retval = UA_AsymmetricAlgorithmSecurityHeader_encodeBinary(&asymHeader, &message, &offset);
  164. retval |= UA_SequenceHeader_encodeBinary(&seqHeader, &message, &offset);
  165. retval |= UA_NodeId_encodeBinary(&requestType, &message, &offset);
  166. retval |= UA_OpenSecureChannelRequest_encodeBinary(&opnSecRq, &message, &offset);
  167. messageHeader.messageHeader.messageSize = offset;
  168. offset = 0;
  169. retval |= UA_SecureConversationMessageHeader_encodeBinary(&messageHeader, &message, &offset);
  170. UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&asymHeader);
  171. UA_OpenSecureChannelRequest_deleteMembers(&opnSecRq);
  172. if(retval != UA_STATUSCODE_GOOD) {
  173. client->connection.releaseSendBuffer(&client->connection, &message);
  174. return retval;
  175. }
  176. message.length = messageHeader.messageHeader.messageSize;
  177. retval = client->connection.send(&client->connection, &message);
  178. if(retval != UA_STATUSCODE_GOOD)
  179. return retval;
  180. UA_ByteString reply;
  181. UA_ByteString_init(&reply);
  182. do {
  183. retval = client->connection.recv(&client->connection, &reply, client->config.timeout);
  184. if(retval != UA_STATUSCODE_GOOD) {
  185. UA_LOG_DEBUG(client->logger, UA_LOGCATEGORY_SECURECHANNEL,
  186. "Receiving OpenSecureChannelResponse failed");
  187. return retval;
  188. }
  189. } while(!reply.data);
  190. offset = 0;
  191. UA_SecureConversationMessageHeader_decodeBinary(&reply, &offset, &messageHeader);
  192. UA_AsymmetricAlgorithmSecurityHeader_decodeBinary(&reply, &offset, &asymHeader);
  193. UA_SequenceHeader_decodeBinary(&reply, &offset, &seqHeader);
  194. UA_NodeId_decodeBinary(&reply, &offset, &requestType);
  195. UA_NodeId expectedRequest = UA_NODEID_NUMERIC(0, UA_NS0ID_OPENSECURECHANNELRESPONSE +
  196. UA_ENCODINGOFFSET_BINARY);
  197. if(!UA_NodeId_equal(&requestType, &expectedRequest)) {
  198. UA_ByteString_deleteMembers(&reply);
  199. UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&asymHeader);
  200. UA_NodeId_deleteMembers(&requestType);
  201. UA_LOG_DEBUG(client->logger, UA_LOGCATEGORY_CLIENT,
  202. "Reply answers the wrong request. Expected OpenSecureChannelResponse.");
  203. return UA_STATUSCODE_BADINTERNALERROR;
  204. }
  205. UA_OpenSecureChannelResponse response;
  206. UA_OpenSecureChannelResponse_init(&response);
  207. retval = UA_OpenSecureChannelResponse_decodeBinary(&reply, &offset, &response);
  208. if(retval != UA_STATUSCODE_GOOD) {
  209. UA_LOG_DEBUG(client->logger, UA_LOGCATEGORY_SECURECHANNEL,
  210. "Decoding OpenSecureChannelResponse failed");
  211. UA_ByteString_deleteMembers(&reply);
  212. UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&asymHeader);
  213. UA_OpenSecureChannelResponse_init(&response);
  214. response.responseHeader.serviceResult = retval;
  215. return retval;
  216. }
  217. client->scExpiresAt = UA_DateTime_now() + response.securityToken.revisedLifetime * 10000;
  218. UA_ByteString_deleteMembers(&reply);
  219. retval = response.responseHeader.serviceResult;
  220. if(retval != UA_STATUSCODE_GOOD)
  221. UA_LOG_DEBUG(client->logger, UA_LOGCATEGORY_SECURECHANNEL,
  222. "SecureChannel could not be opened / renewed");
  223. else if(!renew) {
  224. UA_ChannelSecurityToken_copy(&response.securityToken, &client->channel.securityToken);
  225. /* if the handshake is repeated, replace the old nonce */
  226. UA_ByteString_deleteMembers(&client->channel.serverNonce);
  227. UA_ByteString_copy(&response.serverNonce, &client->channel.serverNonce);
  228. UA_LOG_DEBUG(client->logger, UA_LOGCATEGORY_SECURECHANNEL, "SecureChannel opened");
  229. } else
  230. UA_LOG_DEBUG(client->logger, UA_LOGCATEGORY_SECURECHANNEL, "SecureChannel renewed");
  231. UA_OpenSecureChannelResponse_deleteMembers(&response);
  232. UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&asymHeader);
  233. return retval;
  234. }
  235. static UA_StatusCode ActivateSession(UA_Client *client) {
  236. UA_ActivateSessionRequest request;
  237. UA_ActivateSessionRequest_init(&request);
  238. request.requestHeader.requestHandle = 2; //TODO: is it a magic number?
  239. request.requestHeader.authenticationToken = client->authenticationToken;
  240. request.requestHeader.timestamp = UA_DateTime_now();
  241. request.requestHeader.timeoutHint = 10000;
  242. UA_AnonymousIdentityToken identityToken;
  243. UA_AnonymousIdentityToken_init(&identityToken);
  244. UA_String_copy(&client->token.policyId, &identityToken.policyId);
  245. //manual ExtensionObject encoding of the identityToken
  246. request.userIdentityToken.encoding = UA_EXTENSIONOBJECT_ENCODINGMASK_BODYISBYTESTRING;
  247. request.userIdentityToken.typeId = UA_TYPES[UA_TYPES_ANONYMOUSIDENTITYTOKEN].typeId;
  248. request.userIdentityToken.typeId.identifier.numeric+=UA_ENCODINGOFFSET_BINARY;
  249. if (identityToken.policyId.length >= 0)
  250. UA_ByteString_newMembers(&request.userIdentityToken.body, identityToken.policyId.length+4);
  251. else {
  252. identityToken.policyId.length = -1;
  253. UA_ByteString_newMembers(&request.userIdentityToken.body, 4);
  254. }
  255. size_t offset = 0;
  256. UA_ByteString_encodeBinary(&identityToken.policyId,&request.userIdentityToken.body,&offset);
  257. UA_ActivateSessionResponse response;
  258. __UA_Client_Service(client, &request, &UA_TYPES[UA_TYPES_ACTIVATESESSIONREQUEST],
  259. &response, &UA_TYPES[UA_TYPES_ACTIVATESESSIONRESPONSE]);
  260. UA_AnonymousIdentityToken_deleteMembers(&identityToken);
  261. UA_ActivateSessionRequest_deleteMembers(&request);
  262. UA_ActivateSessionResponse_deleteMembers(&response);
  263. return response.responseHeader.serviceResult; // not deleted
  264. }
  265. static UA_StatusCode EndpointsHandshake(UA_Client *client) {
  266. UA_GetEndpointsRequest request;
  267. UA_GetEndpointsRequest_init(&request);
  268. request.requestHeader.authenticationToken = client->authenticationToken;
  269. request.requestHeader.timestamp = UA_DateTime_now();
  270. request.requestHeader.timeoutHint = 10000;
  271. request.endpointUrl = client->endpointUrl;
  272. UA_String profileUri = UA_STRING("http://opcfoundation.org/UA-Profile/Transport/uatcp-uasc-uabinary");
  273. request.profileUris = &profileUri;
  274. request.profileUrisSize = 1;
  275. UA_GetEndpointsResponse response;
  276. UA_GetEndpointsResponse_init(&response);
  277. __UA_Client_Service(client, &request, &UA_TYPES[UA_TYPES_GETENDPOINTSREQUEST],
  278. &response, &UA_TYPES[UA_TYPES_GETENDPOINTSRESPONSE]);
  279. UA_Boolean endpointFound = UA_FALSE;
  280. UA_Boolean tokenFound = UA_FALSE;
  281. UA_String securityNone = UA_STRING("http://opcfoundation.org/UA/SecurityPolicy#None");
  282. for(UA_Int32 i = 0; i < response.endpointsSize; i++) {
  283. UA_EndpointDescription* endpoint = &response.endpoints[i];
  284. /* look out for an endpoint without security */
  285. if(!UA_String_equal(&endpoint->securityPolicyUri, &securityNone))
  286. continue;
  287. endpointFound = UA_TRUE;
  288. /* endpoint with no security found */
  289. /* look for a user token policy with an anonymous token */
  290. for(UA_Int32 j=0; j<endpoint->userIdentityTokensSize; ++j) {
  291. UA_UserTokenPolicy* userToken = &endpoint->userIdentityTokens[j];
  292. if(userToken->tokenType != UA_USERTOKENTYPE_ANONYMOUS)
  293. continue;
  294. tokenFound = UA_TRUE;
  295. UA_UserTokenPolicy_copy(userToken, &client->token);
  296. break;
  297. }
  298. }
  299. UA_GetEndpointsResponse_deleteMembers(&response);
  300. if(!endpointFound) {
  301. UA_LOG_ERROR(client->logger, UA_LOGCATEGORY_CLIENT, "No suitable endpoint found");
  302. return UA_STATUSCODE_BADINTERNALERROR;
  303. }
  304. if(!tokenFound) {
  305. UA_LOG_ERROR(client->logger, UA_LOGCATEGORY_CLIENT, "No anonymous token found");
  306. return UA_STATUSCODE_BADINTERNALERROR;
  307. }
  308. return response.responseHeader.serviceResult;
  309. }
  310. static UA_StatusCode SessionHandshake(UA_Client *client) {
  311. UA_CreateSessionRequest request;
  312. UA_CreateSessionRequest_init(&request);
  313. // todo: is this needed for all requests?
  314. UA_NodeId_copy(&client->authenticationToken, &request.requestHeader.authenticationToken);
  315. request.requestHeader.timestamp = UA_DateTime_now();
  316. request.requestHeader.timeoutHint = 10000;
  317. UA_ByteString_copy(&client->channel.clientNonce, &request.clientNonce);
  318. request.requestedSessionTimeout = 1200000;
  319. request.maxResponseMessageSize = UA_INT32_MAX;
  320. UA_CreateSessionResponse response;
  321. UA_CreateSessionResponse_init(&response);
  322. __UA_Client_Service(client, &request, &UA_TYPES[UA_TYPES_CREATESESSIONREQUEST],
  323. &response, &UA_TYPES[UA_TYPES_CREATESESSIONRESPONSE]);
  324. UA_NodeId_copy(&response.authenticationToken, &client->authenticationToken);
  325. UA_CreateSessionRequest_deleteMembers(&request);
  326. UA_CreateSessionResponse_deleteMembers(&response);
  327. return response.responseHeader.serviceResult; // not deleted
  328. }
  329. static UA_StatusCode CloseSession(UA_Client *client) {
  330. UA_CloseSessionRequest request;
  331. UA_CloseSessionRequest_init(&request);
  332. request.requestHeader.timestamp = UA_DateTime_now();
  333. request.requestHeader.timeoutHint = 10000;
  334. request.deleteSubscriptions = UA_TRUE;
  335. UA_NodeId_copy(&client->authenticationToken, &request.requestHeader.authenticationToken);
  336. UA_CloseSessionResponse response;
  337. __UA_Client_Service(client, &request, &UA_TYPES[UA_TYPES_CLOSESESSIONREQUEST],
  338. &response, &UA_TYPES[UA_TYPES_CLOSESESSIONRESPONSE]);
  339. UA_CloseSessionRequest_deleteMembers(&request);
  340. UA_CloseSessionResponse_deleteMembers(&response);
  341. return response.responseHeader.serviceResult; // not deleted
  342. }
  343. static UA_StatusCode CloseSecureChannel(UA_Client *client) {
  344. UA_SecureChannel *channel = &client->channel;
  345. UA_CloseSecureChannelRequest request;
  346. UA_CloseSecureChannelRequest_init(&request);
  347. request.requestHeader.requestHandle = 1; //TODO: magic number?
  348. request.requestHeader.timestamp = UA_DateTime_now();
  349. request.requestHeader.timeoutHint = 10000;
  350. request.requestHeader.authenticationToken = client->authenticationToken;
  351. UA_SecureConversationMessageHeader msgHeader;
  352. msgHeader.messageHeader.messageTypeAndFinal = UA_MESSAGETYPEANDFINAL_CLOF;
  353. msgHeader.secureChannelId = client->channel.securityToken.channelId;
  354. UA_SymmetricAlgorithmSecurityHeader symHeader;
  355. symHeader.tokenId = channel->securityToken.tokenId;
  356. UA_SequenceHeader seqHeader;
  357. seqHeader.sequenceNumber = ++channel->sequenceNumber;
  358. seqHeader.requestId = ++client->requestId;
  359. UA_NodeId typeId = UA_NODEID_NUMERIC(0, UA_NS0ID_CLOSESECURECHANNELREQUEST + UA_ENCODINGOFFSET_BINARY);
  360. UA_ByteString message;
  361. UA_Connection *c = &client->connection;
  362. UA_StatusCode retval = c->getSendBuffer(c, c->remoteConf.recvBufferSize, &message);
  363. if(retval != UA_STATUSCODE_GOOD)
  364. return retval;
  365. size_t offset = 12;
  366. retval |= UA_SymmetricAlgorithmSecurityHeader_encodeBinary(&symHeader, &message, &offset);
  367. retval |= UA_SequenceHeader_encodeBinary(&seqHeader, &message, &offset);
  368. retval |= UA_NodeId_encodeBinary(&typeId, &message, &offset);
  369. retval |= UA_encodeBinary(&request, &UA_TYPES[UA_TYPES_CLOSESECURECHANNELREQUEST], &message, &offset);
  370. msgHeader.messageHeader.messageSize = offset;
  371. offset = 0;
  372. retval |= UA_SecureConversationMessageHeader_encodeBinary(&msgHeader, &message, &offset);
  373. if(retval != UA_STATUSCODE_GOOD) {
  374. client->connection.releaseSendBuffer(&client->connection, &message);
  375. return retval;
  376. }
  377. message.length = msgHeader.messageHeader.messageSize;
  378. retval = client->connection.send(&client->connection, &message);
  379. return retval;
  380. }
  381. UA_StatusCode UA_Client_connect(UA_Client *client, UA_ConnectClientConnection connectFunc,
  382. const char *endpointUrl) {
  383. if(client->state == UA_CLIENTSTATE_CONNECTED)
  384. return UA_STATUSCODE_GOOD;
  385. if(client->state == UA_CLIENTSTATE_ERRORED) {
  386. UA_Client_reset(client);
  387. }
  388. UA_StatusCode retval = UA_STATUSCODE_GOOD;
  389. client->connection = connectFunc(UA_ConnectionConfig_standard, endpointUrl, client->logger);
  390. if(client->connection.state != UA_CONNECTION_OPENING) {
  391. retval = UA_STATUSCODE_BADCONNECTIONCLOSED;
  392. goto cleanup;
  393. }
  394. client->endpointUrl = UA_STRING_ALLOC(endpointUrl);
  395. if(client->endpointUrl.length < 0) {
  396. retval = UA_STATUSCODE_BADOUTOFMEMORY;
  397. goto cleanup;
  398. }
  399. client->connection.localConf = client->config.localConnectionConfig;
  400. retval = HelAckHandshake(client);
  401. if(retval == UA_STATUSCODE_GOOD)
  402. retval = SecureChannelHandshake(client, UA_FALSE);
  403. if(retval == UA_STATUSCODE_GOOD)
  404. retval = EndpointsHandshake(client);
  405. if(retval == UA_STATUSCODE_GOOD)
  406. retval = SessionHandshake(client);
  407. if(retval == UA_STATUSCODE_GOOD)
  408. retval = ActivateSession(client);
  409. if(retval == UA_STATUSCODE_GOOD) {
  410. client->connection.state = UA_CONNECTION_ESTABLISHED;
  411. client->state = UA_CLIENTSTATE_CONNECTED;
  412. } else {
  413. goto cleanup;
  414. }
  415. return retval;
  416. cleanup:
  417. client->state = UA_CLIENTSTATE_ERRORED;
  418. UA_Client_reset(client);
  419. return retval;
  420. }
  421. UA_StatusCode UA_Client_disconnect(UA_Client *client) {
  422. UA_StatusCode retval = UA_STATUSCODE_GOOD;
  423. if(client->channel.connection->state == UA_CONNECTION_ESTABLISHED){
  424. retval = CloseSession(client);
  425. if(retval == UA_STATUSCODE_GOOD)
  426. retval = CloseSecureChannel(client);
  427. }
  428. return retval;
  429. }
  430. UA_StatusCode UA_Client_manuallyRenewSecureChannel(UA_Client *client) {
  431. return SecureChannelHandshake(client, UA_TRUE);
  432. }
  433. /****************/
  434. /* Raw Services */
  435. /****************/
  436. void __UA_Client_Service(UA_Client *client, const void *r, const UA_DataType *requestType,
  437. void *response, const UA_DataType *responseType) {
  438. /* Requests always begin witih a RequestHeader, therefore we can cast. */
  439. UA_RequestHeader *request = (void*)(uintptr_t)r;
  440. UA_StatusCode retval = UA_STATUSCODE_GOOD;
  441. UA_init(response, responseType);
  442. UA_ResponseHeader *respHeader = (UA_ResponseHeader*)response;
  443. /* make sure we have a valid session */
  444. retval = UA_Client_manuallyRenewSecureChannel(client);
  445. if(retval != UA_STATUSCODE_GOOD) {
  446. respHeader->serviceResult = retval;
  447. client->state = UA_CLIENTSTATE_ERRORED;
  448. return;
  449. }
  450. /* handling request parameters */
  451. UA_NodeId_copy(&client->authenticationToken, &request->authenticationToken);
  452. request->timestamp = UA_DateTime_now();
  453. request->requestHandle = ++client->requestHandle;
  454. /* Send the request */
  455. UA_UInt32 requestId = ++client->requestId;
  456. UA_LOG_DEBUG(client->logger, UA_LOGCATEGORY_CLIENT,
  457. "Sending a request of type %i", requestType->typeId.identifier.numeric);
  458. retval = UA_SecureChannel_sendBinaryMessage(&client->channel, requestId, request, requestType);
  459. if(retval) {
  460. if(retval == UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED)
  461. respHeader->serviceResult = UA_STATUSCODE_BADREQUESTTOOLARGE;
  462. else
  463. respHeader->serviceResult = retval;
  464. client->state = UA_CLIENTSTATE_ERRORED;
  465. return;
  466. }
  467. /* Retrieve the response */
  468. // Todo: push this into the generic securechannel implementation for client and server
  469. UA_ByteString reply;
  470. UA_ByteString_init(&reply);
  471. do {
  472. retval = client->connection.recv(&client->connection, &reply, client->config.timeout);
  473. if(retval != UA_STATUSCODE_GOOD) {
  474. respHeader->serviceResult = retval;
  475. client->state = UA_CLIENTSTATE_ERRORED;
  476. return;
  477. }
  478. } while(!reply.data);
  479. size_t offset = 0;
  480. UA_SecureConversationMessageHeader msgHeader;
  481. retval |= UA_SecureConversationMessageHeader_decodeBinary(&reply, &offset, &msgHeader);
  482. UA_SymmetricAlgorithmSecurityHeader symHeader;
  483. retval |= UA_SymmetricAlgorithmSecurityHeader_decodeBinary(&reply, &offset, &symHeader);
  484. UA_SequenceHeader seqHeader;
  485. retval |= UA_SequenceHeader_decodeBinary(&reply, &offset, &seqHeader);
  486. UA_NodeId responseId;
  487. retval |= UA_NodeId_decodeBinary(&reply, &offset, &responseId);
  488. UA_NodeId expectedNodeId = UA_NODEID_NUMERIC(0, responseType->typeId.identifier.numeric +
  489. UA_ENCODINGOFFSET_BINARY);
  490. if(retval != UA_STATUSCODE_GOOD) {
  491. goto finish;
  492. }
  493. /* Todo: we need to demux responses since a publish responses may come at any time */
  494. if(!UA_NodeId_equal(&responseId, &expectedNodeId) || seqHeader.requestId != requestId) {
  495. if(responseId.identifier.numeric != UA_NS0ID_SERVICEFAULT + UA_ENCODINGOFFSET_BINARY) {
  496. UA_LOG_ERROR(client->logger, UA_LOGCATEGORY_CLIENT,
  497. "Reply answers the wrong request. Expected ns=%i,i=%i. But retrieved ns=%i,i=%i",
  498. expectedNodeId.namespaceIndex, expectedNodeId.identifier.numeric,
  499. responseId.namespaceIndex, responseId.identifier.numeric);
  500. respHeader->serviceResult = UA_STATUSCODE_BADINTERNALERROR;
  501. } else
  502. retval = UA_decodeBinary(&reply, &offset, respHeader, &UA_TYPES[UA_TYPES_SERVICEFAULT]);
  503. goto finish;
  504. }
  505. retval = UA_decodeBinary(&reply, &offset, response, responseType);
  506. if(retval == UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED)
  507. retval = UA_STATUSCODE_BADRESPONSETOOLARGE;
  508. finish:
  509. UA_SymmetricAlgorithmSecurityHeader_deleteMembers(&symHeader);
  510. UA_ByteString_deleteMembers(&reply);
  511. if(retval != UA_STATUSCODE_GOOD){
  512. UA_LOG_INFO(client->logger, UA_LOGCATEGORY_CLIENT, "Error receiving the response");
  513. client->state = UA_CLIENTSTATE_ERRORED;
  514. respHeader->serviceResult = retval;
  515. }
  516. UA_LOG_DEBUG(client->logger, UA_LOGCATEGORY_CLIENT,
  517. "Received a response of type %i", responseId.identifier.numeric);
  518. }