blob: eadc44de34e2e5b6a63ecf5ac058783dc5f333ee [file] [log] [blame]
/*
*
* Copyright (c) 2018 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
* General utility functions available on all platforms.
*/
#include <Weave/DeviceLayer/internal/WeaveDeviceLayerInternal.h>
namespace nl {
namespace Weave {
namespace DeviceLayer {
WEAVE_ERROR ParseCompilerDateStr(const char * dateStr, uint16_t & year, uint8_t & month, uint8_t & dayOfMonth)
{
WEAVE_ERROR err = WEAVE_NO_ERROR;
char monthStr[4];
const char * p;
char* endptr;
static const char months[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
VerifyOrExit(strlen(dateStr) == 11, err = WEAVE_ERROR_INVALID_ARGUMENT);
memcpy(monthStr, dateStr, 3);
monthStr[3] = 0;
p = strstr(months, monthStr);
VerifyOrExit(p != NULL, err = WEAVE_ERROR_INVALID_ARGUMENT);
month = ((p - months) / 3) + 1;
dayOfMonth = strtoul(dateStr + 4, &endptr, 10);
VerifyOrExit(endptr == dateStr + 6, err = WEAVE_ERROR_INVALID_ARGUMENT);
year = strtoul(dateStr + 7, &endptr, 10);
VerifyOrExit(endptr == dateStr + 11, err = WEAVE_ERROR_INVALID_ARGUMENT);
exit:
return err;
}
WEAVE_ERROR Parse24HourTimeStr(const char * timeStr, uint8_t & hour, uint8_t & minute, uint8_t & second)
{
WEAVE_ERROR err = WEAVE_NO_ERROR;
char * p;
VerifyOrExit(strlen(timeStr) == 8, err = WEAVE_ERROR_INVALID_ARGUMENT);
hour = strtoul(timeStr, &p, 10);
VerifyOrExit(p == timeStr + 2, err = WEAVE_ERROR_INVALID_ARGUMENT);
minute = strtoul(timeStr + 3, &p, 10);
VerifyOrExit(p == timeStr + 5, err = WEAVE_ERROR_INVALID_ARGUMENT);
second = strtoul(timeStr + 6, &p, 10);
VerifyOrExit(p == timeStr + 8, err = WEAVE_ERROR_INVALID_ARGUMENT);
exit:
return err;
}
const char * CharacterizeIPv6Address(const IPAddress & ipAddr)
{
if (ipAddr.IsIPv6LinkLocal())
{
return "IPv6 link-local address";
}
else if (ipAddr.IsIPv6ULA())
{
if (FabricState.FabricId != kFabricIdNotSpecified && ipAddr.GlobalId() == nl::Weave::WeaveFabricIdToIPv6GlobalId(FabricState.FabricId))
{
switch (ipAddr.Subnet())
{
case kWeaveSubnetId_PrimaryWiFi:
return "Weave WiFi subnet address";
case kWeaveSubnetId_Service:
return "Weave Service subnet address";
case kWeaveSubnetId_ThreadMesh:
return "Weave Thread subnet address";
case kWeaveSubnetId_ThreadAlarm:
return "Weave Thread Alarm subnet address";
case kWeaveSubnetId_WiFiAP:
return "Weave WiFi AP subnet address";
case kWeaveSubnetId_MobileDevice:
return "Weave Mobile subnet address";
default:
return "Weave IPv6 address";
}
}
else
{
return "IPv6 unique local address";
}
}
else if ((ntohl(ipAddr.Addr[0]) & 0xE0000000U) == 0x20000000U)
{
return "IPv6 global unicast address";
}
return "IPv6 address";
}
const char * CharacterizeIPv6Prefix(const Inet::IPPrefix & inPrefix)
{
if (inPrefix.IPAddr.IsIPv6ULA())
{
if (::nl::Weave::DeviceLayer::FabricState.FabricId != kFabricIdNotSpecified &&
inPrefix.IPAddr.GlobalId() == nl::Weave::WeaveFabricIdToIPv6GlobalId(::nl::Weave::DeviceLayer::FabricState.FabricId))
{
if (inPrefix.Length == 48)
{
return "Weave fabric prefix";
}
if (inPrefix.Length == 64)
{
switch (inPrefix.IPAddr.Subnet())
{
case kWeaveSubnetId_PrimaryWiFi:
return "Weave WiFi prefix";
case kWeaveSubnetId_Service:
return "Weave Service prefix";
case kWeaveSubnetId_ThreadMesh:
return "Weave Thread prefix";
case kWeaveSubnetId_ThreadAlarm:
return "Weave Thread Alarm prefix";
case kWeaveSubnetId_WiFiAP:
return "Weave WiFi AP prefix";
case kWeaveSubnetId_MobileDevice:
return "Weave Mobile prefix";
default:
return "Weave IPv6 prefix";
}
}
}
}
return NULL;
}
/**
* Register a text error formatter for Device Layer errors.
*/
void RegisterDeviceLayerErrorFormatter(void)
{
static ErrorFormatter sDeviceLayerErrorFormatter =
{
FormatDeviceLayerError,
NULL
};
RegisterErrorFormatter(&sDeviceLayerErrorFormatter);
}
/**
* Given Device Layer error, returns a human-readable NULL-terminated C string
* describing the error.
*
* @param[in] buf Buffer into which the error string will be placed.
* @param[in] bufSize Size of the supplied buffer in bytes.
* @param[in] err The error to be described.
*
* @return true If a descriptions string was written into the supplied buffer.
* @return false If the supplied error was not a Device Layer error.
*
*/
bool FormatDeviceLayerError(char * buf, uint16_t bufSize, int32_t err)
{
const char * desc = NULL;
if (err < WEAVE_DEVICE_ERROR_MIN || err > WEAVE_DEVICE_ERROR_MAX)
{
return false;
}
#if !WEAVE_CONFIG_SHORT_ERROR_STR
switch (err)
{
case WEAVE_DEVICE_ERROR_CONFIG_NOT_FOUND : desc = "Config not found"; break;
case WEAVE_DEVICE_ERROR_NOT_SERVICE_PROVISIONED : desc = "Not service provisioned"; break;
}
#endif // !WEAVE_CONFIG_SHORT_ERROR_STR
FormatError(buf, bufSize, "Device Layer", err, desc);
return true;
}
} // namespace DeviceLayer
} // namespace Weave
} // namespace nl