Commit 752a8cfc authored by George Nash's avatar George Nash Committed by Kishen Maloor

Add oc_endpoint_string_parse_path function

This enables getting just the uri portion of an endpoint from
an endpoint string.

This is useful for a few reasons.
- The introspection contains an endpoint string to
  the introspection data. Since we typically already have the
  endpoint there is no need to used the oc_string_to_endpoint
  function and allocate another copy of the endpoint when we are
  only interested in the path part of the string.

- Language bindings with Java. Functions that return multiple
  values through variables require unusual workarounds to get
  a clean Java API.  By making this availible in a separate
  function we can make two functions with only one
  responability. Making the Java APIs cleaner.

While testing the oc_endpoint_string_parse_path function
multiple failures showed up in the StringToEndpoint unit test.
Once I figured out the failures were due to the fact that my
build did not have IPV4=1 I updated the StringToEndpoint test so
it will not test IPV4 strings if OC_IPV4 is not defined.
Signed-off-by: George Nash's avatarGeorge Nash <george.nash@intel.com>
parent b0e9dac7
Pipeline #211 passed with stage
in 48 seconds
......@@ -496,6 +496,52 @@ oc_string_to_endpoint(oc_string_t *endpoint_str, oc_endpoint_t *endpoint,
return -1;
}
int
oc_endpoint_string_parse_path(oc_string_t *endpoint_str, oc_string_t *path)
{
if (!endpoint_str) {
return -1;
}
if (!path) {
return -1;
}
const char *address = NULL;
address = strstr(oc_string(*endpoint_str), "://");
if(!address) {
return -1;
}
// 3 is string length of "://"
address += 3;
size_t len = oc_string_len(*endpoint_str) - (address - oc_string(*endpoint_str));
// the smallest possible address is '0' anything smaller is invalid.
if(len < 1) {
return -1;
}
/* Extract a uri path if available */
const char *path_start = NULL;
const char *query_start = NULL;
path_start = memchr(address, '/', len);
if (!path_start) {
// no path found return error
return -1;
}
query_start = memchr((address + (path_start - address)), '?',
(len - (path_start - address)));
if (query_start) {
oc_new_string(path, path_start, (query_start - path_start));
} else {
oc_new_string(path, path_start, (len - (path_start - address)));
}
return 0;
}
int
oc_ipv6_endpoint_is_link_local(oc_endpoint_t *endpoint)
{
......
......@@ -18,49 +18,70 @@
#include <cstdlib>
#include "oc_endpoint.h"
#include "oc_helpers.h"
TEST(OCEndpoints, StringToEndpoint)
{
const char *spu[4] = { "coaps://10.211.55.3:56789/a/light",
"coap://openconnectivity.org",
"coap://openconnectivity.org/alpha",
"coaps://openconnectivity.org:3456/alpha" };
for (int i = 0; i < 4; i++) {
#ifdef OC_IPV4
const char *spu0[1] = { "coaps://10.211.55.3:56789/a/light" };
for (int i = 0; i < 1; i++) {
oc_string_t s;
oc_new_string(&s, spu0[i], strlen(spu0[i]));
oc_endpoint_t ep;
memset(&ep, 0, sizeof(oc_endpoint_t));
oc_string_t uri;
memset(&uri, 0, sizeof(oc_string_t));
int ret = oc_string_to_endpoint(&s, &ep, &uri);
EXPECT_EQ(ret, 0) << "spu0[" << i << "] " << spu0[i];
switch (i) {
case 0: {
EXPECT_TRUE(ep.flags & IPV4);
EXPECT_TRUE(ep.flags & SECURED);
EXPECT_FALSE(ep.flags & TCP);
EXPECT_EQ(ep.addr.ipv4.port, 56789);
EXPECT_STREQ(oc_string(uri), "/a/light");
uint8_t addr[4] = { 10, 211, 55, 3 };
EXPECT_EQ(0, memcmp(ep.addr.ipv4.address, addr, 4));
} break;
default:
break;
}
oc_free_string(&s);
oc_free_string(&uri);
}
#endif /* OC_IPV4 */
const char *spu1[3] = { "coap://openconnectivity.org",
"coap://openconnectivity.org/alpha",
"coaps://openconnectivity.org:3456/alpha" };
for (int i = 0; i < 3; i++) {
oc_string_t s;
oc_new_string(&s, spu[i], strlen(spu[i]));
oc_new_string(&s, spu1[i], strlen(spu1[i]));
oc_endpoint_t ep;
memset(&ep, 0, sizeof(oc_endpoint_t));
oc_string_t uri;
memset(&uri, 0, sizeof(oc_string_t));
int ret = oc_string_to_endpoint(&s, &ep, &uri);
EXPECT_EQ(ret, 0) << "spu[" << i << "] " << spu[i];
EXPECT_EQ(ret, 0) << "spu1[" << i << "] " << spu1[i];
switch (i) {
case 0: {
EXPECT_TRUE(ep.flags & IPV4);
EXPECT_TRUE(ep.flags & SECURED);
EXPECT_FALSE(ep.flags & TCP);
EXPECT_EQ(ep.addr.ipv4.port, 56789);
EXPECT_STREQ(oc_string(uri), "/a/light");
uint8_t addr[4] = { 10, 211, 55, 3 };
EXPECT_EQ(0, memcmp(ep.addr.ipv4.address, addr, 4));
} break;
case 1:
case 0:
ASSERT_TRUE((ep.flags & IPV4) || (ep.flags & IPV6));
ASSERT_FALSE(ep.flags & SECURED);
ASSERT_FALSE(ep.flags & TCP);
EXPECT_EQ(ep.addr.ipv4.port, 5683);
EXPECT_EQ(oc_string_len(uri), 0);
break;
case 2:
case 1:
ASSERT_TRUE((ep.flags & IPV4) || (ep.flags & IPV6));
ASSERT_FALSE(ep.flags & SECURED);
ASSERT_FALSE(ep.flags & TCP);
EXPECT_EQ(ep.addr.ipv4.port, 5683);
EXPECT_STREQ(oc_string(uri), "/alpha");
break;
case 3:
case 2:
ASSERT_TRUE((ep.flags & IPV4) || (ep.flags & IPV6));
ASSERT_TRUE(ep.flags & SECURED);
ASSERT_FALSE(ep.flags & TCP);
......@@ -75,50 +96,70 @@ TEST(OCEndpoints, StringToEndpoint)
}
#ifdef OC_TCP
const char *spu2[6] = { "coaps+tcp://10.211.55.3/a/light",
"coap+tcp://1.2.3.4:2568",
"coaps+tcp://openconnectivity.org:3456",
#ifdef OC_IPV4
const char *spu2[2] = { "coaps+tcp://10.211.55.3/a/light",
"coap+tcp://1.2.3.4:2568"};
for (int i = 0; i < 2; i++) {
oc_string_t s;
oc_new_string(&s, spu2[i], strlen(spu2[i]));
oc_endpoint_t ep;
memset(&ep, 0, sizeof(oc_endpoint_t));
oc_string_t uri;
memset(&uri, 0, sizeof(oc_string_t));
int ret = oc_string_to_endpoint(&s, &ep, &uri);
EXPECT_EQ(ret, 0) << "spu2[" << i << "] " << spu2[i];
switch (i) {
case 0: {
EXPECT_TRUE(ep.flags & IPV4);
EXPECT_TRUE(ep.flags & SECURED);
EXPECT_TRUE(ep.flags & TCP);
EXPECT_EQ(ep.addr.ipv4.port, 5684);
EXPECT_STREQ(oc_string(uri), "/a/light");
uint8_t addr[4] = { 10, 211, 55, 3 };
EXPECT_EQ(0, memcmp(ep.addr.ipv4.address, addr, 4));
} break;
case 1: {
EXPECT_TRUE(ep.flags & IPV4);
EXPECT_FALSE(ep.flags & SECURED);
EXPECT_TRUE(ep.flags & TCP);
EXPECT_EQ(ep.addr.ipv4.port, 2568);
EXPECT_EQ(oc_string_len(uri), 0);
uint8_t addr[4] = { 1, 2, 3, 4 };
EXPECT_EQ(0, memcmp(ep.addr.ipv4.address, addr, 4));
} break;
default:
break;
}
oc_free_string(&s);
oc_free_string(&uri);
}
#endif /* OC_IPV4 */
const char *spu3[4] = { "coaps+tcp://openconnectivity.org:3456",
"coap+tcp://[ff02::158]",
"coaps+tcp://[ff02::158]/a/light",
"coaps+tcp://[fe80::12]:2439/a/light" };
for (int i = 0; i < 6; i++) {
for (int i = 0; i < 4; i++) {
oc_string_t s;
oc_new_string(&s, spu2[i], strlen(spu2[i]));
oc_new_string(&s, spu3[i], strlen(spu3[i]));
oc_endpoint_t ep;
memset(&ep, 0, sizeof(oc_endpoint_t));
oc_string_t uri;
memset(&uri, 0, sizeof(oc_string_t));
int ret = oc_string_to_endpoint(&s, &ep, &uri);
EXPECT_EQ(ret, 0) << "spu2[" << i << "] " << spu2[i];
EXPECT_EQ(ret, 0) << "spu3[" << i << "] " << spu3[i];
switch (i) {
case 0: {
EXPECT_TRUE(ep.flags & IPV4);
EXPECT_TRUE(ep.flags & SECURED);
EXPECT_TRUE(ep.flags & TCP);
EXPECT_EQ(ep.addr.ipv4.port, 5684);
EXPECT_STREQ(oc_string(uri), "/a/light");
uint8_t addr[4] = { 10, 211, 55, 3 };
EXPECT_EQ(0, memcmp(ep.addr.ipv4.address, addr, 4));
} break;
case 1: {
EXPECT_TRUE(ep.flags & IPV4);
EXPECT_FALSE(ep.flags & SECURED);
EXPECT_TRUE(ep.flags & TCP);
EXPECT_EQ(ep.addr.ipv4.port, 2568);
EXPECT_EQ(oc_string_len(uri), 0);
uint8_t addr[4] = { 1, 2, 3, 4 };
EXPECT_EQ(0, memcmp(ep.addr.ipv4.address, addr, 4));
} break;
case 2:
case 0:
ASSERT_TRUE((ep.flags & IPV4) || (ep.flags & IPV6));
ASSERT_TRUE(ep.flags & SECURED);
ASSERT_TRUE(ep.flags & TCP);
EXPECT_EQ(ep.addr.ipv4.port, 3456);
EXPECT_EQ(oc_string_len(uri), 0);
break;
case 3: {
case 1: {
ASSERT_TRUE(ep.flags & IPV6);
ASSERT_FALSE(ep.flags & SECURED);
ASSERT_TRUE(ep.flags & TCP);
......@@ -128,7 +169,7 @@ TEST(OCEndpoints, StringToEndpoint)
0, 0, 0, 0, 0, 0, 0x01, 0x58 };
EXPECT_EQ(0, memcmp(ep.addr.ipv6.address, addr, 16));
} break;
case 4: {
case 2: {
ASSERT_TRUE(ep.flags & IPV6);
ASSERT_TRUE(ep.flags & SECURED);
ASSERT_TRUE(ep.flags & TCP);
......@@ -138,7 +179,7 @@ TEST(OCEndpoints, StringToEndpoint)
EXPECT_EQ(0, memcmp(ep.addr.ipv6.address, addr, 16));
EXPECT_STREQ(oc_string(uri), "/a/light");
} break;
case 5: {
case 3: {
ASSERT_TRUE(ep.flags & IPV6);
ASSERT_TRUE(ep.flags & SECURED);
ASSERT_TRUE(ep.flags & TCP);
......@@ -156,19 +197,141 @@ TEST(OCEndpoints, StringToEndpoint)
}
// test dns lookup when uri is NULL
const char *spu3[4] = { "coap://10.211.55.3:56789/a/light",
const char *spu4[4] = { "coap://10.211.55.3:56789/a/light",
"coaps+tcp://10.211.55.3/a/light",
"coap://openconnectivity.org/alpha",
"coaps://openconnectivity.org:3456/alpha" };
for (int i = 0; i < 4; i++) {
oc_string_t s;
oc_new_string(&s, spu3[i], strlen(spu[i]));
oc_new_string(&s, spu4[i], strlen(spu4[i]));
oc_endpoint_t ep;
memset(&ep, 0, sizeof(oc_endpoint_t));
int ret = oc_string_to_endpoint(&s, &ep, NULL);
EXPECT_EQ(ret, 0) << "spu3[" << i << "] " << spu3[i];
EXPECT_EQ(ret, 0) << "spu4[" << i << "] " << spu4[i];
}
#endif
}
TEST(OCEndpoints, EndpointStringParsePath)
{
const char *spu[12] = { "coaps://10.211.55.3:56789/a/light",
"coap://openconnectivity.org",
"coap://openconnectivity.org/alpha",
"coaps://openconnectivity.org:3456/alpha",
"coaps+tcp://10.211.55.3/a/light",
"coap+tcp://1.2.3.4:2568",
"coaps+tcp://openconnectivity.org:3456",
"coap+tcp://[ff02::158]",
"coaps+tcp://[ff02::158]/a/light",
"coaps+tcp://[fe80::12]:2439/a/light",
"coaps+tcp://[fe80::12]:2439/a/light?s=100",
"coap://0/foo"};
for (int i = 0; i < 12; i++) {
oc_string_t s;
oc_string_t path;
int ret = -1;
oc_new_string(&s, spu[i], strlen(spu[i]));
memset(&path, 0, sizeof(oc_string_t));
switch (i) {
case 0:
ret = oc_endpoint_string_parse_path(&s, &path);
EXPECT_EQ(0, ret) << "spu[" << i << "] " << spu[i];
EXPECT_STREQ(oc_string(path), "/a/light");
break;
case 1:
ret = oc_endpoint_string_parse_path(&s, &path);
EXPECT_EQ(-1, ret) << "spu[" << i << "] " << spu[i];
EXPECT_EQ(path.ptr, NULL);
break;
case 2:
ret = oc_endpoint_string_parse_path(&s, &path);
EXPECT_EQ(0, ret) << "spu[" << i << "] " << spu[i];
EXPECT_STREQ(oc_string(path), "/alpha");
break;
case 3:
ret = oc_endpoint_string_parse_path(&s, &path);
EXPECT_EQ(0, ret) << "spu[" << i << "] " << spu[i];
EXPECT_STREQ(oc_string(path), "/alpha");
break;
case 4:
ret = oc_endpoint_string_parse_path(&s, &path);
EXPECT_EQ(0, ret) << "spu[" << i << "] " << spu[i];
EXPECT_STREQ(oc_string(path), "/a/light");
break;
case 5:
ret = oc_endpoint_string_parse_path(&s, &path);
EXPECT_EQ(-1, ret) << "spu[" << i << "] " << spu[i];
EXPECT_EQ(path.ptr, NULL);
break;
case 6:
ret = oc_endpoint_string_parse_path(&s, &path);
EXPECT_EQ(-1, ret) << "spu[" << i << "] " << spu[i];
EXPECT_EQ(path.ptr, NULL);
break;
case 7:
ret = oc_endpoint_string_parse_path(&s, &path);
EXPECT_EQ(-1, ret) << "spu[" << i << "] " << spu[i];
EXPECT_EQ(path.ptr, NULL);
break;
case 8:
ret = oc_endpoint_string_parse_path(&s, &path);
EXPECT_EQ(0, ret) << "spu[" << i << "] " << spu[i];
EXPECT_STREQ(oc_string(path), "/a/light");
break;
case 9:
ret = oc_endpoint_string_parse_path(&s, &path);
EXPECT_EQ(0, ret) << "spu[" << i << "] " << spu[i];
EXPECT_STREQ(oc_string(path), "/a/light");
break;
case 10:
ret = oc_endpoint_string_parse_path(&s, &path);
EXPECT_EQ(0, ret) << "spu[" << i << "] " << spu[i];
EXPECT_STREQ(oc_string(path), "/a/light");
break;
case 11:
ret = oc_endpoint_string_parse_path(&s, &path);
EXPECT_EQ(0, ret) << "spu[" << i << "] " << spu[i];
EXPECT_STREQ(oc_string(path), "/foo");
break;
default:
break;
}
}
// paths with expected errors
const char *spu2[2] = { "coaps://", // no address
"coaps:/10.211.55.3:56789/a/light" // missing ://
};
for (int i = 0; i < 2; i++) {
oc_string_t s;
oc_new_string(&s, spu2[i], strlen(spu2[i]));
oc_string_t path;
memset(&path, 0, sizeof(oc_string_t));
int ret = oc_endpoint_string_parse_path(&s, &path);
EXPECT_EQ(-1, ret) << "spu2[" << i << "] " << spu2[i];
oc_free_string(&s);
oc_free_string(&path);
}
{
oc_string_t path;
int ret = oc_endpoint_string_parse_path(NULL, &path);
EXPECT_EQ(-1, ret);
if (-1 != ret) {
// If code is working as expected this should never run.
oc_free_string(&path);
}
}
{
oc_string_t s;
oc_new_string(&s, "coap://0/p", strlen("coap://0/p"));
EXPECT_EQ(-1, oc_endpoint_string_parse_path(&s, NULL));
oc_free_string(&s);
}
}
......@@ -89,6 +89,7 @@ void oc_endpoint_set_di(oc_endpoint_t *endpoint, oc_uuid_t *di);
int oc_endpoint_to_string(oc_endpoint_t *endpoint, oc_string_t *endpoint_str);
int oc_string_to_endpoint(oc_string_t *endpoint_str, oc_endpoint_t *endpoint,
oc_string_t *uri);
int oc_endpoint_string_parse_path(oc_string_t *endpoint_str, oc_string_t *path);
int oc_ipv6_endpoint_is_link_local(oc_endpoint_t *endpoint);
int oc_endpoint_compare(const oc_endpoint_t *ep1, const oc_endpoint_t *ep2);
int oc_endpoint_compare_address(oc_endpoint_t *ep1, oc_endpoint_t *ep2);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment