blob: 755129bb690b0632d77e817959093ffba6e6ad36 [file] [log] [blame]
/* -*- Mode: C++; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil -*-
*
* Copyright (c) 2013-2016 Nest Labs, Inc.
* All rights reserved.
*
* This document is the property of Nest. It is considered
* confidential and proprietary information.
*
* This document may not be reproduced or transmitted in any form,
* in whole or in part, without the express written permission of
* Nest.
*
*/
/**
* @file
* This file defines constants, classes, and messages used by the Weave Alarm Profile.
*
*/
#ifndef _WEAVE_ALARM_PROFILE_H
#define _WEAVE_ALARM_PROFILE_H
// __STDC_FORMAT_MACROS must be defined for PRIX64 to be defined for pre-C++11 clib
#ifndef __STDC_FORMAT_MACROS
#define __STDC_FORMAT_MACROS
#endif // __STDC_FORMAT_MACROS
// __STDC_LIMIT_MACROS must be defined for UINT8_MAX and INT32_MAX to be defined for pre-C++11 clib
#ifndef __STDC_LIMIT_MACROS
#define __STDC_LIMIT_MACROS
#endif // __STDC_LIMIT_MACROS
// __STDC_CONSTANT_MACROS must be defined for INT64_C and UINT64_C to be defined for pre-C++11 clib
#ifndef __STDC_CONSTANT_MACROS
#define __STDC_CONSTANT_MACROS
#endif // __STDC_CONSTANT_MACROS
// it is important for this first inclusion of inttypes.h to have all the right switches turned ON
#include <inttypes.h>
#include <Weave/Support/NLDLLUtil.h>
#include <Weave/Core/WeaveCore.h>
#include <Weave/Core/WeaveServerBase.h>
#include <Weave/Profiles/ProfileCommon.h>
#include <Weave/Support/crypto/HMAC.h>
/**
* @name Alarm state definitions
*
* Alarm conditions are composed of the alarm source and alarm state.
* Alarm state occupies the lower four bits of the alarm condition.
* The following states are defined at this time:
*
* @{
*/
/**
* @def WEAVE_ALARM_STATE_STANDBY
*
* @brief
* Alarm state indicating that the alarm is in the "all clear" state.
*
*/
#define WEAVE_ALARM_STATE_STANDBY 0x00
/**
* @def WEAVE_ALARM_STATE_HEADS_UP_1
*
* @brief
* Pre-alarm state: the first heads-up threshold was exceeded
*
*/
#define WEAVE_ALARM_STATE_HEADS_UP_1 0x01
/**
* @def WEAVE_ALARM_STATE_HEADS_UP_2
*
* @brief
* Pre-alarm state: the second heads-up threshold was exceeded
*
*/
#define WEAVE_ALARM_STATE_HEADS_UP_2 0x02
/**
* @def WEAVE_ALARM_STATE_HU_HUSH
*
* @brief
* Pre-alarm state: the alarm was hushed either in heads up 1 or
* heads up 2 state.
*
*/
#define WEAVE_ALARM_STATE_HU_HUSH 0x03
/**
* @def WEAVE_ALARM_STATE_ALARM_HUSHABLE
*
* @brief
* Alarm state indicating that the alarm is active but may be
* hushed.
*
*/
#define WEAVE_ALARM_STATE_ALARM_HUSHABLE 0x04
/**
* @def WEAVE_ALARM_STATE_ALARM_NONHUSHABLE
*
* @brief
* Alarm state indicating that the alarm is active but may be
* not hushed.
*
*/
#define WEAVE_ALARM_STATE_ALARM_NONHUSHABLE 0x05
/**
* @def WEAVE_ALARM_STATE_ALARM_GLOBAL_HUSH
*
* @brief
* Alarm state indicating that all the participating nodes
* (both the originating node and the remote nodes) are hushed.
*
*/
#define WEAVE_ALARM_STATE_ALARM_GLOBAL_HUSH 0x06
/**
* @def WEAVE_ALARM_STATE_ALARM_REMOTE_HUSH
*
* @brief
* Alarm state indicating that the originating node is alarming
* and the remote nodes are hushed.
*
*/
#define WEAVE_ALARM_STATE_ALARM_REMOTE_HUSH 0x07
/**
* @def WEAVE_ALARM_STATE_SELFTEST
*
* @brief
* Alarm state indicating self test state.
*
*/
#define WEAVE_ALARM_STATE_SELFTEST 0x08
/**
* @def WEAVE_ALARM_ANNOUNCE_HEADS_UP_1
*
* @brief
* Alarm state indicating heads-up state 1.
*
*/
#define WEAVE_ALARM_ANNOUNCE_HEADS_UP_1 0x09
/**
* @def WEAVE_ALARM_ANNOUNCE_HEADS_UP_2
*
* @brief
* Alarm state indicating heads-up state 2.
*
*/
#define WEAVE_ALARM_ANNOUNCE_HEADS_UP_2 0x0A
/**
* @def WEAVE_ALARM_STATE_INVALID
*
* @brief
* Alarm state indicating invalid state.
*
*/
#define WEAVE_ALARM_STATE_INVALID 0xFF
/**
* @}
*/
/**
* @name Alarm source
*
* Alarm conditions are composed of the alarm source and alarm state.
* Alarm source occupies the upper 4 bits of the alarm condition. The
* following alarm sources are defined at this time:
*
* @{
*/
/**
* @def WEAVE_ALARM_SMOKE
*
* @brief
* Alarm is triggered by the smoke sensor.
*/
#define WEAVE_ALARM_SMOKE 0x10
/**
* @def WEAVE_ALARM_TEMP
*
* @brief
* Alarm is triggered by the temperature sensor.
*/
#define WEAVE_ALARM_TEMP 0x20
/**
* @def WEAVE_ALARM_CO
*
* @brief
* Alarm is triggered by the carbon monoxide sensor.
*/
#define WEAVE_ALARM_CO 0x30
/**
* @def WEAVE_ALARM_CH4
*
* @brief
* Alarm is triggered by the natural gas sensor.
*/
#define WEAVE_ALARM_CH4 0x40
/**
* @def WEAVE_ALARM_HUMIDITY
*
* @brief
* Alarm is triggered by the humidity sensor.
*/
#define WEAVE_ALARM_HUMIDITY 0x50
/**
* @def WEAVE_ALARM_OTHER
*
* @brief
* Alarm is triggered by a sensor not captured in the previous
* definitions.
*/
#define WEAVE_ALARM_OTHER 0xf0
/**
* @def WEAVE_ALARM_INVALID
*
* @brief
* Invalid alarm source.
*/
#define WEAVE_ALARM_INVALID 0xff
/**
* @}
*/
/**
* @name Parameters that govern the runtime of the alarm source.
*
* The following constants guide the runtime characteristics of Weave
* Alarm rebroadcasts.
*
* @{
*/
/**
* @def WEAVE_ALARM_DEFAULT_REBROADCAST_PERIOD_MSEC
*
* @brief
* Defines the default interval, in milliseconds, of rebroadcasting
* the alarm message.
*
* This constant defines the time interval that guides the rebroadcast
* interval of the current message. Each node participating in the
* alarm protocol will resend a message at most once within that time
* interval. The constant is analogous to `T` in the Trickle algorithm
* (<a href="https://tools.ietf.org/html/rfc6206">RFC 6206</a>).
*/
#define WEAVE_ALARM_DEFAULT_REBROADCAST_PERIOD_MSEC 3000 // in ms
/**
* @def WEAVE_ALARM_DEFAULT_REBROADCAST_THRESH
*
* @brief
* Number of received broadcasts required to suppress retransmission
*
* The constant is analogous to redundancy constant `k` in Trickle
* algorithm (<a href="https://tools.ietf.org/html/rfc6206">RFC
* 6206</a>) description. Its current value is an artifact of the
* behaviors observed in the 802.15.4 stack used, where each link
* local multicast was automatically resent by the firmware three
* times.
*
*/
#define WEAVE_ALARM_DEFAULT_REBROADCAST_THRESH 6
/**
* @def WEAVE_ALARM_DEFAULT_REBROADCAST_TIMEOUT_MSEC
*
* @brief
* Defines the default interval, in milliseconds, of refreshing the
* alarm message.
*
* The constant defines the how frequently the alarm should be
* refreshed before it is considered stale. Stale alarms cease to be
* rebroadcast. The constant should be several lengths of the
* #WEAVE_ALARM_DEFAULT_REBROADCAST_PERIOD_MSEC. After an alarm
* becomes stale, the associated alarm session enters the grace
* period.
*
*/
#define WEAVE_ALARM_DEFAULT_REBROADCAST_TIMEOUT_MSEC 30000
/**
* @def WEAVE_ALARM_MAX_NUM_HOPS
*
* @brief
* The max number of hops an alarm event is expected to reach
*
* The constant is used to drive timeouts dependent on the alarm
* propagation delay across the network.
*
*/
#define WEAVE_ALARM_MAX_NUM_HOPS 4
/**
* @def WEAVE_ALARM_DEFAULT_GRACE_PERIOD_MSEC
*
* @brief
* Defines the default duration, in milliseconds, of the grace
* period.
*
* After the alarm becomes stale, the associated session enters the
* grace period. During the grace period, the node remains awake,
* listening for the any delayed alarm notifications. The constant
* reflects the maximum propagation delay for alarm messages across
* the mesh network for a given level of reliable delivery.
*
*/
#define WEAVE_ALARM_DEFAULT_GRACE_PERIOD_MSEC 30000
/**
* @}
*/
/**
* @name Constants driving the size of state occupied by the Weave Alarm
*
* @{
*/
/**
* @def MAX_CONCURRENT_ALERTS
*
* @brief
* Defines the number of concurrent alarms in the network.
*
* The constant drives the pool size of objects allocated to track
* individual alarm sessions. Any node in the Weave fabric can
* originate at most a single alarm session at a time, though the
* specifics of the alarm condition will vary over the lifetime of the
* session. For example, a single alarm session might start with a
* pre-alarm carbon monoxide warning, evolve into a non-hushable smoke
* alarm, and ultimately return to all clear. The constant should
* generally be sized the number of devices in the network. If some
* alarm aggregation fidelity loss is permitted, the number may
* alternatively be sized to the number of distinct UX actions taken
* by the system; e.g. if the alarm system UI speaks different
* sentences for up to 3 alarm locations, and lumps all other
* locations into a single sentence, the concurrent alerts could be
* sized to 5 (1 alarm session for the current node, and 4 for the
* distinct UX treatments)
*
*/
#define MAX_CONCURRENT_ALERTS 10
/**
* @def MAX_CONCURRENT_MESSAGES
*
* @brief
* Number of concurrent alarm messages allocated by Weave Alarm
*
* The number of messages required is either
* - one message per node in the network, or
* - one message per concurrent alarm (the alarm session holds onto
* the messages for retransmission purposes) plus at least one
* message so we can determine whether the incoming alarm message
* from a new client is more urgent than any alarm sessions in
* displayed in the current UX.
*
*/
#define MAX_CONCURRENT_MESSAGES ((MAX_CONCURRENT_ALERTS) + 1)
/**
* @def WEAVE_ALARM_MAX_INCOMING_ALARM_MESSAGE_SIZE
*
* @brief
* Maximum message size to allocate for Weave Alarm payloads
*
* Weave Alarm retains a number of different messages for
* rebroadcasts. The standard PacketBuffer objects are sized for
* maximum sized IP packets, and the PacketBuffer API contains no
* provisions for allocating smaller messages. To ease the memory
* pressure, Weave Alarm maintains its own pool of small messages.
* The maximum value for the constant below is the size of the small
* message - alignment offset - #WEAVE_HEADER_RESERVE_SIZE. For small
* messages of 128 bytes, the maximum value would be 76.
*
*/
#define WEAVE_ALARM_MAX_INCOMING_ALARM_MESSAGE_SIZE 64
/**
* @}
*/
/**
* @name Other constants
*/
/**
* @def WEAVE_ALARM_FORWARD_COUNTER_DISTANCE_LIMIT
*
* @brief
* Maximum valid counter distance
*
* Counter is implemented as a `uint8_t` value that rolls over. The constant
* defines as the "distance" the next alarm counter can be to be
* considered as a successor to the current one. It shall be no more
* than the half MAX value of the counter (in whatever size is
* subsequently chosen).
*/
#define WEAVE_ALARM_FORWARD_COUNTER_DISTANCE_LIMIT (UINT8_MAX/2)
// TODO: constant currently unused. Can we remove it?
// TODO: Replace this once we have the new key id scheme defined in Weave
// WEAVE-232 has been created for this item
/**
* @def WEAVE_ALARM_HUSH_KEY_ID
*
* @brief
* ID of a key used to secure the hush request.
*
* This constant is intended to be used by application code, during
* the process of filling and verifying the hush request. Alarm
* profile code just packs the id value in and uses the given key to
* sign the request.
*
*/
#define WEAVE_ALARM_HUSH_KEY_ID (0x2)
/**
* @def ALARM_MULTICAST_ADDR
*
* @brief
* If defined, all multicasts related to Alarm messages go to this
* address, no matter what the peer node ID implies. Otherwise an
* IPv6 link-local multicast address would be picked, as the
* default value implies.
*/
#ifndef ALARM_MULTICAST_ADDR
#define ALARM_MULTICAST_ADDR IPAddress::MakeIPv6Multicast(kIPv6MulticastScope_Link, kIPV6MulticastGroup_AllNodes)
#endif // ALARM_MULTICAST_ADDR
/**
* @}
*/
namespace nl {
namespace Weave {
namespace Profiles {
enum {
/**
* Alarm message type. Alarm messages ultimately originate at
* the alarm originator, and are sent to all nodes within the
* network
*/
kAlarmMessageType_Alarm = 1,
/**
* @deprecated
* Alarm update message type. Alarm updates are sent from remote
* nodes to the originator to request state change
*/
kAlarmMessageType_AlarmUpdate = 2,
/**
* @deprecated
* Alarm ack message type. Alarm acks messages are sent from the
* originator to the remote requesting update, and are used as a
* reliability layer for the Alarm Update messages.
*/
kAlarmMessageType_AlarmAck = 3,
/**
* Alarm hush message type.
*/
kAlarmMessageType_AlarmHushRequest = 4,
/**
* Alarm hush response message type.
*/
kAlarmMessageType_AlarmHushResponse = 5,
};
/**
*
* @brief
* Profile-specific status code used in StatusReport as response to
* any request.
*
* @detail
* Common status codes are listed in CommonProfile, like
* kStatus_BadRequest and kStatus_Busy.
*
*/
enum {
/**
* Alarm update succeeded.
*/
kAlarmUpdateStatus_Success = 0,
/**
* @deprecated
* Alarm update was rejected by the application layer as not
* applicable under current policy, e.g. requesting a hush for an
* unhushable alarm.
*/
kAlarmUpdateStatus_Rejected = 1,
/**
* @deprecated
* Alarm update was rejected as invalid, e.g. it pertained to
* stale state or specified an invalid transition.
*/
kAlarmUpdateStatus_Invalid = 2,
/**
* @deprecated
* Alarm update could not be used in a timely manner.
*/
kAlarmUpdateStatus_Timeout = 3,
/**
* Hush was rejected because proximity validation failed.
*/
kAlarmStatusReport_HushRejected_ProximityValidationFailure = 4,
/**
* Hush was rejected because signature validation failed.
*/
kAlarmStatusReport_HushRejected_SignatureValidationFailure = 5,
};
/**
* @brief
* Possible results in an AlarmHushResponse message.
*
* @note
* The response to a AlarmHushRequest could also be a StatusReport
* message, especially when the response is generated within
* AlarmServer without contacting the application layer. The
* AlarmHushResponse carries both result code and (updated) alarm
* condition. If no alarm condition is needed in the response,
* application layer should consider using a StatusReport message.
*
*/
enum {
kAlarmHushResult_Success = 0, ///< Hush was successful, and the the condition list is valid
};
/**
* @class Alarm
*
* @brief
* Message class to represent the Weave Alarm payloads
*
* Alarm class contains the values from the Alarm message along with
* the methods to serialize and deserialize the message, a number of
* accessor functions, and convenience functions for manipulating
* alarms.
*/
class NL_DLL_EXPORT Alarm {
friend class WeaveAlarmClient;
public:
enum
{
/// Max number of alarm conditions, for both V1 and V2
kMaxNumAlarmConditions = 8,
/// Size of payload in V1 alarm messages, without the actual conditions
/// 1 byte for alarm counter
/// 1 byte for length
/// 1 byte for where
kPayloadSizeWithoutConditions_V1 = 3,
/// Size of payload in V2 alarm messages, without the actual conditions
/// everything in V1, plus
/// 4 bytes for session id
/// 4 bytes for extended event sequence number
kPayloadSizeWithoutConditions_V2 = kPayloadSizeWithoutConditions_V1 + 8,
};
Alarm(void);
WEAVE_ERROR init(void);
bool operator == (const Alarm &) const;
uint8_t GetAlarmState(uint8_t) const;
uint8_t GetAlarmCondition(uint8_t) const;
uint8_t GetAlarm(uint8_t) const;
void SetAlarmState(uint8_t, uint8_t);
void SetAlarmCondition(uint8_t, uint8_t);
void SetAlarm(uint8_t, uint8_t);
void AddAlarm(uint8_t);
bool KeepReBroadcasting(void) const;
// parsing
WEAVE_ERROR pack(PacketBuffer *);
static WEAVE_ERROR parse(const PacketBuffer *, Alarm *);
// data members
/// Alarm counter used to determine the alarm freshness
uint8_t mAlarmCtr;
/// Length of the alarm condition list
uint8_t mLength;
//TODO: FIXME: more flexible alarm allocations
/// List of alarm conditions (each condition contains both the alarm state and alarm source
uint8_t mConditions[kMaxNumAlarmConditions];
/// Location of the alarm originator. The mWhere is populated
/// with the spoken where ID in the namespace of the spoken
/// locations.
uint8_t mWhere;
/// true if this alarm message comes with session ID,
/// or if pack should encode session ID into the message buffer
bool mIsSessionIdAndExtEvtSnValid;
/// 4-byte session ID
uint32_t mSessionId;
/// 4-byte extended event sequence number
uint32_t mExtEvtSeqNum;
private:
};
/**
* @class AlarmHushSignature
*
* @brief
* storage of a signature for AlarmHushRequest
*
* This class can be used to compare two signatures
*/
class AlarmHushSignature {
public:
AlarmHushSignature(void);
bool operator == (const AlarmHushSignature &rhs) const;
bool operator != (const AlarmHushSignature &rhs) const;
bool mIsSigned;
uint16_t mKeyId;
uint8_t mKeyedHash[Crypto::HMACSHA1::kDigestLength];
};
/**
*
* @class AlarmHush
*
* @brief
* pack and parse AlarmHush request message
*
* This class can pack as well as parse AlarmHush request message
*/
class AlarmHushRequest {
public:
enum
{
// Note that HMAC is tricky if you use variable key sizes.
// The best policy is to use a long, fixed-length key with a proper random number generator
// One example for the trickiness: [1, 0, 0] is the same as [1] to HMAC with block size larger than 3
kAlarmHush_MinKeySize = 16
};
AlarmHushRequest(void);
WEAVE_ERROR init(void);
WEAVE_ERROR pack(PacketBuffer *);
WEAVE_ERROR sign(uint32_t aChallenge, uint16_t aKeyId, const uint8_t aKey[], uint16_t aKeySize);
static WEAVE_ERROR parse(const PacketBuffer*, AlarmHushRequest*);
uint32_t mProximityVerificationCode;
AlarmHushSignature mSignature;
};
/**
* @class AlarmHushResponse
*
* @brief
* pack and parse AlarmHushResponse request message
*
* This class can pack as well as parse AlarmHushResponse request message
*/
class AlarmHushResponse {
public:
enum
{
/// Size of payload in alarm hush response messages, without the actual conditions
/// 1 byte for alarm counter
/// 1 byte for length
kPayloadSizeWithoutConditions = 2,
};
AlarmHushResponse(void);
WEAVE_ERROR init(uint8_t aResult, uint8_t aNumEntry, const uint8_t * aAlarmCondition);
WEAVE_ERROR pack(PacketBuffer *);
static WEAVE_ERROR parse(const PacketBuffer*, AlarmHushResponse*);
uint8_t mHushResult;
uint8_t mLength;
uint8_t mConditions[Alarm::kMaxNumAlarmConditions];
AlarmHushSignature mSignature;
};
class WeaveAlarmServer;
/**
* @class WeaveAlarmClient
*
* @brief
* A class to track an alarm session from a single originator
* (either self or remote)
*
* The core runtime class of the Weave Alarm protocol. This class
* provides behaviors for both the originator and the remotes to track
* protocol behaviors across a single alarm session.
*/
class NL_DLL_EXPORT WeaveAlarmClient {
friend class WeaveAlarmServer;
friend class WeaveAlarmClientIterator;
public:
/**
* @enum WeaveAlarmClient::ClientState
*
* @brief
* Enum describing the possible states of the WeaveAlarmClient
*/
enum ClientState
{
/**
* Client is closed. There is no active state associated with
* the client object, and the object may be used to allocate a
* new alarm client. A new alarm message, via an unsolicited
* message handler and appropriate allocations, results in a
* transition to kAlarmClientState_Active.
*/
kAlarmClientState_Closed = 0,
/**
* Client is active. The session is actively (re-)transmitting
* alarm messages, and considers the alarm state to be fresh
* and current. Upon a timeout, the alarm client transitions
* to kAlarmClientState_GracePeriod.
*/
kAlarmClientState_Active,
/**
* Client in the grace period. The alarm state is considered
* stale, __but__ the alarm client is willing to accept new
* messages; if the message is judged to contain fresh and
* current alarm state (based on the AlarmCounter), the client
* will transition back to kAlarmClientState_Active.
*/
kAlarmClientState_GracePeriod,
/**
* Client is in linger state. This state is analogous to the
* TCP linger state, and prevents collisions between two
* consecutive sessions started by the same originator. Upon
* exiting the linger state, the client transitions to
* kAlarmClientState_Closed.
*/
kAlarmClientState_Linger,
};
WeaveAlarmClient(void);
WEAVE_ERROR SendAlarm(const Alarm *aPayload);
uint64_t GetOriginator(void);
Alarm GetCurrentAlarm(void);
uint8_t GetOriginatorWhere(void);
bool IsLocalAlarm(void) const;
void Close(void);
void HandleAlarm(const IPPacketInfo *aPktInfo, const WeaveMessageInfo *aMsgInfo, PacketBuffer *aPayload, const Alarm & aParsedAlarm);
static WEAVE_ERROR GenerateProximityVerificationCode(uint32_t * const aResult);
static WEAVE_ERROR GenerateHushChallenge(uint32_t * const aResult);
const ClientState GetClientState(void) const;
static const char * GetClientStateName(const ClientState aState);
/// Call this when app layer thinks it's safe to do so
WEAVE_ERROR RegenerateSessionId(void);
WEAVE_ERROR TryAdvanceExtEvtSeqNum(void);
/**
* @var mCurrentAlarm
*
* @brief
* The object representing the "current" alarm message
* associated with the alarm client.
*
* The message object is used to determine whether the incoming
* message is more current than the one we currently have and to
* (re-)transmit the messages as appropriate.
*/
Alarm mCurrentAlarm;
private:
static void HandleMessage(ExchangeContext *aEc, const IPPacketInfo *aPktInfo, const WeaveMessageInfo *aMsgInfo,
uint32_t aProfileId, uint8_t aMsgType, PacketBuffer *aPayload);
static void HandleRetransmissionTimeout(ExchangeContext *aEc);
void initAlarmClient(WeaveAlarmServer * const aAlarmServer);
int FindClientIndex(void) const;
void ForceClientStateChangeNoError(ClientState aNewState);
WEAVE_ERROR SetClientState_Active(void);
WEAVE_ERROR SetClientState_Closed(bool aNotifyAppLayer = true);
WEAVE_ERROR SetClientState_GracePeriod(void);
WEAVE_ERROR SetClientState_Linger(void);
void CancelAllTimersExceptForTrickle(void);
static void _HandleLingerTimeout(System::Layer* aSystemLayer, void* aAppState, System::Error aError);
void HandleLingerTimeout(void);
static void _HandleGracePeriodTimeout(System::Layer* aSystemLayer, void* aAppState, System::Error aError);
void HandleGracePeriodTimeout(void);
/// ExchangeContext object used to track the messages within the alarm session.
ExchangeContext * mEc;
/// The current state of the alarm client.
ClientState mClientState;
/// A flag used to distinguish whether the alarm is local (set to
/// true on the originator of the alarm) or remote (set to false
/// on all the remotes participating in the alarm session.
bool mIsLocalAlarm;
/// A server object responsible for initial allocation and
/// lifecycle of the alarm client object.
WeaveAlarmServer *mServer;
};
#if WEAVE_SYSTEM_CONFIG_USE_LWIP
#include "lwip/pbuf.h"
struct tiny_custom_pbuf {
struct pbuf_custom pc;
uint32_t payload[32];
};
#endif // WEAVE_SYSTEM_CONFIG_USE_LWIP
/**
* @class AlarmDelegate
*
* @brief
* Interface for delegation for alarm-related application-level
* operations
*
*/
class AlarmDelegate
{
public:
/**
* Called when an AlarmHushRequest is received when there is no
* other hush operation in progress.
*
* Application logic shall use the exchange context to verify the
* security settings of this message, and also to restrict the
* connection type.
*
* Application logic shall send a response to this request using
* either SendHushResponse or SendStatusReport, which also closes
* the exchange context internally.
*
* @param ec A pointer to the exchange context created for this
* incoming request
*
* @param proximityVerificationCode A random, 32-bit challenge,
* originally created by the alarm originator.
* The challenge proves the applicability of the
* hush request to this alarm.
*
* @param signature A read-only reference to the signature that
* comes with the request. Callee shall make a
* copy of this object if the content is needed
* after return.
*
* @return #WEAVE_NO_ERROR on success, otherwise AlarmServer would
* close the exchange context
*/
virtual WEAVE_ERROR OnHushRequest(ExchangeContext *aEc, uint32_t aProximityVerificationCode, const AlarmHushSignature & aSignature) = 0;
virtual void OnAlarmClientStateChange(WeaveAlarmClient * const aClient) = 0;
virtual void OnNewRemoteAlarmDropped(const Alarm & aAlarm) = 0;
virtual int CompareSeverity(const Alarm & aAlarm1, const Alarm & aAlarm2) = 0;
};
/**
* @class WeaveAlarmServer
*
* @brief
* A class to act as the alarm server: manage individual alarm
* clients and message pools.
*
* @detail
* There must be at most one instance of this class per Weave
* client. Weave Alarms are not processed until this class is
* initialized, so it is critical that the instance of the class is
* initialized as soon as possible in the client's life cycle, and
* that the instance remains active through the lifetime of the
* Weave client.
*
*/
class NL_DLL_EXPORT WeaveAlarmServer: public nl::Weave::WeaveServerBase {
friend class WeaveAlarmClient;
friend class WeaveAlarmClientIterator;
public :
WeaveAlarmServer(void);
WEAVE_ERROR Init(WeaveExchangeManager *aExchangeMgr, void *aAppState) ;
WEAVE_ERROR Shutdown(void);
WeaveAlarmClient *NewClient(uint64_t aPeer, uint8_t aEncryptionType, uint16_t aKeyId);
void UpdateAllClients(void);
/**
* @var mAlarmRebroadcastPeriodMsec
*
* @brief
* Specifies the interval, in milliseconds, between rounds
* of Trickle retransmission.
*
* This variable defines the time interval that guides the
* rebroadcast interval of the current message. Each node
* participating in the alarm protocol will resend a message at
* most once within that time interval. The constant is analogous
* to `T` in the Trickle algorithm (<a
* href="https://tools.ietf.org/html/rfc6206">RFC 6206</a>). The
* value must be the same for all nodes in the network and it is
* initially set to #WEAVE_ALARM_DEFAULT_REBROADCAST_PERIOD_MSEC.
*/
uint32_t mAlarmRebroadcastPeriodMsec;
/**
* @var mAlarmRefreshPeriodMsec
*
* @brief
* Specifies the period, in milliseconds, in which the
* originator should refresh the alarm counter
*
* This variable defines the how frequently the alarm should be
* refreshed before it is considered stale. Stale alarms cease to
* be rebroadcast. The constant should be several lengths of the
* mAlarmRebroadcastPeriodMsec. After alarm becomes stale, the
* associated alarm session enters the grace period. The value
* must be the same for all nodes in the network and it is
* initially set to #WEAVE_ALARM_DEFAULT_REBROADCAST_TIMEOUT_MSEC.
*/
uint32_t mAlarmRefreshPeriodMsec;
/**
* @var mAlarmRebroadcastThreshold
*
* @brief
* Specifies the number of message receptions required to
* suppress a retransmission
*
* This variable is analogous to redundancy constant `k` in
* Trickle algorithm description (<a
* href="https://tools.ietf.org/html/rfc6206">RFC 6206</a>). Its
* current value is an artifact of the behaviors observed in the
* 802.15.4 stack used, where each link local multicast was
* automatically resent by the firmware three times. The value
* must be the same for all nodes in the network and it is
* initially set to #WEAVE_ALARM_DEFAULT_REBROADCAST_THRESH.
*/
uint8_t mAlarmRebroadcastThreshold;
/**
* @var mAlarmGracePeriodMsec
*
* @brief
* Specifies the duration, in milliseconds, of the grace period.
*
* After the alarm becomes stale, the associated session enters
* the grace period. During the grace period, the node remains
* awake, listening for the any delayed alarm notifications. The
* value reflects the maximum propagation delay for alarm messages
* across the mesh network for a given level of reliable delivery.
* The value must be the same for all nodes in the network and it
* is initially set to #WEAVE_ALARM_DEFAULT_GRACE_PERIOD_MSEC.
*
*/
uint32_t mAlarmGracePeriodMsec;
/**
*
* @var mInterfaceId
*
* @brief
* An ID of the designated interface for accepting Weave Alarm
* packets, #INET_NULL_INTERFACEID for accepting packets on any
* interface.
*/
InterfaceId mInterfaceId;
/**
* @var mAppState
*
* @brief
* A pointer to any application-specific state, passed in via
* `WeaveAlarmServer::Init()` method.
*
*/
void* mAppState;
void SetAlarmDelegate(AlarmDelegate * aDelegate);
WEAVE_ERROR SendHushResponse(uint8_t aHushResult, uint8_t aLength = 0, uint8_t *aConditions = NULL);
WEAVE_ERROR SendStatusReport(uint32_t aStatusProfileId, uint16_t aStatusCode, WEAVE_ERROR aSysError = WEAVE_NO_ERROR);
private:
/// delegate for application level operations
AlarmDelegate * mAlarmDelegate;
/// exchange context for the current operation under processing in the delegate
ExchangeContext * mCurrentDelegateOp;
WeaveAlarmClient mClientPool[MAX_CONCURRENT_ALERTS];
#if WEAVE_SYSTEM_CONFIG_USE_LWIP
struct tiny_custom_pbuf mTinyPbufPool[MAX_CONCURRENT_MESSAGES];
#endif // WEAVE_SYSTEM_CONFIG_USE_LWIP
WeaveAlarmClient *AllocAlarmClientUsingExchangeContext(ExchangeContext *aEc, uint8_t aEncryptionType,
uint16_t aKeyId, bool aRemoteOnly);
void DispatchAlarmMessage(const IPPacketInfo *aPktInfo, const WeaveMessageInfo *aMsgInfo, PacketBuffer *aPayload);
WEAVE_ERROR InitializeBackingStore(void);
void ShutdownBackingStore(void);
PacketBuffer * NewPacketBuffer(void);
/// parse the hush request message and deliver to the delegate
WEAVE_ERROR HandleHushRequest(PacketBuffer *aPayload);
void OnAlarmClientStateChange(WeaveAlarmClient * const aClient);
int GetClientIndex (const WeaveAlarmClient * aClient) const;
bool IsRemoteClientPoolFull(void) const;
WEAVE_ERROR CloseLessSevereAlarmClient(uint64_t aSrcNodeId, const Alarm & aAlarm);
static void UnsolicitedMessageHandler(ExchangeContext *aEc, const IPPacketInfo *aPktInfo, const WeaveMessageInfo *aMsgInfo,
uint32_t aProfileId, uint8_t aMsgType, PacketBuffer *aPayload);
};
/**
* @class WeaveAlarmClientIterator
*
* @brief
* A helper class to iterate through a list of alarm clients.
*/
class WeaveAlarmClientIterator {
public:
WeaveAlarmClientIterator(WeaveAlarmServer *);
bool hasNext(void);
WeaveAlarmClient * next(void);
private:
WeaveAlarmServer *mServer;
int mIndex;
};
}//ns Profiles
}//ns Weave
}//ns nl
#endif // _WEAVE_ALARM_PROFILE_H