static const char COAP_HEADER[] = "coap://[::]/";
static uint32_t SEED = 0;
+/**
+ * Helper that uses libcoap to parse either the path or the parameters of a URI
+ * and populate the supplied options list.
+ *
+ * @param str the input partial URI string (either path or query).
+ * @param length the length of the supplied partial URI.
+ * @param target the part of the URI to parse (either COAP_OPTION_URI_PATH
+ * or COAP_OPTION_URI_QUERY).
+ * @param optlist options information.
+ */
+static void CAParseUriPartial(const unsigned char *str, size_t length,
+ int target, coap_list_t **optlist);
+
void CAGetRequestInfoFromPdu(const coap_pdu_t *pdu, CARequestInfo_t *outReqInfo, char *outUri,
uint32_t buflen)
{
coap_uri_t uri;
coap_split_uri((unsigned char *) uriInfo, strlen(uriInfo), &uri);
- unsigned char portbuf[2];
if (uri.port != COAP_DEFAULT_PORT)
{
+ unsigned char portbuf[2];
coap_insert(
optlist,
CACreateNewOptionNode(COAP_OPTION_URI_PORT,
CAOrderOpts);
}
- unsigned char uriBuffer[CA_BUFSIZE] =
- { 0 };
- unsigned char *pBuf = uriBuffer;
- uint32_t buflen;
- int32_t res;
- if (uri.path.length)
- {
- buflen = CA_BUFSIZE;
- res = coap_split_path(uri.path.s, uri.path.length, pBuf, &buflen);
+ CAParseUriPartial(uri.path.s, uri.path.length, COAP_OPTION_URI_PATH, optlist);
- if (res > 0)
- {
- uint32_t prevIdx = 0;
- while (res--)
- {
- coap_insert(
- optlist,
- CACreateNewOptionNode(COAP_OPTION_URI_PATH, COAP_OPT_LENGTH(pBuf),
- COAP_OPT_VALUE(pBuf)),
- CAOrderOpts);
+ CAParseUriPartial(uri.query.s, uri.query.length, COAP_OPTION_URI_QUERY, optlist);
- uint32_t optSize = COAP_OPT_SIZE(pBuf);
- uint32_t nextIdx = prevIdx + optSize;
- if (nextIdx < buflen)
- {
- pBuf += optSize;
- prevIdx += nextIdx;
- }
- }
- }
- }
+ OIC_LOG(DEBUG, TAG, "CAParseURI OUT");
+}
- if (uri.query.length)
+void CAParseUriPartial(const unsigned char *str, size_t length,
+ int target, coap_list_t **optlist)
+{
+ if ((target != COAP_OPTION_URI_PATH) && (target != COAP_OPTION_URI_QUERY))
{
- buflen = CA_BUFSIZE;
- pBuf = uriBuffer;
- res = coap_split_query(uri.query.s, uri.query.length, pBuf, &buflen);
+ // should never occur. Log just in case.
+ OIC_LOG(DEBUG, TAG, "Unexpected URI component.");
+ }
+ else if (str && length)
+ {
+ unsigned char uriBuffer[CA_BUFSIZE] = { 0 };
+ unsigned char *pBuf = uriBuffer;
+ size_t buflen = sizeof(uriBuffer);
+ int res = (target == COAP_OPTION_URI_PATH) ?
+ coap_split_path(str, length, pBuf, &buflen) :
+ coap_split_query(str, length, pBuf, &buflen);
if (res > 0)
{
- uint32_t prevIdx = 0;
+ size_t prevIdx = 0;
while (res--)
{
coap_insert(
optlist,
- CACreateNewOptionNode(COAP_OPTION_URI_QUERY, COAP_OPT_LENGTH(pBuf),
+ CACreateNewOptionNode(target, COAP_OPT_LENGTH(pBuf),
COAP_OPT_VALUE(pBuf)),
CAOrderOpts);
- uint32_t optSize = COAP_OPT_SIZE(pBuf);
- uint32_t nextIdx = prevIdx + optSize;
- if (nextIdx < buflen)
+ size_t optSize = COAP_OPT_SIZE(pBuf);
+ if ((prevIdx + optSize) < buflen)
{
pBuf += optSize;
- prevIdx += nextIdx;
+ prevIdx += optSize;
}
}
}
+ else
+ {
+ OIC_LOG_V(DEBUG, TAG, "Problem parsing URI : %d for %d", res, target);
+ }
}
-
- OIC_LOG(DEBUG, TAG, "CAParseURI OUT");
}
void CAParseHeadOption(const uint32_t code, const CAInfo_t info, coap_list_t **optlist)
--- /dev/null
+//******************************************************************
+//
+// Copyright 2015 Samsung Electronics All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#include <stdio.h>
+
+#include "gtest/gtest.h"
+
+#include "caprotocolmessage.h"
+
+namespace {
+
+static const char COAP_HEADER[] = "coap://[::]/";
+
+class CoAPOptionCase
+{
+public:
+ unsigned short key;
+ unsigned int length;
+ std::string dataStr; // data could be binary... for testing we'll use str
+};
+
+
+
+/**
+ * Helper to validate the state of CoAP URI parsing.
+ *
+ * @param cases array of expected parse results.
+ * @param numCases number of expected parse results.
+ * @param optlist parsed option list to verify.
+ */
+void verifyParsedOptions(CoAPOptionCase const *cases,
+ size_t numCases,
+ coap_list_t *optlist)
+{
+ size_t index = 0;
+ for (coap_list_t *opt = optlist; opt; opt = opt->next)
+ {
+ coap_option *option = (coap_option *) opt->data;
+ EXPECT_TRUE(option != NULL);
+ EXPECT_LT(index, numCases);
+ if (option && (index < numCases))
+ {
+ unsigned short key = COAP_OPTION_KEY(*option);
+ unsigned int length = COAP_OPTION_LENGTH(*option);
+ std::string dataStr((const char*)COAP_OPTION_DATA(*option), length);
+ // First validate the test case:
+ EXPECT_EQ(cases[index].length, cases[index].dataStr.length());
+
+ // Ensure data matches expected parsing
+ EXPECT_EQ(cases[index].key, key);
+ EXPECT_EQ(cases[index].length, length);
+ EXPECT_EQ(cases[index].dataStr, dataStr);
+ }
+
+ index++;
+ }
+ // Ensure we saw the proper number of parts:
+ EXPECT_EQ(numCases, index);
+}
+
+} // namespace
+
+TEST(CAProtocolMessage, CAParseURIBase)
+{
+ char sampleURI[] = "coap://[::]/oc/core?rt=core.sensor&if=core.mi.ll";
+
+ CoAPOptionCase cases[] = {
+ {COAP_OPTION_URI_PATH, 2, "oc"},
+ {COAP_OPTION_URI_PATH, 4, "core"},
+ {COAP_OPTION_URI_QUERY, 14, "rt=core.sensor"},
+ {COAP_OPTION_URI_QUERY, 13, "if=core.mi.ll"},
+ };
+ size_t numCases = sizeof(cases) / sizeof(cases[0]);
+
+
+ coap_list_t *optlist = NULL;
+ CAParseURI(sampleURI, &optlist);
+
+
+ verifyParsedOptions(cases, numCases, optlist);
+}
+
+// Try for multiple URI path components that still total less than 128
+TEST(CAProtocolMessage, CAParseURIManyPath)
+{
+ char sampleURI[] = "coap://[::]"
+ "/medium/a/b/c/d/e/f/g/h/i/j/"
+ "?rt=core.sensor&if=core.mi.ll";
+
+ CoAPOptionCase cases[] = {
+ {COAP_OPTION_URI_PATH, 6, "medium"},
+ {COAP_OPTION_URI_PATH, 1, "a"},
+ {COAP_OPTION_URI_PATH, 1, "b"},
+ {COAP_OPTION_URI_PATH, 1, "c"},
+ {COAP_OPTION_URI_PATH, 1, "d"},
+ {COAP_OPTION_URI_PATH, 1, "e"},
+ {COAP_OPTION_URI_PATH, 1, "f"},
+ {COAP_OPTION_URI_PATH, 1, "g"},
+ {COAP_OPTION_URI_PATH, 1, "h"},
+ {COAP_OPTION_URI_PATH, 1, "i"},
+ {COAP_OPTION_URI_PATH, 1, "j"},
+ {COAP_OPTION_URI_QUERY, 14, "rt=core.sensor"},
+ {COAP_OPTION_URI_QUERY, 13, "if=core.mi.ll"},
+ };
+ size_t numCases = sizeof(cases) / sizeof(cases[0]);
+
+
+ coap_list_t *optlist = NULL;
+ CAParseURI(sampleURI, &optlist);
+
+
+ verifyParsedOptions(cases, numCases, optlist);
+}
+
+// Try for multiple URI parameters that still total less than 128
+TEST(CAProtocolMessage, CAParseURIManyParams)
+{
+ char sampleURI[] = "coap://[::]/oc/core/"
+ "?rt=core.sensor&a=0&b=1&c=2&d=3&e=4&f=5&g=6&h=7&i=8&j=9";
+
+ CoAPOptionCase cases[] = {
+ {COAP_OPTION_URI_PATH, 2, "oc"},
+ {COAP_OPTION_URI_PATH, 4, "core"},
+ {COAP_OPTION_URI_QUERY, 14, "rt=core.sensor"},
+ {COAP_OPTION_URI_QUERY, 3, "a=0"},
+ {COAP_OPTION_URI_QUERY, 3, "b=1"},
+ {COAP_OPTION_URI_QUERY, 3, "c=2"},
+ {COAP_OPTION_URI_QUERY, 3, "d=3"},
+ {COAP_OPTION_URI_QUERY, 3, "e=4"},
+ {COAP_OPTION_URI_QUERY, 3, "f=5"},
+ {COAP_OPTION_URI_QUERY, 3, "g=6"},
+ {COAP_OPTION_URI_QUERY, 3, "h=7"},
+ {COAP_OPTION_URI_QUERY, 3, "i=8"},
+ {COAP_OPTION_URI_QUERY, 3, "j=9"},
+ };
+ size_t numCases = sizeof(cases) / sizeof(cases[0]);
+
+
+ coap_list_t *optlist = NULL;
+ CAParseURI(sampleURI, &optlist);
+
+
+ verifyParsedOptions(cases, numCases, optlist);
+}
+
+// Test that an initial long path component won't hide latter ones.
+TEST(CAProtocolMessage, CAParseURILongPath)
+{
+ char sampleURI[] = "coap://[::]/oc"
+ "123456789012345678901234567890123456789012345678901234567890"
+ "12345678901234567890123456789012345678901234567890"
+ "/core?rt=core.sensor&if=core.mi.ll";
+
+ CoAPOptionCase cases[] = {
+ {COAP_OPTION_URI_PATH, 112, "oc"
+ "123456789012345678901234567890123456789012345678901234567890"
+ "12345678901234567890123456789012345678901234567890"},
+ {COAP_OPTION_URI_PATH, 4, "core"},
+ {COAP_OPTION_URI_QUERY, 14, "rt=core.sensor"},
+ {COAP_OPTION_URI_QUERY, 13, "if=core.mi.ll"},
+ };
+ size_t numCases = sizeof(cases) / sizeof(cases[0]);
+
+
+ coap_list_t *optlist = NULL;
+ CAParseURI(sampleURI, &optlist);
+
+
+ verifyParsedOptions(cases, numCases, optlist);
+}