mirror of
https://github.com/espressif/openthread.git
synced 2026-10-02 13:57:38 +00:00
[linked-list] adding LinkedList class (#4357)
This commit adds a linked list module which provides a template implementation of a singly linked list. The new class is then used in different core modules (netif (unicast/multicast addresses), UDP6 sockets/receiver, coap resources, etc). This commit also adds a unit test `test_linked_list` for the linked list module.
This commit is contained in:
committed by
Jonathan Hui
parent
15e26f0e64
commit
e17c82b0b9
@@ -310,6 +310,7 @@ HEADERS_COMMON = \
|
|||||||
common/encoding.hpp \
|
common/encoding.hpp \
|
||||||
common/extension.hpp \
|
common/extension.hpp \
|
||||||
common/instance.hpp \
|
common/instance.hpp \
|
||||||
|
common/linked_list.hpp \
|
||||||
common/locator.hpp \
|
common/locator.hpp \
|
||||||
common/locator-getters.hpp \
|
common/locator-getters.hpp \
|
||||||
common/logging.hpp \
|
common/logging.hpp \
|
||||||
|
|||||||
+5
-32
@@ -49,7 +49,7 @@ namespace Coap {
|
|||||||
CoapBase::CoapBase(Instance &aInstance, Sender aSender)
|
CoapBase::CoapBase(Instance &aInstance, Sender aSender)
|
||||||
: InstanceLocator(aInstance)
|
: InstanceLocator(aInstance)
|
||||||
, mRetransmissionTimer(aInstance, &Coap::HandleRetransmissionTimer, this)
|
, mRetransmissionTimer(aInstance, &Coap::HandleRetransmissionTimer, this)
|
||||||
, mResources(NULL)
|
, mResources()
|
||||||
, mContext(NULL)
|
, mContext(NULL)
|
||||||
, mInterceptor(NULL)
|
, mInterceptor(NULL)
|
||||||
, mResponsesQueue(aInstance)
|
, mResponsesQueue(aInstance)
|
||||||
@@ -81,40 +81,13 @@ void CoapBase::ClearRequestsAndResponses(void)
|
|||||||
|
|
||||||
otError CoapBase::AddResource(Resource &aResource)
|
otError CoapBase::AddResource(Resource &aResource)
|
||||||
{
|
{
|
||||||
otError error = OT_ERROR_NONE;
|
return mResources.Add(aResource);
|
||||||
|
|
||||||
for (Resource *cur = mResources; cur; cur = cur->GetNext())
|
|
||||||
{
|
|
||||||
VerifyOrExit(cur != &aResource, error = OT_ERROR_ALREADY);
|
|
||||||
}
|
|
||||||
|
|
||||||
aResource.mNext = mResources;
|
|
||||||
mResources = &aResource;
|
|
||||||
|
|
||||||
exit:
|
|
||||||
return error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CoapBase::RemoveResource(Resource &aResource)
|
void CoapBase::RemoveResource(Resource &aResource)
|
||||||
{
|
{
|
||||||
if (mResources == &aResource)
|
mResources.Remove(aResource);
|
||||||
{
|
aResource.SetNext(NULL);
|
||||||
mResources = aResource.GetNext();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (Resource *cur = mResources; cur; cur = cur->GetNext())
|
|
||||||
{
|
|
||||||
if (cur->mNext == &aResource)
|
|
||||||
{
|
|
||||||
cur->mNext = aResource.mNext;
|
|
||||||
ExitNow();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
exit:
|
|
||||||
aResource.mNext = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CoapBase::SetDefaultHandler(otCoapRequestHandler aHandler, void *aContext)
|
void CoapBase::SetDefaultHandler(otCoapRequestHandler aHandler, void *aContext)
|
||||||
@@ -611,7 +584,7 @@ void CoapBase::ProcessReceivedRequest(Message &aMessage, const Ip6::MessageInfo
|
|||||||
|
|
||||||
curUriPath[0] = '\0';
|
curUriPath[0] = '\0';
|
||||||
|
|
||||||
for (const Resource *resource = mResources; resource; resource = resource->GetNext())
|
for (const Resource *resource = mResources.GetHead(); resource; resource = resource->GetNext())
|
||||||
{
|
{
|
||||||
if (strcmp(resource->mUriPath, uriPath) == 0)
|
if (strcmp(resource->mUriPath, uriPath) == 0)
|
||||||
{
|
{
|
||||||
|
|||||||
+3
-10
@@ -35,6 +35,7 @@
|
|||||||
|
|
||||||
#include "coap/coap_message.hpp"
|
#include "coap/coap_message.hpp"
|
||||||
#include "common/debug.hpp"
|
#include "common/debug.hpp"
|
||||||
|
#include "common/linked_list.hpp"
|
||||||
#include "common/locator.hpp"
|
#include "common/locator.hpp"
|
||||||
#include "common/message.hpp"
|
#include "common/message.hpp"
|
||||||
#include "common/timer.hpp"
|
#include "common/timer.hpp"
|
||||||
@@ -175,7 +176,7 @@ private:
|
|||||||
* This class implements CoAP resource handling.
|
* This class implements CoAP resource handling.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
class Resource : public otCoapResource
|
class Resource : public otCoapResource, public LinkedListEntry<Resource>
|
||||||
{
|
{
|
||||||
friend class CoapBase;
|
friend class CoapBase;
|
||||||
|
|
||||||
@@ -200,14 +201,6 @@ public:
|
|||||||
mNext = NULL;
|
mNext = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This method returns a pointer to the next resource.
|
|
||||||
*
|
|
||||||
* @returns A pointer to the next resource.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
Resource *GetNext(void) const { return static_cast<Resource *>(mNext); }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns a pointer to the Uri-Path.
|
* This method returns a pointer to the Uri-Path.
|
||||||
*
|
*
|
||||||
@@ -678,7 +671,7 @@ private:
|
|||||||
uint16_t mMessageId;
|
uint16_t mMessageId;
|
||||||
TimerMilliContext mRetransmissionTimer;
|
TimerMilliContext mRetransmissionTimer;
|
||||||
|
|
||||||
Resource *mResources;
|
LinkedList<Resource> mResources;
|
||||||
|
|
||||||
void * mContext;
|
void * mContext;
|
||||||
Interceptor mInterceptor;
|
Interceptor mInterceptor;
|
||||||
|
|||||||
@@ -0,0 +1,317 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019, The OpenThread Authors.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of the copyright holder nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* This file includes definitions for a generic singly linked list.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LINKED_LIST_HPP_
|
||||||
|
#define LINKED_LIST_HPP_
|
||||||
|
|
||||||
|
#include "openthread-core-config.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <openthread/error.h>
|
||||||
|
|
||||||
|
namespace ot {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @addtogroup core-linked-list
|
||||||
|
*
|
||||||
|
* @brief
|
||||||
|
* This module includes definitions for OpenThread Singly Linked List.
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This template class represents a linked list entry.
|
||||||
|
*
|
||||||
|
* This class provides methods to `GetNext()` and `SetNext()` in the linked list entry.
|
||||||
|
*
|
||||||
|
* Users of this class should follow CRTP-style inheritance, i.e., the `Type` class itself should publicly inherit
|
||||||
|
* from `LinkedListEntry<Type>`.
|
||||||
|
*
|
||||||
|
* The template type `Type` should contain a `mNext` member variable. The `mNext` should be of a type that can be
|
||||||
|
* down-casted to `Type` itself.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
template <class Type> class LinkedListEntry
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* This method gets the next entry in the linked list.
|
||||||
|
*
|
||||||
|
* @returns A pointer to the next entry in the linked list or NULL if at the end of the list.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
const Type *GetNext(void) const { return static_cast<const Type *>(static_cast<const Type *>(this)->mNext); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method gets the next entry in the linked list.
|
||||||
|
*
|
||||||
|
* @returns A pointer to the next entry in the linked list or NULL if at the end of the list.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
Type *GetNext(void) { return static_cast<Type *>(static_cast<Type *>(this)->mNext); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method sets the next pointer on the entry.
|
||||||
|
*
|
||||||
|
* @param[in] aNext A pointer to the next entry.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void SetNext(Type *aNext) { static_cast<Type *>(this)->mNext = aNext; }
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This template class represents a singly linked list.
|
||||||
|
*
|
||||||
|
* The template type `Type` should provide `GetNext()` and `SetNext()` methods (which can be realized by `Type`
|
||||||
|
* inheriting from `LinkedListEntry<Type>` class).
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
template <typename Type> class LinkedList
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* This constructor initializes the linked list.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
LinkedList(void)
|
||||||
|
: mHead(NULL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method returns the entry at the head of the linked list
|
||||||
|
*
|
||||||
|
* @returns Pointer to the entry at the head of the linked list, or NULL if list is empty.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
Type *GetHead(void) { return mHead; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method returns the entry at the head of the linked list.
|
||||||
|
*
|
||||||
|
* @returns Pointer to the entry at the head of the linked list, or NULL if list is empty.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
const Type *GetHead(void) const { return mHead; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method sets the head of the linked list to a given entry.
|
||||||
|
*
|
||||||
|
* @param[in] aHead A pointer to an entry to set as the head of the linked list.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void SetHead(Type *aHead) { mHead = aHead; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method clears the linked list.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void Clear(void) { mHead = NULL; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method indicates whether the linked list is empty or not.
|
||||||
|
*
|
||||||
|
* @retval TRUE If the linked list is empty.
|
||||||
|
* @retval FALSE If the linked list is not empty.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
bool IsEmpty(void) const { return (mHead == NULL); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method pushes an entry at the head of the linked list.
|
||||||
|
*
|
||||||
|
* @param[in] aEntry A reference to an entry to push at the head of linked list.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void Push(Type &aEntry)
|
||||||
|
{
|
||||||
|
aEntry.SetNext(mHead);
|
||||||
|
mHead = &aEntry;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method pushes an entry after a given previous existing entry in the linked list.
|
||||||
|
*
|
||||||
|
* @param[in] aEntry A reference to an entry to push into the list.
|
||||||
|
* @param[in] aPrevEntry A reference to a previous entry (new entry @p aEntry will be pushed after this).
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void PushAfter(Type &aEntry, Type &aPrevEntry)
|
||||||
|
{
|
||||||
|
aEntry.SetNext(aPrevEntry.GetNext());
|
||||||
|
aPrevEntry.SetNext(&aEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method pops an entry from head of the linked list.
|
||||||
|
*
|
||||||
|
* @note This method does not change the popped entry itself, i.e., the popped entry next pointer stays as before.
|
||||||
|
*
|
||||||
|
* @returns The entry that was popped if list is not empty, or NULL if list is empty.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
Type *Pop(void)
|
||||||
|
{
|
||||||
|
Type *entry = mHead;
|
||||||
|
|
||||||
|
if (mHead != NULL)
|
||||||
|
{
|
||||||
|
mHead = mHead->GetNext();
|
||||||
|
}
|
||||||
|
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method pops an entry after a given previous entry.
|
||||||
|
*
|
||||||
|
* @note This method does not change the popped entry itself, i.e., the popped entry next pointer stays as before.
|
||||||
|
*
|
||||||
|
* @param[in] aPrevEntry A reference to n previous entry (the entry after this will be popped).
|
||||||
|
|
||||||
|
* @returns The entry that was popped if list is not empty, or NULL if there is no entry after the given one.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
Type *PopAfter(Type &aPrevEntry)
|
||||||
|
{
|
||||||
|
Type *entry = aPrevEntry.GetNext();
|
||||||
|
|
||||||
|
if (entry != NULL)
|
||||||
|
{
|
||||||
|
aPrevEntry.SetNext(entry->GetNext());
|
||||||
|
}
|
||||||
|
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method indicates whether the linked list contains a given entry.
|
||||||
|
*
|
||||||
|
* @param[in] aEntry A reference to an entry.
|
||||||
|
*
|
||||||
|
* @retval TRUE The linked list contains @p aEntry.
|
||||||
|
* @retval FALSE The linked list does not contain @p aEntry.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
bool Contains(Type &aEntry) const
|
||||||
|
{
|
||||||
|
bool contains = false;
|
||||||
|
|
||||||
|
for (Type *cur = mHead; cur != NULL; cur = cur->GetNext())
|
||||||
|
{
|
||||||
|
if (cur == &aEntry)
|
||||||
|
{
|
||||||
|
contains = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return contains;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method adds an entry (at the head of the linked list) if it is not already in the list.
|
||||||
|
*
|
||||||
|
* @param[in] aEntry A reference to an entry to add.
|
||||||
|
*
|
||||||
|
* @retval OT_ERROR_NONE The entry was successfully added at the head of the list.
|
||||||
|
* @retval OT_ERROR_ALREADY The entry is already in the list.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
otError Add(Type &aEntry)
|
||||||
|
{
|
||||||
|
otError error = OT_ERROR_NONE;
|
||||||
|
|
||||||
|
if (Contains(aEntry))
|
||||||
|
{
|
||||||
|
error = OT_ERROR_ALREADY;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Push(aEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method removes an entry from the linked list.
|
||||||
|
*
|
||||||
|
* @note This method does not change the removed entry @p aEntry itself (it is `const`), i.e., the entry next
|
||||||
|
* pointer of @p aEntry stays as before.
|
||||||
|
*
|
||||||
|
* @param[in] aEntry A reference to an entry to remove.
|
||||||
|
*
|
||||||
|
* @retval OT_ERROR_NONE The entry was successfully removed from the list.
|
||||||
|
* @retval OT_ERROR_NOT_FOUND Could not find the entry in the list.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
otError Remove(const Type &aEntry)
|
||||||
|
{
|
||||||
|
otError error = OT_ERROR_NOT_FOUND;
|
||||||
|
|
||||||
|
if (mHead == &aEntry)
|
||||||
|
{
|
||||||
|
Pop();
|
||||||
|
error = OT_ERROR_NONE;
|
||||||
|
}
|
||||||
|
else if (mHead != NULL)
|
||||||
|
{
|
||||||
|
for (Type *cur = mHead; cur->GetNext() != NULL; cur = cur->GetNext())
|
||||||
|
{
|
||||||
|
if (cur->GetNext() == &aEntry)
|
||||||
|
{
|
||||||
|
cur->SetNext(cur->GetNext()->GetNext());
|
||||||
|
error = OT_ERROR_NONE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Type *mHead;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
} // namespace ot
|
||||||
|
|
||||||
|
#endif // LINKED_LIST_HPP_
|
||||||
@@ -54,7 +54,7 @@ Notifier::Notifier(Instance &aInstance)
|
|||||||
, mFlagsToSignal(0)
|
, mFlagsToSignal(0)
|
||||||
, mSignaledFlags(0)
|
, mSignaledFlags(0)
|
||||||
, mTask(aInstance, &Notifier::HandleStateChanged, this)
|
, mTask(aInstance, &Notifier::HandleStateChanged, this)
|
||||||
, mCallbacks(NULL)
|
, mCallbacks()
|
||||||
{
|
{
|
||||||
for (unsigned int i = 0; i < kMaxExternalHandlers; i++)
|
for (unsigned int i = 0; i < kMaxExternalHandlers; i++)
|
||||||
{
|
{
|
||||||
@@ -65,8 +65,7 @@ Notifier::Notifier(Instance &aInstance)
|
|||||||
|
|
||||||
void Notifier::RegisterCallback(Callback &aCallback)
|
void Notifier::RegisterCallback(Callback &aCallback)
|
||||||
{
|
{
|
||||||
aCallback.mNext = mCallbacks;
|
mCallbacks.Push(aCallback);
|
||||||
mCallbacks = &aCallback;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
otError Notifier::RegisterCallback(otStateChangedCallback aCallback, void *aContext)
|
otError Notifier::RegisterCallback(otStateChangedCallback aCallback, void *aContext)
|
||||||
@@ -151,7 +150,7 @@ void Notifier::HandleStateChanged(void)
|
|||||||
|
|
||||||
LogChangedFlags(flags);
|
LogChangedFlags(flags);
|
||||||
|
|
||||||
for (Callback *callback = mCallbacks; callback != NULL; callback = callback->mNext)
|
for (Callback *callback = mCallbacks.GetHead(); callback != NULL; callback = callback->GetNext())
|
||||||
{
|
{
|
||||||
callback->Invoke(flags);
|
callback->Invoke(flags);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,6 +42,7 @@
|
|||||||
#include <openthread/instance.h>
|
#include <openthread/instance.h>
|
||||||
#include <openthread/platform/toolchain.h>
|
#include <openthread/platform/toolchain.h>
|
||||||
|
|
||||||
|
#include "common/linked_list.hpp"
|
||||||
#include "common/locator.hpp"
|
#include "common/locator.hpp"
|
||||||
#include "common/tasklet.hpp"
|
#include "common/tasklet.hpp"
|
||||||
|
|
||||||
@@ -79,9 +80,10 @@ public:
|
|||||||
* This class defines a `Notifier` callback instance.
|
* This class defines a `Notifier` callback instance.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
class Callback : public OwnerLocator
|
class Callback : public OwnerLocator, public LinkedListEntry<Callback>
|
||||||
{
|
{
|
||||||
friend class Notifier;
|
friend class Notifier;
|
||||||
|
friend class LinkedListEntry<Callback>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
@@ -232,11 +234,11 @@ private:
|
|||||||
void LogChangedFlags(otChangedFlags aFlags) const;
|
void LogChangedFlags(otChangedFlags aFlags) const;
|
||||||
const char *FlagToString(otChangedFlags aFlag) const;
|
const char *FlagToString(otChangedFlags aFlag) const;
|
||||||
|
|
||||||
otChangedFlags mFlagsToSignal;
|
otChangedFlags mFlagsToSignal;
|
||||||
otChangedFlags mSignaledFlags;
|
otChangedFlags mSignaledFlags;
|
||||||
Tasklet mTask;
|
Tasklet mTask;
|
||||||
Callback * mCallbacks;
|
LinkedList<Callback> mCallbacks;
|
||||||
ExternalCallback mExternalCallbacks[kMaxExternalHandlers];
|
ExternalCallback mExternalCallbacks[kMaxExternalHandlers];
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+23
-50
@@ -100,73 +100,45 @@ void TimerMilli::Stop(void)
|
|||||||
|
|
||||||
void TimerScheduler::Add(Timer &aTimer, const AlarmApi &aAlarmApi)
|
void TimerScheduler::Add(Timer &aTimer, const AlarmApi &aAlarmApi)
|
||||||
{
|
{
|
||||||
|
Timer *prev = NULL;
|
||||||
|
Time now(aAlarmApi.AlarmGetNow());
|
||||||
|
|
||||||
Remove(aTimer, aAlarmApi);
|
Remove(aTimer, aAlarmApi);
|
||||||
|
|
||||||
if (mHead == NULL)
|
for (Timer *cur = mTimerList.GetHead(); cur; prev = cur, cur = cur->GetNext())
|
||||||
{
|
{
|
||||||
mHead = &aTimer;
|
if (aTimer.DoesFireBefore(*cur, now))
|
||||||
aTimer.mNext = NULL;
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prev == NULL)
|
||||||
|
{
|
||||||
|
mTimerList.Push(aTimer);
|
||||||
SetAlarm(aAlarmApi);
|
SetAlarm(aAlarmApi);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Timer *prev = NULL;
|
mTimerList.PushAfter(aTimer, *prev);
|
||||||
Timer *cur;
|
|
||||||
|
|
||||||
for (cur = mHead; cur; cur = cur->mNext)
|
|
||||||
{
|
|
||||||
Time now(aAlarmApi.AlarmGetNow());
|
|
||||||
|
|
||||||
if (aTimer.DoesFireBefore(*cur, now))
|
|
||||||
{
|
|
||||||
if (prev)
|
|
||||||
{
|
|
||||||
aTimer.mNext = cur;
|
|
||||||
prev->mNext = &aTimer;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
aTimer.mNext = mHead;
|
|
||||||
mHead = &aTimer;
|
|
||||||
SetAlarm(aAlarmApi);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
prev = cur;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cur == NULL)
|
|
||||||
{
|
|
||||||
prev->mNext = &aTimer;
|
|
||||||
aTimer.mNext = NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimerScheduler::Remove(Timer &aTimer, const AlarmApi &aAlarmApi)
|
void TimerScheduler::Remove(Timer &aTimer, const AlarmApi &aAlarmApi)
|
||||||
{
|
{
|
||||||
VerifyOrExit(aTimer.mNext != &aTimer);
|
VerifyOrExit(aTimer.IsRunning());
|
||||||
|
|
||||||
if (mHead == &aTimer)
|
if (mTimerList.GetHead() == &aTimer)
|
||||||
{
|
{
|
||||||
mHead = aTimer.mNext;
|
mTimerList.Pop();
|
||||||
SetAlarm(aAlarmApi);
|
SetAlarm(aAlarmApi);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for (Timer *cur = mHead; cur; cur = cur->mNext)
|
mTimerList.Remove(aTimer);
|
||||||
{
|
|
||||||
if (cur->mNext == &aTimer)
|
|
||||||
{
|
|
||||||
cur->mNext = aTimer.mNext;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
aTimer.mNext = &aTimer;
|
aTimer.SetNext(&aTimer);
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
return;
|
return;
|
||||||
@@ -174,16 +146,17 @@ exit:
|
|||||||
|
|
||||||
void TimerScheduler::SetAlarm(const AlarmApi &aAlarmApi)
|
void TimerScheduler::SetAlarm(const AlarmApi &aAlarmApi)
|
||||||
{
|
{
|
||||||
if (mHead == NULL)
|
if (mTimerList.IsEmpty())
|
||||||
{
|
{
|
||||||
aAlarmApi.AlarmStop(&GetInstance());
|
aAlarmApi.AlarmStop(&GetInstance());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
Timer * timer = mTimerList.GetHead();
|
||||||
Time now(aAlarmApi.AlarmGetNow());
|
Time now(aAlarmApi.AlarmGetNow());
|
||||||
uint32_t remaining;
|
uint32_t remaining;
|
||||||
|
|
||||||
remaining = (now < mHead->mFireTime) ? (mHead->mFireTime - now) : 0;
|
remaining = (now < timer->mFireTime) ? (timer->mFireTime - now) : 0;
|
||||||
|
|
||||||
aAlarmApi.AlarmStartAt(&GetInstance(), now.GetValue(), remaining);
|
aAlarmApi.AlarmStartAt(&GetInstance(), now.GetValue(), remaining);
|
||||||
}
|
}
|
||||||
@@ -191,7 +164,7 @@ void TimerScheduler::SetAlarm(const AlarmApi &aAlarmApi)
|
|||||||
|
|
||||||
void TimerScheduler::ProcessTimers(const AlarmApi &aAlarmApi)
|
void TimerScheduler::ProcessTimers(const AlarmApi &aAlarmApi)
|
||||||
{
|
{
|
||||||
Timer *timer = mHead;
|
Timer *timer = mTimerList.GetHead();
|
||||||
|
|
||||||
if (timer)
|
if (timer)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -43,6 +43,7 @@
|
|||||||
#include <openthread/platform/alarm-milli.h>
|
#include <openthread/platform/alarm-milli.h>
|
||||||
|
|
||||||
#include "common/debug.hpp"
|
#include "common/debug.hpp"
|
||||||
|
#include "common/linked_list.hpp"
|
||||||
#include "common/locator.hpp"
|
#include "common/locator.hpp"
|
||||||
#include "common/tasklet.hpp"
|
#include "common/tasklet.hpp"
|
||||||
#include "common/time.hpp"
|
#include "common/time.hpp"
|
||||||
@@ -65,9 +66,10 @@ class TimerMilliScheduler;
|
|||||||
* This class implements a timer.
|
* This class implements a timer.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
class Timer : public InstanceLocator, public OwnerLocator
|
class Timer : public InstanceLocator, public OwnerLocator, public LinkedListEntry<Timer>
|
||||||
{
|
{
|
||||||
friend class TimerScheduler;
|
friend class TimerScheduler;
|
||||||
|
friend class LinkedListEntry<Timer>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
@@ -273,7 +275,7 @@ protected:
|
|||||||
*/
|
*/
|
||||||
explicit TimerScheduler(Instance &aInstance)
|
explicit TimerScheduler(Instance &aInstance)
|
||||||
: InstanceLocator(aInstance)
|
: InstanceLocator(aInstance)
|
||||||
, mHead(NULL)
|
, mTimerList()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -311,7 +313,7 @@ protected:
|
|||||||
*/
|
*/
|
||||||
void SetAlarm(const AlarmApi &aAlarmApi);
|
void SetAlarm(const AlarmApi &aAlarmApi);
|
||||||
|
|
||||||
Timer *mHead;
|
LinkedList<Timer> mTimerList;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+3
-17
@@ -50,7 +50,7 @@ namespace Ip6 {
|
|||||||
|
|
||||||
Icmp::Icmp(Instance &aInstance)
|
Icmp::Icmp(Instance &aInstance)
|
||||||
: InstanceLocator(aInstance)
|
: InstanceLocator(aInstance)
|
||||||
, mHandlers(NULL)
|
, mHandlers()
|
||||||
, mEchoSequence(1)
|
, mEchoSequence(1)
|
||||||
, mEchoMode(OT_ICMP6_ECHO_HANDLER_ALL)
|
, mEchoMode(OT_ICMP6_ECHO_HANDLER_ALL)
|
||||||
{
|
{
|
||||||
@@ -63,21 +63,7 @@ Message *Icmp::NewMessage(uint16_t aReserved)
|
|||||||
|
|
||||||
otError Icmp::RegisterHandler(IcmpHandler &aHandler)
|
otError Icmp::RegisterHandler(IcmpHandler &aHandler)
|
||||||
{
|
{
|
||||||
otError error = OT_ERROR_NONE;
|
return mHandlers.Add(aHandler);
|
||||||
|
|
||||||
for (IcmpHandler *cur = mHandlers; cur; cur = cur->GetNext())
|
|
||||||
{
|
|
||||||
if (cur == &aHandler)
|
|
||||||
{
|
|
||||||
ExitNow(error = OT_ERROR_ALREADY);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
aHandler.mNext = mHandlers;
|
|
||||||
mHandlers = &aHandler;
|
|
||||||
|
|
||||||
exit:
|
|
||||||
return error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
otError Icmp::SendEchoRequest(Message &aMessage, const MessageInfo &aMessageInfo, uint16_t aIdentifier)
|
otError Icmp::SendEchoRequest(Message &aMessage, const MessageInfo &aMessageInfo, uint16_t aIdentifier)
|
||||||
@@ -163,7 +149,7 @@ otError Icmp::HandleMessage(Message &aMessage, MessageInfo &aMessageInfo)
|
|||||||
|
|
||||||
aMessage.MoveOffset(sizeof(icmp6Header));
|
aMessage.MoveOffset(sizeof(icmp6Header));
|
||||||
|
|
||||||
for (IcmpHandler *handler = mHandlers; handler; handler = handler->GetNext())
|
for (IcmpHandler *handler = mHandlers.GetHead(); handler; handler = handler->GetNext())
|
||||||
{
|
{
|
||||||
handler->HandleReceiveMessage(aMessage, aMessageInfo, icmp6Header);
|
handler->HandleReceiveMessage(aMessage, aMessageInfo, icmp6Header);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,6 +39,7 @@
|
|||||||
#include <openthread/icmp6.h>
|
#include <openthread/icmp6.h>
|
||||||
|
|
||||||
#include "common/encoding.hpp"
|
#include "common/encoding.hpp"
|
||||||
|
#include "common/linked_list.hpp"
|
||||||
#include "common/locator.hpp"
|
#include "common/locator.hpp"
|
||||||
#include "net/ip6_headers.hpp"
|
#include "net/ip6_headers.hpp"
|
||||||
|
|
||||||
@@ -201,7 +202,7 @@ public:
|
|||||||
* This class implements ICMPv6 message handlers.
|
* This class implements ICMPv6 message handlers.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
class IcmpHandler : public otIcmp6Handler
|
class IcmpHandler : public otIcmp6Handler, public LinkedListEntry<IcmpHandler>
|
||||||
{
|
{
|
||||||
friend class Icmp;
|
friend class Icmp;
|
||||||
|
|
||||||
@@ -225,8 +226,6 @@ private:
|
|||||||
{
|
{
|
||||||
mReceiveCallback(mContext, &aMessage, &aMessageInfo, &aIcmp6Header);
|
mReceiveCallback(mContext, &aMessage, &aMessageInfo, &aIcmp6Header);
|
||||||
}
|
}
|
||||||
|
|
||||||
IcmpHandler *GetNext(void) { return static_cast<IcmpHandler *>(mNext); }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -347,7 +346,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
otError HandleEchoRequest(Message &aRequestMessage, const MessageInfo &aMessageInfo);
|
otError HandleEchoRequest(Message &aRequestMessage, const MessageInfo &aMessageInfo);
|
||||||
|
|
||||||
IcmpHandler *mHandlers;
|
LinkedList<IcmpHandler> mHandlers;
|
||||||
|
|
||||||
uint16_t mEchoSequence;
|
uint16_t mEchoSequence;
|
||||||
otIcmp6EchoMode mEchoMode;
|
otIcmp6EchoMode mEchoMode;
|
||||||
|
|||||||
+45
-107
@@ -82,8 +82,8 @@ const otNetifMulticastAddress Netif::kLinkLocalAllRoutersMulticastAddress = {
|
|||||||
|
|
||||||
Netif::Netif(Instance &aInstance)
|
Netif::Netif(Instance &aInstance)
|
||||||
: InstanceLocator(aInstance)
|
: InstanceLocator(aInstance)
|
||||||
, mUnicastAddresses(NULL)
|
, mUnicastAddresses()
|
||||||
, mMulticastAddresses(NULL)
|
, mMulticastAddresses()
|
||||||
, mMulticastPromiscuous(false)
|
, mMulticastPromiscuous(false)
|
||||||
, mNext(NULL)
|
, mNext(NULL)
|
||||||
, mAddressCallback(NULL)
|
, mAddressCallback(NULL)
|
||||||
@@ -107,7 +107,7 @@ bool Netif::IsMulticastSubscribed(const Address &aAddress) const
|
|||||||
{
|
{
|
||||||
bool rval = false;
|
bool rval = false;
|
||||||
|
|
||||||
for (NetifMulticastAddress *cur = mMulticastAddresses; cur; cur = cur->GetNext())
|
for (const NetifMulticastAddress *cur = mMulticastAddresses.GetHead(); cur; cur = cur->GetNext())
|
||||||
{
|
{
|
||||||
if (cur->GetAddress() == aAddress)
|
if (cur->GetAddress() == aAddress)
|
||||||
{
|
{
|
||||||
@@ -121,10 +121,10 @@ exit:
|
|||||||
|
|
||||||
void Netif::SubscribeAllNodesMulticast(void)
|
void Netif::SubscribeAllNodesMulticast(void)
|
||||||
{
|
{
|
||||||
assert(mMulticastAddresses == NULL);
|
assert(mMulticastAddresses.IsEmpty());
|
||||||
|
|
||||||
mMulticastAddresses = static_cast<NetifMulticastAddress *>(
|
mMulticastAddresses.SetHead(static_cast<NetifMulticastAddress *>(
|
||||||
const_cast<otNetifMulticastAddress *>(&kLinkLocalAllNodesMulticastAddress));
|
const_cast<otNetifMulticastAddress *>(&kLinkLocalAllNodesMulticastAddress)));
|
||||||
|
|
||||||
if (mAddressCallback != NULL)
|
if (mAddressCallback != NULL)
|
||||||
{
|
{
|
||||||
@@ -140,9 +140,9 @@ void Netif::SubscribeAllNodesMulticast(void)
|
|||||||
|
|
||||||
void Netif::UnsubscribeAllNodesMulticast(void)
|
void Netif::UnsubscribeAllNodesMulticast(void)
|
||||||
{
|
{
|
||||||
assert(mMulticastAddresses == NULL || mMulticastAddresses == &kLinkLocalAllNodesMulticastAddress);
|
assert(mMulticastAddresses.IsEmpty() || mMulticastAddresses.GetHead() == &kLinkLocalAllNodesMulticastAddress);
|
||||||
|
|
||||||
mMulticastAddresses = NULL;
|
mMulticastAddresses.SetHead(NULL);
|
||||||
|
|
||||||
if (mAddressCallback != NULL)
|
if (mAddressCallback != NULL)
|
||||||
{
|
{
|
||||||
@@ -160,14 +160,14 @@ otError Netif::SubscribeAllRoutersMulticast(void)
|
|||||||
{
|
{
|
||||||
otError error = OT_ERROR_NONE;
|
otError error = OT_ERROR_NONE;
|
||||||
|
|
||||||
if (mMulticastAddresses == &kLinkLocalAllNodesMulticastAddress)
|
if (mMulticastAddresses.GetHead() == &kLinkLocalAllNodesMulticastAddress)
|
||||||
{
|
{
|
||||||
mMulticastAddresses = static_cast<NetifMulticastAddress *>(
|
mMulticastAddresses.SetHead(static_cast<NetifMulticastAddress *>(
|
||||||
const_cast<otNetifMulticastAddress *>(&kLinkLocalAllRoutersMulticastAddress));
|
const_cast<otNetifMulticastAddress *>(&kLinkLocalAllRoutersMulticastAddress)));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for (NetifMulticastAddress *cur = mMulticastAddresses; cur; cur = cur->GetNext())
|
for (NetifMulticastAddress *cur = mMulticastAddresses.GetHead(); cur; cur = cur->GetNext())
|
||||||
{
|
{
|
||||||
if (cur == &kLinkLocalAllRoutersMulticastAddress)
|
if (cur == &kLinkLocalAllRoutersMulticastAddress)
|
||||||
{
|
{
|
||||||
@@ -201,14 +201,14 @@ otError Netif::UnsubscribeAllRoutersMulticast(void)
|
|||||||
{
|
{
|
||||||
otError error = OT_ERROR_NONE;
|
otError error = OT_ERROR_NONE;
|
||||||
|
|
||||||
if (mMulticastAddresses == &kLinkLocalAllRoutersMulticastAddress)
|
if (mMulticastAddresses.GetHead() == &kLinkLocalAllRoutersMulticastAddress)
|
||||||
{
|
{
|
||||||
mMulticastAddresses = static_cast<NetifMulticastAddress *>(
|
mMulticastAddresses.SetHead(static_cast<NetifMulticastAddress *>(
|
||||||
const_cast<otNetifMulticastAddress *>(&kLinkLocalAllNodesMulticastAddress));
|
const_cast<otNetifMulticastAddress *>(&kLinkLocalAllNodesMulticastAddress)));
|
||||||
ExitNow();
|
ExitNow();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (NetifMulticastAddress *cur = mMulticastAddresses; cur; cur = cur->GetNext())
|
for (NetifMulticastAddress *cur = mMulticastAddresses.GetHead(); cur; cur = cur->GetNext())
|
||||||
{
|
{
|
||||||
if (cur->mNext == &kLinkLocalAllRoutersMulticastAddress)
|
if (cur->mNext == &kLinkLocalAllRoutersMulticastAddress)
|
||||||
{
|
{
|
||||||
@@ -240,18 +240,9 @@ exit:
|
|||||||
|
|
||||||
otError Netif::SubscribeMulticast(NetifMulticastAddress &aAddress)
|
otError Netif::SubscribeMulticast(NetifMulticastAddress &aAddress)
|
||||||
{
|
{
|
||||||
otError error = OT_ERROR_NONE;
|
otError error;
|
||||||
|
|
||||||
for (NetifMulticastAddress *cur = mMulticastAddresses; cur; cur = cur->GetNext())
|
SuccessOrExit(error = mMulticastAddresses.Add(aAddress));
|
||||||
{
|
|
||||||
if (cur == &aAddress)
|
|
||||||
{
|
|
||||||
ExitNow(error = OT_ERROR_ALREADY);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
aAddress.mNext = mMulticastAddresses;
|
|
||||||
mMulticastAddresses = &aAddress;
|
|
||||||
|
|
||||||
if (mAddressCallback != NULL)
|
if (mAddressCallback != NULL)
|
||||||
{
|
{
|
||||||
@@ -266,39 +257,18 @@ exit:
|
|||||||
|
|
||||||
otError Netif::UnsubscribeMulticast(const NetifMulticastAddress &aAddress)
|
otError Netif::UnsubscribeMulticast(const NetifMulticastAddress &aAddress)
|
||||||
{
|
{
|
||||||
otError error = OT_ERROR_NONE;
|
otError error;
|
||||||
|
|
||||||
if (mMulticastAddresses == &aAddress)
|
SuccessOrExit(error = mMulticastAddresses.Remove(aAddress));
|
||||||
|
|
||||||
|
if (mAddressCallback != NULL)
|
||||||
{
|
{
|
||||||
mMulticastAddresses = mMulticastAddresses->GetNext();
|
mAddressCallback(&aAddress.mAddress, kMulticastPrefixLength, false, mAddressCallbackContext);
|
||||||
ExitNow();
|
|
||||||
}
|
|
||||||
else if (mMulticastAddresses != NULL)
|
|
||||||
{
|
|
||||||
for (NetifMulticastAddress *cur = mMulticastAddresses; cur->GetNext(); cur = cur->GetNext())
|
|
||||||
{
|
|
||||||
if (cur->mNext == &aAddress)
|
|
||||||
{
|
|
||||||
cur->mNext = aAddress.mNext;
|
|
||||||
ExitNow();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ExitNow(error = OT_ERROR_NOT_FOUND);
|
Get<Notifier>().Signal(OT_CHANGED_IP6_MULTICAST_UNSUBSCRIBED);
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
|
|
||||||
if (error != OT_ERROR_NOT_FOUND)
|
|
||||||
{
|
|
||||||
if (mAddressCallback != NULL)
|
|
||||||
{
|
|
||||||
mAddressCallback(&aAddress.mAddress, kMulticastPrefixLength, false, mAddressCallbackContext);
|
|
||||||
}
|
|
||||||
|
|
||||||
Get<Notifier>().Signal(OT_CHANGED_IP6_MULTICAST_UNSUBSCRIBED);
|
|
||||||
}
|
|
||||||
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -332,7 +302,7 @@ otError Netif::SubscribeExternalMulticast(const Address &aAddress)
|
|||||||
otError error = OT_ERROR_NONE;
|
otError error = OT_ERROR_NONE;
|
||||||
NetifMulticastAddress *entry;
|
NetifMulticastAddress *entry;
|
||||||
|
|
||||||
VerifyOrExit(mMulticastAddresses != NULL, error = OT_ERROR_INVALID_STATE);
|
VerifyOrExit(!mMulticastAddresses.IsEmpty(), error = OT_ERROR_INVALID_STATE);
|
||||||
|
|
||||||
if (IsMulticastSubscribed(aAddress))
|
if (IsMulticastSubscribed(aAddress))
|
||||||
{
|
{
|
||||||
@@ -352,9 +322,8 @@ otError Netif::SubscribeExternalMulticast(const Address &aAddress)
|
|||||||
VerifyOrExit(entry < OT_ARRAY_END(mExtMulticastAddresses), error = OT_ERROR_NO_BUFS);
|
VerifyOrExit(entry < OT_ARRAY_END(mExtMulticastAddresses), error = OT_ERROR_NO_BUFS);
|
||||||
|
|
||||||
// Copy the address into the available entry and add it to linked-list.
|
// Copy the address into the available entry and add it to linked-list.
|
||||||
entry->mAddress = aAddress;
|
entry->mAddress = aAddress;
|
||||||
entry->mNext = mMulticastAddresses;
|
mMulticastAddresses.Push(*entry);
|
||||||
mMulticastAddresses = entry;
|
|
||||||
Get<Notifier>().Signal(OT_CHANGED_IP6_MULTICAST_SUBSCRIBED);
|
Get<Notifier>().Signal(OT_CHANGED_IP6_MULTICAST_SUBSCRIBED);
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
@@ -367,7 +336,7 @@ otError Netif::UnsubscribeExternalMulticast(const Address &aAddress)
|
|||||||
NetifMulticastAddress *entry;
|
NetifMulticastAddress *entry;
|
||||||
NetifMulticastAddress *last = NULL;
|
NetifMulticastAddress *last = NULL;
|
||||||
|
|
||||||
for (entry = mMulticastAddresses; entry; entry = entry->GetNext())
|
for (entry = mMulticastAddresses.GetHead(); entry; entry = entry->GetNext())
|
||||||
{
|
{
|
||||||
if (entry->GetAddress() == aAddress)
|
if (entry->GetAddress() == aAddress)
|
||||||
{
|
{
|
||||||
@@ -376,11 +345,11 @@ otError Netif::UnsubscribeExternalMulticast(const Address &aAddress)
|
|||||||
|
|
||||||
if (last)
|
if (last)
|
||||||
{
|
{
|
||||||
last->mNext = entry->GetNext();
|
mMulticastAddresses.PopAfter(*last);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mMulticastAddresses = entry->GetNext();
|
mMulticastAddresses.Pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -421,18 +390,9 @@ void Netif::SetAddressCallback(otIp6AddressCallback aCallback, void *aCallbackCo
|
|||||||
|
|
||||||
otError Netif::AddUnicastAddress(NetifUnicastAddress &aAddress)
|
otError Netif::AddUnicastAddress(NetifUnicastAddress &aAddress)
|
||||||
{
|
{
|
||||||
otError error = OT_ERROR_NONE;
|
otError error;
|
||||||
|
|
||||||
for (NetifUnicastAddress *cur = mUnicastAddresses; cur; cur = cur->GetNext())
|
SuccessOrExit(error = mUnicastAddresses.Add(aAddress));
|
||||||
{
|
|
||||||
if (cur == &aAddress)
|
|
||||||
{
|
|
||||||
ExitNow(error = OT_ERROR_ALREADY);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
aAddress.mNext = mUnicastAddresses;
|
|
||||||
mUnicastAddresses = &aAddress;
|
|
||||||
|
|
||||||
if (mAddressCallback != NULL)
|
if (mAddressCallback != NULL)
|
||||||
{
|
{
|
||||||
@@ -447,39 +407,18 @@ exit:
|
|||||||
|
|
||||||
otError Netif::RemoveUnicastAddress(const NetifUnicastAddress &aAddress)
|
otError Netif::RemoveUnicastAddress(const NetifUnicastAddress &aAddress)
|
||||||
{
|
{
|
||||||
otError error = OT_ERROR_NONE;
|
otError error;
|
||||||
|
|
||||||
if (mUnicastAddresses == &aAddress)
|
SuccessOrExit(error = mUnicastAddresses.Remove(aAddress));
|
||||||
|
|
||||||
|
if (mAddressCallback != NULL)
|
||||||
{
|
{
|
||||||
mUnicastAddresses = mUnicastAddresses->GetNext();
|
mAddressCallback(&aAddress.mAddress, aAddress.mPrefixLength, false, mAddressCallbackContext);
|
||||||
ExitNow();
|
|
||||||
}
|
|
||||||
else if (mUnicastAddresses != NULL)
|
|
||||||
{
|
|
||||||
for (NetifUnicastAddress *cur = mUnicastAddresses; cur->GetNext(); cur = cur->GetNext())
|
|
||||||
{
|
|
||||||
if (cur->mNext == &aAddress)
|
|
||||||
{
|
|
||||||
cur->mNext = aAddress.mNext;
|
|
||||||
ExitNow();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ExitNow(error = OT_ERROR_NOT_FOUND);
|
Get<Notifier>().Signal(aAddress.mRloc ? OT_CHANGED_THREAD_RLOC_REMOVED : OT_CHANGED_IP6_ADDRESS_REMOVED);
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
|
|
||||||
if (error != OT_ERROR_NOT_FOUND)
|
|
||||||
{
|
|
||||||
if (mAddressCallback != NULL)
|
|
||||||
{
|
|
||||||
mAddressCallback(&aAddress.mAddress, aAddress.mPrefixLength, false, mAddressCallbackContext);
|
|
||||||
}
|
|
||||||
|
|
||||||
Get<Notifier>().Signal(aAddress.mRloc ? OT_CHANGED_THREAD_RLOC_REMOVED : OT_CHANGED_IP6_ADDRESS_REMOVED);
|
|
||||||
}
|
|
||||||
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -490,7 +429,7 @@ otError Netif::AddExternalUnicastAddress(const NetifUnicastAddress &aAddress)
|
|||||||
|
|
||||||
VerifyOrExit(!aAddress.GetAddress().IsLinkLocal(), error = OT_ERROR_INVALID_ARGS);
|
VerifyOrExit(!aAddress.GetAddress().IsLinkLocal(), error = OT_ERROR_INVALID_ARGS);
|
||||||
|
|
||||||
for (entry = mUnicastAddresses; entry; entry = entry->GetNext())
|
for (entry = mUnicastAddresses.GetHead(); entry; entry = entry->GetNext())
|
||||||
{
|
{
|
||||||
if (entry->GetAddress() == aAddress.GetAddress())
|
if (entry->GetAddress() == aAddress.GetAddress())
|
||||||
{
|
{
|
||||||
@@ -517,9 +456,8 @@ otError Netif::AddExternalUnicastAddress(const NetifUnicastAddress &aAddress)
|
|||||||
VerifyOrExit(entry < OT_ARRAY_END(mExtUnicastAddresses), error = OT_ERROR_NO_BUFS);
|
VerifyOrExit(entry < OT_ARRAY_END(mExtUnicastAddresses), error = OT_ERROR_NO_BUFS);
|
||||||
|
|
||||||
// Copy the new address into the available entry and insert it in linked-list.
|
// Copy the new address into the available entry and insert it in linked-list.
|
||||||
*entry = aAddress;
|
*entry = aAddress;
|
||||||
entry->mNext = mUnicastAddresses;
|
mUnicastAddresses.Push(*entry);
|
||||||
mUnicastAddresses = entry;
|
|
||||||
|
|
||||||
Get<Notifier>().Signal(OT_CHANGED_IP6_ADDRESS_ADDED);
|
Get<Notifier>().Signal(OT_CHANGED_IP6_ADDRESS_ADDED);
|
||||||
|
|
||||||
@@ -533,7 +471,7 @@ otError Netif::RemoveExternalUnicastAddress(const Address &aAddress)
|
|||||||
NetifUnicastAddress *entry;
|
NetifUnicastAddress *entry;
|
||||||
NetifUnicastAddress *last = NULL;
|
NetifUnicastAddress *last = NULL;
|
||||||
|
|
||||||
for (entry = mUnicastAddresses; entry; entry = entry->GetNext())
|
for (entry = mUnicastAddresses.GetHead(); entry; entry = entry->GetNext())
|
||||||
{
|
{
|
||||||
if (entry->GetAddress() == aAddress)
|
if (entry->GetAddress() == aAddress)
|
||||||
{
|
{
|
||||||
@@ -542,11 +480,11 @@ otError Netif::RemoveExternalUnicastAddress(const Address &aAddress)
|
|||||||
|
|
||||||
if (last)
|
if (last)
|
||||||
{
|
{
|
||||||
last->mNext = entry->mNext;
|
mUnicastAddresses.PopAfter(*last);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mUnicastAddresses = entry->GetNext();
|
mUnicastAddresses.Pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -582,7 +520,7 @@ bool Netif::IsUnicastAddress(const Address &aAddress) const
|
|||||||
{
|
{
|
||||||
bool rval = false;
|
bool rval = false;
|
||||||
|
|
||||||
for (const NetifUnicastAddress *cur = mUnicastAddresses; cur; cur = cur->GetNext())
|
for (const NetifUnicastAddress *cur = mUnicastAddresses.GetHead(); cur; cur = cur->GetNext())
|
||||||
{
|
{
|
||||||
if (cur->GetAddress() == aAddress)
|
if (cur->GetAddress() == aAddress)
|
||||||
{
|
{
|
||||||
|
|||||||
+10
-32
@@ -36,6 +36,7 @@
|
|||||||
|
|
||||||
#include "openthread-core-config.h"
|
#include "openthread-core-config.h"
|
||||||
|
|
||||||
|
#include "common/linked_list.hpp"
|
||||||
#include "common/locator.hpp"
|
#include "common/locator.hpp"
|
||||||
#include "common/message.hpp"
|
#include "common/message.hpp"
|
||||||
#include "common/tasklet.hpp"
|
#include "common/tasklet.hpp"
|
||||||
@@ -62,7 +63,7 @@ class Ip6;
|
|||||||
* This class implements an IPv6 network interface unicast address.
|
* This class implements an IPv6 network interface unicast address.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
class NetifUnicastAddress : public otNetifAddress
|
class NetifUnicastAddress : public otNetifAddress, public LinkedListEntry<NetifUnicastAddress>
|
||||||
{
|
{
|
||||||
friend class Netif;
|
friend class Netif;
|
||||||
|
|
||||||
@@ -93,29 +94,13 @@ public:
|
|||||||
{
|
{
|
||||||
return mScopeOverrideValid ? static_cast<uint8_t>(mScopeOverride) : GetAddress().GetScope();
|
return mScopeOverrideValid ? static_cast<uint8_t>(mScopeOverride) : GetAddress().GetScope();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This method returns the next unicast address assigned to the interface.
|
|
||||||
*
|
|
||||||
* @returns A pointer to the next unicast address.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
const NetifUnicastAddress *GetNext(void) const { return static_cast<const NetifUnicastAddress *>(mNext); }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method returns the next unicast address assigned to the interface.
|
|
||||||
*
|
|
||||||
* @returns A pointer to the next unicast address.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
NetifUnicastAddress *GetNext(void) { return static_cast<NetifUnicastAddress *>(mNext); }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class implements an IPv6 network interface multicast address.
|
* This class implements an IPv6 network interface multicast address.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
class NetifMulticastAddress : public otNetifMulticastAddress
|
class NetifMulticastAddress : public otNetifMulticastAddress, public LinkedListEntry<NetifMulticastAddress>
|
||||||
{
|
{
|
||||||
friend class Netif;
|
friend class Netif;
|
||||||
|
|
||||||
@@ -160,7 +145,7 @@ public:
|
|||||||
* This class implements an IPv6 network interface.
|
* This class implements an IPv6 network interface.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
class Netif : public InstanceLocator
|
class Netif : public InstanceLocator, public LinkedListEntry<Netif>
|
||||||
{
|
{
|
||||||
friend class Ip6;
|
friend class Ip6;
|
||||||
|
|
||||||
@@ -173,13 +158,6 @@ public:
|
|||||||
*/
|
*/
|
||||||
Netif(Instance &aInstance);
|
Netif(Instance &aInstance);
|
||||||
|
|
||||||
/**
|
|
||||||
* This method returns the next network interface in the list.
|
|
||||||
*
|
|
||||||
* @returns A pointer to the next network interface.
|
|
||||||
*/
|
|
||||||
Netif *GetNext(void) const { return mNext; }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method registers a callback to notify internal IPv6 address changes.
|
* This method registers a callback to notify internal IPv6 address changes.
|
||||||
*
|
*
|
||||||
@@ -195,7 +173,7 @@ public:
|
|||||||
* @returns A pointer to the list of unicast addresses.
|
* @returns A pointer to the list of unicast addresses.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
const NetifUnicastAddress *GetUnicastAddresses(void) const { return mUnicastAddresses; }
|
const NetifUnicastAddress *GetUnicastAddresses(void) const { return mUnicastAddresses.GetHead(); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method adds a unicast address to the network interface.
|
* This method adds a unicast address to the network interface.
|
||||||
@@ -295,7 +273,7 @@ public:
|
|||||||
* @returns A pointer to the list of multicast addresses.
|
* @returns A pointer to the list of multicast addresses.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
const NetifMulticastAddress *GetMulticastAddresses(void) const { return mMulticastAddresses; }
|
const NetifMulticastAddress *GetMulticastAddresses(void) const { return mMulticastAddresses.GetHead(); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method subscribes the network interface to a multicast address.
|
* This method subscribes the network interface to a multicast address.
|
||||||
@@ -402,10 +380,10 @@ private:
|
|||||||
kMulticastPrefixLength = 128, ///< Multicast prefix length used to notify internal address changes.
|
kMulticastPrefixLength = 128, ///< Multicast prefix length used to notify internal address changes.
|
||||||
};
|
};
|
||||||
|
|
||||||
NetifUnicastAddress * mUnicastAddresses;
|
LinkedList<NetifUnicastAddress> mUnicastAddresses;
|
||||||
NetifMulticastAddress *mMulticastAddresses;
|
LinkedList<NetifMulticastAddress> mMulticastAddresses;
|
||||||
bool mMulticastPromiscuous;
|
bool mMulticastPromiscuous;
|
||||||
Netif * mNext;
|
Netif * mNext;
|
||||||
|
|
||||||
otIp6AddressCallback mAddressCallback;
|
otIp6AddressCallback mAddressCallback;
|
||||||
void * mAddressCallbackContext;
|
void * mAddressCallbackContext;
|
||||||
|
|||||||
+14
-68
@@ -205,8 +205,8 @@ exit:
|
|||||||
Udp::Udp(Instance &aInstance)
|
Udp::Udp(Instance &aInstance)
|
||||||
: InstanceLocator(aInstance)
|
: InstanceLocator(aInstance)
|
||||||
, mEphemeralPort(kDynamicPortMin)
|
, mEphemeralPort(kDynamicPortMin)
|
||||||
, mReceivers(NULL)
|
, mReceivers()
|
||||||
, mSockets(NULL)
|
, mSockets()
|
||||||
#if OPENTHREAD_CONFIG_UDP_FORWARD_ENABLE
|
#if OPENTHREAD_CONFIG_UDP_FORWARD_ENABLE
|
||||||
, mUdpForwarderContext(NULL)
|
, mUdpForwarderContext(NULL)
|
||||||
, mUdpForwarder(NULL)
|
, mUdpForwarder(NULL)
|
||||||
@@ -216,86 +216,32 @@ Udp::Udp(Instance &aInstance)
|
|||||||
|
|
||||||
otError Udp::AddReceiver(UdpReceiver &aReceiver)
|
otError Udp::AddReceiver(UdpReceiver &aReceiver)
|
||||||
{
|
{
|
||||||
otError error = OT_ERROR_NONE;
|
return mReceivers.Add(aReceiver);
|
||||||
|
|
||||||
for (UdpReceiver *cur = mReceivers; cur; cur = cur->GetNext())
|
|
||||||
{
|
|
||||||
if (cur == &aReceiver)
|
|
||||||
{
|
|
||||||
ExitNow(error = OT_ERROR_ALREADY);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
aReceiver.SetNext(mReceivers);
|
|
||||||
mReceivers = &aReceiver;
|
|
||||||
|
|
||||||
exit:
|
|
||||||
return error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
otError Udp::RemoveReceiver(UdpReceiver &aReceiver)
|
otError Udp::RemoveReceiver(UdpReceiver &aReceiver)
|
||||||
{
|
{
|
||||||
otError error = OT_ERROR_NOT_FOUND;
|
otError error;
|
||||||
|
|
||||||
if (mReceivers == &aReceiver)
|
SuccessOrExit(error = mReceivers.Remove(aReceiver));
|
||||||
{
|
aReceiver.SetNext(NULL);
|
||||||
mReceivers = mReceivers->GetNext();
|
|
||||||
aReceiver.SetNext(NULL);
|
|
||||||
error = OT_ERROR_NONE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (UdpReceiver *handler = mReceivers; handler; handler = handler->GetNext())
|
|
||||||
{
|
|
||||||
if (handler->GetNext() == &aReceiver)
|
|
||||||
{
|
|
||||||
handler->SetNext(aReceiver.GetNext());
|
|
||||||
aReceiver.SetNext(NULL);
|
|
||||||
error = OT_ERROR_NONE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
exit:
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Udp::AddSocket(UdpSocket &aSocket)
|
void Udp::AddSocket(UdpSocket &aSocket)
|
||||||
{
|
{
|
||||||
for (UdpSocket *cur = mSockets; cur; cur = cur->GetNext())
|
mSockets.Add(aSocket);
|
||||||
{
|
|
||||||
if (cur == &aSocket)
|
|
||||||
{
|
|
||||||
ExitNow();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
aSocket.SetNext(mSockets);
|
|
||||||
mSockets = &aSocket;
|
|
||||||
|
|
||||||
exit:
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Udp::RemoveSocket(UdpSocket &aSocket)
|
void Udp::RemoveSocket(UdpSocket &aSocket)
|
||||||
{
|
{
|
||||||
if (mSockets == &aSocket)
|
SuccessOrExit(mSockets.Remove(aSocket));
|
||||||
{
|
|
||||||
mSockets = mSockets->GetNext();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (UdpSocket *socket = mSockets; socket; socket = socket->GetNext())
|
|
||||||
{
|
|
||||||
if (socket->GetNext() == &aSocket)
|
|
||||||
{
|
|
||||||
socket->SetNext(aSocket.GetNext());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
aSocket.SetNext(NULL);
|
aSocket.SetNext(NULL);
|
||||||
|
|
||||||
|
exit:
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t Udp::GetEphemeralPort(void)
|
uint16_t Udp::GetEphemeralPort(void)
|
||||||
@@ -382,7 +328,7 @@ otError Udp::HandleMessage(Message &aMessage, MessageInfo &aMessageInfo)
|
|||||||
VerifyOrExit(IsMle(GetInstance(), aMessageInfo.mSockPort));
|
VerifyOrExit(IsMle(GetInstance(), aMessageInfo.mSockPort));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
for (UdpReceiver *receiver = mReceivers; receiver; receiver = receiver->GetNext())
|
for (UdpReceiver *receiver = mReceivers.GetHead(); receiver; receiver = receiver->GetNext())
|
||||||
{
|
{
|
||||||
VerifyOrExit(!receiver->HandleMessage(aMessage, aMessageInfo));
|
VerifyOrExit(!receiver->HandleMessage(aMessage, aMessageInfo));
|
||||||
}
|
}
|
||||||
@@ -396,7 +342,7 @@ exit:
|
|||||||
void Udp::HandlePayload(Message &aMessage, MessageInfo &aMessageInfo)
|
void Udp::HandlePayload(Message &aMessage, MessageInfo &aMessageInfo)
|
||||||
{
|
{
|
||||||
// find socket
|
// find socket
|
||||||
for (UdpSocket *socket = mSockets; socket; socket = socket->GetNext())
|
for (UdpSocket *socket = mSockets.GetHead(); socket; socket = socket->GetNext())
|
||||||
{
|
{
|
||||||
if (socket->GetSockName().mPort != aMessageInfo.GetSockPort())
|
if (socket->GetSockName().mPort != aMessageInfo.GetSockPort())
|
||||||
{
|
{
|
||||||
|
|||||||
+7
-12
@@ -38,6 +38,7 @@
|
|||||||
|
|
||||||
#include <openthread/udp.h>
|
#include <openthread/udp.h>
|
||||||
|
|
||||||
|
#include "common/linked_list.hpp"
|
||||||
#include "common/locator.hpp"
|
#include "common/locator.hpp"
|
||||||
#include "net/ip6_headers.hpp"
|
#include "net/ip6_headers.hpp"
|
||||||
|
|
||||||
@@ -60,7 +61,7 @@ class Udp;
|
|||||||
* This class implements a UDP receiver.
|
* This class implements a UDP receiver.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
class UdpReceiver : public otUdpReceiver
|
class UdpReceiver : public otUdpReceiver, public LinkedListEntry<UdpReceiver>
|
||||||
{
|
{
|
||||||
friend class Udp;
|
friend class Udp;
|
||||||
|
|
||||||
@@ -80,9 +81,6 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
UdpReceiver *GetNext(void) { return static_cast<UdpReceiver *>(mNext); }
|
|
||||||
void SetNext(UdpReceiver *aReceiver) { mNext = static_cast<otUdpReceiver *>(aReceiver); }
|
|
||||||
|
|
||||||
bool HandleMessage(Message &aMessage, const MessageInfo &aMessageInfo)
|
bool HandleMessage(Message &aMessage, const MessageInfo &aMessageInfo)
|
||||||
{
|
{
|
||||||
return mHandler(mContext, &aMessage, &aMessageInfo);
|
return mHandler(mContext, &aMessage, &aMessageInfo);
|
||||||
@@ -93,7 +91,7 @@ private:
|
|||||||
* This class implements a UDP/IPv6 socket.
|
* This class implements a UDP/IPv6 socket.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
class UdpSocket : public otUdpSocket, public InstanceLocator
|
class UdpSocket : public otUdpSocket, public InstanceLocator, public LinkedListEntry<UdpSocket>
|
||||||
{
|
{
|
||||||
friend class Udp;
|
friend class Udp;
|
||||||
|
|
||||||
@@ -202,9 +200,6 @@ public:
|
|||||||
SockAddr &GetPeerName(void) { return *static_cast<SockAddr *>(&mPeerName); }
|
SockAddr &GetPeerName(void) { return *static_cast<SockAddr *>(&mPeerName); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
UdpSocket *GetNext(void) { return static_cast<UdpSocket *>(mNext); }
|
|
||||||
void SetNext(UdpSocket *socket) { mNext = static_cast<otUdpSocket *>(socket); }
|
|
||||||
|
|
||||||
void HandleUdpReceive(Message &aMessage, const MessageInfo &aMessageInfo)
|
void HandleUdpReceive(Message &aMessage, const MessageInfo &aMessageInfo)
|
||||||
{
|
{
|
||||||
mHandler(mContext, &aMessage, &aMessageInfo);
|
mHandler(mContext, &aMessage, &aMessageInfo);
|
||||||
@@ -329,7 +324,7 @@ public:
|
|||||||
void UpdateChecksum(Message &aMessage, uint16_t aChecksum);
|
void UpdateChecksum(Message &aMessage, uint16_t aChecksum);
|
||||||
|
|
||||||
#if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
|
#if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
|
||||||
otUdpSocket *GetUdpSockets(void) { return mSockets; }
|
otUdpSocket *GetUdpSockets(void) { return mSockets.GetHead(); }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if OPENTHREAD_CONFIG_UDP_FORWARD_ENABLE
|
#if OPENTHREAD_CONFIG_UDP_FORWARD_ENABLE
|
||||||
@@ -354,9 +349,9 @@ private:
|
|||||||
kDynamicPortMax = 65535, ///< Service Name and Transport Protocol Port Number Registry
|
kDynamicPortMax = 65535, ///< Service Name and Transport Protocol Port Number Registry
|
||||||
};
|
};
|
||||||
|
|
||||||
uint16_t mEphemeralPort;
|
uint16_t mEphemeralPort;
|
||||||
UdpReceiver *mReceivers;
|
LinkedList<UdpReceiver> mReceivers;
|
||||||
UdpSocket * mSockets;
|
LinkedList<UdpSocket> mSockets;
|
||||||
#if OPENTHREAD_CONFIG_UDP_FORWARD_ENABLE
|
#if OPENTHREAD_CONFIG_UDP_FORWARD_ENABLE
|
||||||
void * mUdpForwarderContext;
|
void * mUdpForwarderContext;
|
||||||
otUdpForwarder mUdpForwarder;
|
otUdpForwarder mUdpForwarder;
|
||||||
|
|||||||
@@ -111,6 +111,7 @@ check_PROGRAMS += \
|
|||||||
test-hmac-sha256 \
|
test-hmac-sha256 \
|
||||||
test-ip6-address \
|
test-ip6-address \
|
||||||
test-link-quality \
|
test-link-quality \
|
||||||
|
test-linked-list \
|
||||||
test-lowpan \
|
test-lowpan \
|
||||||
test-mac-frame \
|
test-mac-frame \
|
||||||
test-message \
|
test-message \
|
||||||
@@ -185,6 +186,9 @@ test_ip6_address_SOURCES = test_platform.cpp test_ip6_address.cpp
|
|||||||
test_link_quality_LDADD = $(COMMON_LDADD)
|
test_link_quality_LDADD = $(COMMON_LDADD)
|
||||||
test_link_quality_SOURCES = test_platform.cpp test_link_quality.cpp
|
test_link_quality_SOURCES = test_platform.cpp test_link_quality.cpp
|
||||||
|
|
||||||
|
test_linked_list_LDADD = $(COMMON_LDADD)
|
||||||
|
test_linked_list_SOURCES = test_platform.cpp test_linked_list.cpp
|
||||||
|
|
||||||
test_lowpan_LDADD = $(COMMON_LDADD)
|
test_lowpan_LDADD = $(COMMON_LDADD)
|
||||||
test_lowpan_SOURCES = test_platform.cpp test_lowpan.cpp test_util.cpp
|
test_lowpan_SOURCES = test_platform.cpp test_lowpan.cpp test_util.cpp
|
||||||
|
|
||||||
@@ -243,6 +247,7 @@ PRETTY_FILES = \
|
|||||||
$(test_heap_SOURCES) \
|
$(test_heap_SOURCES) \
|
||||||
$(test_hmac_sha256_SOURCES) \
|
$(test_hmac_sha256_SOURCES) \
|
||||||
$(test_link_quality_SOURCES) \
|
$(test_link_quality_SOURCES) \
|
||||||
|
$(test_linked_list_SOURCES) \
|
||||||
$(test_lowpan_SOURCES) \
|
$(test_lowpan_SOURCES) \
|
||||||
$(test_mac_frame_SOURCES) \
|
$(test_mac_frame_SOURCES) \
|
||||||
$(test_message_queue_SOURCES) \
|
$(test_message_queue_SOURCES) \
|
||||||
|
|||||||
@@ -0,0 +1,152 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019, The OpenThread Authors.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of the copyright holder nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
#include "test_platform.h"
|
||||||
|
|
||||||
|
#include <openthread/config.h>
|
||||||
|
|
||||||
|
#include "common/debug.hpp"
|
||||||
|
#include "common/instance.hpp"
|
||||||
|
#include "common/linked_list.hpp"
|
||||||
|
|
||||||
|
#include "test_util.h"
|
||||||
|
|
||||||
|
struct EntryBase
|
||||||
|
{
|
||||||
|
EntryBase *mNext;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Entry : public EntryBase, ot::LinkedListEntry<Entry>
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
// This function verifies the content of the linked list matches a given list of entries.
|
||||||
|
void VerifyLinkedListContent(const ot::LinkedList<Entry> &aList, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
Entry * argEntry;
|
||||||
|
|
||||||
|
va_start(args, aList);
|
||||||
|
|
||||||
|
for (const Entry *entry = aList.GetHead(); entry; entry = entry->GetNext())
|
||||||
|
{
|
||||||
|
argEntry = va_arg(args, Entry *);
|
||||||
|
VerifyOrQuit(argEntry != NULL, "List contains more entries than expected");
|
||||||
|
VerifyOrQuit(argEntry == entry, "List does not contain the same entry");
|
||||||
|
VerifyOrQuit(aList.Contains(*argEntry), "List::Contains() failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
argEntry = va_arg(args, Entry *);
|
||||||
|
VerifyOrQuit(argEntry == NULL, "List contains less entries than expected");
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestLinkedList(void)
|
||||||
|
{
|
||||||
|
Entry a, b, c, d, e;
|
||||||
|
ot::LinkedList<Entry> list;
|
||||||
|
|
||||||
|
VerifyOrQuit(list.IsEmpty(), "LinkedList::IsEmpty() failed after init");
|
||||||
|
VerifyOrQuit(list.GetHead() == NULL, "LinkedList::GetHead() failed after init");
|
||||||
|
VerifyOrQuit(list.Pop() == NULL, "LinkedList::Pop() failed when empty");
|
||||||
|
|
||||||
|
VerifyLinkedListContent(list, NULL);
|
||||||
|
|
||||||
|
list.Push(a);
|
||||||
|
VerifyOrQuit(!list.IsEmpty(), "LinkedList::IsEmpty() failed");
|
||||||
|
VerifyLinkedListContent(list, &a, NULL);
|
||||||
|
|
||||||
|
SuccessOrQuit(list.Add(b), "LinkedList::Add() failed");
|
||||||
|
VerifyLinkedListContent(list, &b, &a, NULL);
|
||||||
|
|
||||||
|
list.Push(c);
|
||||||
|
VerifyLinkedListContent(list, &c, &b, &a, NULL);
|
||||||
|
|
||||||
|
SuccessOrQuit(list.Add(d), "LinkedList::Add() failed");
|
||||||
|
VerifyLinkedListContent(list, &d, &c, &b, &a, NULL);
|
||||||
|
|
||||||
|
SuccessOrQuit(list.Add(e), "LinkedList::Add() failed");
|
||||||
|
VerifyLinkedListContent(list, &e, &d, &c, &b, &a, NULL);
|
||||||
|
|
||||||
|
VerifyOrQuit(list.Add(a) == OT_ERROR_ALREADY, "LinkedList::Add() did not detect duplicate");
|
||||||
|
VerifyOrQuit(list.Add(b) == OT_ERROR_ALREADY, "LinkedList::Add() did not detect duplicate");
|
||||||
|
VerifyOrQuit(list.Add(d) == OT_ERROR_ALREADY, "LinkedList::Add() did not detect duplicate");
|
||||||
|
VerifyOrQuit(list.Add(e) == OT_ERROR_ALREADY, "LinkedList::Add() did not detect duplicate");
|
||||||
|
|
||||||
|
VerifyOrQuit(list.Pop() == &e, "LinkedList::Pop() failed");
|
||||||
|
VerifyLinkedListContent(list, &d, &c, &b, &a, NULL);
|
||||||
|
|
||||||
|
list.SetHead(&e);
|
||||||
|
VerifyLinkedListContent(list, &e, &d, &c, &b, &a, NULL);
|
||||||
|
|
||||||
|
SuccessOrQuit(list.Remove(c), "LinkedList::Remove() failed");
|
||||||
|
VerifyLinkedListContent(list, &e, &d, &b, &a, NULL);
|
||||||
|
|
||||||
|
VerifyOrQuit(list.Remove(c) == OT_ERROR_NOT_FOUND, "LinkedList::Remove() failed");
|
||||||
|
VerifyLinkedListContent(list, &e, &d, &b, &a, NULL);
|
||||||
|
|
||||||
|
SuccessOrQuit(list.Remove(e), "LinkedList::Remove() failed");
|
||||||
|
VerifyLinkedListContent(list, &d, &b, &a, NULL);
|
||||||
|
|
||||||
|
SuccessOrQuit(list.Remove(a), "LinkedList::Remove() failed");
|
||||||
|
VerifyLinkedListContent(list, &d, &b, NULL);
|
||||||
|
|
||||||
|
list.Push(a);
|
||||||
|
list.Push(c);
|
||||||
|
list.Push(e);
|
||||||
|
VerifyLinkedListContent(list, &e, &c, &a, &d, &b, NULL);
|
||||||
|
|
||||||
|
VerifyOrQuit(list.PopAfter(a) == &d, "LinkedList::PopAfter() failed");
|
||||||
|
VerifyLinkedListContent(list, &e, &c, &a, &b, NULL);
|
||||||
|
|
||||||
|
VerifyOrQuit(list.PopAfter(b) == NULL, "LinkedList::PopAfter() failed");
|
||||||
|
VerifyLinkedListContent(list, &e, &c, &a, &b, NULL);
|
||||||
|
|
||||||
|
VerifyOrQuit(list.PopAfter(e) == &c, "LinkedList::PopAfter() failed");
|
||||||
|
VerifyLinkedListContent(list, &e, &a, &b, NULL);
|
||||||
|
|
||||||
|
list.PushAfter(c, b);
|
||||||
|
VerifyLinkedListContent(list, &e, &a, &b, &c, NULL);
|
||||||
|
|
||||||
|
list.PushAfter(d, a);
|
||||||
|
VerifyLinkedListContent(list, &e, &a, &d, &b, &c, NULL);
|
||||||
|
|
||||||
|
list.Clear();
|
||||||
|
VerifyOrQuit(list.IsEmpty(), "LinkedList::IsEmpty() failed after Clear()");
|
||||||
|
VerifyLinkedListContent(list, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef ENABLE_TEST_MAIN
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
TestLinkedList();
|
||||||
|
printf("All tests passed\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
Reference in New Issue
Block a user