ua_client.c 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. #include "ua_client.h"
  2. #include "ua_types_encoding_binary.h"
  3. #include "ua_transport_generated.h"
  4. struct UA_Client {
  5. UA_ClientNetworkLayer networkLayer;
  6. void *connectionHandle;
  7. UA_String endpointUrl;
  8. UA_Connection connection;
  9. /* UA_UInt32 channelId; */
  10. /* UA_SequenceHeader sequenceHdr; */
  11. /* UA_NodeId authenticationToken; */
  12. /* UA_UInt32 tokenId; */
  13. /* UA_Connection *connection; */
  14. };
  15. UA_Client * UA_Client_new(void) {
  16. UA_Client *c = UA_malloc(sizeof(UA_Client));
  17. if(!c)
  18. return UA_NULL;
  19. UA_String_init(&c->endpointUrl);
  20. c->connection.state = UA_CONNECTION_OPENING;
  21. return c;
  22. }
  23. static UA_StatusCode HelAckHandshake(UA_Client *c);
  24. static UA_StatusCode SecureChannelHandshake(UA_Client *c);
  25. UA_StatusCode UA_Client_connect(UA_Client *c, UA_ConnectionConfig conf, UA_ClientNetworkLayer networkLayer,
  26. char *endpointUrl) {
  27. UA_StatusCode retval = UA_String_copycstring(endpointUrl, &c->endpointUrl);
  28. if(retval != UA_STATUSCODE_GOOD)
  29. return UA_STATUSCODE_BADOUTOFMEMORY;
  30. c->networkLayer = networkLayer;
  31. c->connection.localConf = conf;
  32. retval = networkLayer.connect(c->endpointUrl, &c->connectionHandle);
  33. if(!retval != UA_STATUSCODE_GOOD)
  34. return retval;
  35. HelAckHandshake(c);
  36. // securechannel
  37. // session
  38. return UA_STATUSCODE_GOOD;
  39. }
  40. UA_StatusCode UA_EXPORT UA_Client_disconnect(UA_Client *c) {
  41. return UA_STATUSCODE_GOOD;
  42. }
  43. // The tcp connection is established. Now do the handshake
  44. static UA_StatusCode HelAckHandshake(UA_Client *c) {
  45. UA_TcpMessageHeader messageHeader;
  46. messageHeader.messageTypeAndFinal = UA_MESSAGETYPEANDFINAL_HELF;
  47. UA_TcpHelloMessage hello;
  48. UA_String_copy(&c->endpointUrl, &hello.endpointUrl);
  49. UA_Connection *conn = &c->connection;
  50. hello.maxChunkCount = conn->localConf.maxChunkCount;
  51. hello.maxMessageSize = conn->localConf.maxMessageSize;
  52. hello.protocolVersion = conn->localConf.protocolVersion;
  53. hello.receiveBufferSize = conn->localConf.recvBufferSize;
  54. hello.sendBufferSize = conn->localConf.sendBufferSize;
  55. messageHeader.messageSize = UA_TcpHelloMessage_calcSizeBinary((UA_TcpHelloMessage const*) &hello) +
  56. UA_TcpMessageHeader_calcSizeBinary((UA_TcpMessageHeader const*) &messageHeader);
  57. UA_ByteString message;
  58. message.data = UA_alloca(messageHeader.messageSize);
  59. message.length = messageHeader.messageSize;
  60. size_t offset = 0;
  61. UA_TcpMessageHeader_encodeBinary(&messageHeader, &message, &offset);
  62. UA_TcpHelloMessage_encodeBinary(&hello, &message, &offset);
  63. UA_ByteStringArray buf = {.stringsSize = 1, .strings = &message};
  64. UA_StatusCode retval = c->networkLayer.send(c->connectionHandle, buf);
  65. if(retval)
  66. return retval;
  67. UA_Byte replybuf[1024];
  68. UA_ByteString reply = {.data = replybuf, .length = 1024};
  69. retval = c->networkLayer.awaitResponse(c->connectionHandle, &reply, 100);
  70. if (retval)
  71. return retval;
  72. offset = 0;
  73. UA_TcpAcknowledgeMessage ackMessage;
  74. retval = UA_TcpAcknowledgeMessage_decodeBinary(&reply, &offset, &ackMessage);
  75. if(retval != UA_STATUSCODE_GOOD) {
  76. UA_TcpAcknowledgeMessage_deleteMembers(&ackMessage);
  77. return retval;
  78. }
  79. conn->remoteConf.maxChunkCount = ackMessage.maxChunkCount;
  80. conn->remoteConf.maxMessageSize = ackMessage.maxMessageSize;
  81. conn->remoteConf.protocolVersion = ackMessage.protocolVersion;
  82. conn->remoteConf.recvBufferSize = ackMessage.receiveBufferSize;
  83. conn->remoteConf.sendBufferSize = ackMessage.sendBufferSize;
  84. conn->state = UA_CONNECTION_ESTABLISHED;
  85. return UA_STATUSCODE_GOOD;
  86. }
  87. static UA_StatusCode SecureChannelHandshake(UA_Client *c) {
  88. UA_SecureConversationMessageHeader msghdr;
  89. msghdr.messageHeader.messageTypeAndFinal = UA_MESSAGETYPEANDFINAL_OPNF;
  90. msghdr.secureChannelId = 0;
  91. UA_AsymmetricAlgorithmSecurityHeader asymHeader;
  92. UA_AsymmetricAlgorithmSecurityHeader_init(&asymHeader);
  93. UA_String_copycstring("http://opcfoundation.org/UA/SecurityPolicy#None", &asymHeader.securityPolicyUri);
  94. UA_SequenceHeader seqHeader;
  95. seqHeader.sequenceNumber = 51; // why is that???
  96. seqHeader.requestId = 1;
  97. UA_NodeId requestType = {.identifierType = UA_NODEIDTYPE_NUMERIC, .namespaceIndex = 0,
  98. .identifier.numeric = 446}; // id of opensecurechannelrequest
  99. UA_OpenSecureChannelRequest opnSecRq;
  100. UA_OpenSecureChannelRequest_init(&opnSecRq);
  101. opnSecRq.requestHeader.timestamp = UA_DateTime_now();
  102. UA_ByteString_newMembers(&opnSecRq.clientNonce, 1);
  103. opnSecRq.clientNonce.data[0] = 0;
  104. opnSecRq.clientProtocolVersion = 0;
  105. opnSecRq.requestedLifetime = 30000;
  106. opnSecRq.securityMode = UA_MESSAGESECURITYMODE_NONE;
  107. opnSecRq.requestType = UA_SECURITYTOKENREQUESTTYPE_ISSUE;
  108. opnSecRq.requestHeader.authenticationToken.identifier.numeric = 10;
  109. opnSecRq.requestHeader.authenticationToken.identifierType = UA_NODEIDTYPE_NUMERIC;
  110. opnSecRq.requestHeader.authenticationToken.namespaceIndex = 10;
  111. msghdr.messageHeader.messageSize = UA_SecureConversationMessageHeader_calcSizeBinary(&msghdr) +
  112. UA_AsymmetricAlgorithmSecurityHeader_calcSizeBinary(&asymHeader) +
  113. UA_SequenceHeader_calcSizeBinary(&seqHeader) +
  114. UA_NodeId_calcSizeBinary(&requestType) +
  115. UA_OpenSecureChannelRequest_calcSizeBinary(&opnSecRq);
  116. UA_ByteString message;
  117. UA_ByteString_newMembers(&message, msghdr.messageHeader.messageSize);
  118. size_t offset = 0;
  119. UA_SecureConversationMessageHeader_encodeBinary(&msghdr, &message, &offset);
  120. UA_AsymmetricAlgorithmSecurityHeader_encodeBinary(&asymHeader, &message, &offset);
  121. UA_SequenceHeader_encodeBinary(&seqHeader, &message, &offset);
  122. UA_NodeId_encodeBinary(&requestType, &message, &offset);
  123. UA_OpenSecureChannelRequest_encodeBinary(&opnSecRq, &message, &offset);
  124. UA_OpenSecureChannelRequest_deleteMembers(&opnSecRq);
  125. UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&asymHeader);
  126. UA_ByteStringArray buf = {.stringsSize = 1, .strings = &message};
  127. UA_StatusCode retval = c->networkLayer.send(c->connectionHandle, buf);
  128. UA_ByteString_deleteMembers(&message);
  129. // parse the response
  130. UA_ByteString response;
  131. UA_ByteString_newMembers(&response, c->connection.localConf.recvBufferSize);
  132. retval = c->networkLayer.awaitResponse(c->connectionHandle, &response, 1000);
  133. /* UA_SecureConversationMessageHeader_init(&msghdr); */
  134. /* UA_AsymmetricAlgorithmSecurityHeader_init(&asymHeader); */
  135. /* UA_SequenceHeader_init(&seqHeader); */
  136. /* UA_OpenSecureChannelResponse opnSecRq; */
  137. /* UA_SecureConversationMessageHeader_calcSizeBinary(&respHeader) */
  138. /* + UA_AsymmetricAlgorithmSecurityHeader_calcSizeBinary(&asymHeader) */
  139. /* + UA_SequenceHeader_calcSizeBinary(&seqHeader) */
  140. /* + UA_NodeId_calcSizeBinary(&responseType) */
  141. /* + UA_OpenSecureChannelResponse_calcSizeBinary(&p); */
  142. //UA_SecureConversationMessageHeader respHeader;
  143. //UA_NodeId responseType = UA_NODEIDS[UA_OPENSECURECHANNELRESPONSE];
  144. return retval;
  145. }