| /* |
| * |
| * Copyright (c) 2013-2017 Nest Labs, Inc. |
| * 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. |
| */ |
| |
| /** |
| * @file |
| * This file implements a class for managing and manipulating a Host |
| * Port List, a compact, binary-encoded collection of host and port |
| * identifier tuples associated with the Weave Service Directory. |
| * |
| */ |
| |
| #include "HostPortList.h" |
| |
| #include <Weave/Core/WeaveEncoding.h> |
| #include <Weave/Support/CodeUtils.h> |
| |
| namespace nl { |
| namespace Weave { |
| |
| using namespace nl::Weave::Encoding; |
| |
| /** |
| * Class default (void) constructor. |
| * |
| */ |
| HostPortList::HostPortList(void) |
| { |
| Clear(); |
| } |
| |
| /** |
| * Reset the list to empty. |
| * |
| */ |
| void HostPortList::Clear(void) |
| { |
| mElements = mSuffixTable = NULL; |
| mCount = mSuffixCount = 0; |
| } |
| |
| /** |
| * Get the host name and port at the specified index from the list. |
| * |
| * @param[in] index The position in the list to return the host |
| * name and port. |
| * |
| * @param[inout] hostBuf A pointer to storage into which to copy the |
| * host name. |
| * |
| * @param[in] hostBufSize The amount of storage available in hostBuf. |
| * |
| * @param[out] port The port number. |
| * |
| * @retval #WEAVE_ERROR_INVALID_ARGUMENT The requested index |
| * exceeds the size of |
| * the list. |
| * @retval #WEAVE_ERROR_UNSUPPORTED_HOST_PORT_ELEMENT The Host Port element |
| * requested was an |
| * unsupported type. |
| * @retval #WEAVE_ERROR_BUFFER_TOO_SMALL The Host Port host |
| * name length |
| * is longer |
| * than the |
| * provided |
| * buffer. |
| * @retval #WEAVE_NO_ERROR On success. |
| */ |
| WEAVE_ERROR HostPortList::Get(uint8_t index, char *hostBuf, uint32_t hostBufSize, uint16_t& port) const |
| { |
| WEAVE_ERROR err = WEAVE_NO_ERROR; |
| const uint8_t *elem; |
| |
| VerifyOrExit(index < mCount, err = WEAVE_ERROR_INVALID_ARGUMENT); |
| |
| elem = mElements; |
| for ( ; index > 0; index--) |
| { |
| err = Skip(elem); |
| SuccessOrExit(err); |
| } |
| |
| err = Get(elem, hostBuf, hostBufSize, port); |
| |
| exit: |
| return err; |
| } |
| |
| /** |
| * Get and remove the first host name and port from the list. |
| * |
| * @param[inout] hostBuf A pointer to storage into which to copy the |
| * host name. |
| * |
| * @param[in] hostBufSize The amount of storage available in hostBuf. |
| * |
| * @param[out] port The port number. |
| * |
| * @retval #WEAVE_ERROR_HOST_PORT_LIST_EMPTY There are no entries |
| * in the list. |
| * @retval #WEAVE_ERROR_UNSUPPORTED_HOST_PORT_ELEMENT The Host Port element |
| * encountered was an |
| * unsupported type. |
| * @retval #WEAVE_ERROR_BUFFER_TOO_SMALL The Host Port host |
| * name length |
| * is longer |
| * than the |
| * provided |
| * buffer. |
| * @retval #WEAVE_NO_ERROR On success. |
| */ |
| WEAVE_ERROR HostPortList::Pop(char *hostBuf, uint32_t hostBufSize, uint16_t& port) |
| { |
| WEAVE_ERROR err = WEAVE_NO_ERROR; |
| |
| VerifyOrExit(mCount > 0, err = WEAVE_ERROR_HOST_PORT_LIST_EMPTY); |
| |
| err = Get(mElements, hostBuf, hostBufSize, port); |
| if (err == WEAVE_NO_ERROR) |
| mCount--; |
| |
| exit: |
| return err; |
| } |
| |
| /** |
| * Get the host name and port at the specified element. |
| * |
| * @param[inout] elem The host name and port element to get. The |
| * pointer will be advanced to the next |
| * element on success and may be left in |
| * an indeterminate state on failure. |
| * |
| * @param[inout] hostBuf A pointer to storage into which to copy the |
| * host name. |
| * |
| * @param[in] hostBufSize The amount of storage available in hostBuf. |
| * |
| * @param[out] port The port number. |
| * |
| * @retval #WEAVE_ERROR_UNSUPPORTED_HOST_PORT_ELEMENT The Host Port element |
| * encountered was an |
| * unsupported type. |
| * @retval #WEAVE_ERROR_BUFFER_TOO_SMALL The Host Port host |
| * name length |
| * is longer |
| * than the |
| * provided |
| * buffer. |
| * @retval #WEAVE_NO_ERROR On success. |
| */ |
| WEAVE_ERROR HostPortList::Get(const uint8_t *& elem, char *hostBuf, uint32_t hostBufSize, uint16_t& port) const |
| { |
| WEAVE_ERROR err = WEAVE_NO_ERROR; |
| uint8_t control, type, hostLen; |
| |
| control = *elem++; |
| type = control & kHostPortControl_TypeMask; |
| VerifyOrExit(type == kHostPortType_FullyQualified || type == kHostPortType_Indexed, err = WEAVE_ERROR_UNSUPPORTED_HOST_PORT_ELEMENT); |
| |
| hostLen = *elem++; |
| VerifyOrExit(hostLen < hostBufSize, err = WEAVE_ERROR_BUFFER_TOO_SMALL); |
| |
| memcpy(hostBuf, elem, hostLen); |
| elem += hostLen; |
| |
| if ((control & kHostPortControl_HasSuffixIndex) != 0) |
| { |
| if (type == kHostPortType_Indexed) |
| { |
| uint8_t suffixLen; |
| err = GetSuffix(*elem, hostBuf + hostLen, hostBufSize - hostLen, suffixLen); |
| SuccessOrExit(err); |
| |
| hostLen += suffixLen; |
| } |
| |
| elem++; |
| } |
| |
| hostBuf[hostLen] = 0; |
| |
| if ((control & kHostPortControl_HasPort) != 0) |
| port = LittleEndian::Read16(elem); |
| else |
| port = WEAVE_PORT; |
| |
| exit: |
| return err; |
| } |
| |
| /** |
| * Skip the host name and port at the specified element. |
| * |
| * @param[inout] elem The host name and port element to skip. The pointer |
| * will be advanced to the next element on success and |
| * may be left in an indeterminate state on failure. |
| * |
| * @retval #WEAVE_ERROR_UNSUPPORTED_HOST_PORT_ELEMENT The Host Port element |
| * encountered was an |
| * unsupported type. |
| * @retval #WEAVE_NO_ERROR On success. |
| */ |
| WEAVE_ERROR HostPortList::Skip(const uint8_t *& elem) const |
| { |
| WEAVE_ERROR err = WEAVE_NO_ERROR; |
| uint8_t control, type, hostLen; |
| |
| control = *elem++; |
| type = control & kHostPortControl_TypeMask; |
| VerifyOrExit(type == kHostPortType_FullyQualified || type == kHostPortType_Indexed, err = WEAVE_ERROR_UNSUPPORTED_HOST_PORT_ELEMENT); |
| |
| hostLen = *elem++; |
| elem += hostLen; |
| |
| if ((control & kHostPortControl_HasSuffixIndex) != 0) |
| elem++; |
| |
| if ((control & kHostPortControl_HasPort) != 0) |
| elem += 2; |
| |
| exit: |
| return err; |
| } |
| |
| /** |
| * Get the Host Port element host name suffix (e.g. ".acme.com") at the |
| * specified position in the list. |
| * |
| * @param[in] index The position in the list to return the host |
| * name suffix. |
| * |
| * @param[inout] buf A pointer to storage into which to copy the |
| * host name suffix. |
| * |
| * @param[in] bufSize The amount of storage available in buf. |
| * |
| * @param[out] suffixLen The length, in characters, of the host name |
| * suffix. |
| * |
| * @retval #WEAVE_ERROR_INVALID_HOST_SUFFIX_INDEX The requested index |
| * exceeds the size of the |
| * list. |
| * @retval #WEAVE_ERROR_BUFFER_TOO_SMALL The Host Port host |
| * suffix name length is |
| * longer than the provided |
| * buffer. |
| * @retval #WEAVE_NO_ERROR On success. |
| * |
| */ |
| WEAVE_ERROR HostPortList::GetSuffix(uint8_t index, char *buf, uint32_t bufSize, uint8_t& suffixLen) const |
| { |
| WEAVE_ERROR err = WEAVE_NO_ERROR; |
| const uint8_t *elem; |
| |
| VerifyOrExit(index < mSuffixCount, err = WEAVE_ERROR_INVALID_HOST_SUFFIX_INDEX); |
| |
| elem = mSuffixTable; |
| for ( ; index > 0; index--) |
| elem += 1 + elem[0]; |
| |
| suffixLen = *elem++; |
| VerifyOrExit(suffixLen < bufSize, err = WEAVE_ERROR_BUFFER_TOO_SMALL); |
| |
| memcpy(buf, elem, suffixLen); |
| buf[suffixLen] = 0; |
| |
| exit: |
| return err; |
| } |
| |
| |
| } /* namespace Weave */ |
| } /* namespace nl */ |