ua_util.c 3.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. /* This Source Code Form is subject to the terms of the Mozilla Public
  2. * License, v. 2.0. If a copy of the MPL was not distributed with this
  3. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  4. *
  5. * Copyright 2014, 2017 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
  6. * Copyright 2014 (c) Florian Palm
  7. * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
  8. */
  9. #include "ua_util.h"
  10. #include "ua_plugin_network.h"
  11. size_t
  12. UA_readNumber(u8 *buf, size_t buflen, u32 *number) {
  13. UA_assert(buf);
  14. UA_assert(number);
  15. u32 n = 0;
  16. size_t progress = 0;
  17. /* read numbers until the end or a non-number character appears */
  18. while(progress < buflen) {
  19. u8 c = buf[progress];
  20. if(c < '0' || c > '9')
  21. break;
  22. n = (n*10) + (u32)(c-'0');
  23. ++progress;
  24. }
  25. *number = n;
  26. return progress;
  27. }
  28. UA_StatusCode
  29. UA_parseEndpointUrl(const UA_String *endpointUrl, UA_String *outHostname,
  30. u16 *outPort, UA_String *outPath) {
  31. /* Url must begin with "opc.tcp://" */
  32. if(endpointUrl->length < 11 || strncmp((char*)endpointUrl->data, "opc.tcp://", 10) != 0)
  33. return UA_STATUSCODE_BADTCPENDPOINTURLINVALID;
  34. /* Where does the hostname end? */
  35. size_t curr = 10;
  36. if(endpointUrl->data[curr] == '[') {
  37. /* IPv6: opc.tcp://[2001:0db8:85a3::8a2e:0370:7334]:1234/path */
  38. for(; curr < endpointUrl->length; ++curr) {
  39. if(endpointUrl->data[curr] == ']')
  40. break;
  41. }
  42. if(curr == endpointUrl->length)
  43. return UA_STATUSCODE_BADTCPENDPOINTURLINVALID;
  44. curr++;
  45. } else {
  46. /* IPv4 or hostname: opc.tcp://something.something:1234/path */
  47. for(; curr < endpointUrl->length; ++curr) {
  48. if(endpointUrl->data[curr] == ':' || endpointUrl->data[curr] == '/')
  49. break;
  50. }
  51. }
  52. /* Set the hostname */
  53. outHostname->data = &endpointUrl->data[10];
  54. outHostname->length = curr - 10;
  55. if(curr == endpointUrl->length)
  56. return UA_STATUSCODE_GOOD;
  57. /* Set the port */
  58. if(endpointUrl->data[curr] == ':') {
  59. if(++curr == endpointUrl->length)
  60. return UA_STATUSCODE_BADTCPENDPOINTURLINVALID;
  61. u32 largeNum;
  62. size_t progress = UA_readNumber(&endpointUrl->data[curr], endpointUrl->length - curr, &largeNum);
  63. if(progress == 0 || largeNum > 65535)
  64. return UA_STATUSCODE_BADTCPENDPOINTURLINVALID;
  65. /* Test if the end of a valid port was reached */
  66. curr += progress;
  67. if(curr == endpointUrl->length || endpointUrl->data[curr] == '/')
  68. *outPort = (u16)largeNum;
  69. if(curr == endpointUrl->length)
  70. return UA_STATUSCODE_GOOD;
  71. }
  72. /* Set the path */
  73. UA_assert(curr < endpointUrl->length);
  74. if(endpointUrl->data[curr] != '/')
  75. return UA_STATUSCODE_BADTCPENDPOINTURLINVALID;
  76. if(++curr == endpointUrl->length)
  77. return UA_STATUSCODE_GOOD;
  78. outPath->data = &endpointUrl->data[curr];
  79. outPath->length = endpointUrl->length - curr;
  80. /* Remove trailing slash from the path */
  81. if(endpointUrl->data[endpointUrl->length - 1] == '/')
  82. outPath->length--;
  83. return UA_STATUSCODE_GOOD;
  84. }