ua_util.c 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  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. #include "ua_util.h"
  5. #include "ua_plugin_network.h"
  6. size_t
  7. UA_readNumber(u8 *buf, size_t buflen, u32 *number) {
  8. UA_assert(buf);
  9. UA_assert(number);
  10. u32 n = 0;
  11. size_t progress = 0;
  12. /* read numbers until the end or a non-number character appears */
  13. while(progress < buflen) {
  14. u8 c = buf[progress];
  15. if(c < '0' || c > '9')
  16. break;
  17. n = (n*10) + (u32)(c-'0');
  18. ++progress;
  19. }
  20. *number = n;
  21. return progress;
  22. }
  23. UA_StatusCode
  24. UA_parseEndpointUrl(const UA_String *endpointUrl, UA_String *outHostname,
  25. u16 *outPort, UA_String *outPath) {
  26. /* Url must begin with "opc.tcp://" */
  27. if(endpointUrl->length < 11 || strncmp((char*)endpointUrl->data, "opc.tcp://", 10) != 0)
  28. return UA_STATUSCODE_BADTCPENDPOINTURLINVALID;
  29. /* Where does the hostname end? */
  30. size_t curr = 10;
  31. if(endpointUrl->data[curr] == '[') {
  32. /* IPv6: opc.tcp://[2001:0db8:85a3::8a2e:0370:7334]:1234/path */
  33. for(; curr < endpointUrl->length; ++curr) {
  34. if(endpointUrl->data[curr] == ']')
  35. break;
  36. }
  37. if(curr == endpointUrl->length)
  38. return UA_STATUSCODE_BADTCPENDPOINTURLINVALID;
  39. curr++;
  40. } else {
  41. /* IPv4 or hostname: opc.tcp://something.something:1234/path */
  42. for(; curr < endpointUrl->length; ++curr) {
  43. if(endpointUrl->data[curr] == ':' || endpointUrl->data[curr] == '/')
  44. break;
  45. }
  46. }
  47. /* Set the hostname */
  48. outHostname->data = &endpointUrl->data[10];
  49. outHostname->length = curr - 10;
  50. if(curr == endpointUrl->length)
  51. return UA_STATUSCODE_GOOD;
  52. /* Set the port */
  53. if(endpointUrl->data[curr] == ':') {
  54. if(++curr == endpointUrl->length)
  55. return UA_STATUSCODE_BADTCPENDPOINTURLINVALID;
  56. u32 largeNum;
  57. size_t progress = UA_readNumber(&endpointUrl->data[curr], endpointUrl->length - curr, &largeNum);
  58. if(progress == 0 || largeNum > 65535)
  59. return UA_STATUSCODE_BADTCPENDPOINTURLINVALID;
  60. /* Test if the end of a valid port was reached */
  61. curr += progress;
  62. if(curr == endpointUrl->length || endpointUrl->data[curr] == '/')
  63. *outPort = (u16)largeNum;
  64. if(curr == endpointUrl->length)
  65. return UA_STATUSCODE_GOOD;
  66. }
  67. /* Set the path */
  68. UA_assert(curr < endpointUrl->length);
  69. if(endpointUrl->data[curr] != '/')
  70. return UA_STATUSCODE_BADTCPENDPOINTURLINVALID;
  71. if(++curr == endpointUrl->length)
  72. return UA_STATUSCODE_GOOD;
  73. outPath->data = &endpointUrl->data[curr];
  74. outPath->length = endpointUrl->length - curr;
  75. /* Remove trailing slash from the path */
  76. if(endpointUrl->data[endpointUrl->length - 1] == '/')
  77. outPath->length--;
  78. return UA_STATUSCODE_GOOD;
  79. }