ua_connection.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. #include "ua_util.h"
  2. #include "ua_connection.h"
  3. #include "ua_types_encoding_binary.h"
  4. const char *UA_LoggerCategoryNames[4] = {"communication", "server", "client", "userland"};
  5. // max message size is 64k
  6. const UA_ConnectionConfig UA_ConnectionConfig_standard =
  7. {.protocolVersion = 0, .sendBufferSize = 65536, .recvBufferSize = 65536,
  8. .maxMessageSize = 65536, .maxChunkCount = 1};
  9. void UA_Connection_init(UA_Connection *connection) {
  10. connection->state = UA_CONNECTION_CLOSED;
  11. connection->localConf = (UA_ConnectionConfig){0,0,0,0,0};
  12. connection->remoteConf = (UA_ConnectionConfig){0,0,0,0,0};
  13. connection->channel = UA_NULL;
  14. connection->sockfd = 0;
  15. connection->handle = UA_NULL;
  16. UA_ByteString_init(&connection->incompleteMessage);
  17. connection->write = UA_NULL;
  18. connection->close = UA_NULL;
  19. connection->recv = UA_NULL;
  20. }
  21. void UA_Connection_deleteMembers(UA_Connection *connection) {
  22. UA_ByteString_deleteMembers(&connection->incompleteMessage);
  23. }
  24. UA_ByteString UA_Connection_completeMessages(UA_Connection *connection, UA_ByteString received)
  25. {
  26. if(received.length == -1)
  27. return received;
  28. /* concat the existing incomplete message with the new message */
  29. UA_ByteString current;
  30. if(connection->incompleteMessage.length < 0)
  31. current = received;
  32. else {
  33. current.data = UA_realloc(connection->incompleteMessage.data,
  34. connection->incompleteMessage.length + received.length);
  35. if(!current.data) {
  36. /* not enough memory */
  37. UA_ByteString_deleteMembers(&connection->incompleteMessage);
  38. connection->incompleteMessage.length = -1;
  39. UA_ByteString_deleteMembers(&received);
  40. received.length = -1;
  41. return received;
  42. }
  43. UA_memcpy(current.data + connection->incompleteMessage.length, received.data, received.length);
  44. current.length = connection->incompleteMessage.length + received.length;
  45. UA_ByteString_deleteMembers(&received);
  46. UA_ByteString_init(&connection->incompleteMessage);
  47. }
  48. /* find the first non-complete message */
  49. size_t end_pos = 0; // the end of the last complete message
  50. while(current.length - end_pos >= 16) {
  51. if(!(current.data[0] == 'M' && current.data[1] == 'S' && current.data[2] == 'G') &&
  52. !(current.data[0] == 'O' && current.data[1] == 'P' && current.data[2] == 'N') &&
  53. !(current.data[0] == 'H' && current.data[1] == 'E' && current.data[2] == 'L') &&
  54. !(current.data[0] == 'A' && current.data[1] == 'C' && current.data[2] == 'K') &&
  55. !(current.data[0] == 'C' && current.data[1] == 'L' && current.data[2] == 'O')) {
  56. current.length = end_pos; // throw the remaining bytestring away
  57. break;
  58. }
  59. UA_Int32 length = 0;
  60. size_t pos = end_pos + 4;
  61. UA_StatusCode retval = UA_Int32_decodeBinary(&current, &pos, &length);
  62. if(retval != UA_STATUSCODE_GOOD || length < 16 ||
  63. length > (UA_Int32)connection->localConf.maxMessageSize) {
  64. current.length = end_pos; // throw the remaining bytestring away
  65. break;
  66. }
  67. if(length + (UA_Int32)end_pos > current.length)
  68. break; // the message is incomplete
  69. end_pos += length;
  70. }
  71. if(current.length == 0) {
  72. /* throw everything away */
  73. UA_ByteString_deleteMembers(&current);
  74. current.length = -1;
  75. return current;
  76. }
  77. if(end_pos == 0) {
  78. /* no complete message in current */
  79. connection->incompleteMessage = current;
  80. UA_ByteString_init(&current);
  81. } else if(current.length != (UA_Int32)end_pos) {
  82. /* there is an incomplete message at the end of current */
  83. connection->incompleteMessage.data = UA_malloc(current.length - end_pos);
  84. if(connection->incompleteMessage.data) {
  85. UA_memcpy(connection->incompleteMessage.data, &current.data[end_pos], current.length - end_pos);
  86. connection->incompleteMessage.length = current.length - end_pos;
  87. }
  88. current.length = end_pos;
  89. }
  90. return current;
  91. }