blob: 439b7a89c74ebb2ac8acde0c30e14d7b9f156fd6 [file] [log] [blame]
///////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2000-2020 Ericsson Telecom AB
//
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v2.0
// which accompanies this distribution, and is available at
// https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html
///////////////////////////////////////////////////////////////////////////////
// File: EPTF_COAP_LGen_Functions.ttcn
// Description:
// Rev: R1A
// Prodnr: CNL 113 858
// Updated: 2020-03-04
// Contact: http://ttcn.ericsson.se
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////
// Module: EPTF_COAP_LGen_Functions
//
// Purpose:
// This module contains the functions of the COAP load generator component
//
// See also:
// <EPTF_COAP_LGen_Definitions>
///////////////////////////////////////////////////////////////
module EPTF_COAP_LGen_Functions
{
import from EPTF_COAP_LGen_Definitions all;
import from EPTF_COAP_Transport_Definitions all;
import from EPTF_CLL_Base_Definitions all;
import from EPTF_CLL_Base_Functions all;
import from EPTF_CLL_Common_Definitions all;
import from EPTF_CLL_Variable_Definitions all;
import from EPTF_CLL_Variable_Functions all;
import from EPTF_CLL_LGenBase_Definitions all;
import from EPTF_CLL_LGenBase_ConfigFunctions all;
import from EPTF_CLL_LGenBase_Functions all;
import from EPTF_CLL_LGenBase_EventHandlingFunctions all;
import from EPTF_CLL_Logging_Definitions all;
import from EPTF_CLL_Logging_Functions all;
import from EPTF_CLL_FBQ_Functions all;
import from EPTF_CLL_HashMapStr2Int_Functions all;
import from EPTF_CLL_Scheduler_Definitions all;
import from EPTF_CLL_RBTScheduler_Functions all;
import from CoAP_Types all;
import from IPL4asp_Types all;
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_LGen_init
//
// Purpose:
// The main initialization function for the <EPTF_COAP_LGen_CT> component type
//
// Parameters:
// pl_name - *in* *charstring* - the name for the component instance
//
// Related Type:
// <EPTF_COAP_LGen_CT>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_LGen_init(in charstring pl_name)
runs on EPTF_COAP_LGen_CT
{
if (v_COAP_initialized){return;}
f_EPTF_LGenBase_init(pl_name, 0, pl_name);
f_EPTF_Logging_init_CT(pl_name);
f_EPTF_str2int_HashMap_Init();
v_COAP_bIdx := f_EPTF_LGenBase_declareBehaviorType(
c_COAP_behaviorType,
tsp_EPTF_COAP_LGen_maxBindableCtx,
refers(f_COAP_eCtxReset),
refers(f_COAP_eCtxBind),
refers(f_COAP_eCtxUnbind)
);
f_EPTF_COAP_LGen_initLogging();
f_EPTF_COAP_Logging_DEBUG(log2str(%definitionId,": my behavior idx is ", v_COAP_bIdx));
f_EPTF_COAP_EntityCtxDB_init();
f_EPTF_COAP_FsmCtxDB_init();
f_EPTF_COAP_transportEndpointDB_init();
f_EPTF_COAP_trDB_init();
f_EPTF_COAP_rrDB_init();
f_EPTF_COAP_templateDB_init();
f_EPTF_COAP_observedResourceDB_init();
f_EPTF_COAP_observationDB_init();
f_EPTF_COAP_blockwiseDB_init();
f_EPTF_COAP_niddDB_init();
f_EPTF_COAP_declareSteps();
f_EPTF_COAP_declareEvents();
f_EPTF_Base_registerCleanup(refers(f_COAP_cleanUp));
v_COAP_initialized := true;
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_LGen_initLogging
//
// Purpose:
// Initializing CLL's logging feature on the <EPTF_COAP_LGen_CT> component type
//
// Related Type:
// <EPTF_COAP_LGen_CT>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_LGen_initLogging()
runs on EPTF_COAP_LGen_CT
{
f_EPTF_Logging_init_CT("COAP_LGen");
v_COAP_loggingMaskId :=
f_EPTF_Logging_registerComponentMasks(
"COAP_LGen_Logging",
{"WARNING", "DEBUG", "DEBUGV", "ERROR"},
EPTF_Logging_CLL
);
if(tsp_EPTF_COAP_LGen_log_error){
f_EPTF_Logging_enableLocalMask(v_COAP_loggingMaskId, c_COAP_LGen_Logging_ERROR);
}
else {
f_EPTF_Logging_disableLocalMask(v_COAP_loggingMaskId, c_COAP_LGen_Logging_ERROR);
}
if(tsp_EPTF_COAP_LGen_log_warning){
f_EPTF_Logging_enableLocalMask(v_COAP_loggingMaskId, c_COAP_LGen_Logging_WARNING);
}
else {
f_EPTF_Logging_disableLocalMask(v_COAP_loggingMaskId, c_COAP_LGen_Logging_WARNING);
}
if(tsp_EPTF_COAP_LGen_debug){
f_EPTF_Logging_enableLocalMask(v_COAP_loggingMaskId, c_COAP_LGen_Logging_DEBUG);
}
else {
f_EPTF_Logging_disableLocalMask(v_COAP_loggingMaskId, c_COAP_LGen_Logging_DEBUG);
}
if(tsp_EPTF_COAP_LGen_debugVerbose) {
f_EPTF_Logging_enableLocalMask(v_COAP_loggingMaskId, c_COAP_LGen_Logging_DEBUGV);
}
else {
f_EPTF_Logging_disableLocalMask(v_COAP_loggingMaskId, c_COAP_LGen_Logging_DEBUGV);
}
}
///////////////////////////////////////////////////////////
// Function: f_COAP_cleanUp
//
// Purpose:
// The main clean up function for the <EPTF_COAP_LGen_CT> component type
//
// Related Type:
// <EPTF_COAP_LGen_CT>
///////////////////////////////////////////////////////////
function f_COAP_cleanUp()
runs on EPTF_COAP_LGen_CT
{
f_EPTF_COAP_EntityCtxDB_cleanUp();
f_EPTF_COAP_FsmCtxDB_cleanUp();
f_EPTF_COAP_transportEndpointDB_cleanUp();
f_EPTF_COAP_trDB_cleanUp();
f_EPTF_COAP_rrDB_cleanUp();
f_EPTF_COAP_templateDB_cleanUp();
f_EPTF_COAP_observedResourceDB_cleanUp();
f_EPTF_COAP_observationDB_cleanUp();
f_EPTF_COAP_blockwiseDB_cleanUp();
f_EPTF_COAP_niddDB_cleanUp();
vf_COAP_msgReceived := null;
vf_COAP_eventIndication := null;
v_COAP_initialized := false;
}
///////////////////////////////////////////////////////////
// Function: f_COAP_eCtxBind
//
// Purpose:
// This function is called by the CLL for each entity instance created on a particular instace of <EPTF_COAP_LGen_CT>
// The function will allocate and initialize an instance of <COAP_EntityCtx> in *v_COAP_EntityCtxDB* <COAP_EntityCtx_DB>
//
// Parameters:
// pl_eIdx - *in* *integer* - the index of the entity instance on this load generator component instance
//
// Returns:
// <EPTF_IntegerList> - The list will contain the index of the <COAP_EntityCtx> instance in the *v_COAP_EntityCtxDB*
//
// Related Type:
// <EPTF_COAP_LGen_CT>
///////////////////////////////////////////////////////////
function f_COAP_eCtxBind(in integer pl_eIdx)
runs on EPTF_COAP_LGen_CT
return EPTF_IntegerList
{
var integer vl_eCtxIdx := f_EPTF_FBQ_getOrCreateFreeSlot(v_COAP_EntityCtxDB.queue);
f_EPTF_FBQ_moveFromFreeHeadToBusyTail(v_COAP_EntityCtxDB.queue);
v_COAP_EntityCtxDB.data[vl_eCtxIdx] := c_COAP_EntityCtx_init;
v_COAP_EntityCtxDB.data[vl_eCtxIdx].eIdx := pl_eIdx;
v_COAP_EntityCtxDB.data[vl_eCtxIdx].nextToken := float2int(int2float(tsp_EPTF_COAP_maxToken)*rnd());
v_COAP_EntityCtxDB.data[vl_eCtxIdx].nextMID := float2int(int2float(65535)*rnd());
return {vl_eCtxIdx};
}
///////////////////////////////////////////////////////////
// Function: f_COAP_eCtxUnbind
//
// Purpose:
// The reverse operation of <f_COAP_eCtxBind>. Cleans up resources reserved during <f_COAP_eCtxBind>. Called by the CLL.
//
// Parameters:
// pl_eIdx - *in* *integer* - the index of the entity instance on this load generator component instance
//
// Related Type:
// <EPTF_COAP_LGen_CT>
///////////////////////////////////////////////////////////
function f_COAP_eCtxUnbind(in integer pl_eIdx)
runs on EPTF_COAP_LGen_CT
{
if (not v_COAP_initialized) {return;}
var integer vl_eCtxIdx:= f_EPTF_LGenBase_getBehaviorCtxItem(pl_eIdx, v_COAP_bIdx, 0);
f_EPTF_FBQ_moveFromBusyToFreeTail(vl_eCtxIdx, v_COAP_EntityCtxDB.queue);
}
///////////////////////////////////////////////////////////
// Function: f_COAP_eCtxReset
//
// Purpose:
// The resources reserved during <f_COAP_eCtxBind> are reinitalized (reset). Called by the CLL.
//
// Parameters:
// pl_eIdx - *in* *integer* - the index of the entity instance on this load generator component instance
//
// Related Type:
// <EPTF_COAP_LGen_CT>
///////////////////////////////////////////////////////////
function f_COAP_eCtxReset(in integer pl_eIdx)
runs on EPTF_COAP_LGen_CT
{
var integer vl_eCtxIdx:= f_EPTF_LGenBase_getBehaviorCtxItem(pl_eIdx, v_COAP_bIdx, 0);
v_COAP_EntityCtxDB.data[vl_eCtxIdx] := c_COAP_EntityCtx_init;
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_EntityCtxDB_init
//
// Purpose:
// Initializes the *v_COAP_EntityCtxDB* <COAP_EntityCtx_DB> database
//
// Related Type:
// <COAP_EntityCtx_DB>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_EntityCtxDB_init()
runs on EPTF_COAP_LGen_CT
{
f_EPTF_FBQ_initFreeBusyQueue(v_COAP_EntityCtxDB.queue);
v_COAP_EntityCtxDB.data := {};
v_COAP_EntityCtxDB.hashRef := f_EPTF_str2int_HashMap_New("EPTF_COAP_EnityCtxDB_Hash");
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_EntityCtxDB_cleanUp
//
// Purpose:
// Cleans up the reserved resources of the *v_COAP_EntityCtxDB* <COAP_EntityCtx_DB> database
//
// Related Type:
// <COAP_EntityCtx_DB>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_EntityCtxDB_cleanUp()
runs on EPTF_COAP_LGen_CT
{
f_EPTF_FBQ_initFreeBusyQueue(v_COAP_EntityCtxDB.queue);
v_COAP_EntityCtxDB.data :={}
f_EPTF_str2int_HashMap_Delete("EPTF_COAP_EnityCtxDB_Hash");
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_FsmCtxDB_init
//
// Purpose:
// Initializes the *v_COAP_FsmCtxDB* <COAP_FsmCtx_DB> database
//
// Related Type:
// <COAP_FsmCtx_DB>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_FsmCtxDB_init()
runs on EPTF_COAP_LGen_CT
{
f_EPTF_FBQ_initFreeBusyQueue(v_COAP_FsmCtxDB.queue);
v_COAP_FsmCtxDB.data := {};
v_COAP_FsmCtxDB.hashRef := f_EPTF_str2int_HashMap_New("EPTF_COAP_FsmCtxDB_Hash");
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_FsmCtxDB_cleanUp
//
// Purpose:
// Cleans up the reserved resources of the *v_COAP_FsmCtxDB* <COAP_FsmCtx_DB> database
//
// Related Type:
// <COAP_FsmCtx_DB>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_FsmCtxDB_cleanUp()
runs on EPTF_COAP_LGen_CT
{
f_EPTF_FBQ_initFreeBusyQueue(v_COAP_FsmCtxDB.queue);
v_COAP_FsmCtxDB.data :={}
f_EPTF_str2int_HashMap_Delete("EPTF_COAP_FsmCtxDB_Hash");
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_transportEndpointDB_init
//
// Purpose:
// Initializes the *v_COAP_transportEndpointDB* <COAP_TransportEndpointDB> database
//
// Related Type:
// <COAP_TransportEndpointDB>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_transportEndpointDB_init()
runs on EPTF_COAP_LGen_CT
{
f_EPTF_FBQ_initFreeBusyQueue(v_COAP_transportEndpointDB.queue);
v_COAP_transportEndpointDB.data := {};
v_COAP_transportEndpointDB.hashRef := f_EPTF_str2int_HashMap_New("EPTF_COAP_addressDB_Hash");
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_transportEndpointDB_cleanUp
//
// Purpose:
// Cleans up the reserved resources of the *v_COAP_transportEndpointDB* <COAP_TransportEndpointDB> database
//
// Related Type:
// <COAP_TransportEndpointDB>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_transportEndpointDB_cleanUp()
runs on EPTF_COAP_LGen_CT
{
f_EPTF_FBQ_initFreeBusyQueue(v_COAP_transportEndpointDB.queue);
v_COAP_transportEndpointDB.data := {};
f_EPTF_str2int_HashMap_Delete("EPTF_COAP_addressDB_Hash");
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_transportEndpointDB_add
//
// Purpose:
// Adds a new element to the *v_COAP_transportEndpointDB* <COAP_TransportEndpointDB> database
//
// Parameters:
// p_te - *in* <COAP_TransportEndpoint> - the element to be added
//
// Returns:
// p_idx - *out* *integer* - the index of the added element in the database
//
// Related Type:
// <COAP_TransportEndpointDB>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_transportEndpointDB_add(in COAP_TransportEndpoint p_te, inout integer p_idx)
runs on EPTF_COAP_LGen_CT
{
p_idx := f_EPTF_COAP_transportEndpointDB_lookUp(p_te);
if (p_idx == -1)
{
p_idx := f_EPTF_FBQ_getOrCreateFreeSlot(v_COAP_transportEndpointDB.queue);
f_EPTF_FBQ_moveFromFreeHeadToBusyTail(v_COAP_transportEndpointDB.queue);
f_EPTF_COAP_Logging_DEBUG(log2str(": "," adding target address ", p_idx, " ", p_te.socket, " ", p_te.proto));
f_EPTF_str2int_HashMap_Insert(v_COAP_transportEndpointDB.hashRef, f_EPTF_COAP_transportEndpointDB_Socket2String(p_te.socket), p_idx);
v_COAP_transportEndpointDB.data[p_idx] := p_te;
}
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_transportEndpointDB_get
//
// Purpose:
// Retrieves an element from the *v_COAP_transportEndpointDB* <COAP_TransportEndpointDB> database
//
// Parameters:
// p_idx - *in* *integer* - the index of the element to retrieved
//
// Returns:
// p_te - *inout* <COAP_TransportEndpoint> - the retrieved element
//
// Related Type:
// <COAP_TransportEndpointDB>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_transportEndpointDB_get(inout COAP_TransportEndpoint p_te, in integer p_idx)
runs on EPTF_COAP_LGen_CT
{
if (p_idx < sizeof(v_COAP_transportEndpointDB.data))
{
p_te := v_COAP_transportEndpointDB.data[p_idx];
}
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_transportEndpointDB_lookUp
//
// Purpose:
// Gets the index of an <COAP_TransportEndpoint> element in *v_COAP_transportEndpointDB* <COAP_TransportEndpointDB> database
// based on its socket member field
//
// Parameters:
// p_te - *in* <COAP_TransportEndpoint> - the retrieved element
//
// Returns:
// *integer* - the index of the element, or -1 if not found
//
// Related Type:
// <COAP_TransportEndpointDB>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_transportEndpointDB_lookUp(in COAP_TransportEndpoint p_te)
runs on EPTF_COAP_LGen_CT
return integer
{
var integer vl_idx := -1;
f_EPTF_str2int_HashMap_Find(v_COAP_transportEndpointDB.hashRef, f_EPTF_COAP_transportEndpointDB_Socket2String(p_te.socket), vl_idx);
return vl_idx;
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_transportEndpointDB_Socket2String
//
// Purpose:
// Hash function for lookups used by the *v_COAP_transportEndpointDB* <COAP_TransportEndpointDB> database
//
// Parameters:
// p_sock - *in* <Socket> - the address (of a <COAP_TransportEndpoint>)
//
// Returns:
// *charstring* - string hash unique for the <Socket> parameter
//
// Related Type:
// <COAP_TransportEndpointDB>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_transportEndpointDB_Socket2String(Socket p_sock)
return charstring
{
return p_sock.hostName&":"&int2str(p_sock.portNumber);
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_rrDB_init
//
// Purpose:
// Initializes the *v_COAP_rrDB* <COAP_RR_DB> database
//
// Related Type:
// <COAP_RR_DB>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_rrDB_init()
runs on EPTF_COAP_LGen_CT
{
f_EPTF_FBQ_initFreeBusyQueue(v_COAP_rrDB.queue);
v_COAP_rrDB.data := {};
v_COAP_rrDB.hashRef := f_EPTF_str2int_HashMap_New("v_COAP_rrDB");
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_rrDB_add
//
// Purpose:
// Adds a new element to the *v_COAP_rrDB* <COAP_RR_DB> database
//
// Parameters:
// p_rr - *in* <COAP_RR> - the element to be added
//
// Returns:
// *integer* - the index of the added element in the database
//
// Related Type:
// <COAP_RR_DB>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_rrDB_add(in COAP_RR p_rr)
runs on EPTF_COAP_LGen_CT
return integer
{
f_EPTF_COAP_transportEndpointDB_get(v_COAP_transportEndpoint, p_rr.addrIdx);
var integer v_idx := f_EPTF_FBQ_getOrCreateFreeSlot(v_COAP_rrDB.queue);
f_EPTF_FBQ_moveFromFreeHeadToBusyTail(v_COAP_rrDB.queue);
f_EPTF_COAP_Logging_DEBUG(log2str(": "," adding rr ", v_idx, " ", p_rr));
f_EPTF_str2int_HashMap_Insert(v_COAP_rrDB.hashRef, f_EPTF_COAP_rrDB_tokenHash(v_COAP_transportEndpoint.socket, p_rr.token), v_idx);
v_COAP_rrDB.data[v_idx] := p_rr;
return v_idx;
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_rrDB_lookUp
//
// Purpose:
// Gets the index of an <COAP_RR> element in *v_COAP_rrDB* <COAP_RR_DB> database
//
// Parameters:
// p_rr - *in* <Socket> - the socket (IP) address
// p_token - *in* *octetstring* - the token value
//
//
// Returns:
// *integer* - the index of the added element in the database, or -1 if not found
//
// Related Type:
// <COAP_RR_DB>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_rrDB_lookUp(in Socket p_sock, in octetstring p_token)
runs on EPTF_COAP_LGen_CT
return integer
{
var integer vl_idx := -1;
f_EPTF_str2int_HashMap_Find(v_COAP_rrDB.hashRef, f_EPTF_COAP_rrDB_tokenHash(p_sock, p_token), vl_idx);
return vl_idx;
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_rrDB_get
//
// Purpose:
// Retrieves an element from the *v_COAP_rrDB* <COAP_RR> database
//
// Parameters:
// p_idx - *in* *integer* - the index of the element to be retrieved
//
// Returns:
// p_rr - *inout* <COAP_RR> - the retrieved element
//
// Related Type:
// <COAP_RR_DB>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_rrDB_get(in integer p_idx, inout COAP_RR p_rr)
runs on EPTF_COAP_LGen_CT
{
if (p_idx < sizeof(v_COAP_rrDB.data))
{
p_rr := v_COAP_rrDB.data[p_idx];
}
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_rrDB_remove
//
// Purpose:
// Removes an element from the *v_COAP_rrDB* <COAP_RR> database and frees up its reserved resources
//
// Parameters:
// p_idx - *in* *integer* - the index of the element to be removed
//
// Related Type:
// <COAP_RR_DB>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_rrDB_remove(in integer p_idx)
runs on EPTF_COAP_LGen_CT
{
f_EPTF_COAP_transportEndpointDB_get(v_COAP_transportEndpoint, v_COAP_rrDB.data[p_idx].addrIdx);
f_EPTF_str2int_HashMap_Erase(v_COAP_rrDB.hashRef, f_EPTF_COAP_rrDB_tokenHash(v_COAP_transportEndpoint.socket, v_COAP_rrDB.data[p_idx].token));
v_COAP_rrDB.data[p_idx] := c_COAP_RR_init;
f_EPTF_FBQ_moveFromBusyToFreeTail(p_idx, v_COAP_rrDB.queue);
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_rrDB_cleanUp
//
// Purpose:
// Cleans up the reserved resources of the *v_COAP_rrDB* <COAP_RR_DB> database
//
// Related Type:
// <COAP_RR_DB>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_rrDB_cleanUp()
runs on EPTF_COAP_LGen_CT
{
f_EPTF_FBQ_initFreeBusyQueue(v_COAP_rrDB.queue);
v_COAP_rrDB.data := {};
f_EPTF_str2int_HashMap_Delete("v_COAP_rrDB");
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_rrDB_tokenHash
//
// Purpose:
// Hash function for lookups used by the *v_COAP_rrDB* <COAP_RR_DB> database
//
// Parameters:
// p_sock - *in* <Socket> - the address (of a <COAP_TransportEndpoint>)
// p_token - *in* *octetstring* - the token value
//
// Returns:
// *charstring* - string hash unique for a <COAP_RR> element
//
// Related Type:
// <COAP_RR_DB>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_rrDB_tokenHash(in Socket p_sock, in octetstring p_token)
return charstring
{
return oct2str(p_token)&":"&p_sock.hostName&":"&int2str(p_sock.portNumber);
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_observationDB_init
//
// Purpose:
// Initializes the *v_COAP_observationDB* <COAP_Observation_DB> database
//
// Related Type:
// <COAP_Observation_DB>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_observationDB_init()
runs on EPTF_COAP_LGen_CT
{
f_EPTF_FBQ_initFreeBusyQueue(v_COAP_observationDB.queue);
v_COAP_observationDB.data := {};
v_COAP_observationDB.hashRef := f_EPTF_str2int_HashMap_New("v_COAP_observationDB");
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_observationDB_add
//
// Purpose:
// Adds a new element to the *v_COAP_observationDB* <COAP_Observation_DB> database
//
// Parameters:
// p_os - *in* <COAP_Observation_Server> - the element to be added
//
// Returns:
// *integer* - the index of the added element in the database
//
// Related Type:
// <COAP_Observation_DB>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_observationDB_add(in COAP_Observation_Server p_os)
runs on EPTF_COAP_LGen_CT
return integer
{
var integer v_idx := f_EPTF_FBQ_getOrCreateFreeSlot(v_COAP_observationDB.queue);
f_EPTF_FBQ_moveFromFreeHeadToBusyTail(v_COAP_observationDB.queue);
f_EPTF_COAP_Logging_DEBUG(log2str(": "," adding observation server ", v_idx, " ", p_os));
f_EPTF_str2int_HashMap_Insert(
v_COAP_observationDB.hashRef,
f_EPTF_COAP_observationDB_tokenHash(p_os.remoteAddress, p_os.remotePort, p_os.resourceId, p_os.observedResourceIdx), v_idx
);
v_COAP_observationDB.data[v_idx] := p_os;
return v_idx;
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_observationDB_lookUp
//
// Purpose:
// Gets the index of an <COAP_Observation_Server> element in *v_COAP_observationDB* <COAP_Observation_DB> database
//
// Parameters:
// p_remoteAddr - *in* *charstring* - the address (host) of the observer
// p_remotePort - *in* *integer* - the port of the observer
// p_resId - *in* *charstring* - the id of the observed resource
//
//
// Returns:
// *integer* - the index of the added element in the database, or -1 if not found
//
// Related Type:
// <COAP_Observation_DB>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_observationDB_lookUp(in charstring p_remoteAddr, in integer p_remotePort, in charstring p_resId, in integer p_resIdx)
runs on EPTF_COAP_LGen_CT
return integer
{
var integer vl_idx := -1;
f_EPTF_str2int_HashMap_Find(
v_COAP_observationDB.hashRef,
f_EPTF_COAP_observationDB_tokenHash(p_remoteAddr, p_remotePort, p_resId, p_resIdx), vl_idx
);
return vl_idx;
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_observationDB_get
//
// Purpose:
// Retrieves an element from the *v_COAP_observationDB* <COAP_Observation_DB> database
//
// Parameters:
// p_idx - *in* *integer* - the index of the element to be retrieved
//
// Returns:
// p_os - *inout* <COAP_Observation_Server> - the retrieved element
//
// Related Type:
// <COAP_Observation_DB>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_observationDB_get(in integer p_idx, inout COAP_Observation_Server p_os)
runs on EPTF_COAP_LGen_CT
{
if (p_idx < sizeof(v_COAP_observationDB.data))
{
p_os := v_COAP_observationDB.data[p_idx];
}
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_observationDB_remove
//
// Purpose:
// Removes an element from the *v_COAP_observationDB* <COAP_Observation_DB> database and frees up its reserved resources
//
// Parameters:
// p_idx - *in* *integer* - the index of the element to be removed
//
// Related Type:
// <COAP_Observation_DB>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_observationDB_remove(in integer p_idx)
runs on EPTF_COAP_LGen_CT
{
f_EPTF_str2int_HashMap_Erase(
v_COAP_observationDB.hashRef,
f_EPTF_COAP_observationDB_tokenHash(
v_COAP_observationDB.data[p_idx].remoteAddress,
v_COAP_observationDB.data[p_idx].remotePort,
v_COAP_observationDB.data[p_idx].resourceId,
v_COAP_observationDB.data[p_idx].observedResourceIdx
)
);
v_COAP_observationDB.data[p_idx] := c_COAP_Observation_Server_init;
f_EPTF_FBQ_moveFromBusyToFreeTail(p_idx, v_COAP_observationDB.queue);
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_observationDB_cleanUp
//
// Purpose:
// Cleans up the reserved resources of the *v_COAP_observationDB* <COAP_Observation_DB> database
//
// Related Type:
// <COAP_Observation_DB>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_observationDB_cleanUp()
runs on EPTF_COAP_LGen_CT
{
f_EPTF_FBQ_initFreeBusyQueue(v_COAP_observationDB.queue);
v_COAP_observationDB.data := {};
f_EPTF_str2int_HashMap_Delete("v_COAP_observationDB");
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_observationDB_tokenHash
//
// Purpose:
// Hash function for lookups used by the *v_COAP_rrDB* <COAP_Observation_DB> database
//
// Parameters:
// p_remoteAddr - *in* *charstring* - the address (host) of the observer
// p_remotePort - *in* *integer* - the port of the observer
// p_resId - *in* *charstring* - the id of the observed resource
//
// Returns:
// *charstring* - string hash unique of a <COAP_Observation_Server> element
//
// Related Type:
// <COAP_Observation_DB>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_observationDB_tokenHash(in charstring p_remoteAddr, in integer p_remotePort, in charstring p_resId, in integer p_resIdx)
return charstring
{
return int2str(p_resIdx)&":"&p_remoteAddr&":"&int2str(p_remotePort)&p_resId;
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_blockwiseDB_init
//
// Purpose:
// Initializes the *v_COAP_blockwiseDB* <COAP_Blockwise_DB> database
//
// Related Type:
// <COAP_Blockwise_DB>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_blockwiseDB_init()
runs on EPTF_COAP_LGen_CT
{
f_EPTF_FBQ_initFreeBusyQueue(v_COAP_blockwiseDB.queue);
v_COAP_blockwiseDB.data := {};
v_COAP_blockwiseDB.hashRef := f_EPTF_str2int_HashMap_New("v_COAP_blockwiseDB");
v_COAP_blockwiseDB.collectContent := tsp_EPTF_COAP_BlockwiseTransfer_collectContent;
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_blockwiseDB_add
//
// Purpose:
// Adds a new element to the *v_COAP_blockwiseDB* <COAP_Blockwise_DB> database
//
// Parameters:
// p_bs - *in* <COAP_Blockwise_Server> - the element to be added
//
// Returns:
// *integer* - the index of the added element in the database
//
// Related Type:
// <COAP_Blockwise_DB>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_blockwiseDB_add(in COAP_Blockwise_Transfer p_bt)
runs on EPTF_COAP_LGen_CT
return integer
{
var integer v_idx := f_EPTF_FBQ_getOrCreateFreeSlot(v_COAP_blockwiseDB.queue);
f_EPTF_FBQ_moveFromFreeHeadToBusyTail(v_COAP_blockwiseDB.queue);
f_EPTF_COAP_Logging_DEBUG(log2str(": "," adding blockwise transfer ", v_idx, " ", p_bt));
f_EPTF_str2int_HashMap_Insert(
v_COAP_blockwiseDB.hashRef,
f_EPTF_COAP_blockwiseDB_tokenHash(p_bt.localAddress, p_bt.localPort, p_bt.resourceId), v_idx
);
v_COAP_blockwiseDB.data[v_idx] := p_bt;
return v_idx;
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_blockwiseDB_lookUp
//
// Purpose:
// Gets the index of an <COAP_Blockwise_Transfer> element in *v_COAP_blockwiseDB* <COAP_Blockwise_DB> database
//
// Parameters:
// p_localAddr - *in* *charstring* - the address (host) of the observer
// p_localPort - *in* *integer* - the port of the observer
// p_resId - *in* *charstring* - the id of the observed resource
//
//
// Returns:
// *integer* - the index of the added element in the database, or -1 if not found
//
// Related Type:
// <COAP_Blockwise_DB>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_blockwiseDB_lookUp(in charstring p_localAddr, in integer p_localPort, in charstring p_resId)
runs on EPTF_COAP_LGen_CT
return integer
{
var integer vl_idx := -1;
f_EPTF_str2int_HashMap_Find(
v_COAP_blockwiseDB.hashRef,
f_EPTF_COAP_blockwiseDB_tokenHash(p_localAddr, p_localPort, p_resId), vl_idx
);
return vl_idx;
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_blockwiseDB_get
//
// Purpose:
// Retrieves an element from the *v_COAP_blockwiseDB* <COAP_Blockwise_DB> database
//
// Parameters:
// p_idx - *in* *integer* - the index of the element to be retrieved
//
// Returns:
// p_bs - *inout* <COAP_Blockwise_Transfer> - the retrieved element
//
// Related Type:
// <COAP_Blockwise_DB>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_blockwiseDB_get(in integer p_idx, inout COAP_Blockwise_Transfer p_bt)
runs on EPTF_COAP_LGen_CT
{
if (p_idx < sizeof(v_COAP_blockwiseDB.data))
{
p_bt := v_COAP_blockwiseDB.data[p_idx];
}
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_blockwiseDB_remove
//
// Purpose:
// Removes an element from the *v_COAP_blockwiseDB* <COAP_Blockwise_DB> database and frees up its reserved resources
//
// Parameters:
// p_idx - *in* *integer* - the index of the element to be removed
//
// Related Type:
// <COAP_Blockwise_DB>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_blockwiseDB_remove(in integer p_idx)
runs on EPTF_COAP_LGen_CT
{
f_EPTF_str2int_HashMap_Erase(
v_COAP_blockwiseDB.hashRef,
f_EPTF_COAP_blockwiseDB_tokenHash(
v_COAP_blockwiseDB.data[p_idx].localAddress,
v_COAP_blockwiseDB.data[p_idx].localPort,
v_COAP_blockwiseDB.data[p_idx].resourceId
)
);
v_COAP_blockwiseDB.data[p_idx] := c_COAP_Blockwise_Transfer_init;
f_EPTF_FBQ_moveFromBusyToFreeTail(p_idx, v_COAP_blockwiseDB.queue);
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_blockwiseDB_cleanUp
//
// Purpose:
// Cleans up the reserved resources of the *v_COAP_blockwiseDB* <COAP_Blockwise_DB> database
//
// Related Type:
// <COAP_Blockwise_DB>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_blockwiseDB_cleanUp()
runs on EPTF_COAP_LGen_CT
{
f_EPTF_FBQ_initFreeBusyQueue(v_COAP_blockwiseDB.queue);
v_COAP_blockwiseDB.data := {};
f_EPTF_str2int_HashMap_Delete("v_COAP_blockwiseDB");
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_blockwiseDB_tokenHash
//
// Purpose:
// Hash function for lookups used by the *v_COAP_blockwiseDB* <COAP_Blockwise_DB> database
//
// Parameters:
// p_localAddr - *in* *charstring* - the address (host) of resource
// p_localPort - *in* *integer* - the port of the resource
// p_resId - *in* *charstring* - the id of the observed resource
//
// Returns:
// *charstring* - string hash unique of a <COAP_Blockwise_Server> element
//
// Related Type:
// <COAP_Blockwise_DB>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_blockwiseDB_tokenHash(in charstring p_localAddr, in integer p_localPort, in charstring p_resId)
return charstring
{
return p_localAddr&":"&int2str(p_localPort)&p_resId;
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_trDB_init
//
// Purpose:
// Initializes the *v_COAP_trDB* <COAP_Transaction_DB> database
//
// Related Type:
// <COAP_Transaction_DB>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_trDB_init()
runs on EPTF_COAP_LGen_CT
{
f_EPTF_FBQ_initFreeBusyQueue(v_COAP_trDB.queue);
v_COAP_trDB.data := {};
v_COAP_trDB.hashRefOutgoing := f_EPTF_str2int_HashMap_New("v_COAP_outTrDB");
v_COAP_trDB.hashRefIncoming := f_EPTF_str2int_HashMap_New("v_COAP_incTrDB");
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_trDB_add
//
// Purpose:
// Adds a new element to the *v_COAP_trDB* <COAP_Transaction_DB> database
//
// Parameters:
// p_tr - *in* <COAP_Transaction> - the element to be added
//
// Returns:
// *integer* - the index of the added element in the database
//
// Related Type:
// <COAP_Transaction_DB>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_trDB_add(in COAP_Transaction p_tr)
runs on EPTF_COAP_LGen_CT
return integer
{
f_EPTF_COAP_transportEndpointDB_get(v_COAP_transportEndpoint, p_tr.addrIdx);
var integer v_idx := f_EPTF_FBQ_getOrCreateFreeSlot(v_COAP_trDB.queue);
f_EPTF_FBQ_moveFromFreeHeadToBusyTail(v_COAP_trDB.queue);
f_EPTF_COAP_Logging_DEBUG(log2str(": "," adding tr ", v_idx, " ", p_tr));
if (p_tr.direction == OUTGOING)
{
f_EPTF_str2int_HashMap_Insert(v_COAP_trDB.hashRefOutgoing, f_EPTF_COAP_trDB_midHash(v_COAP_transportEndpoint.socket, p_tr.mid), v_idx);
}
else
{
f_EPTF_COAP_Logging_DEBUG(log2str("adding tr ", v_idx, " ", f_EPTF_COAP_trDB_midHash(v_COAP_transportEndpoint.socket, p_tr.mid)));
f_EPTF_str2int_HashMap_Insert(v_COAP_trDB.hashRefIncoming, f_EPTF_COAP_trDB_midHash(v_COAP_transportEndpoint.socket, p_tr.mid), v_idx);
}
v_COAP_trDB.data[v_idx] := p_tr;
return v_idx;
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_trDB_lookUp
//
// Purpose:
// Gets the index of an <COAP_Transaction> element in *v_COAP_trDB* <COAP_Transaction_DB> database
//
// Parameters:
// p_sock - *in* <Socket> - the local address of a <COAP_Transaction>
// p_mid - *in* *integer* - the message id of the <COAP_Transaction>
// p_dir - *in* <COAP_Transaction_Direction> - the direction of the <COAP_Transaction>
//
//
// Returns:
// *integer* - the index of the added element in the database, or -1 if not found
//
// Related Type:
// <COAP_Transaction_DB>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_trDB_lookUp(in Socket p_sock, in integer p_mid, COAP_Transaction_Direction p_dir)
runs on EPTF_COAP_LGen_CT
return integer
{
var integer vl_idx := -1;
if (p_dir == OUTGOING)
{
f_EPTF_str2int_HashMap_Find(v_COAP_trDB.hashRefOutgoing, f_EPTF_COAP_trDB_midHash(p_sock, p_mid), vl_idx);
}
else
{
f_EPTF_COAP_Logging_VERBOSE(log2str("look up tr ", f_EPTF_COAP_trDB_midHash(p_sock, p_mid)));
f_EPTF_str2int_HashMap_Find(v_COAP_trDB.hashRefIncoming, f_EPTF_COAP_trDB_midHash(p_sock, p_mid), vl_idx);
}
return vl_idx;
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_trDB_get
//
// Purpose:
// Retrieves an element from the *v_COAP_trDB* <COAP_Transaction_DB> database
//
// Parameters:
// p_idx - *in* *integer* - the index of the element to be retrieved
//
// Returns:
// p_os - *inout* <COAP_Transaction> - the retrieved element
//
// Related Type:
// <COAP_Transaction_DB>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_trDB_get(in integer p_idx, inout COAP_Transaction p_tr)
runs on EPTF_COAP_LGen_CT
{
if (p_idx < sizeof(v_COAP_trDB.data))
{
p_tr := v_COAP_trDB.data[p_idx];
}
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_trDB_remove
//
// Purpose:
// Removes an element from the *v_COAP_trDB* <COAP_Transaction_DB> database and frees up its reserved resources
//
// Parameters:
// p_idx - *in* *integer* - the index of the element to be removed
//
// Related Type:
// <COAP_Transaction_DB>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_trDB_remove(in integer p_idx)
runs on EPTF_COAP_LGen_CT
{
f_EPTF_COAP_transportEndpointDB_get(v_COAP_transportEndpoint, v_COAP_trDB.data[p_idx].addrIdx);
if (v_COAP_trDB.data[p_idx].direction == OUTGOING)
{
f_EPTF_str2int_HashMap_Erase(v_COAP_trDB.hashRefOutgoing, f_EPTF_COAP_trDB_midHash(v_COAP_transportEndpoint.socket, v_COAP_trDB.data[p_idx].mid));
}
else
{
f_EPTF_str2int_HashMap_Erase(v_COAP_trDB.hashRefIncoming, f_EPTF_COAP_trDB_midHash(v_COAP_transportEndpoint.socket, v_COAP_trDB.data[p_idx].mid));
}
v_COAP_trDB.data[p_idx] := c_COAP_Transaction_init;
f_EPTF_FBQ_moveFromBusyToFreeTail(p_idx, v_COAP_trDB.queue);
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_trDB_cleanUp
//
// Purpose:
// Cleans up the reserved resources of the *v_COAP_trDB* <COAP_Transaction_DB> database
//
// Related Type:
// <COAP_Transaction_DB>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_trDB_cleanUp()
runs on EPTF_COAP_LGen_CT
{
f_EPTF_FBQ_initFreeBusyQueue(v_COAP_trDB.queue);
v_COAP_trDB.data := {};
f_EPTF_str2int_HashMap_Delete("v_COAP_outTrDB");
f_EPTF_str2int_HashMap_Delete("v_COAP_incTrDB");
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_trDB_midHash
//
// Purpose:
// Hash function for lookups used by the *v_COAP_trDB* <COAP_Transaction_DB> database
//
// Parameters:
// p_sock - *in* <Socket> - the local address of a <COAP_Transaction>
// p_mid - *in* *integer* - the message id of the <COAP_Transaction>
//
// Returns:
// *charstring* - string hash unique of a <COAP_Transaction> element
//
// Related Type:
// <COAP_Transaction_DB>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_trDB_midHash(in Socket p_sock, in integer p_mid)
return charstring
{
return int2str(p_mid)&":"&p_sock.hostName&":"&int2str(p_sock.portNumber);
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_observedResourceDB_init
//
// Purpose:
// Initializes the *v_COAP_observedResourceDB* <COAP_ObservedResource_DB> database
//
// Related Type:
// <COAP_ObservedResource_DB>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_observedResourceDB_init()
runs on EPTF_COAP_LGen_CT
{
f_EPTF_FBQ_initFreeBusyQueue(v_COAP_observedResourceDB.queue);
v_COAP_observedResourceDB.data := {};
v_COAP_observedResourceDB.hashRef := f_EPTF_str2int_HashMap_New("EPTF_COAP_observedResourceDB_Hash");
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_observedResourceDB_add
//
// Purpose:
// Adds a new element to the *v_COAP_observedResourceDB* <COAP_ObservedResource_DB> database
//
// Parameters:
// p_or - *in* <COAP_ObservedResource> - the element to be added
//
// Returns:
// *integer* - the index of the added element in the database
//
// Related Type:
// <COAP_ObservedResource_DB>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_observedResourceDB_add(in COAP_ObservedResource p_or)
runs on EPTF_COAP_LGen_CT
return integer
{
if (f_EPTF_COAP_observedResourceDB_lookUp(p_or.localAddress, p_or.localPort, p_or.resourceId)!=-1)
{
f_EPTF_COAP_Logging_WARNING(log2str(%definitionId, " observed resource is already added with id: ", p_or.resourceId));
return -1;
}
var integer v_idx := f_EPTF_FBQ_getOrCreateFreeSlot(v_COAP_observedResourceDB.queue);
f_EPTF_FBQ_moveFromFreeHeadToBusyTail(v_COAP_observedResourceDB.queue);
f_EPTF_COAP_Logging_DEBUG(log2str(": "," adding observed resource ", v_idx, " ", p_or));
f_EPTF_str2int_HashMap_Insert(
v_COAP_observedResourceDB.hashRef,
f_EPTF_COAP_observedResourceDB_tokenHash(p_or.localAddress, p_or.localPort, p_or.resourceId),
v_idx
);
v_COAP_observedResourceDB.data[v_idx] := p_or;
f_EPTF_COAP_Logging_VERBOSE(log2str(%definitionId, " observed resource was added with id: ", p_or.resourceId, " at idx: ",v_idx));
return v_idx;
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_observedResourceDB_lookUp
//
// Purpose:
// Gets the index of an <COAP_ObservedResource> element in *v_COAP_observedResourceDB* <COAP_ObservedResource_DB> database
//
// Parameters:
// p_localAddr - *in* *charstring* - the local address of a <COAP_ObservedResource>
// p_localPort - *in* *integer* - the local port of the <COAP_ObservedResource>
// p_resourceId - *in* *charstring* - the resource id of the <COAP_ObservedResource>
//
//
// Returns:
// *integer* - the index of the added element in the database, or -1 if not found
//
// Related Type:
// <COAP_ObservedResource_DB>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_observedResourceDB_lookUp(in charstring p_localAddr, in integer p_localPort, in charstring p_resourceId)
runs on EPTF_COAP_LGen_CT
return integer
{
var integer vl_idx := -1;
if (not f_EPTF_str2int_HashMap_Find(
v_COAP_observedResourceDB.hashRef,
f_EPTF_COAP_observedResourceDB_tokenHash(p_localAddr, p_localPort, p_resourceId),
vl_idx)
)
{
vl_idx := -1;
}
return vl_idx;
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_observedResourceDB_get
//
// Purpose:
// Retrieves an element from the *v_COAP_observedResourceDB* <COAP_ObservedResource_DB> database
//
// Parameters:
// p_idx - *in* *integer* - the index of the element to be retrieved
//
// Returns:
// p_or - *inout* <COAP_ObservedResource> - the retrieved element
//
// Related Type:
// <COAP_ObservedResource_DB>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_observedResourceDB_get(in integer p_idx, inout COAP_ObservedResource p_or)
runs on EPTF_COAP_LGen_CT
{
if (p_idx < sizeof(v_COAP_observedResourceDB.data))
{
p_or := v_COAP_observedResourceDB.data[p_idx];
}
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_observedResourceDB_remove
//
// Purpose:
// Removes an element from the *v_COAP_observedResourceDB* <COAP_ObservedResource_DB> database and frees up its reserved resources
//
// Parameters:
// p_idx - *in* *integer* - the index of the element to be removed
//
// Related Type:
// <COAP_ObservedResource_DB>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_observedResourceDB_remove(in integer p_idx)
runs on EPTF_COAP_LGen_CT
{
f_EPTF_str2int_HashMap_Erase(
v_COAP_observedResourceDB.hashRef,
f_EPTF_COAP_observedResourceDB_tokenHash(
v_COAP_observedResourceDB.data[p_idx].localAddress,
v_COAP_observedResourceDB.data[p_idx].localPort,
v_COAP_observedResourceDB.data[p_idx].resourceId
)
);
v_COAP_observedResourceDB.data[p_idx] := c_COAP_ObservedResource_init;
f_EPTF_FBQ_moveFromBusyToFreeTail(p_idx, v_COAP_observedResourceDB.queue);
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_observedResourceDB_cleanUp
//
// Purpose:
// Cleans up the reserved resources of the *v_COAP_observedResourceDB* <COAP_ObservedResource_DB> database
//
// Related Type:
// <COAP_ObservedResource_DB>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_observedResourceDB_cleanUp()
runs on EPTF_COAP_LGen_CT
{
f_EPTF_FBQ_initFreeBusyQueue(v_COAP_observedResourceDB.queue);
v_COAP_observedResourceDB.data := {};
f_EPTF_str2int_HashMap_Delete("EPTF_COAP_observedResourceDB_Hash");
}
function f_EPTF_COAP_observedResourceDB_tokenHash(in charstring p_localAddr, in integer p_localPort, in charstring p_resourceId)
return charstring
{
return p_localAddr&":"&int2str(p_localPort)&p_resourceId;
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_templateDB_init
//
// Purpose:
// Initializes the *v_COAP_templateDB* <COAP_Template_DB> database by adding the templates given in <tsp_EPTF_COAP_LGen_templates>
//
// Related Type:
// <COAP_Template_DB>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_templateDB_init()
runs on EPTF_COAP_LGen_CT
{
v_COAP_templateDB.data := {};
v_COAP_templateDB.hashRef := f_EPTF_str2int_HashMap_New("EPTF_COAP_templateDB_Hash");
for (var integer i:=0; i<sizeof(tsp_EPTF_COAP_LGen_templates); i:=i+1) {
f_EPTF_COAP_templateDB_add(tsp_EPTF_COAP_LGen_templates[i]);
}
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_templateDB_add
//
// Purpose:
// Adds a new element to the *v_COAP_templateDB* <COAP_Template_DB> database
//
// Parameters:
// p_template - *in* <CoAP_Template> - the element to be added
//
// Returns:
// *integer* - the index of the added element in the database
//
// Related Type:
// <COAP_Template_DB>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_templateDB_add(in CoAP_Template p_template)
runs on EPTF_COAP_LGen_CT
return integer
{
if (f_EPTF_COAP_templateDB_lookUp(p_template.id)!=-1)
{
f_EPTF_COAP_Logging_WARNING(log2str(%definitionId, " template is already added with id: ", p_template.id));
return -1;
}
var integer v_idx := sizeof(v_COAP_templateDB.data);
v_COAP_templateDB.data[v_idx] := p_template;
f_EPTF_str2int_HashMap_Insert(v_COAP_templateDB.hashRef, p_template.id, v_idx);
f_EPTF_COAP_Logging_VERBOSE(log2str(%definitionId, " template was added with id: ", p_template.id, " at idx: ",v_idx));
return v_idx;
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_templateDB_lookUp
//
// Purpose:
// Gets the index of an <CoAP_Template> element in *v_COAP_templateDB* <COAP_Template_DB> database
//
// Parameters:
// p_id - *in* *charstring* - the id of the <CoAP_Template>
//
// Returns:
// *integer* - the index of the added element in the database, or -1 if not found
//
// Related Type:
// <COAP_Template_DB>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_templateDB_lookUp(in charstring p_id)
runs on EPTF_COAP_LGen_CT
return integer
{
var integer vl_idx := -1;
if (not f_EPTF_str2int_HashMap_Find(v_COAP_templateDB.hashRef, p_id, vl_idx))
{
vl_idx := -1;
}
return vl_idx;
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_templateDB_get
//
// Purpose:
// Retrieves an element from the *v_COAP_templateDB* <COAP_Template_DB> database
//
// Parameters:
// p_idx - *in* *integer* - the index of the element to be retrieved
//
// Returns:
// p_or - *inout* <CoAP_ReqResp> - the retrieved element
//
// Related Type:
// <COAP_Template_DB>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_templateDB_get(in integer p_idx, inout CoAP_ReqResp p_pdu)
runs on EPTF_COAP_LGen_CT
{
if (p_idx < sizeof(v_COAP_templateDB.data) and p_idx >= 0)
{
f_EPTF_COAP_Logging_VERBOSE(log2str(%definitionId, " template is fetched with idx: ", p_idx));
p_pdu := v_COAP_templateDB.data[p_idx].msg;
}
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_templateDB_cleanUp
//
// Purpose:
// Cleans up the reserved resources of the *v_COAP_templateDB* <COAP_Template_DB> database
//
// Related Type:
// <COAP_Template_DB>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_templateDB_cleanUp()
runs on EPTF_COAP_LGen_CT
{
v_COAP_templateDB.data := {};
f_EPTF_str2int_HashMap_Delete("EPTF_COAP_templateDB_Hash");
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_niddDB_init
//
// Purpose:
// Initializes the *v_COAP_niddDB* <COAP_NIDD_DB> database
//
// Related Type:
// <COAP_NIDD_DB>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_niddDB_init()
runs on EPTF_COAP_LGen_CT
{
f_EPTF_FBQ_initFreeBusyQueue(v_COAP_niddDB.queue);
v_COAP_niddDB.data := {};
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_niddDB_add
//
// Purpose:
// Adds a new element to the *v_COAP_niddDB* <COAP_NIDD_DB> database
//
// Parameters:
// p_msg - *in octetstring* - the element to be added
//
// Returns:
// *integer* - the index of the added element in the database
//
// Related Type:
// <COAP_NIDD_DB>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_niddDB_add(in octetstring p_msg)
runs on EPTF_COAP_LGen_CT
return integer
{
var integer v_idx := f_EPTF_FBQ_getOrCreateFreeSlot(v_COAP_niddDB.queue);
f_EPTF_FBQ_moveFromFreeHeadToBusyTail(v_COAP_niddDB.queue);
f_EPTF_COAP_Logging_DEBUG(log2str(": "," adding nidd message at ", v_idx));
v_COAP_niddDB.data[v_idx] := p_msg;
return v_idx;
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_niddDB_get
//
// Purpose:
// Retrieves an element from the *v_COAP_niddDB* <COAP_NIDD_DB> database
//
// Parameters:
// p_idx - *in* *integer* - the index of the element to be retrieved
//
// Returns:
// p_msg - *inout octetstring* - the retrieved element
//
// Related Type:
// <COAP_NIDD_DB>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_niddDB_get(in integer p_idx, inout octetstring p_msg)
runs on EPTF_COAP_LGen_CT
{
if (p_idx < sizeof(v_COAP_niddDB.data) and p_idx >= 0)
{
p_msg := v_COAP_niddDB.data[p_idx];
}
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_niddDB_remove
//
// Purpose:
// Removes an element from the *v_COAP_niddDB* <COAP_NIDD_DB> database and frees up its reserved resources
//
// Parameters:
// p_idx - *in* *integer* - the index of the element to be removed
//
// Related Type:
// <COAP_NIDD_DB>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_niddDB_remove(in integer p_idx)
runs on EPTF_COAP_LGen_CT
{
v_COAP_niddDB.data[p_idx] := ''O;
f_EPTF_FBQ_moveFromBusyToFreeTail(p_idx, v_COAP_niddDB.queue);
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_niddDB_cleanUp
//
// Purpose:
// Cleans up the reserved resources of the *v_COAP_niddDB* <COAP_NIDD_DB> database
//
// Related Type:
// <COAP_NIDD_DB>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_niddDB_cleanUp()
runs on EPTF_COAP_LGen_CT
{
v_COAP_niddDB.data := {};
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_getNextMID
//
// Purpose:
// Generate the next unused message id for an entity
//
// Parameters:
// p_ctx - *in* <COAP_StepCtx> - pointers for the instances related to a particular simulated entity
//
// Returns:
// *integer* - the generated message id
//
// Related Type:
// <COAP_EntityCtx>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_getNextMID(in COAP_StepCtx p_ctx)
runs on EPTF_COAP_LGen_CT
return integer
{
if (v_COAP_EntityCtxDB.data[p_ctx.eCtxIdx].nextMID < 65535)
{
v_COAP_EntityCtxDB.data[p_ctx.eCtxIdx].nextMID := v_COAP_EntityCtxDB.data[p_ctx.eCtxIdx].nextMID + 1;
}
else
{
v_COAP_EntityCtxDB.data[p_ctx.eCtxIdx].nextMID := 0;
}
return v_COAP_EntityCtxDB.data[p_ctx.eCtxIdx].nextMID;
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_getNextToken
//
// Purpose:
// Generate the next unused token for an entity
//
// Parameters:
// p_ctx - *in* <COAP_StepCtx> - pointers for the instances related to a particular simulated entity
//
// Returns:
// *octetstring* - the generated token identifier
//
// Related Type:
// <COAP_EntityCtx>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_getNextToken(in COAP_StepCtx p_ctx)
runs on EPTF_COAP_LGen_CT
return octetstring
{
if (v_COAP_EntityCtxDB.data[p_ctx.eCtxIdx].nextToken < tsp_EPTF_COAP_maxToken)
{
v_COAP_EntityCtxDB.data[p_ctx.eCtxIdx].nextToken := v_COAP_EntityCtxDB.data[p_ctx.eCtxIdx].nextToken + 1;
}
else
{
v_COAP_EntityCtxDB.data[p_ctx.eCtxIdx].nextToken := 0;
}
return int2oct(v_COAP_EntityCtxDB.data[p_ctx.eCtxIdx].nextToken, 4);
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_LGen_send
//
// Purpose:
// The transport layer implementation <EPTF_COAP_Transport_Provider_CT> can report received <EPTF_COAP_PDU> message
// to the load generator layer <EPTF_COAP_Transport_User_CT> extended by <EPTF_COAP_LGen_CT> using this function.
//
// Parameters:
// pl_msg - *in* <EPTF_COAP_PDU> - received message
//
// Related Types:
// - <EPTF_COAP_LGen_CT>
// - <EPTF_COAP_Transport_Provider_CT>
// - <EPTF_COAP_Transport_User_CT>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_LGen_send(in EPTF_COAP_PDU pl_msg)
runs on EPTF_COAP_LGen_CT
{
if (ischosen(pl_msg.transportParams.transport.nidd))
{
var integer vl_eCtxIdx := f_EPTF_LGenBase_getBehaviorCtxItem(pl_msg.eIdx, v_COAP_bIdx, 0);
f_CoAP_enc(CoAP_Message: {msg := pl_msg.pdu}, v_COAP_encoded);
f_EPTF_COAP_EntityCtx_addOutgoingNiddMessage(vl_eCtxIdx, v_COAP_encoded);
f_EPTF_COAP_dispatchEvent(c_COAP_eventIdx_niddMessageBuffered, pl_msg.eIdx, -1, {});
}
else
{
vf_EPTF_COAP_Transport_send.apply(pl_msg);
}
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_LGen_receiveMessage
//
// Purpose:
// The transport layer implementation <EPTF_COAP_Transport_Provider_CT> can report received <EPTF_COAP_PDU> message
// to the load generator layer <EPTF_COAP_Transport_User_CT> extended by <EPTF_COAP_LGen_CT> using this function.
//
// Parameters:
// pl_message - *in* <EPTF_COAP_PDU> - received message
//
// Related Types:
// - <EPTF_COAP_LGen_CT>
// - <fcb_EPTF_COAP_Transport_receiveMessage>
// - <EPTF_COAP_Transport_Provider_CT>
// - <EPTF_COAP_Transport_User_CT>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_LGen_receiveMessage(in EPTF_COAP_PDU pl_message)
runs on EPTF_COAP_LGen_CT
{
f_EPTF_COAP_Logging_VERBOSE(log2str(%definitionId, " ", pl_message));
v_COAP_msgToProcess := pl_message;
f_EPTF_COAP_updateMessageStatistics(v_COAP_stats.incoming, v_COAP_msgToProcess);
var boolean v_duplicate := not f_EPTF_COAP_stack_fromEnv(v_COAP_msgToProcess);
if (v_duplicate) {
v_COAP_stats.noDuplicates := v_COAP_stats.noDuplicates + 1;
}
if (vf_COAP_msgReceived != null)
{
vf_COAP_msgReceived.apply(v_COAP_msgToProcess, v_duplicate, v_COAP_Stack_autoHandled);
}
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_LGen_receiveEvent
//
// Purpose:
// The transport layer implementation <EPTF_COAP_Transport_Provider_CT> can report received <ASP_Event> events
// to the load generator layer <EPTF_COAP_Transport_User_CT> extended by <EPTF_COAP_LGen_CT> using this function.
//
// Parameters:
// pl_message - *in* <ASP_Event> - received event
//
// Related Types:
// - <EPTF_COAP_LGen_CT>
// - <fcb_EPTF_COAP_Transport_receiveEvent>
// - <EPTF_COAP_Transport_Provider_CT>
// - <EPTF_COAP_Transport_User_CT>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_LGen_receiveEvent(in ASP_Event p_event)
runs on EPTF_COAP_LGen_CT
{
f_EPTF_COAP_Logging_VERBOSE(log2str(%definitionId, " ", p_event));
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_LGen_transportApiResponse
//
// Purpose:
// The transport layer implementation <EPTF_COAP_Transport_Provider_CT> can report received <EPTF_COAP_Transport_Response> responses
// to the load generator layer <EPTF_COAP_Transport_User_CT> extended by <EPTF_COAP_LGen_CT> using this function.
//
// Parameters:
// pl_rsp - *in* <EPTF_COAP_Transport_Response> - received transport api response
//
// Related Types:
// - <EPTF_COAP_LGen_CT>
// - <fcb_EPTF_COAP_Transport_apiResponse>
// - <EPTF_COAP_Transport_Provider_CT>
// - <EPTF_COAP_Transport_User_CT>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_LGen_transportApiResponse(in EPTF_COAP_Transport_Response pl_rsp)
runs on EPTF_COAP_LGen_CT
{
f_EPTF_COAP_Logging_VERBOSE(log2str("api response: ", pl_rsp));
if (ispresent(pl_rsp.params))
{
if (ischosen(pl_rsp.params.dtlsConnectionClosed)) {
}
}
if (pl_rsp.succ)
{
f_EPTF_COAP_dispatchEvent(c_COAP_eventIdx_transportSucc, pl_rsp.eIdx, pl_rsp.fsmIdx, {});
}
else
{
f_EPTF_COAP_dispatchEvent(c_COAP_eventIdx_transportFail, pl_rsp.eIdx, pl_rsp.fsmIdx, {});
}
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_stack_fromApp
//
// Purpose:
// This is the main entry point for the COAP stack realization of the <EPTF_COAP_LGen_CT>
// component that handles messages received from the application layer (e.g. FSMs)
//
// Parameters:
// p_msg - *inout* <EPTF_COAP_PDU> - message that enters into the stack (will be modified by the stack)
// p_ctx - *in* <COAP_StepCtx> - pointers for the instances related to a particular simulated entity
//
// Related Types:
// <EPTF_COAP_LGen_CT>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_stack_fromApp(inout EPTF_COAP_PDU p_msg, in COAP_StepCtx p_ctx)
runs on EPTF_COAP_LGen_CT
{
// New Req-Resp
if (v_COAP_FsmCtxDB.data[p_ctx.fsmCtxIdx].rrIdx == -1)
{
f_EPTF_COAP_Logging_VERBOSE(log2str(%definitionId, " new request response"));
var COAP_RR vl_rr := c_COAP_RR_init;
vl_rr.eIdx := p_ctx.eIdx;
vl_rr.fsmIdx := p_ctx.fsmIdx;
vl_rr.fsmCtxIdx := p_ctx.fsmCtxIdx;
vl_rr.addrIdx := v_COAP_EntityCtxDB.data[p_ctx.eCtxIdx].localAddressIdx;
vl_rr.token := f_EPTF_COAP_getNextToken(p_ctx);
vl_rr.state.client := IDLE;
p_msg.pdu.token := vl_rr.token;
var integer vl_rrIdx := f_EPTF_COAP_rrDB_add(vl_rr);
f_EPTF_COAP_rr_setState(vl_rrIdx, {client := IDLE});
v_COAP_FsmCtxDB.data[p_ctx.fsmCtxIdx].rrIdx := vl_rrIdx;
f_EPTF_COAP_rr_handleMsg(p_msg, v_COAP_FsmCtxDB.data[p_ctx.fsmCtxIdx].rrIdx);
}
// Ongoing Req-Resp
else
{
f_EPTF_COAP_Logging_VERBOSE(log2str(%definitionId, " ongoing request response"));
if (f_EPTF_COAP_isRequest(p_msg.pdu))
{
f_EPTF_COAP_Logging_WARNING(log2str(%definitionId, " replacing ongoing request response with new RR"));
var COAP_RR vl_rr := c_COAP_RR_init;
vl_rr.eIdx := p_ctx.eIdx;
vl_rr.fsmIdx := p_ctx.fsmIdx;
vl_rr.fsmCtxIdx := p_ctx.fsmCtxIdx;
vl_rr.addrIdx := v_COAP_EntityCtxDB.data[p_ctx.eCtxIdx].localAddressIdx;
vl_rr.token := f_EPTF_COAP_getNextToken(p_ctx);
vl_rr.state.client := IDLE;
p_msg.pdu.token := vl_rr.token;
var integer vl_rrIdx := f_EPTF_COAP_rrDB_add(vl_rr);
f_EPTF_COAP_rr_setState(vl_rrIdx, {client := IDLE});
v_COAP_FsmCtxDB.data[p_ctx.fsmCtxIdx].rrIdx := vl_rrIdx;
f_EPTF_COAP_rr_handleMsg(p_msg, v_COAP_FsmCtxDB.data[p_ctx.fsmCtxIdx].rrIdx);
}
else
{
f_EPTF_COAP_Logging_VERBOSE(log2str(%definitionId, " handling ongoing request response with original RR"));
f_EPTF_COAP_rr_handleMsg(p_msg, v_COAP_FsmCtxDB.data[p_ctx.fsmCtxIdx].rrIdx);
}
}
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_stack_fromEnv
//
// Purpose:
// This is the main entry point for the COAP stack realization of the <EPTF_COAP_LGen_CT>
// component that handles messages received from the environment layer (e.g. transport layer)
//
// Parameters:
// p_msg - *inout* <EPTF_COAP_PDU> - message that enters into the stack (will be modified by the stack)
//
// Returns:
// *boolean* - true, if the *p_msg* message was a duplicate, false if it was not
//
// Related Types:
// <EPTF_COAP_LGen_CT>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_stack_fromEnv(inout EPTF_COAP_PDU p_msg)
runs on EPTF_COAP_LGen_CT
return boolean
{
// We clear the the flag that indicates automatic handling by the stack
v_COAP_Stack_autoHandled := false;
// Answer for an ongoing tr
var integer vl_trIdx := f_EPTF_COAP_trDB_lookUp(p_msg.transportParams.localAddress, p_msg.pdu.header.message_id, OUTGOING);
if (vl_trIdx >= 0)
{
f_EPTF_COAP_Logging_VERBOSE(log2str(%definitionId, " answer for ongoing tr"));
f_EPTF_COAP_tr_fromEnv(p_msg, vl_trIdx);
return true;
}
else
{
vl_trIdx := f_EPTF_COAP_trDB_lookUp(p_msg.transportParams.localAddress, p_msg.pdu.header.message_id, INCOMING);
// Deduplication. Already ongoing tr for a request
if (vl_trIdx != -1 and (p_msg.pdu.header.msg_type == CONFIRMABLE or p_msg.pdu.header.msg_type == NON_CONFIRMABLE))
{
f_EPTF_COAP_Logging_VERBOSE(log2str(%definitionId, " duplicate received ", p_msg));
if (ispresent(v_COAP_trDB.data[vl_trIdx].cache))
{
f_EPTF_COAP_tr_send(v_COAP_trDB.data[vl_trIdx].cache, vl_trIdx);
}
return false;
}
// New incoming request
else
{
f_EPTF_COAP_Logging_VERBOSE(log2str(%definitionId, " new incoming request ", p_msg));
// Create new tr
var integer vl_eCtxIdx := f_EPTF_LGenBase_getBehaviorCtxItem(p_msg.eIdx, v_COAP_bIdx, 0);
var COAP_Transaction vl_tr := c_COAP_Transaction_init;
vl_tr.mid := p_msg.pdu.header.message_id;
vl_tr.eIdx := p_msg.eIdx;
vl_tr.addrIdx := v_COAP_EntityCtxDB.data[vl_eCtxIdx].localAddressIdx;
vl_tr.state := CLOSED;
vl_tr.direction := INCOMING;
vl_tr.retransmitTimerValue := tsp_EPTF_COAP_LGen_retransmitTimerInitialValue;
vl_trIdx := f_EPTF_COAP_trDB_add(vl_tr);
f_EPTF_COAP_tr_setState(vl_trIdx, CLOSED);
f_EPTF_COAP_tr_fromEnv(v_COAP_msgToProcess, vl_trIdx);
return true;
}
}
}
/*****************************************************************
@startuml EPTF_COAP_LGen_Functions.COAP_RR_Server.jpg
[*] --> IDLE
IDLE --> SERVING: trIn: request CON
IDLE --> SEPARATE: trIn: request NON
SERVING --> REMOVING: appIn: response
SERVING --> REMOVING: appIn: empty ACK
SEPARATE --> REMOVING: appIn: response
REMOVING --> [*]
@enduml
******************************************************************/
/*****************************************************************
@startuml EPTF_COAP_LGen_Functions.COAP_RR_Client.jpg
[*] --> IDLE
IDLE --> WAITING: appIn: request
WAITING --> REMOVING: appIn: cancel
WAITING --> REMOVING: trIn: timeout
WAITING --> REMOVING: trIn: reset
WAITING --> REMOVING: trIn: response
REMOVING --> [*]
@enduml
******************************************************************/
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_rr_handleMsg
//
// Purpose:
// This function implements a COAP request-response state machine
//
// Parameters:
// p_msg - *inout* <EPTF_COAP_PDU> - message that enters into the stack (will be modified by the stack)
// p_rrIdx - *in* *integer* - index of the <COAP_RR> in the <COAP_RR_DB> that will handle the message
//
// Related Types:
// <COAP_RR>
//
// FSM Diagram of client request-response:
// (see EPTF_COAP_LGen_Functions.COAP_RR_Client.jpg)
//
// FSM Diagram of server request-response:
// (see EPTF_COAP_LGen_Functions.COAP_RR_Server.jpg)
///////////////////////////////////////////////////////////
function f_EPTF_COAP_rr_handleMsg(inout EPTF_COAP_PDU p_msg, in integer p_rrIdx)
runs on EPTF_COAP_LGen_CT
{
if (p_rrIdx < 0 or p_rrIdx >= sizeof(v_COAP_rrDB.data)) { return }
f_EPTF_COAP_Logging_VERBOSE(log2str(%definitionId, " rr [",v_COAP_rrDB.data[p_rrIdx].token,"] current state: ",v_COAP_rrDB.data[p_rrIdx].state));
f_EPTF_COAP_setCtx(v_COAP_rrDB.data[p_rrIdx].eIdx, v_COAP_rrDB.data[p_rrIdx].fsmIdx, v_COAP_ctx);
// RR: Client
if (ischosen(v_COAP_rrDB.data[p_rrIdx].state.client))
{
// State: IDLE
if (v_COAP_rrDB.data[p_rrIdx].state.client == IDLE)
{
// appIn: request
if (f_EPTF_COAP_isRequest(p_msg.pdu))
{
// Create new TR
var COAP_Transaction vl_tr := c_COAP_Transaction_init;
vl_tr.mid := f_EPTF_COAP_getNextMID(v_COAP_ctx);
vl_tr.eIdx := v_COAP_ctx.eIdx;
vl_tr.rrIdx := p_rrIdx;
vl_tr.addrIdx := v_COAP_EntityCtxDB.data[v_COAP_ctx.eCtxIdx].localAddressIdx;
vl_tr.state := CLOSED;
vl_tr.direction := OUTGOING;
vl_tr.retransmitTimerValue := tsp_EPTF_COAP_LGen_retransmitTimerInitialValue;
p_msg.pdu.header.message_id := vl_tr.mid;
var integer vl_trIdx := f_EPTF_COAP_trDB_add(vl_tr);
f_EPTF_COAP_tr_setState(vl_trIdx, CLOSED);
v_COAP_rrDB.data[p_rrIdx].trIdx := vl_trIdx;
// trOut.send
v_COAP_rrDB.data[p_rrIdx].request := p_msg;
f_EPTF_COAP_tr_fromRR(p_msg, v_COAP_rrDB.data[p_rrIdx].trIdx);
// next state: WAITING
f_EPTF_COAP_rr_setState(p_rrIdx, {client := WAITING});
}
else
{
f_EPTF_COAP_Logging_WARNING(log2str(%definitionId, " only request can be handled in rr::client::IDLE. Ignoring:", p_msg));
}
}
// State: WAITING
else if (v_COAP_rrDB.data[p_rrIdx].state.client == WAITING)
{
// trIn: response
if (f_EPTF_COAP_isResponse(p_msg.pdu))
{
v_COAP_rrDB.data[p_rrIdx].response := p_msg;
// If response is CON then immediatelly answer with empty ack
if (p_msg.pdu.header.msg_type == CONFIRMABLE and
v_COAP_rrDB.data[p_rrIdx].trIdx != -1 and
ispresent(v_COAP_rrDB.data[p_rrIdx].request)
) {
var EPTF_COAP_PDU vl_empty_ack := v_COAP_rrDB.data[p_rrIdx].request;
vl_empty_ack.pdu := valueof(t_CoAP_EmptyAck);
//vl_empty_ack.pdu.token := int2oct(v_COAP_rrDB.data[p_rrIdx].token, 4);
f_EPTF_COAP_tr_fromRR(vl_empty_ack, v_COAP_rrDB.data[p_rrIdx].trIdx);
}
// report to app
f_EPTF_COAP_dispatchEventsForCode(
p_msg.pdu.header.code,
v_COAP_rrDB.data[p_rrIdx].eIdx,
v_COAP_rrDB.data[p_rrIdx].fsmIdx,
{}
);
p_msg.fsmIdx := v_COAP_rrDB.data[p_rrIdx].fsmIdx;
// finish
f_EPTF_COAP_rr_remove(p_rrIdx);
}
else
{
f_EPTF_COAP_Logging_WARNING(log2str(%definitionId," only response can be handled in rr::client::WAITING. Ignoring: ", p_msg));
}
}
else
{
f_EPTF_COAP_Logging_WARNING(log2str(%definitionId," rr: unknown client state ", v_COAP_rrDB.data[p_rrIdx].state.client));
}
}
// RR: Server
else
{
// State: IDLE
if (v_COAP_rrDB.data[p_rrIdx].state.server == IDLE)
{
v_COAP_rrDB.data[p_rrIdx].remoteAddress := p_msg.transportParams.remoteAddress;
v_COAP_rrDB.data[p_rrIdx].remoteProtocol := p_msg.transportParams.transport;
v_COAP_rrDB.data[p_rrIdx].request := p_msg;
// appIn: request && CON
if (p_msg.pdu.header.msg_type == CONFIRMABLE)
{
// next state: SERVING
f_EPTF_COAP_rr_setState(p_rrIdx, {server := SERVING});
}
// appIn: request && NON
else if (p_msg.pdu.header.msg_type == NON_CONFIRMABLE)
{
// next state: SEPARATE
f_EPTF_COAP_rr_setState(p_rrIdx, {server := SEPARATE});
}
else
{
f_EPTF_COAP_Logging_WARNING(log2str(%definitionId, " message type not handled in rr:server::IDLE ", p_msg));
}
}
// State: SEPARATE
else if (v_COAP_rrDB.data[p_rrIdx].state.server == SEPARATE)
{
// appIn: response
if (f_EPTF_COAP_isResponse(p_msg.pdu))
{
p_msg.pdu.token := v_COAP_rrDB.data[p_rrIdx].token;
f_EPTF_COAP_rr_handle_Observe_request(p_rrIdx, p_msg);
f_EPTF_COAP_rr_handle_BlockwiseTransfer_request(p_rrIdx, p_msg, v_COAP_ctx.eCtxIdx);
// create new TR
var COAP_Transaction vl_tr := c_COAP_Transaction_init;
vl_tr.mid := f_EPTF_COAP_getNextMID(v_COAP_ctx);
vl_tr.eIdx := v_COAP_ctx.eIdx;
vl_tr.rrIdx := p_rrIdx;
vl_tr.addrIdx := v_COAP_EntityCtxDB.data[v_COAP_ctx.eCtxIdx].localAddressIdx;
vl_tr.state := CLOSED;
vl_tr.direction := OUTGOING;
vl_tr.retransmitTimerValue := tsp_EPTF_COAP_LGen_retransmitTimerInitialValue;
p_msg.pdu.header.message_id := vl_tr.mid;
var integer vl_trIdx := f_EPTF_COAP_trDB_add(vl_tr);
f_EPTF_COAP_tr_setState(vl_trIdx, CLOSED);
v_COAP_rrDB.data[p_rrIdx].trIdx := vl_trIdx;
if (ispresent(v_COAP_rrDB.data[p_rrIdx].remoteAddress))
{
p_msg.transportParams.remoteAddress := v_COAP_rrDB.data[p_rrIdx].remoteAddress;
}
if (ispresent(v_COAP_rrDB.data[p_rrIdx].remoteProtocol))
{
p_msg.transportParams.transport := v_COAP_rrDB.data[p_rrIdx].remoteProtocol;
}
// trOut.send
v_COAP_rrDB.data[p_rrIdx].response := p_msg;
f_EPTF_COAP_tr_fromRR(p_msg, v_COAP_rrDB.data[p_rrIdx].trIdx);
// finish
f_EPTF_COAP_rr_remove(p_rrIdx);
}
else
{
f_EPTF_COAP_Logging_WARNING(log2str(%definitionId," only response can be handled in rr::server::SEPARATE. Ignoring: ", p_msg));
}
}
// State: SERVING
else if (v_COAP_rrDB.data[p_rrIdx].state.server == SERVING)
{
// appIn: response
if (f_EPTF_COAP_isResponse(p_msg.pdu) and p_msg.pdu.header.msg_type == ACKNOWLEDGEMENT)
{
// Get the TR
if (v_COAP_rrDB.data[p_rrIdx].trIdx != -1)
{
p_msg.pdu.token := v_COAP_rrDB.data[p_rrIdx].token;
f_EPTF_COAP_rr_handle_Observe_request(p_rrIdx, p_msg);
f_EPTF_COAP_rr_handle_BlockwiseTransfer_request(p_rrIdx, p_msg, v_COAP_ctx.eCtxIdx);
if (ispresent(v_COAP_rrDB.data[p_rrIdx].remoteAddress))
{
p_msg.transportParams.remoteAddress := v_COAP_rrDB.data[p_rrIdx].remoteAddress;
}
if (ispresent(v_COAP_rrDB.data[p_rrIdx].remoteProtocol))
{
p_msg.transportParams.transport := v_COAP_rrDB.data[p_rrIdx].remoteProtocol;
}
// trOut.send
v_COAP_rrDB.data[p_rrIdx].response := p_msg;
f_EPTF_COAP_tr_fromRR(p_msg, v_COAP_rrDB.data[p_rrIdx].trIdx);
f_EPTF_COAP_rr_remove(p_rrIdx);
}
else
{
f_EPTF_COAP_Logging_WARNING(log2str(%definitionId," couldn't find ongoing transaction in rr::server::SERVING. Ignoring: ", p_msg));
}
}
// appIn: empty ACK
else if (f_EPTF_COAP_isEmpty(p_msg.pdu) and p_msg.pdu.header.msg_type == ACKNOWLEDGEMENT)
{
// Get the TR
if (v_COAP_rrDB.data[p_rrIdx].trIdx != -1)
{
// Empty ACK has no token
//p_msg.pdu.token := int2oct(v_COAP_rrDB.data[p_rrIdx].token, 4);
if (ispresent(v_COAP_rrDB.data[p_rrIdx].remoteAddress))
{
p_msg.transportParams.remoteAddress := v_COAP_rrDB.data[p_rrIdx].remoteAddress;
}
if (ispresent(v_COAP_rrDB.data[p_rrIdx].remoteProtocol))
{
p_msg.transportParams.transport := v_COAP_rrDB.data[p_rrIdx].remoteProtocol;
}
// trOut.send
f_EPTF_COAP_tr_fromRR(p_msg, v_COAP_rrDB.data[p_rrIdx].trIdx);
f_EPTF_COAP_rr_setState(p_rrIdx, {server := SEPARATE});
}
else
{
f_EPTF_COAP_Logging_WARNING(log2str(%definitionId," couldn't find ongoing transaction in rr::server::SERVING. Ignoring: ", p_msg));
}
}
else
{
f_EPTF_COAP_Logging_WARNING(log2str(%definitionId," response must be an ACK, message cannot be handled in rr::server::SERVING. Ignoring: ", p_msg));
}
}
else
{
f_EPTF_COAP_Logging_WARNING(log2str(%definitionId, "unknown server state ", v_COAP_rrDB.data[p_rrIdx].state.server));
}
}
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_rr_reset
//
// Purpose:
// This function handles the *reset* event of a <COAP_RR> state machine
//
// Parameters:
// p_rrIdx - *in* *integer* - index of the <COAP_RR> in the <COAP_RR_DB> that will handle the message
//
// Related Types:
// <COAP_RR>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_rr_reset(in integer p_rrIdx)
runs on EPTF_COAP_LGen_CT
{
if (p_rrIdx < 0 or p_rrIdx >= sizeof(v_COAP_rrDB.data)) { return }
// RR: Client
if (ischosen(v_COAP_rrDB.data[p_rrIdx].state.client))
{
// State: WAITING
if (v_COAP_rrDB.data[p_rrIdx].state.client == WAITING)
{
f_EPTF_COAP_dispatchEvent(
c_COAP_eventIdx_trRST,
v_COAP_rrDB.data[p_rrIdx].eIdx,
v_COAP_rrDB.data[p_rrIdx].fsmIdx,
{}
);
f_EPTF_COAP_rr_remove(p_rrIdx);
}
else
{
f_EPTF_COAP_Logging_WARNING(log2str(%definitionId, " reset only handled rr:client::WAITING"));
}
}
else
{
f_EPTF_COAP_Logging_WARNING(log2str(%definitionId, " reset not handled in rr:server"));
}
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_rr_timeout
//
// Purpose:
// This function handles the *timeout* event of a <COAP_RR> state machine
//
// Parameters:
// p_rrIdx - *in* *integer* - index of the <COAP_RR> in the <COAP_RR_DB> that will handle the message
//
// Related Types:
// <COAP_RR>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_rr_timeout(in integer p_rrIdx)
runs on EPTF_COAP_LGen_CT
{
if (p_rrIdx < 0 or p_rrIdx >= sizeof(v_COAP_rrDB.data)) { return }
// RR: Client
if (ischosen(v_COAP_rrDB.data[p_rrIdx].state.client))
{
// State: WAITING
if (v_COAP_rrDB.data[p_rrIdx].state.client == WAITING)
{
v_COAP_stats.noTransactionTimeouts := v_COAP_stats.noTransactionTimeouts + 1;
f_EPTF_COAP_dispatchEvent(
c_COAP_eventIdx_trTimeout,
v_COAP_rrDB.data[p_rrIdx].eIdx,
v_COAP_rrDB.data[p_rrIdx].fsmIdx,
{}
);
f_EPTF_COAP_rr_remove(p_rrIdx);
}
else
{
f_EPTF_COAP_Logging_WARNING(log2str(%definitionId, " reset only handled rr:client::WAITING"));
}
}
else
{
f_EPTF_COAP_Logging_WARNING(log2str(%definitionId, " reset not handled in rr:server"));
}
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_rr_cancel
//
// Purpose:
// This function handles the *cancel* event of a <COAP_RR> state machine
//
// Parameters:
// p_rrIdx - *in* *integer* - index of the <COAP_RR> in the <COAP_RR_DB> that will handle the message
//
// Related Types:
// <COAP_RR>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_rr_cancel(in integer p_rrIdx)
runs on EPTF_COAP_LGen_CT
{
if (p_rrIdx < 0 or p_rrIdx >= sizeof(v_COAP_rrDB.data)) { return }
// RR: Client
if (ischosen(v_COAP_rrDB.data[p_rrIdx].state.client))
{
// State: WAITING
if (v_COAP_rrDB.data[p_rrIdx].state.client == WAITING)
{
if (v_COAP_rrDB.data[p_rrIdx].trIdx != -1)
{
f_EPTF_COAP_tr_cancel(v_COAP_rrDB.data[p_rrIdx].trIdx);
f_EPTF_COAP_rr_remove(p_rrIdx);
}
else
{
f_EPTF_COAP_Logging_WARNING(log2str(%definitionId, " there is no ongoing transaction to handle cancel"));
}
}
else
{
f_EPTF_COAP_Logging_WARNING(log2str(%definitionId, " cancel only handled rr:client::WAITING"));
}
}
else
{
f_EPTF_COAP_Logging_WARNING(log2str(%definitionId, " cance; not handled in rr:server"));
}
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_rr_remove
//
// Purpose:
// This function handles the removal and clean up of a <COAP_RR> state machine instance from the DB
//
// Parameters:
// p_rrIdx - *in* *integer* - index of the <COAP_RR> in the <COAP_RR_DB>
//
// Related Types:
// <COAP_RR>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_rr_remove(in integer p_rrIdx)
runs on EPTF_COAP_LGen_CT
{
if (p_rrIdx < 0 or p_rrIdx >= sizeof(v_COAP_rrDB.data)) { return }
if (ischosen(v_COAP_rrDB.data[p_rrIdx].state.client))
{
f_EPTF_COAP_rr_setState(p_rrIdx, {client := REMOVING});
}
else
{
f_EPTF_COAP_rr_setState(p_rrIdx, {server := REMOVING});
}
//action(%definitionId, " rr: (rrIdx: ",p_rrIdx,") ",v_COAP_rrDB.data[p_rrIdx]);
if (v_COAP_rrDB.data[p_rrIdx].trIdx != -1)
{
if (v_COAP_trDB.data[v_COAP_rrDB.data[p_rrIdx].trIdx].rrIdx == p_rrIdx)
{
v_COAP_trDB.data[v_COAP_rrDB.data[p_rrIdx].trIdx].rrIdx := -1;
}
}
if (v_COAP_rrDB.data[p_rrIdx].fsmCtxIdx != -1)
{
//action(%definitionId, " fsm: ",v_COAP_FsmCtxDB.data[v_COAP_rrDB.data[p_rrIdx].fsmCtxIdx]);
if (v_COAP_FsmCtxDB.data[v_COAP_rrDB.data[p_rrIdx].fsmCtxIdx].rrIdx == p_rrIdx)
{
v_COAP_FsmCtxDB.data[v_COAP_rrDB.data[p_rrIdx].fsmCtxIdx].rrIdx := -1;
}
}
f_EPTF_COAP_rrDB_remove(p_rrIdx);
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_rr_setState
//
// Purpose:
// This function sets the current state of a <COAP_RR> state machine instance
//
// Parameters:
// p_rrIdx - *in* *integer* - index of the <COAP_RR> in the <COAP_RR_DB> that will handle the message
// p_nextState - *in* <COAP_RR_State> - next state of the state machine
//
// Related Types:
// <COAP_RR>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_rr_setState(in integer p_rrIdx, in COAP_RR_State p_nextState)
runs on EPTF_COAP_LGen_CT
{
if (p_rrIdx < 0 or p_rrIdx >= sizeof(v_COAP_rrDB.data)) { return }
v_COAP_rrDB.data[p_rrIdx].state := p_nextState;
f_EPTF_COAP_Logging_VERBOSE(log2str("rr [", v_COAP_rrDB.data[p_rrIdx].token,"] next state: ", v_COAP_rrDB.data[p_rrIdx].state));
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_rr_handle_Observe_request
//
// Purpose:
// This function handles an incoming Observe request as part of a <COAP_RR> state machine instance
//
// Parameters:
// p_rrIdx - *in* *integer* - index of the <COAP_RR> in the <COAP_RR_DB> that will handle the message
// p_msg - *in* <EPTF_COAP_PDU> - incoming message
//
// Related Types:
// <COAP_RR>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_rr_handle_Observe_request(in integer p_rrIdx, inout EPTF_COAP_PDU p_msg)
runs on EPTF_COAP_LGen_CT
{
// In case it's a response to an Observe request
var integer v_observeOptionIdx := f_EPTF_COAP_hasObserve(v_COAP_rrDB.data[p_rrIdx].request.pdu);
if (v_observeOptionIdx >= 0)
{
// In case the request was an observe subscribe
if (v_COAP_rrDB.data[p_rrIdx].request.pdu.options[v_observeOptionIdx].observe == 0)
{
// In case it is a positive (2xx) response
if (p_msg.pdu.header.code.class == 2)
{
// We are adding the observation to the DB
f_EPTF_COAP_EntityCtx_addObservation(v_COAP_ctx.eCtxIdx, v_COAP_rrDB.data[p_rrIdx].request);
f_EPTF_COAP_addOption(p_msg.pdu, { observe := c_COAP_Observation_initSeqNum });
}
}
// In case the request was an observe unsubscribe
else if (v_COAP_rrDB.data[p_rrIdx].request.pdu.options[v_observeOptionIdx].observe == 1)
{
// Let's fetch the uri path
var charstring vl_resourceId := f_EPTF_COAP_uriPathToString(v_COAP_rrDB.data[p_rrIdx].request.pdu);
f_EPTF_COAP_Logging_DEBUG(log2str("observe unsubscribe for ", vl_resourceId));
// Let's try to look up the observed resource
var integer vl_observedResourceIdx := f_EPTF_COAP_observedResourceDB_lookUp(
v_COAP_rrDB.data[p_rrIdx].request.transportParams.localAddress.hostName,
v_COAP_rrDB.data[p_rrIdx].request.transportParams.localAddress.portNumber,
vl_resourceId
);
f_EPTF_COAP_Logging_DEBUG(log2str("observedResourceIdx: ", vl_observedResourceIdx));
if (vl_observedResourceIdx != -1)
{
// Let's try to look up the observation server
var integer vl_observationIdx := f_EPTF_COAP_observationDB_lookUp(
v_COAP_rrDB.data[p_rrIdx].request.transportParams.remoteAddress.hostName,
v_COAP_rrDB.data[p_rrIdx].request.transportParams.remoteAddress.portNumber,
vl_resourceId,
vl_observedResourceIdx
);
f_EPTF_COAP_Logging_DEBUG(log2str("observationIdx: ", vl_observationIdx));
if (vl_observationIdx != -1)
{
f_EPTF_COAP_ObservationServer_cancelReceivedFromEnv(vl_observationIdx);
}
}
}
}
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_rr_handle_BlockwiseTransfer_request
//
// Purpose:
// This function handles an incoming blockwise transfer request as part of a <COAP_RR> state machine instance
//
// Parameters:
// p_rrIdx - *in* *integer* - index of the <COAP_RR> in the <COAP_RR_DB> that will handle the message
// p_msg - *in* <EPTF_COAP_PDU> - incoming message
// p_eCtxIdx - *in* *integer* - entity context index
//
// Related Types:
// <COAP_RR>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_rr_handle_BlockwiseTransfer_request(in integer p_rrIdx, inout EPTF_COAP_PDU p_msg, in integer p_eCtxIdx)
runs on EPTF_COAP_LGen_CT
{
// In case it's a response to a Block1 request
var integer v_block1OptionIdx := f_EPTF_COAP_hasBlock1(v_COAP_rrDB.data[p_rrIdx].request.pdu);
if (v_block1OptionIdx >= 0)
{
// In case it is a positive (2xx) response
if (p_msg.pdu.header.code.class == 2)
{
// 204 response -> stateless block1 server
if (p_msg.pdu.header.code.detail == 4)
{
f_EPTF_COAP_addOption(p_msg.pdu,
{
block1 := {
num := v_COAP_rrDB.data[p_rrIdx].request.pdu.options[v_block1OptionIdx].block1.num,
m := false,
szx := v_COAP_rrDB.data[p_rrIdx].request.pdu.options[v_block1OptionIdx].block1.szx
}
});
}
// 231 response -> atomic server creation
else if (p_msg.pdu.header.code.detail == 31)
{
// if it is an initial block we can add an atomic server
if (v_COAP_rrDB.data[p_rrIdx].request.pdu.options[v_block1OptionIdx].block1.num == 0)
{
f_EPTF_COAP_EntityCtx_addBlockwiseTransfer(
v_COAP_ctx.eIdx, v_COAP_ctx.fsmIdx, v_COAP_ctx.eCtxIdx,
v_block1OptionIdx, v_COAP_rrDB.data[p_rrIdx].request);
// If we have a smaller preferred block size, we send that back
if (
ispresent(v_COAP_EntityCtxDB.data[p_eCtxIdx].preferredBlocksize) and
v_COAP_EntityCtxDB.data[p_eCtxIdx].preferredBlocksize < v_COAP_rrDB.data[p_rrIdx].request.pdu.options[v_block1OptionIdx].block1.szx
)
{
f_EPTF_COAP_addOption(p_msg.pdu,
{
block1 := {
num := v_COAP_rrDB.data[p_rrIdx].request.pdu.options[v_block1OptionIdx].block1.num,
m := v_COAP_rrDB.data[p_rrIdx].request.pdu.options[v_block1OptionIdx].block1.m,
szx := v_COAP_EntityCtxDB.data[p_eCtxIdx].preferredBlocksize
}
});
}
else
{
f_EPTF_COAP_addOption(p_msg.pdu,
{
block1 := {
num := v_COAP_rrDB.data[p_rrIdx].request.pdu.options[v_block1OptionIdx].block1.num,
m := v_COAP_rrDB.data[p_rrIdx].request.pdu.options[v_block1OptionIdx].block1.m,
szx := v_COAP_rrDB.data[p_rrIdx].request.pdu.options[v_block1OptionIdx].block1.szx
}
});
}
}
// not an initial block
else
{
f_EPTF_COAP_addOption(p_msg.pdu,
{
block1 := {
num := v_COAP_rrDB.data[p_rrIdx].request.pdu.options[v_block1OptionIdx].block1.num,
m := v_COAP_rrDB.data[p_rrIdx].request.pdu.options[v_block1OptionIdx].block1.m,
szx := v_COAP_rrDB.data[p_rrIdx].request.pdu.options[v_block1OptionIdx].block1.szx
}
});
}
}
}
}
}
/*****************************************************************
@startuml EPTF_COAP_LGen_Functions.COAP_Transaction.jpg
[*] --> CLOSED
CLOSED --> CLOSED: envIn: NON
CLOSED --> CLOSED: rrIn: NON
CLOSED --> CLOSED: envIn: RST
CLOSED --> REMOVING: T_lifetime
CLOSED --> REMOVING: rrIn: ACK
CLOSED --> RELIABLE_TX: rrIn: CON
RELIABLE_TX --> CLOSED: envIn: ACK
RELIABLE_TX --> CLOSED: envIn: RST
RELIABLE_TX --> CLOSED: rrIn: CANCEL
RELIABLE_TX --> RELIABLE_TX: T_retransmit
RELIABLE_TX --> REMOVING: T_lifetime
ACK_PENDING --> CLOSED: rrIn: ACK
ACK_PENDING --> CLOSED: rrIn: RST
ACK_PENDING --> REMOVING: T_lifetime
REMOVING --> [*]
@enduml
******************************************************************/
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_tr_fromRR
//
// Purpose:
// This function implements a COAP request-response state machine by handling the incoming message from a <COAP_RR>
//
// Parameters:
// p_msg - *inout* <EPTF_COAP_PDU> - message that enters into the transaction (will be modified by the stack)
// p_trIdx - *in* *integer* - index of the <COAP_Transaction> instance in the <COAP_Transaction_DB> that will handle the message
//
// Related Types:
// <COAP_Transaction>
//
// FSM Diagram of a COAP transaction:
// (see EPTF_COAP_LGen_Functions.COAP_Transaction.jpg)
///////////////////////////////////////////////////////////
function f_EPTF_COAP_tr_fromRR(inout EPTF_COAP_PDU p_msg, in integer p_trIdx)
runs on EPTF_COAP_LGen_CT
{
if (p_trIdx < 0 or p_trIdx >= sizeof(v_COAP_trDB.data)) { return }
f_EPTF_COAP_Logging_DEBUG(log2str("current state: ", v_COAP_trDB.data[p_trIdx].state));
// State: CLOSED
if (v_COAP_trDB.data[p_trIdx].state == CLOSED)
{
// rrIn: CON
if (p_msg.pdu.header.msg_type == CONFIRMABLE)
{
f_EPTF_COAP_tr_startT_retransmit(p_trIdx);
// start EXCHANGE_LIFETIME
f_EPTF_COAP_tr_startT_lifetime(p_trIdx, tsp_EPTF_COAP_EXCHANGE_LIFETIME);
f_EPTF_COAP_tr_startT_rtt(p_trIdx);
// send to env
f_EPTF_COAP_tr_send(p_msg, p_trIdx);
// next state: RELIABLE_TX
f_EPTF_COAP_tr_setState(p_trIdx, RELIABLE_TX);
}
// rrIn: NON
else if (p_msg.pdu.header.msg_type == NON_CONFIRMABLE)
{
// start EXCHANGE_LIFETIME
f_EPTF_COAP_tr_startT_lifetime(p_trIdx, tsp_EPTF_COAP_EXCHANGE_LIFETIME);
// out.send
f_EPTF_COAP_tr_send(p_msg, p_trIdx);
// next state: CLOSED
f_EPTF_COAP_tr_setState(p_trIdx, CLOSED);
// OLD: finish f_EPTF_COAP_tr_remove(p_trIdx);
}
// rrIn: ACK
else if (p_msg.pdu.header.msg_type == ACKNOWLEDGEMENT)
{
// out.send
f_EPTF_COAP_tr_send(p_msg, p_trIdx);
// finish
f_EPTF_COAP_tr_remove(p_trIdx);
}
else
{
f_EPTF_COAP_Logging_WARNING(log2str(%definitionId, "cannot handle msg type ",p_msg.pdu.header.msg_type," in state ",v_COAP_trDB.data[p_trIdx].state));
}
}
// State: ACK_PENDING
else if (v_COAP_trDB.data[p_trIdx].state == ACK_PENDING)
{
// rrIn: ACK
if (p_msg.pdu.header.msg_type == ACKNOWLEDGEMENT)
{
p_msg.pdu.header.message_id := v_COAP_trDB.data[p_trIdx].mid;
// store in cache
v_COAP_trDB.data[p_trIdx].cache := p_msg;
// out.send
f_EPTF_COAP_tr_send(p_msg, p_trIdx);
// next state: CLOSED
f_EPTF_COAP_tr_setState(p_trIdx, CLOSED);
}
// rrIn: RST
else if (p_msg.pdu.header.msg_type == RESET)
{
p_msg.pdu.header.message_id := v_COAP_trDB.data[p_trIdx].mid;
// store in cache
v_COAP_trDB.data[p_trIdx].cache := p_msg;
// out.send
f_EPTF_COAP_tr_send(p_msg, p_trIdx);
// next state: CLOSED
f_EPTF_COAP_tr_setState(p_trIdx, CLOSED);
}
else
{
f_EPTF_COAP_Logging_WARNING(log2str(%definitionId, "cannot handle msg type ",p_msg.pdu.header.msg_type," in state ",v_COAP_trDB.data[p_trIdx].state));
}
}
else
{
f_EPTF_COAP_Logging_ERROR(log2str(%definitionId, "unknown state ", p_msg));
}
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_tr_fromEnv
//
// Purpose:
// This function implements a COAP request-response state machine by handling the incoming message from a <COAP_RR>
//
// Parameters:
// p_msg - *inout* <EPTF_COAP_PDU> - message that enters into the transaction (will be modified by the stack)
// p_trIdx - *in* *integer* - index of the <COAP_Transaction> instance in the <COAP_Transaction_DB> that will handle the message
//
// Related Types:
// <COAP_Transaction>
//
// FSM Diagram of a COAP transaction:
// (see EPTF_COAP_LGen_Functions.COAP_Transaction.jpg)
///////////////////////////////////////////////////////////
function f_EPTF_COAP_tr_fromEnv(inout EPTF_COAP_PDU p_msg, in integer p_trIdx)
runs on EPTF_COAP_LGen_CT
{
if (p_trIdx < 0 or p_trIdx >= sizeof(v_COAP_trDB.data)) { return }
f_EPTF_COAP_Logging_VERBOSE(log2str(%definitionId, "current state: ", v_COAP_trDB.data[p_trIdx].state));
// State: CLOSED
if (v_COAP_trDB.data[p_trIdx].state == CLOSED)
{
// envIn: NON
if (p_msg.pdu.header.msg_type == NON_CONFIRMABLE)
{
// start NON_LIFETIME
f_EPTF_COAP_tr_startT_lifetime(p_trIdx, tsp_EPTF_COAP_NON_LIFETIME);
// next state: CLOSED
f_EPTF_COAP_tr_setState(p_trIdx, CLOSED);
// rrOut.send
if (v_COAP_trDB.data[p_trIdx].rrIdx == -1)
{
var integer vl_rrIdx := f_EPTF_COAP_rrDB_lookUp(p_msg.transportParams.localAddress, p_msg.pdu.token);
if (vl_rrIdx >= 0)
{
v_COAP_trDB.data[p_trIdx].rrIdx := vl_rrIdx;
v_COAP_rrDB.data[vl_rrIdx].trIdx := p_trIdx;
f_EPTF_COAP_rr_handleMsg(p_msg, vl_rrIdx);
}
else
{
f_EPTF_COAP_dispatchEventForObserve_ifExists(p_msg.pdu, p_msg.eIdx, -1);
if (not f_EPTF_COAP_tr_handleBlockwiseTransfer(p_trIdx, p_msg))
{
f_EPTF_COAP_dispatchEventsForCode(
p_msg.pdu.header.code,
p_msg.eIdx,
-1,
{}
);
}
}
}
else
{
f_EPTF_COAP_rr_handleMsg(p_msg, v_COAP_trDB.data[p_trIdx].rrIdx);
}
}
// envIn: CON
else if (p_msg.pdu.header.msg_type == CONFIRMABLE)
{
// start EXCHANGE_LIFETIME
f_EPTF_COAP_tr_startT_lifetime(p_trIdx, tsp_EPTF_COAP_EXCHANGE_LIFETIME);
// next state: ACK_PENDING
f_EPTF_COAP_tr_setState(p_trIdx, ACK_PENDING);
// rrOut.send
if (v_COAP_trDB.data[p_trIdx].rrIdx == -1)
{
var integer vl_rrIdx := f_EPTF_COAP_rrDB_lookUp(p_msg.transportParams.localAddress, p_msg.pdu.token);
if (vl_rrIdx >= 0)
{
v_COAP_trDB.data[p_trIdx].rrIdx := vl_rrIdx;
v_COAP_rrDB.data[vl_rrIdx].trIdx := p_trIdx;
f_EPTF_COAP_rr_handleMsg(p_msg, vl_rrIdx);
}
else
{
f_EPTF_COAP_dispatchEventForObserve_ifExists(p_msg.pdu, p_msg.eIdx, -1);
if (not f_EPTF_COAP_tr_handleBlockwiseTransfer(p_trIdx, p_msg))
{
f_EPTF_COAP_dispatchEventsForCode(
p_msg.pdu.header.code,
p_msg.eIdx,
-1,
{}
);
}
}
}
else
{
f_EPTF_COAP_rr_handleMsg(p_msg, v_COAP_trDB.data[p_trIdx].rrIdx);
}
}
// envIn: RST
else if (p_msg.pdu.header.msg_type == RESET)
{
// report reset
if (v_COAP_trDB.data[p_trIdx].rrIdx != -1) {
f_EPTF_COAP_rr_reset(v_COAP_trDB.data[p_trIdx].rrIdx);
}
// report observe cancel
if (v_COAP_trDB.data[p_trIdx].obsIdx != -1) {
f_EPTF_COAP_ObservationServer_cancelReceivedFromEnv(v_COAP_trDB.data[p_trIdx].obsIdx);
}
// next state: CLOSED
f_EPTF_COAP_tr_setState(p_trIdx, CLOSED);
}
else
{
f_EPTF_COAP_Logging_WARNING(log2str(%definitionId, "cannot handle msg type ",p_msg.pdu.header.msg_type," in state ",v_COAP_trDB.data[p_trIdx].state));
}
}
// State: RELIABLE_TX
else if (v_COAP_trDB.data[p_trIdx].state == RELIABLE_TX)
{
if (p_msg.pdu.header.msg_type == ACKNOWLEDGEMENT)
{
// cancel T retransmission
f_EPTF_COAP_tr_cancelT_retransmit(p_trIdx);
f_EPTF_COAP_tr_stopT_rtt(p_trIdx);
if (not f_EPTF_COAP_isEmpty(p_msg.pdu) and v_COAP_trDB.data[p_trIdx].rrIdx != -1)
{
f_EPTF_COAP_rr_handleMsg(p_msg, v_COAP_trDB.data[p_trIdx].rrIdx);
}
// next state: CLOSED
f_EPTF_COAP_tr_setState(p_trIdx, CLOSED);
}
else if (p_msg.pdu.header.msg_type == RESET)
{
// cancel T retransmission
f_EPTF_COAP_tr_cancelT_retransmit(p_trIdx);
// report reset
if (v_COAP_trDB.data[p_trIdx].rrIdx != -1) {
f_EPTF_COAP_rr_reset(v_COAP_trDB.data[p_trIdx].rrIdx);
}
// report observe cancel
if (v_COAP_trDB.data[p_trIdx].obsIdx != -1) {
f_EPTF_COAP_ObservationServer_cancelReceivedFromEnv(v_COAP_trDB.data[p_trIdx].obsIdx);
}
// next state: CLOSED
f_EPTF_COAP_tr_setState(p_trIdx, CLOSED);
}
else
{
f_EPTF_COAP_Logging_WARNING(log2str(%definitionId, "cannot handle msg type ",p_msg.pdu.header.msg_type," in state ",v_COAP_trDB.data[p_trIdx].state));
}
}
else if (v_COAP_trDB.data[p_trIdx].state == ACK_PENDING)
{
f_EPTF_COAP_Logging_WARNING(log2str(%definitionId, " messages from environment in ACK_PENDING are not expected"));
}
else
{
f_EPTF_COAP_Logging_ERROR(log2str(%definitionId, " unknown state"));
}
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_tr_handleBlockwiseTransfer
//
// Purpose:
// This function handles incoming COAP messages in case they are blockwise transfer related.
//
// Parameters:
// p_msg - *inout* <EPTF_COAP_PDU> - message that enters into the transaction
// p_trIdx - *in* *integer* - index of the <COAP_Transaction> instance in the <COAP_Transaction_DB> that will handle the message
//
// Returns:
// *boolean* - true if the message is blockwise transfer related
//
// Related Types:
// <COAP_Transaction>
//
// FSM Diagram of a COAP transaction:
// (see EPTF_COAP_LGen_Functions.COAP_Transaction.jpg)
///////////////////////////////////////////////////////////
function f_EPTF_COAP_tr_handleBlockwiseTransfer(in integer p_trIdx, inout EPTF_COAP_PDU p_msg)
runs on EPTF_COAP_LGen_CT
return boolean
{
var integer v_block1OptionIdx := f_EPTF_COAP_hasBlock1(p_msg.pdu);
// If we have a block1 option
if (v_block1OptionIdx >= 0)
{
v_COAP_stats.block1.noBlocks := v_COAP_stats.block1.noBlocks + 1;
var charstring v_uriPath := f_EPTF_COAP_uriPathToString(p_msg.pdu);
var integer v_blockwiseIdx := f_EPTF_COAP_blockwiseDB_lookUp(
p_msg.transportParams.localAddress.hostName,
p_msg.transportParams.localAddress.portNumber,
v_uriPath
);
// If we have ongoing atomic block1 transfer
// -> the message is handled by the BlockwiseTransfer FSM
if (v_blockwiseIdx >= 0)
{
f_EPTF_COAP_BlockwiseTransfer_in(v_blockwiseIdx, p_msg, v_block1OptionIdx);
// The stack indicates, that the request is automatically handled
v_COAP_Stack_autoHandled := true;
}
// If we don't have a BlockwiseTransfer FSM we dispatch an event to the entity to handle it
else
{
f_EPTF_COAP_dispatchEventForBlock1(p_msg.pdu.options[v_block1OptionIdx].block1, p_msg.eIdx, -1);
}
return true;
}
return false;
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_tr_cancel
//
// Purpose:
// This function handles the *cancel* event of a <COAP_Transaction> state machine instance
//
// Parameters:
// p_trIdx - *in* *integer* - index of the <COAP_Transaction> in the <COAP_Transaction_DB> that will handle the event
//
// Related Types:
// <COAP_Transaction>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_tr_cancel(in integer p_trIdx)
runs on EPTF_COAP_LGen_CT
{
if (p_trIdx < 0 or p_trIdx >= sizeof(v_COAP_trDB.data)) { return }
if (v_COAP_trDB.data[p_trIdx].state == RELIABLE_TX)
{
// cancel T retransmission
f_EPTF_COAP_tr_cancelT_retransmit(p_trIdx);
// next state: CLOSED
f_EPTF_COAP_tr_setState(p_trIdx, CLOSED);
}
else
{
f_EPTF_COAP_Logging_WARNING(log2str(%definitionId, " cancel only handled in RELIABLE_ACK state"));
}
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_tr_lifetime
//
// Purpose:
// This function handles the *T_lifetime* timer's timeout event of a <COAP_Transaction> state machine instance
//
// Parameters:
// pl_action - *in* <EPTF_ScheduledAction> - contains the index of the <COAP_Transaction> in the <COAP_Transaction_DB> that will handle the event
//
// Related Types:
// <COAP_Transaction>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_tr_lifetime(in EPTF_ScheduledAction pl_action, in integer pl_eventIndex)
runs on EPTF_COAP_LGen_CT
return boolean
{
var integer vl_trIdx := pl_action.actionId[0];
if (vl_trIdx < 0 or vl_trIdx >= sizeof(v_COAP_trDB.data)) { return false }
v_COAP_trDB.data[vl_trIdx].lifetimeTimer := -1;
if (v_COAP_trDB.data[vl_trIdx].state == RELIABLE_TX)
{
// cancel T retransmission
f_EPTF_COAP_tr_cancelT_retransmit(vl_trIdx);
// report trTimeout event
f_EPTF_COAP_rr_timeout(v_COAP_trDB.data[vl_trIdx].rrIdx);
// next state: CLOSED
f_EPTF_COAP_tr_setState(vl_trIdx, CLOSED);
}
f_EPTF_COAP_tr_remove(vl_trIdx);
return true;
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_tr_retransmit
//
// Purpose:
// This function handles the *T_retransmit* timer's timeout event of a <COAP_Transaction> state machine instance
//
// Parameters:
// pl_action - *in* <EPTF_ScheduledAction> - contains the index of the <COAP_Transaction> in the <COAP_Transaction_DB> that will handle the event
//
// Related Types:
// <COAP_Transaction>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_tr_retransmit(in EPTF_ScheduledAction pl_action, in integer pl_eventIndex)
runs on EPTF_COAP_LGen_CT
return boolean
{
var integer vl_trIdx := pl_action.actionId[0];
if (vl_trIdx < 0 or vl_trIdx >= sizeof(v_COAP_trDB.data)) { return false }
v_COAP_trDB.data[vl_trIdx].retransmitTimer := -1;
if (ispresent(v_COAP_trDB.data[vl_trIdx].cache))
{
f_EPTF_COAP_tr_startT_retransmit(vl_trIdx);
f_EPTF_COAP_tr_send(v_COAP_trDB.data[vl_trIdx].cache, vl_trIdx);
v_COAP_stats.noRetransmissions := v_COAP_stats.noRetransmissions + 1;
}
else
{
f_EPTF_COAP_Logging_WARNING(log2str(%definitionId, " cannot retransmit empty cache"));
}
return true;
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_tr_startT_retransmit
//
// Purpose:
// This function starts the *T_retransmit* timer of a particular <COAP_Transaction> instance
//
// Parameters:
// p_trIdx - *in* *integer* - index of the <COAP_Transaction> in the <COAP_Transaction_DB> that will start the timer
//
// Related Types:
// <COAP_Transaction>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_tr_startT_retransmit(in integer pl_trIdx)
runs on EPTF_COAP_LGen_CT
return boolean
{
var boolean retval;
var EPTF_ActionId vl_actionId;
var float vl_time := v_COAP_trDB.data[pl_trIdx].retransmitTimerValue;
vl_actionId[0] := pl_trIdx;
retval := f_EPTF_SchedulerComp_scheduleAction(
f_EPTF_SchedulerComp_snapshotTime() + vl_time,
refers(f_EPTF_COAP_tr_retransmit),
vl_actionId,
v_COAP_trDB.data[pl_trIdx].retransmitTimer
);
// start retransTimeout (TODO calculate next rentransmission)
v_COAP_trDB.data[pl_trIdx].retransmitTimerValue := v_COAP_trDB.data[pl_trIdx].retransmitTimerValue * 2.0;
return retval;
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_tr_cancelT_retransmit
//
// Purpose:
// This function cancels the *T_retransmit* timer of a particular <COAP_Transaction> instance
//
// Parameters:
// p_trIdx - *in* *integer* - index of the <COAP_Transaction> in the <COAP_Transaction_DB> that will cancel the timer
//
// Related Types:
// <COAP_Transaction>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_tr_cancelT_retransmit(in integer pl_trIdx)
runs on EPTF_COAP_LGen_CT
{
if (v_COAP_trDB.data[pl_trIdx].retransmitTimer >= 0)
{
if(not f_EPTF_SchedulerComp_CancelEvent(v_COAP_trDB.data[pl_trIdx].retransmitTimer))
{
f_EPTF_COAP_Logging_WARNING(log2str(%definitionId,": could not cancel timer"));
}
v_COAP_trDB.data[pl_trIdx].retransmitTimer := -1;
}
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_tr_startT_lifetime
//
// Purpose:
// This function starts the *T_lifetime* timer of a particular <COAP_Transaction> instance
//
// Parameters:
// p_trIdx - *in* *integer* - index of the <COAP_Transaction> in the <COAP_Transaction_DB> that will start the timer
//
// Related Types:
// <COAP_Transaction>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_tr_startT_lifetime(in integer pl_trIdx, in float pl_time)
runs on EPTF_COAP_LGen_CT
return boolean
{
var boolean retval;
var EPTF_ActionId vl_actionId;
vl_actionId[0] := pl_trIdx;
retval := f_EPTF_SchedulerComp_scheduleAction(
f_EPTF_SchedulerComp_snapshotTime() + pl_time,
refers(f_EPTF_COAP_tr_lifetime),
vl_actionId,
v_COAP_trDB.data[pl_trIdx].lifetimeTimer
);
return retval;
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_tr_cancelT_lifetime
//
// Purpose:
// This function cancels the *T_lifetime* timer of a particular <COAP_Transaction> instance
//
// Parameters:
// p_trIdx - *in* *integer* - index of the <COAP_Transaction> in the <COAP_Transaction_DB> that will cancel the timer
//
// Related Types:
// <COAP_Transaction>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_tr_cancelT_lifetime(in integer pl_trIdx)
runs on EPTF_COAP_LGen_CT
{
if (v_COAP_trDB.data[pl_trIdx].lifetimeTimer >= 0)
{
if(not f_EPTF_SchedulerComp_CancelEvent(v_COAP_trDB.data[pl_trIdx].lifetimeTimer))
{
f_EPTF_COAP_Logging_WARNING(log2str(%definitionId,": could not cancel timer"));
}
v_COAP_trDB.data[pl_trIdx].lifetimeTimer := -1;
}
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_tr_startT_rtt
//
// Purpose:
// This function starts the *T_rtt* timer to measure the round-trip time of the transaction
//
// Parameters:
// p_trIdx - *in* *integer* - index of the <COAP_Transaction> in the <COAP_Transaction_DB> that will start the timer
//
// Related Types:
// <COAP_Transaction>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_tr_startT_rtt(in integer pl_trIdx)
runs on EPTF_COAP_LGen_CT
{
v_COAP_trDB.data[pl_trIdx].rtt := T_EPTF_componentClock.read;
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_tr_stopT_rtt
//
// Purpose:
// This function stops the *T_rtt* timer and reports the measure round-trip time
// via the <vf_COAP_rttIndication> <fcb_EPTF_COAP_rttIndication> call-back function
//
// Parameters:
// p_trIdx - *in* *integer* - index of the <COAP_Transaction> in the <COAP_Transaction_DB> that will measure RTT
//
// Related Types:
// <COAP_Transaction>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_tr_stopT_rtt(in integer pl_trIdx)
runs on EPTF_COAP_LGen_CT
{
if (ispresent(v_COAP_trDB.data[pl_trIdx].rtt))
{
v_COAP_trDB.data[pl_trIdx].rtt := T_EPTF_componentClock.read - v_COAP_trDB.data[pl_trIdx].rtt;
if (vf_COAP_rttIndication != null) {
vf_COAP_rttIndication.apply(v_COAP_trDB.data[pl_trIdx].rtt);
}
}
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_tr_send
//
// Purpose:
// This function is used to send out a message from an instance of a <COAP_Transaction> using the registered
// function <fcb_EPTF_COAP_Transport_sendMessage> of the underlying transport layer instance.
//
// Parameters:
// p_msg - *intout* <EPTF_COAP_PDU> - the message to be sent
// p_trIdx - *in* *integer* - index of the <COAP_Transaction> in the <COAP_Transaction_DB> that will cancel the timer
//
// Related Types:
// <COAP_Transaction>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_tr_send(inout EPTF_COAP_PDU p_msg, in integer p_trIdx)
runs on EPTF_COAP_LGen_CT
{
if (p_trIdx < 0 or p_trIdx >= sizeof(v_COAP_trDB.data)) { return }
v_COAP_trDB.data[p_trIdx].cache := p_msg;
f_EPTF_COAP_updateMessageStatistics(v_COAP_stats.outgoing, p_msg);
f_EPTF_COAP_LGen_send(p_msg);
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_tr_remove
//
// Purpose:
// This function handles the removal and clean up of a <COAP_Transaction> state machine instance from the DB
//
// Parameters:
// p_trIdx - *in* *integer* - index of the <COAP_Transaction> in the <COAP_Transaction_DB>
//
// Related Types:
// <COAP_Transaction>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_tr_remove(in integer p_trIdx)
runs on EPTF_COAP_LGen_CT
{
if (p_trIdx < 0 or p_trIdx >= sizeof(v_COAP_trDB.data)) { return }
f_EPTF_COAP_tr_setState(p_trIdx, REMOVING);
f_EPTF_COAP_tr_cancelT_lifetime(p_trIdx);
f_EPTF_COAP_tr_cancelT_retransmit(p_trIdx);
if (v_COAP_trDB.data[p_trIdx].rrIdx != -1)
{
if (v_COAP_rrDB.data[v_COAP_trDB.data[p_trIdx].rrIdx].trIdx == p_trIdx)
{
v_COAP_rrDB.data[v_COAP_trDB.data[p_trIdx].rrIdx].trIdx := -1;
}
}
f_EPTF_COAP_trDB_remove(p_trIdx);
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_tr_setState
//
// Purpose:
// This function sets the current state of a <COAP_Transaction> state machine instance
//
// Parameters:
// p_trIdx - *in* *integer* - index of the <COAP_Transaction> in the <COAP_Transaction_DB> that will handle the message
// p_nextState - *in* <COAP_Transaction_State> - next state of the state machine
//
// Related Types:
// <COAP_Transaction>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_tr_setState(in integer p_trIdx, in COAP_Transaction_State p_nextState)
runs on EPTF_COAP_LGen_CT
{
if (p_trIdx < 0 or p_trIdx >= sizeof(v_COAP_trDB.data)) { return }
v_COAP_trDB.data[p_trIdx].state := p_nextState;
f_EPTF_COAP_Logging_VERBOSE(log2str("tr [", v_COAP_trDB.data[p_trIdx].mid,"] next state: ", v_COAP_trDB.data[p_trIdx].state));
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_BlockwiseTransfer_in
//
// Purpose:
// This function implements the incoming message handling for a <COAP_Blockwise_Transfer> instance
//
// Parameters:
// p_blockwiseIdx - *in* *integer* - index of the <COAP_Blockwise_Transfer> in the *v_COAP_blockwiseDB* <COAP_Blockwise_DB> database
// p_msg - *inout* <EPTF_COAP_PDU> - the incoming message
// p_block1OptionIdx - *in* *integer* - the index of the block1 option in the message header
//
// Related Types:
// <COAP_Blockwise_Transfer>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_BlockwiseTransfer_in(in integer p_blockwiseIdx, inout EPTF_COAP_PDU p_msg, in integer p_block1OptionIdx)
runs on EPTF_COAP_LGen_CT
{
f_EPTF_COAP_BlockwiseTransfer_cancelT_lifetime(p_blockwiseIdx);
// in case the incoming block is not in sequence (and we didn't ask for smaller block size)
if (
v_COAP_blockwiseDB.data[p_blockwiseIdx].lastBlock1Option.num + 1 != p_msg.pdu.options[p_block1OptionIdx].block1.num
and not v_COAP_blockwiseDB.data[p_blockwiseIdx].ongoingBlocksizeChange
)
{
// Send back 4.08
f_COAP_step_handleRequest(valueof(t_EPTF_COAP_stepArgs(v_COAP_blockwiseDB.data[p_blockwiseIdx].eIdx, v_COAP_blockwiseDB.data[p_blockwiseIdx].fsmIdx)));
v_COAP_msgToSend.pdu := valueof(t_EPTF_COAP_BlockwiseResponse(4,8));
f_COAP_step_sendResponse(valueof(t_EPTF_COAP_stepArgs(v_COAP_blockwiseDB.data[p_blockwiseIdx].eIdx, v_COAP_blockwiseDB.data[p_blockwiseIdx].fsmIdx)));
// Dispatch event: blockwise transfer fail finish
//if (f_EPTF_COAP_isCoapReportEnabledForEntity(v_COAP_blockwiseDB.data[p_blockwiseIdx].eIdx) ) {
f_EPTF_COAP_dispatchEvent(c_COAP_eventIdx_BLOCK1_atomic_fail, v_COAP_blockwiseDB.data[p_blockwiseIdx].eIdx, -1, {});
//}
v_COAP_stats.block1.noAtomicUnsucc := v_COAP_stats.block1.noAtomicUnsucc + 1;
// Remove the blockwise transfer FSM
f_EPTF_COAP_blockwiseDB_remove(p_blockwiseIdx);
return;
}
// Save incoming block1
v_COAP_blockwiseDB.data[p_blockwiseIdx].lastBlock1Option := p_msg.pdu.options[p_block1OptionIdx].block1;
if (ispresent(p_msg.pdu.payload) and v_COAP_blockwiseDB.collectContent)
{
v_COAP_blockwiseDB.data[p_blockwiseIdx].content := v_COAP_blockwiseDB.data[p_blockwiseIdx].content & p_msg.pdu.payload;
}
// if we asked for a smaller blocksize we switch the 'ongoing' flag after the blocksize handshake
if (v_COAP_blockwiseDB.data[p_blockwiseIdx].ongoingBlocksizeChange)
{
v_COAP_blockwiseDB.data[p_blockwiseIdx].ongoingBlocksizeChange := false;
}
// if there are more blocks coming
if (v_COAP_blockwiseDB.data[p_blockwiseIdx].lastBlock1Option.m == true)
{
// Send back 2.31
f_COAP_step_handleRequest(valueof(t_EPTF_COAP_stepArgs(v_COAP_blockwiseDB.data[p_blockwiseIdx].eIdx, v_COAP_blockwiseDB.data[p_blockwiseIdx].fsmIdx)));
v_COAP_msgToSend.pdu := valueof(t_EPTF_COAP_BlockwiseResponse(2,31));
f_COAP_step_sendResponse(valueof(t_EPTF_COAP_stepArgs(v_COAP_blockwiseDB.data[p_blockwiseIdx].eIdx, v_COAP_blockwiseDB.data[p_blockwiseIdx].fsmIdx)));
// Re-Start the lifetime timer for the blockwise transfer
f_EPTF_COAP_BlockwiseTransfer_startT_lifetime(p_blockwiseIdx);
}
// in case it was the last block
else
{
// Send back 2.04
f_COAP_step_handleRequest(valueof(t_EPTF_COAP_stepArgs(v_COAP_blockwiseDB.data[p_blockwiseIdx].eIdx, v_COAP_blockwiseDB.data[p_blockwiseIdx].fsmIdx)));
v_COAP_msgToSend.pdu := valueof(t_EPTF_COAP_BlockwiseResponse(2,4));
f_COAP_step_sendResponse(valueof(t_EPTF_COAP_stepArgs(v_COAP_blockwiseDB.data[p_blockwiseIdx].eIdx, v_COAP_blockwiseDB.data[p_blockwiseIdx].fsmIdx)));
// Dispatch event: blockwise transfer succ finish
if (f_EPTF_COAP_isCoapReportEnabledForEntity(v_COAP_blockwiseDB.data[p_blockwiseIdx].eIdx) ) {
f_EPTF_COAP_dispatchEvent(c_COAP_eventIdx_BLOCK1_atomic_succ, v_COAP_blockwiseDB.data[p_blockwiseIdx].eIdx, -1, {});
}
v_COAP_stats.block1.noAtomicSucc := v_COAP_stats.block1.noAtomicSucc + 1;
// Indicate event to the COAP user layer
if (vf_COAP_eventIndication != null)
{
vf_COAP_eventIndication.apply(
{
atomicBlock1Finished :=
{
v_COAP_blockwiseDB.data[p_blockwiseIdx].eIdx,
v_COAP_blockwiseDB.data[p_blockwiseIdx].uriPath,
v_COAP_blockwiseDB.data[p_blockwiseIdx].headerCode,
v_COAP_blockwiseDB.data[p_blockwiseIdx].contentFormat,
v_COAP_blockwiseDB.data[p_blockwiseIdx].content
}
}
);
}
// Remove the blockwise transfer FSM
f_EPTF_COAP_blockwiseDB_remove(p_blockwiseIdx);
}
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_BlockwiseTransfer_lifetime
//
// Purpose:
// This function handles the incoming T_lifetime timeout event for a <COAP_Blockwise_Transfer> instance
//
// Parameters:
// pl_action - *in* <EPTF_ScheduledAction> - the action descriptor
// pl_eventIndex - *in integer* - event index
//
// Related Types:
// <COAP_Blockwise_Transfer>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_BlockwiseTransfer_lifetime(in EPTF_ScheduledAction pl_action, in integer pl_eventIndex)
runs on EPTF_COAP_LGen_CT
return boolean
{
var integer vl_btIdx := pl_action.actionId[0];
if (vl_btIdx < 0 or vl_btIdx >= sizeof(v_COAP_blockwiseDB.data)) { return false }
v_COAP_blockwiseDB.data[vl_btIdx].lifetimeTimer := -1;
// Dispatch event: blockwise transfer fail finish
//if (f_EPTF_COAP_isCoapReportEnabledForEntity(v_COAP_blockwiseDB.data[vl_btIdx].eIdx) ) {
f_EPTF_COAP_dispatchEvent(c_COAP_eventIdx_BLOCK1_atomic_fail, v_COAP_blockwiseDB.data[vl_btIdx].eIdx, -1, {});
//}
v_COAP_stats.block1.noAtomicTimeouts := v_COAP_stats.block1.noAtomicTimeouts + 1;
// Remove the blockwise transfer FSM
f_EPTF_COAP_blockwiseDB_remove(vl_btIdx);
return true;
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_BlockwiseTransfer_startT_lifetime
//
// Purpose:
// This function starts the *T_lifetime* timer of a particular <COAP_Blockwise_Transfer> instance.
// The timer value is set to <tsp_EPTF_COAP_EXCHANGE_LIFETIME>
//
// Parameters:
// p_btIdx - *in* *integer* - index of the <COAP_Blockwise_Transfer> in the <COAP_Blockwise_DB> that will start the timer
//
// Related Types:
// <COAP_Blockwise_Transfer>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_BlockwiseTransfer_startT_lifetime(in integer pl_btIdx)
runs on EPTF_COAP_LGen_CT
return boolean
{
if (v_COAP_blockwiseDB.data[pl_btIdx].lifetimeTimer != -1)
{
f_EPTF_COAP_BlockwiseTransfer_cancelT_lifetime(pl_btIdx);
}
var boolean retval;
var EPTF_ActionId vl_actionId;
vl_actionId[0] := pl_btIdx;
retval := f_EPTF_SchedulerComp_scheduleAction(
f_EPTF_SchedulerComp_snapshotTime() + tsp_EPTF_COAP_EXCHANGE_LIFETIME,
refers(f_EPTF_COAP_BlockwiseTransfer_lifetime),
vl_actionId,
v_COAP_blockwiseDB.data[pl_btIdx].lifetimeTimer
);
return retval;
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_BlockwiseTransfer_cancelT_lifetime
//
// Purpose:
// This function cancels the *T_lifetime* timer of a particular <COAP_Blockwise_Transfer> instance
//
// Parameters:
// p_btIdx - *in* *integer* - index of the <COAP_Blockwise_Transfer> in the <COAP_Blockwise_DB> that will cancel the timer
//
// Related Types:
// <COAP_Blockwise_Transfer>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_BlockwiseTransfer_cancelT_lifetime(in integer pl_btIdx)
runs on EPTF_COAP_LGen_CT
{
if (v_COAP_blockwiseDB.data[pl_btIdx].lifetimeTimer >= 0)
{
if(not f_EPTF_SchedulerComp_CancelEvent(v_COAP_blockwiseDB.data[pl_btIdx].lifetimeTimer))
{
f_EPTF_COAP_Logging_WARNING(log2str(%definitionId,": could not cancel timer"));
}
v_COAP_blockwiseDB.data[pl_btIdx].lifetimeTimer := -1;
}
}
template EPTF_LGenBase_TestStepArgs t_EPTF_COAP_stepArgs(in integer p_eIdx, in integer p_fsmIdx) :=
{
eIdx := p_eIdx,
refContext :=
{
fCtxIdx := p_fsmIdx,
fRefArgs := {}
},
stepArgs := {},
reportedEvent :=
{
event := { -1,-1,omit,omit },
reportedArgs := {}
}
}
template CoAP_ReqResp t_EPTF_COAP_BlockwiseResponse(in integer p_class, in integer p_detail) :=
{
header :=
{
version := 1,
msg_type := NON_CONFIRMABLE,
code := { class := p_class, detail := p_detail },
message_id := 0
},
token := ''O,
options := {},
payload := omit
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_Logging_VERBOSE
//
// Purpose:
// Logging functions for the VERBOSE log level
//
// Parameters:
// pl_message - *in* *charstring* - string to be logged
//
// Related Types:
// <EPTF_COAP_LGen_CT>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_Logging_VERBOSE(in @lazy charstring pl_message)
runs on EPTF_COAP_LGen_CT
{
if (c_EPTF_Common_debugSwitch) {
f_EPTF_Logging_debugV2(pl_message, v_COAP_loggingMaskId, {c_COAP_LGen_Logging_DEBUGV});
}
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_Logging_DEBUG
//
// Purpose:
// Logging functions for the DEBUG log level
//
// Parameters:
// pl_message - *in* *charstring* - string to be logged
//
// Related Types:
// <EPTF_COAP_LGen_CT>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_Logging_DEBUG(in @lazy charstring pl_message)
runs on EPTF_COAP_LGen_CT
{
if (c_EPTF_Common_debugSwitch) {
f_EPTF_Logging_debugV2(pl_message, v_COAP_loggingMaskId, {c_COAP_LGen_Logging_DEBUG});
}
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_Logging_WARNING
//
// Purpose:
// Logging functions for the WARNING log level
//
// Parameters:
// pl_message - *in* *charstring* - string to be logged
//
// Related Types:
// <EPTF_COAP_LGen_CT>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_Logging_WARNING(in @lazy charstring pl_message)
runs on EPTF_COAP_LGen_CT
{
if (c_EPTF_Common_debugSwitch) {
f_EPTF_Logging_debugV2(pl_message, v_COAP_loggingMaskId, {c_COAP_LGen_Logging_WARNING});
}
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_Logging_ERROR
//
// Purpose:
// Logging functions for the ERROR log level
//
// Parameters:
// pl_message - *in* *charstring* - string to be logged
//
// Related Types:
// <EPTF_COAP_LGen_CT>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_Logging_ERROR(in @lazy charstring pl_message)
runs on EPTF_COAP_LGen_CT
{
if (c_EPTF_Common_debugSwitch) {
f_EPTF_Logging_debugV2(pl_message, v_COAP_loggingMaskId, {c_COAP_LGen_Logging_ERROR});
}
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_EntityCtx_addObservation
//
// Purpose:
// Adds a new observation to the simulated device
//
// Parameters:
// p_eCtxIdx - *in* *integer* - index of the <COAP_EntityCtx> instance in <COAP_EntityCtx_DB>
// p_msg - *in* <EPTF_COAP_PDU> - The incoming OBSERVE request
//
// Related Types:
// <COAP_EntityCtx>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_EntityCtx_addObservation(in integer p_eCtxIdx, in EPTF_COAP_PDU p_msg)
runs on EPTF_COAP_LGen_CT
{
// Fetch the URI path
var charstring v_uriPath := f_EPTF_COAP_uriPathToString(p_msg.pdu);
f_EPTF_COAP_Logging_DEBUG(log2str("addObservation() for ", v_uriPath));
// Do we already have this resource under observation?
var integer v_observedResourceIdx := f_EPTF_COAP_observedResourceDB_lookUp(
p_msg.transportParams.localAddress.hostName,
p_msg.transportParams.localAddress.portNumber,
v_uriPath
);
// If we haven't found it, then we need to add this resource to the list of observed resources
if (v_observedResourceIdx < 0)
{
var COAP_ObservedResource v_observedResource := c_COAP_ObservedResource_init;
v_observedResource.localAddress := p_msg.transportParams.localAddress.hostName;
v_observedResource.localPort := p_msg.transportParams.localAddress.portNumber;
v_observedResource.resourceId := v_uriPath;
v_observedResource.uriPath := f_EPTF_COAP_fetchUriPath(p_msg.pdu);
v_observedResource.eCtxIdx := p_eCtxIdx;
v_observedResourceIdx := f_EPTF_COAP_observedResourceDB_add(v_observedResource);
v_COAP_EntityCtxDB.data[p_eCtxIdx].observedResourceIndices[sizeof(v_COAP_EntityCtxDB.data[p_eCtxIdx].observedResourceIndices)] := v_observedResourceIdx;
}
// Let's add the observer to the observed resource
f_EPTF_COAP_ObservedResource_addObserver(v_observedResourceIdx, p_msg, v_COAP_EntityCtxDB.data[p_eCtxIdx].confirmableNotification);
v_COAP_stats.noObserves := v_COAP_stats.noObserves + 1;
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_EntityCtx_removeObservation
//
// Purpose:
// Removes an existing observation from the simulated device
//
// Parameters:
// p_eCtxIdx - *in* *integer* - index of the <COAP_EntityCtx> instance in <COAP_EntityCtx_DB>
// p_obsResIdx - *in* *integer* - The index of the <COAP_ObservedResource> instance in the <COAP_ObservedResource_DB>
// p_lastObserver - *in* *boolean* - True if this was the last observer for an observed resource (ie observed resource is not observed any more)
//
// Related Types:
// <COAP_EntityCtx>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_EntityCtx_removeObservation(in integer pl_eCtxIdx, in integer p_obsResIdx, in boolean p_lastObserver)
runs on EPTF_COAP_LGen_CT
{
f_EPTF_COAP_Logging_DEBUG(log2str(%definitionId));
if (f_EPTF_COAP_isCoapReportEnabledForEntity(v_COAP_EntityCtxDB.data[pl_eCtxIdx].eIdx) ) {
f_EPTF_COAP_dispatchEvent(
c_COAP_eventIdx_observeCanceled,
v_COAP_EntityCtxDB.data[pl_eCtxIdx].eIdx,
-1, {}
);
}
var COAP_ObservedResourceIdx_List vl_newList := {};
if (p_lastObserver)
{
// Indicate event to the COAP user layer
if (vf_COAP_eventIndication != null)
{
vf_COAP_eventIndication.apply(
{resourceNotObserved := { v_COAP_EntityCtxDB.data[pl_eCtxIdx].eIdx, v_COAP_observedResourceDB.data[p_obsResIdx].uriPath } }
);
}
// Remove the p_obsResIdx from the stored indices
for (var integer i:=0; i<sizeof(v_COAP_EntityCtxDB.data[pl_eCtxIdx].observedResourceIndices); i:=i+1)
{
if (v_COAP_EntityCtxDB.data[pl_eCtxIdx].observedResourceIndices[i] != p_obsResIdx) {
vl_newList[sizeof(vl_newList)] := v_COAP_EntityCtxDB.data[pl_eCtxIdx].observedResourceIndices[i];
}
}
v_COAP_EntityCtxDB.data[pl_eCtxIdx].observedResourceIndices := vl_newList;
// Remove the observed resource from the DB
f_EPTF_COAP_observedResourceDB_remove(p_obsResIdx);
if (f_EPTF_COAP_isCoapReportEnabledForEntity(v_COAP_EntityCtxDB.data[pl_eCtxIdx].eIdx) ) {
f_EPTF_COAP_dispatchEvent(
c_COAP_eventIdx_resourceNotObservedIndication,
v_COAP_EntityCtxDB.data[pl_eCtxIdx].eIdx,
-1, {}
);
}
}
v_COAP_stats.noObserves := v_COAP_stats.noObserves - 1;
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_EntityCtx_removeObservedResource
//
// Purpose:
// Removes an observed resource entry from the simulated device
//
// Parameters:
// p_eCtxIdx - *in* *integer* - index of the <COAP_EntityCtx> instance in <COAP_EntityCtx_DB>
// p_obsResIdx - *in* *integer* - The index of the <COAP_ObservedResource> instance in the <COAP_ObservedResource_DB>
//
// Related Types:
// <COAP_EntityCtx>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_EntityCtx_removeObservedResource(in integer pl_eCtxIdx, in integer p_obsResIdx)
runs on EPTF_COAP_LGen_CT
{
var COAP_ObservedResourceIdx_List vl_newList := {};
// call clean up for the observed resource to remove the observations
f_EPTF_COAP_ObservedResource_cleanUp(p_obsResIdx);
// Remove the p_obsResIdx from the stored indices
for (var integer i:=0; i<sizeof(v_COAP_EntityCtxDB.data[pl_eCtxIdx].observedResourceIndices); i:=i+1)
{
if (v_COAP_EntityCtxDB.data[pl_eCtxIdx].observedResourceIndices[i] != p_obsResIdx) {
vl_newList[sizeof(vl_newList)] := v_COAP_EntityCtxDB.data[pl_eCtxIdx].observedResourceIndices[i];
}
}
v_COAP_EntityCtxDB.data[pl_eCtxIdx].observedResourceIndices := vl_newList;
// Remove the observed resource from the DB
f_EPTF_COAP_observedResourceDB_remove(p_obsResIdx);
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_EntityCtx_addBlockwiseTransfer
//
// Purpose:
// Adds a new blockwise transfer FSM to the simulated device
//
// Parameters:
// p_eCtxIdx - *in* *integer* - index of the <COAP_EntityCtx> instance in <COAP_EntityCtx_DB>
// p_msg - *in* <EPTF_COAP_PDU> - The incoming blockwise (num=0) request (or response)
//
// Related Types:
// <COAP_EntityCtx>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_EntityCtx_addBlockwiseTransfer(
in integer p_eIdx,
in integer p_fsmIdx,
in integer p_eCtxIdx,
in integer p_block1OptionIdx,
in EPTF_COAP_PDU p_msg)
runs on EPTF_COAP_LGen_CT
{
// Fetch the URI path
var charstring v_uriPath := f_EPTF_COAP_uriPathToString(p_msg.pdu);
f_EPTF_COAP_Logging_DEBUG(log2str("addBlockwiseTransfer() for ", v_uriPath));
// Do we already have this resource under observation?
var integer v_blockwiseIdx := f_EPTF_COAP_blockwiseDB_lookUp(
p_msg.transportParams.localAddress.hostName,
p_msg.transportParams.localAddress.portNumber,
v_uriPath
);
// If we haven't found it, then we need to add this FSM to the list of blockwise FSMs
if (v_blockwiseIdx < 0)
{
var COAP_Blockwise_Transfer v_blockwiseTransfer := c_COAP_Blockwise_Transfer_init;
v_blockwiseTransfer.localAddress := p_msg.transportParams.localAddress.hostName;
v_blockwiseTransfer.localPort := p_msg.transportParams.localAddress.portNumber;
v_blockwiseTransfer.remoteAddress := p_msg.transportParams.remoteAddress.hostName;
v_blockwiseTransfer.remotePort := p_msg.transportParams.remoteAddress.portNumber;
v_blockwiseTransfer.resourceId := v_uriPath;
v_blockwiseTransfer.uriPath := f_EPTF_COAP_fetchUriPath(p_msg.pdu);
v_blockwiseTransfer.eIdx := p_eIdx;
v_blockwiseTransfer.fsmIdx := p_fsmIdx;
v_blockwiseTransfer.lastBlock1Option := p_msg.pdu.options[p_block1OptionIdx].block1;
v_blockwiseTransfer.headerCode := p_msg.pdu.header.code;
v_blockwiseTransfer.contentFormat := f_EPTF_COAP_fetchContentFormat(p_msg.pdu);
if (ispresent(p_msg.pdu.payload) and v_COAP_blockwiseDB.collectContent)
{
v_blockwiseTransfer.content := p_msg.pdu.payload;
}
// In case the simualted device has a preferred block size and it is smaller then the offered block1 szx
// -> we will have a block size change
if (
ispresent(v_COAP_EntityCtxDB.data[p_eCtxIdx].preferredBlocksize) and
v_COAP_EntityCtxDB.data[p_eCtxIdx].preferredBlocksize < p_msg.pdu.options[p_block1OptionIdx].block1.szx
)
{
v_blockwiseTransfer.ongoingBlocksizeChange := true;
}
var integer v_blockwiseTransferIdx := f_EPTF_COAP_blockwiseDB_add(v_blockwiseTransfer);
v_COAP_EntityCtxDB.data[p_eCtxIdx].blockwiseIndices[sizeof(v_COAP_EntityCtxDB.data[p_eCtxIdx].blockwiseIndices)] := v_blockwiseTransferIdx;
f_EPTF_COAP_BlockwiseTransfer_startT_lifetime(v_blockwiseTransferIdx);
}
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_EntityCtx_removeBlockwiseTransfer
//
// Purpose:
// Removes an existing blockwise transfer from the simulated device
//
// Parameters:
// p_eCtxIdx - *in* *integer* - index of the <COAP_EntityCtx> instance in <COAP_EntityCtx_DB>
// p_BlockwiseTransferIdx - *in* *integer* - The index of the <COAP_Blockwise_Transfer> instance in the <COAP_Blockwise_DB>
//
// Related Types:
// <COAP_EntityCtx>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_EntityCtx_removeBlockwiseTransfer(in integer pl_eCtxIdx, in integer p_BlockwiseTransferIdx)
runs on EPTF_COAP_LGen_CT
{
var COAP_ObservedResourceIdx_List vl_newList := {};
// Remove the p_BlockwiseTransferIdx from the stored indices
for (var integer i:=0; i<sizeof(v_COAP_EntityCtxDB.data[pl_eCtxIdx].observedResourceIndices); i:=i+1)
{
if (v_COAP_EntityCtxDB.data[pl_eCtxIdx].blockwiseIndices[i] != p_BlockwiseTransferIdx) {
vl_newList[sizeof(vl_newList)] := v_COAP_EntityCtxDB.data[pl_eCtxIdx].blockwiseIndices[i];
}
}
v_COAP_EntityCtxDB.data[pl_eCtxIdx].blockwiseIndices := vl_newList;
// Remove the blockwise transfer from the DB
f_EPTF_COAP_blockwiseDB_remove(p_BlockwiseTransferIdx);
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_EntityCtx_addOutgoingNiddMessage
//
// Purpose:
// Stores a new outgoing encoded NIDD message to the entity context
//
// Parameters:
// p_eCtxIdx - *in* *integer* - index of the <COAP_EntityCtx> instance in <COAP_EntityCtx_DB>
// p_msg - *in octetstring* - The encoded outgoing NIDD message
//
// Related Types:
// <COAP_EntityCtx>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_EntityCtx_addOutgoingNiddMessage(in integer p_eCtxIdx, in octetstring p_msg)
runs on EPTF_COAP_LGen_CT
{
f_EPTF_COAP_Logging_DEBUG(log2str("addOutgoingNiddMessage() for eCtxIdx: ", p_eCtxIdx));
// If we haven't reached the buffer limit
if (sizeof(v_COAP_EntityCtxDB.data[p_eCtxIdx].niddOutgoingMessages) <= tsp_EPTF_COAP_maxNiddBufferSize)
{
var integer v_msgIdx := f_EPTF_COAP_niddDB_add(p_msg);
v_COAP_EntityCtxDB.data[p_eCtxIdx].niddOutgoingMessages[sizeof(v_COAP_EntityCtxDB.data[p_eCtxIdx].niddOutgoingMessages)] := v_msgIdx;
}
else
{
f_EPTF_COAP_Logging_WARNING(log2str("addOutgoingNiddMessage() reached buffering limit, ignoring message! eCtxIdx: ", p_eCtxIdx));
}
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_EntityCtx_clearOutgoingNiddMessages
//
// Purpose:
// Removes all buffered NIDD messages belonging to the entity
//
// Parameters:
// p_eCtxIdx - *in* *integer* - index of the <COAP_EntityCtx> instance in <COAP_EntityCtx_DB>
//
// Related Types:
// <COAP_EntityCtx>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_EntityCtx_clearOutgoingNiddMessages(in integer p_eCtxIdx)
runs on EPTF_COAP_LGen_CT
{
f_EPTF_COAP_Logging_DEBUG(log2str("clearOutgoingNiddMessages() for eCtxIdx: ", p_eCtxIdx));
for (var integer i:=0; i<sizeof(v_COAP_EntityCtxDB.data[p_eCtxIdx].niddOutgoingMessages); i:=i+1)
{
f_EPTF_COAP_niddDB_remove(v_COAP_EntityCtxDB.data[p_eCtxIdx].niddOutgoingMessages[i]);
}
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_EntityCtx_cleanUp
//
// Purpose:
// Cleans up the <COAP_EntityCtx> instance of a simulated device by deleting related instances
//
// Parameters:
// p_eCtxIdx - *in* *integer* - index of the <COAP_EntityCtx> instance in <COAP_EntityCtx_DB>
// p_obsResIdx - *in* *integer* - The index of the <COAP_ObservedResource> instance in the <COAP_ObservedResource_DB>
//
// Related Types:
// <COAP_EntityCtx>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_EntityCtx_cleanUp(in integer p_eCtxIdx)
runs on EPTF_COAP_LGen_CT
{
var integer vl_obsResIdx;
for (var integer i:=0; i<sizeof(v_COAP_EntityCtxDB.data[p_eCtxIdx].observedResourceIndices); i:=i+1)
{
vl_obsResIdx := v_COAP_EntityCtxDB.data[p_eCtxIdx].observedResourceIndices[i];
f_EPTF_COAP_ObservedResource_cleanUp(vl_obsResIdx);
f_EPTF_COAP_observedResourceDB_remove(vl_obsResIdx);
}
f_EPTF_COAP_EntityCtx_clearOutgoingNiddMessages(p_eCtxIdx);
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_ObservedResource_addObserver
//
// Purpose:
// Adds an <COAP_Observation_Server> instance to the <COAP_ObservedResource> instance based on the OBSERVE message
//
// Parameters:
// p_obsResIdx - *in* *integer* - The index of the <COAP_ObservedResource> instance in the <COAP_ObservedResource_DB>
// p_msg - *in* <EPTF_COAP_PDU> - The OBSERVE message that the observer sent to observe a resource
// p_confirmable - *in* *boolean* - when true CON transaction is used else NON is used for notifications
//
// Related Types:
// <COAP_ObservedResource>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_ObservedResource_addObserver(in integer p_obsResIdx, in EPTF_COAP_PDU p_msg, in boolean p_confirmable)
runs on EPTF_COAP_LGen_CT
{
if (p_obsResIdx < 0 or p_obsResIdx >= sizeof(v_COAP_observedResourceDB.data)) { return }
// Do we already have this observer?
var integer v_observationIdx := f_EPTF_COAP_observationDB_lookUp(
p_msg.transportParams.remoteAddress.hostName,
p_msg.transportParams.remoteAddress.portNumber,
v_COAP_observedResourceDB.data[p_obsResIdx].resourceId,
p_obsResIdx
);
// If we haven't found it, then we need to add this observation
if (v_observationIdx < 0)
{
var COAP_Observation_Server v_observationServer := c_COAP_Observation_Server_init;
v_observationServer.remoteAddress := p_msg.transportParams.remoteAddress.hostName;
v_observationServer.remotePort := p_msg.transportParams.remoteAddress.portNumber;
v_observationServer.protocol := p_msg.transportParams.transport;
v_observationServer.resourceId := v_COAP_observedResourceDB.data[p_obsResIdx].resourceId;
v_observationServer.token := p_msg.pdu.token;
v_observationServer.confirmable := p_confirmable;
v_observationServer.observedResourceIdx := p_obsResIdx;
v_observationServer.trIdx := -1;
v_observationIdx := f_EPTF_COAP_observationDB_add(v_observationServer);
v_COAP_observedResourceDB.data[p_obsResIdx].observationServersIndices[sizeof(v_COAP_observedResourceDB.data[p_obsResIdx].observationServersIndices)] :=
v_observationIdx;
}
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_ObservedResource_removeObserver
//
// Purpose:
// Removes an <COAP_Observation_Server> instance from the <COAP_ObservedResource> instance that canceled its observation
//
// Parameters:
// p_obsResIdx - *in* *integer* - The index of the <COAP_ObservedResource> instance in the <COAP_ObservedResource_DB>
// p_obsIdx - *in* *integer* - The index of the <COAP_Observation_Server> instance in the <COAP_Observation_DB>
//
// Related Types:
// <COAP_ObservedResource>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_ObservedResource_removeObserver(in integer p_obsResIdx, in integer p_obsIdx)
runs on EPTF_COAP_LGen_CT
{
f_EPTF_COAP_Logging_DEBUG(log2str(%definitionId));
if (p_obsResIdx < 0 or p_obsResIdx >= sizeof(v_COAP_observedResourceDB.data)) { return }
var ObservationServerIdx_List vl_newList := {};
// Remove the p_obsIdx from the stored indices
for (var integer i:=0; i<sizeof(v_COAP_observedResourceDB.data[p_obsResIdx].observationServersIndices); i:=i+1)
{
if (v_COAP_observedResourceDB.data[p_obsResIdx].observationServersIndices[i] != p_obsIdx) {
vl_newList[sizeof(vl_newList)] := v_COAP_observedResourceDB.data[p_obsResIdx].observationServersIndices[i];
}
}
v_COAP_observedResourceDB.data[p_obsResIdx].observationServersIndices := vl_newList;
// Remove the observation from the DB
f_EPTF_COAP_observationDB_remove(p_obsIdx);
// Was this the last observer?
var boolean vl_lastObserver := false;
if (sizeof(v_COAP_observedResourceDB.data[p_obsResIdx].observationServersIndices)==0) { vl_lastObserver := true; }
// Notify the entity
f_EPTF_COAP_EntityCtx_removeObservation(v_COAP_observedResourceDB.data[p_obsResIdx].eCtxIdx, p_obsResIdx, vl_lastObserver);
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_ObservedResource_sendNotification
//
// Purpose:
// Sends notificiations to all observers, who are observing a particular resource <COAP_ObservedResource>
//
// Parameters:
// p_obsResIdx - *in* *integer* - The index of the <COAP_ObservedResource> instance in the <COAP_ObservedResource_DB>
// p_msg - *inout* <EPTF_COAP_PDU> - The NOTIFICATION message that will be sent to the observers
//
// Related Types:
// <COAP_ObservedResource>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_ObservedResource_sendNotification(in integer p_obsResIdx, inout EPTF_COAP_PDU p_msg)
runs on EPTF_COAP_LGen_CT
{
f_EPTF_COAP_Logging_DEBUG(log2str(%definitionId));
if (p_obsResIdx < 0 or p_obsResIdx >= sizeof(v_COAP_observedResourceDB.data))
{
f_EPTF_COAP_Logging_WARNING(log2str(%definitionId, "Invalid p_obsResIdx: ",p_obsResIdx));
return
}
for (var integer i:=0; i<sizeof(v_COAP_observedResourceDB.data[p_obsResIdx].observationServersIndices); i:=i+1)
{
var integer v_obServerIdx := v_COAP_observedResourceDB.data[p_obsResIdx].observationServersIndices[i];
f_EPTF_COAP_ObservationServer_sendNotification(v_obServerIdx, p_msg);
}
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_ObservedResource_cleanUp
//
// Purpose:
// Cleans up the <COAP_ObservedResource> instance
//
// Parameters:
// p_obsResIdx - *in* *integer* - The index of the <COAP_ObservedResource> instance in the <COAP_ObservedResource_DB>
//
// Related Types:
// <COAP_ObservedResource>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_ObservedResource_cleanUp(in integer p_obsResIdx)
runs on EPTF_COAP_LGen_CT
{
if (p_obsResIdx < 0 or p_obsResIdx >= sizeof(v_COAP_observedResourceDB.data)) { return }
var integer vl_obsIdx;
for (var integer i:=0; i<sizeof(v_COAP_observedResourceDB.data[p_obsResIdx].observationServersIndices); i:=i+1)
{
vl_obsIdx := v_COAP_observedResourceDB.data[p_obsResIdx].observationServersIndices[i];
f_EPTF_COAP_observationDB_remove(vl_obsIdx);
}
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_ObservationServer_sendNotification
//
// Purpose:
// Sends a notification for a particular observer of an observation relationship
//
// Parameters:
// p_obsIdx - *in* *integer* - The index of the <COAP_Observation_Server> instance in the <COAP_Observation_DB>
// p_msg - *inout* <EPTF_COAP_PDU> - The NOTIFICATION message that will be sent to the observer
//
// Related Types:
// <COAP_Observation_Server>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_ObservationServer_sendNotification(in integer p_obsIdx, inout EPTF_COAP_PDU p_msg)
runs on EPTF_COAP_LGen_CT
{
f_EPTF_COAP_Logging_DEBUG(log2str(%definitionId));
if (p_obsIdx < 0 or p_obsIdx >= sizeof(v_COAP_observationDB.data))
{
f_EPTF_COAP_Logging_WARNING(log2str(%definitionId, "Invalid p_obsIdx: ",p_obsIdx));
return
}
// We assume:
// 1. That the template to be sent is already loaded into p_msg!
// 2. That the v_COAP_ctx is set from the f_EPTF_COAP_sendNotification!
if (f_EPTF_COAP_isResponse(v_COAP_msgToSend.pdu))
{
// Setting the msg type
if (v_COAP_observationDB.data[p_obsIdx].confirmable) { p_msg.pdu.header.msg_type := CONFIRMABLE; }
else { p_msg.pdu.header.msg_type := NON_CONFIRMABLE; }
// Setting the observe option
v_COAP_observationDB.data[p_obsIdx].seqNum := v_COAP_observationDB.data[p_obsIdx].seqNum + 1;
var integer vl_obsOptionIdx := f_EPTF_COAP_hasObserve(p_msg.pdu);
if (vl_obsOptionIdx < 0) { vl_obsOptionIdx := sizeof(p_msg.pdu.options); }
p_msg.pdu.options[vl_obsOptionIdx] := { observe := v_COAP_observationDB.data[p_obsIdx].seqNum };
// Set local address
f_EPTF_COAP_transportEndpointDB_get(v_COAP_transportEndpoint, v_COAP_EntityCtxDB.data[v_COAP_ctx.eCtxIdx].localAddressIdx);
p_msg.transportParams.localAddress := v_COAP_transportEndpoint.socket;
p_msg.transportParams.transport := v_COAP_transportEndpoint.proto;
p_msg.eIdx := v_COAP_ctx.eIdx;
// Set remote address
p_msg.transportParams.remoteAddress.hostName := v_COAP_observationDB.data[p_obsIdx].remoteAddress;
p_msg.transportParams.remoteAddress.portNumber := v_COAP_observationDB.data[p_obsIdx].remotePort;
// Set the protocol
p_msg.transportParams.transport := v_COAP_observationDB.data[p_obsIdx].protocol;
// Set the token
p_msg.pdu.token := v_COAP_observationDB.data[p_obsIdx].token;
// create new TR
var COAP_Transaction vl_tr := c_COAP_Transaction_init;
vl_tr.mid := f_EPTF_COAP_getNextMID(v_COAP_ctx);
vl_tr.eIdx := v_COAP_ctx.eIdx;
vl_tr.obsIdx := p_obsIdx;
vl_tr.rrIdx := -1;
vl_tr.addrIdx := v_COAP_EntityCtxDB.data[v_COAP_ctx.eCtxIdx].localAddressIdx;
vl_tr.state := CLOSED;
vl_tr.direction := OUTGOING;
vl_tr.retransmitTimerValue := tsp_EPTF_COAP_LGen_retransmitTimerInitialValue;
p_msg.pdu.header.message_id := vl_tr.mid;
var integer vl_trIdx := f_EPTF_COAP_trDB_add(vl_tr);
f_EPTF_COAP_tr_setState(vl_trIdx, CLOSED);
// Set pointer to tr
v_COAP_observationDB.data[p_obsIdx].trIdx := vl_trIdx;
// trOut.send
f_EPTF_COAP_tr_fromRR(p_msg, vl_trIdx);
v_COAP_stats.outgoing.noNotifications := v_COAP_stats.outgoing.noNotifications + 1;
}
else {
f_EPTF_COAP_Logging_WARNING(log2str(%definitionId, " the message is not a notification therefore it cannot be sent using sendNotification!"));
}
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_ObservationServer_cancelReceivedFromEnv
//
// Purpose:
// When an observation is canceled this can be called function to remove the corresponding <COAP_Observation_Server> instance
//
// Parameters:
// p_obsIdx - *in* *integer* - The index of the <COAP_Observation_Server> instance in the <COAP_Observation_DB>
//
// Related Types:
// <COAP_Observation_Server>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_ObservationServer_cancelReceivedFromEnv(in integer p_obsIdx)
runs on EPTF_COAP_LGen_CT
{
f_EPTF_COAP_Logging_DEBUG(log2str(%definitionId));
if (p_obsIdx < 0 or p_obsIdx >= sizeof(v_COAP_observationDB.data)) { return }
if (v_COAP_observationDB.data[p_obsIdx].observedResourceIdx != -1) {
f_EPTF_COAP_ObservedResource_removeObserver(v_COAP_observationDB.data[p_obsIdx].observedResourceIdx, p_obsIdx);
}
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_declareEvents
//
// Purpose:
// Declares the FSM events to the CLL framework implemented by <EPTF_COAP_LGen_CT>
//
// Related Types:
// <EPTF_COAP_LGen_CT>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_declareEvents()
runs on EPTF_COAP_LGen_CT
{
var integer vl_dummy;
if (
c_COAP_eventIdx_EMPTY != f_EPTF_LGenBase_declareFsmEvent(c_COAP_behaviorType, c_COAP_eventName_EMPTY) or
c_COAP_eventIdx_GET != f_EPTF_LGenBase_declareFsmEvent(c_COAP_behaviorType, c_COAP_eventName_GET) or
c_COAP_eventIdx_POST != f_EPTF_LGenBase_declareFsmEvent(c_COAP_behaviorType, c_COAP_eventName_POST) or
c_COAP_eventIdx_PUT != f_EPTF_LGenBase_declareFsmEvent(c_COAP_behaviorType, c_COAP_eventName_PUT) or
c_COAP_eventIdx_DELETE != f_EPTF_LGenBase_declareFsmEvent(c_COAP_behaviorType, c_COAP_eventName_DELETE) or
c_COAP_eventIdx_OBSERVE != f_EPTF_LGenBase_declareFsmEvent(c_COAP_behaviorType, c_COAP_eventName_OBSERVE)
){
f_EPTF_LGenBase_log();
log("f_EPTF_COAP_declareEvents() error at requests"); mtc.stop
}
for (var integer i:=6; i<700; i:=i+1)
{
vl_dummy := f_EPTF_LGenBase_declareFsmEvent(c_COAP_behaviorType, "COAP rsp: "&int2str(i));
}
if (
c_COAP_eventIdx_1xx != f_EPTF_LGenBase_declareFsmEvent(c_COAP_behaviorType, c_COAP_eventName_1xx) or
c_COAP_eventIdx_2xx != f_EPTF_LGenBase_declareFsmEvent(c_COAP_behaviorType, c_COAP_eventName_2xx) or
c_COAP_eventIdx_3xx != f_EPTF_LGenBase_declareFsmEvent(c_COAP_behaviorType, c_COAP_eventName_3xx) or
c_COAP_eventIdx_4xx != f_EPTF_LGenBase_declareFsmEvent(c_COAP_behaviorType, c_COAP_eventName_4xx) or
c_COAP_eventIdx_5xx != f_EPTF_LGenBase_declareFsmEvent(c_COAP_behaviorType, c_COAP_eventName_5xx) or
c_COAP_eventIdx_6xx != f_EPTF_LGenBase_declareFsmEvent(c_COAP_behaviorType, c_COAP_eventName_6xx) or
c_COAP_eventIdx_3xxto6xx != f_EPTF_LGenBase_declareFsmEvent(c_COAP_behaviorType, c_COAP_eventName_3xxto6xx) or
c_COAP_eventIdx_transportSucc != f_EPTF_LGenBase_declareFsmEvent(c_COAP_behaviorType, c_COAP_eventName_transportSucc) or
c_COAP_eventIdx_transportFail != f_EPTF_LGenBase_declareFsmEvent(c_COAP_behaviorType, c_COAP_eventName_transportFail) or
c_COAP_eventIdx_trRST != f_EPTF_LGenBase_declareFsmEvent(c_COAP_behaviorType, c_COAP_eventName_trRST) or
c_COAP_eventIdx_trTimeout != f_EPTF_LGenBase_declareFsmEvent(c_COAP_behaviorType, c_COAP_eventName_trTimeout) or
c_COAP_eventIdx_observeCanceled != f_EPTF_LGenBase_declareFsmEvent(c_COAP_behaviorType, c_COAP_eventName_observeCanceled) or
c_COAP_eventIdx_resourceNotObservedIndication != f_EPTF_LGenBase_declareFsmEvent(c_COAP_behaviorType, c_COAP_eventName_resourceNotObservedIndication) or
c_COAP_eventIdx_dtlsConnectionClosed != f_EPTF_LGenBase_declareFsmEvent(c_COAP_behaviorType, c_COAP_eventName_dtlsConnectionClosed) or
c_COAP_eventIdx_BLOCK1_init != f_EPTF_LGenBase_declareFsmEvent(c_COAP_behaviorType, c_COAP_eventName_BLOCK1_init) or
c_COAP_eventIdx_BLOCK1_block != f_EPTF_LGenBase_declareFsmEvent(c_COAP_behaviorType, c_COAP_eventName_BLOCK1_block) or
c_COAP_eventIdx_BLOCK1_last != f_EPTF_LGenBase_declareFsmEvent(c_COAP_behaviorType, c_COAP_eventName_BLOCK1_last) or
c_COAP_eventIdx_BLOCK1_atomic_succ != f_EPTF_LGenBase_declareFsmEvent(c_COAP_behaviorType, c_COAP_eventName_BLOCK1_atomic_succ) or
c_COAP_eventIdx_BLOCK1_atomic_fail != f_EPTF_LGenBase_declareFsmEvent(c_COAP_behaviorType, c_COAP_eventName_BLOCK1_atomic_fail) or
c_COAP_eventIdx_niddMessageBuffered != f_EPTF_LGenBase_declareFsmEvent(c_COAP_behaviorType, c_COAP_eventName_niddMessageBuffered)
){
f_EPTF_LGenBase_log();
log("f_EPTF_COAP_declareEvents() error at responses"); mtc.stop
}
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_declareSteps
//
// Purpose:
// Declares the FSM steps to the CLL framework implemented by <EPTF_COAP_LGen_CT>
//
// Related Types:
// <EPTF_COAP_LGen_CT>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_declareSteps()
runs on EPTF_COAP_LGen_CT
{
if (
c_COAP_stepIdx_init != f_EPTF_LGenBase_declareStep(c_COAP_behaviorType,{c_COAP_stepName_init, refers(f_COAP_step_init)}) or
c_COAP_stepIdx_cleanUp != f_EPTF_LGenBase_declareStep(c_COAP_behaviorType,{c_COAP_stepName_cleanUp, refers(f_COAP_step_cleanUp) }) or
c_COAP_stepIdx_setLocalAddress != f_EPTF_LGenBase_declareStep(c_COAP_behaviorType,{c_COAP_stepName_setLocalAddress, refers(f_COAP_step_setLocalAddress)}) or
c_COAP_stepIdx_setRemoteAddress_byIntIdx != f_EPTF_LGenBase_declareStep(c_COAP_behaviorType,{c_COAP_stepName_setRemoteAddress_byIntIdx, refers(f_COAP_step_setRemoteAddress_byIntIdx)}) or
c_COAP_stepIdx_send != f_EPTF_LGenBase_declareStep(c_COAP_behaviorType,{c_COAP_stepName_send, refers(f_COAP_step_send)}) or
c_COAP_stepIdx_loadTemplate_byIntIdx != f_EPTF_LGenBase_declareStep(c_COAP_behaviorType,{c_COAP_stepName_loadTemplate_byIntIdx, refers(f_COAP_step_loadTemplate_byIntIdx)}) or
c_COAP_stepIdx_handleRequest != f_EPTF_LGenBase_declareStep(c_COAP_behaviorType,{c_COAP_stepName_handleRequest, refers(f_COAP_step_handleRequest)}) or
c_COAP_stepIdx_sendResponse != f_EPTF_LGenBase_declareStep(c_COAP_behaviorType,{c_COAP_stepName_sendResponse, refers(f_COAP_step_sendResponse)}) or
c_COAP_stepIdx_sendAccept != f_EPTF_LGenBase_declareStep(c_COAP_behaviorType,{c_COAP_stepName_sendAccept, refers(f_COAP_step_sendAccept)}) or
c_COAP_stepIdx_startListening != f_EPTF_LGenBase_declareStep(c_COAP_behaviorType,{c_COAP_stepName_startListening, refers(f_COAP_step_startListening)}) or
c_COAP_stepIdx_reportCoapEventForEntity != f_EPTF_LGenBase_declareStep(c_COAP_behaviorType,{c_COAP_stepName_reportCoapEventForEntity, refers(f_COAP_step_reportCoapEventForEntity)}) or
c_COAP_stepIdx_loadTemplate_byStringId != f_EPTF_LGenBase_declareStep(c_COAP_behaviorType,{c_COAP_stepName_loadTemplate_byStringId, refers(f_COAP_step_loadTemplate_byStringId)}) or
c_COAP_stepIdx_setRemoteAddress_byVars != f_EPTF_LGenBase_declareStep(c_COAP_behaviorType,{c_COAP_stepName_setRemoteAddress_byVars, refers(f_COAP_step_setRemoteAddress_byVars)}) or
c_COAP_stepIdx_sendNotification_byIntIdx != f_EPTF_LGenBase_declareStep(c_COAP_behaviorType,{c_COAP_stepName_sendNotification_byIntIdx, refers(f_COAP_step_sendNotification_byIntIdx)}) or
c_COAP_stepIdx_sendNotification_byStringId != f_EPTF_LGenBase_declareStep(c_COAP_behaviorType,{c_COAP_stepName_sendNotification_byStringId, refers(f_COAP_step_sendNotification_byStringId)}) or
c_COAP_stepIdx_removeResourceObservations_byIntIdx != f_EPTF_LGenBase_declareStep(c_COAP_behaviorType,{c_COAP_stepName_removeResourceObservations_byIntIdx, refers(f_COAP_step_removeResourceObservations_byIntIdx)}) or
c_COAP_stepIdx_removeResourceObservations_byStringId != f_EPTF_LGenBase_declareStep(c_COAP_behaviorType,{c_COAP_stepName_removeResourceObservations_byStringId, refers(f_COAP_step_removeResourceObservations_byStringId)}) or
c_COAP_stepIdx_startDTLS != f_EPTF_LGenBase_declareStep(c_COAP_behaviorType,{c_COAP_stepName_startDTLS, refers(f_COAP_step_startDTLS)}) or
c_COAP_stepIdx_startDTLS_byVarIds != f_EPTF_LGenBase_declareStep(c_COAP_behaviorType,{c_COAP_stepName_startDTLS_byVarIds, refers(f_COAP_step_startDTLS_byVarIds)}) or
c_COAP_stepIdx_startDTLS_byIntIdx != f_EPTF_LGenBase_declareStep(c_COAP_behaviorType,{c_COAP_stepName_startDTLS_byIntIdx, refers(f_COAP_step_startDTLS_byIntIdx)}) or
c_COAP_stepIdx_confirmableNotificationForEntity != f_EPTF_LGenBase_declareStep(c_COAP_behaviorType,{c_COAP_stepName_confirmableNotificationForEntity, refers(f_COAP_step_confirmableNotificationForEntity)}) or
c_COAP_stepIdx_setPreferredBlocksize != f_EPTF_LGenBase_declareStep(c_COAP_behaviorType,{c_COAP_stepName_setPreferredBlocksize, refers(f_COAP_step_setPreferredBlocksize)})
)
{
f_EPTF_LGenBase_log();
log("f_EPTF_COAP_declareSteps() error"); mtc.stop
}
}
///////////////////////////////////////////////////////////
// Function: f_COAP_step_init
//
// Purpose:
// Test Step to dynamically allocate and initialize the COAP FSM context for the caller FSM. Prerequisite to call any other COAP test step.
//
// Parameters:
// pl_ptr - *in* <EPTF_LGenBase_TestStepArgs> - test step args
//
// Related Constants:
// - <c_COAP_stepIdx_init>
// - <c_COAP_stepName_init>
///////////////////////////////////////////////////////////
function f_COAP_step_init(in EPTF_LGenBase_TestStepArgs pl_ptr)
runs on EPTF_COAP_LGen_CT
{
f_EPTF_COAP_Logging_DEBUG(log2str(%definitionId));
var integer vl_eIdx := pl_ptr.eIdx;
var integer vl_fsmIdx := pl_ptr.refContext.fCtxIdx;
var integer vl_newFsmCtxIdx := -1;
if (f_EPTF_COAP_isFsmInitialized(vl_eIdx, vl_fsmIdx, vl_newFsmCtxIdx)) { return }
vl_newFsmCtxIdx := f_EPTF_FBQ_getOrCreateFreeSlot(v_COAP_FsmCtxDB.queue);
f_EPTF_FBQ_moveFromFreeHeadToBusyTail(v_COAP_FsmCtxDB.queue);
f_EPTF_COAP_Logging_DEBUG(log2str(%definitionId, ": initializing fsm ", vl_fsmIdx, " for entity ",vl_eIdx));
f_EPTF_LGenBase_setAppDataItemOfFsmCtx(vl_eIdx, vl_fsmIdx, v_COAP_bIdx, c_COAP_AppData_fsmCtxIdx, vl_newFsmCtxIdx);
v_COAP_FsmCtxDB.data[vl_newFsmCtxIdx] := c_COAP_FsmCtx_init;
v_COAP_FsmCtxDB.data[vl_newFsmCtxIdx].eIdx := vl_eIdx;
}
///////////////////////////////////////////////////////////
// Function: f_COAP_step_cleanUp
//
// Purpose:
// Test Step to free up the COAP FSM context for the caller FSM. Frees up all allocated instances that were used by this FSM instance.
//
// Parameters:
// pl_ptr - *in* <EPTF_LGenBase_TestStepArgs> - test step args
//
// Related Constants:
// - <c_COAP_stepIdx_cleanUp>
// - <c_COAP_stepName_cleanUp>
///////////////////////////////////////////////////////////
function f_COAP_step_cleanUp(in EPTF_LGenBase_TestStepArgs pl_ptr)
runs on EPTF_COAP_LGen_CT
{
f_EPTF_COAP_Logging_DEBUG(log2str(%definitionId));
var integer vl_eIdx:=pl_ptr.eIdx;
var integer vl_eCtxIdx := f_EPTF_LGenBase_getBehaviorCtxItem(vl_eIdx, v_COAP_bIdx, 0);
var integer vl_fsmIdx := pl_ptr.refContext.fCtxIdx;
var integer vl_fsmCtxIdx := -1;
f_EPTF_COAP_EntityCtx_cleanUp(vl_eCtxIdx);
if (not f_EPTF_COAP_isFsmInitialized(vl_eIdx, vl_fsmIdx, vl_fsmCtxIdx))
{
f_EPTF_COAP_Logging_DEBUG(%definitionId&": FSM has not been initialized");
return;
}
f_EPTF_COAP_Logging_DEBUG(log2str(%definitionId,": FSM database: ",v_COAP_FsmCtxDB.data[vl_fsmCtxIdx]));
//f_EPTF_SIP_CancelAllTimers_FSM(vl_userIdx, vl_FSMIdx);
v_COAP_FsmCtxDB.data[vl_fsmCtxIdx] := c_COAP_FsmCtx_init;
f_EPTF_FBQ_moveFromBusyToFreeTail(vl_fsmCtxIdx, v_COAP_FsmCtxDB.queue);
f_EPTF_LGenBase_setAppDataItemOfFsmCtx(vl_eIdx, vl_fsmIdx, v_COAP_bIdx, c_COAP_AppData_fsmCtxIdx, -1);
}
///////////////////////////////////////////////////////////
// Function: f_COAP_step_setLocalAddress
//
// Purpose:
// Test step to set the local address in the entity context. Integer parameter required.
//
// Parameters:
// pl_ptr - *in* <EPTF_LGenBase_TestStepArgs> - test step args
// pl_ptr.refContext.fRefArgs[0] - *integer* - Index of the endpoint to use as local address
//
// Related Constants:
// - <c_COAP_stepIdx_setLocalAddress>
// - <c_COAP_stepName_setLocalAddress>
///////////////////////////////////////////////////////////
function f_COAP_step_setLocalAddress(in EPTF_LGenBase_TestStepArgs pl_ptr)
runs on EPTF_COAP_LGen_CT
{
f_EPTF_COAP_Logging_DEBUG(log2str(%definitionId));
if (not f_EPTF_COAP_setStepCtx(pl_ptr, v_COAP_ctx)) { return; }
f_EPTF_COAP_getIntValue(pl_ptr.refContext.fRefArgs, 0, v_COAP_EntityCtxDB.data[v_COAP_ctx.eCtxIdx].localAddressIdx);
}
///////////////////////////////////////////////////////////
// Function: f_COAP_step_setRemoteAddress_byIntIdx
//
// Purpose:
// Test step to set the remote address in the FSM context <COAP_FsmCtx>. Integer parameter required.
//
// Parameters:
// pl_ptr - *in* <EPTF_LGenBase_TestStepArgs> - test step args
// pl_ptr.refContext.fRefArgs[0] - *integer* - Index of the endpoint to use as remote address
//
// Related Constants:
// - <c_COAP_stepIdx_setRemoteAddress_byIntIdx>
// - <c_COAP_stepName_setRemoteAddress_byIntIdx>
///////////////////////////////////////////////////////////
function f_COAP_step_setRemoteAddress_byIntIdx(in EPTF_LGenBase_TestStepArgs pl_ptr)
runs on EPTF_COAP_LGen_CT
{
f_EPTF_COAP_Logging_DEBUG(log2str(%definitionId));
if (not f_EPTF_COAP_setStepCtx(pl_ptr, v_COAP_ctx)) { return; }
f_EPTF_COAP_getIntValue(pl_ptr.refContext.fRefArgs, 0, v_COAP_FsmCtxDB.data[v_COAP_ctx.fsmCtxIdx].remoteAddressIdx);
}
///////////////////////////////////////////////////////////
// Function: f_COAP_step_loadTemplate_byIntIdx
//
// Purpose:
// Test step to load a <CoAP_Template> from <tsp_EPTF_COAP_LGen_templates> into *v_COAP_msgToSend*
// (which can be sent using the send test step). Integer parameter required.
//
// Parameters:
// pl_ptr - *in* <EPTF_LGenBase_TestStepArgs> - test step args
// pl_ptr.refContext.fRefArgs[0] - *integer* - Index of the template to load into *v_COAP_msgToSend*
//
// Related Constants:
// - <c_COAP_stepIdx_loadTemplate_byIntIdx>
// - <c_COAP_stepName_loadTemplate_byIntIdx>
//
// Related Steps:
// <f_COAP_step_send>
///////////////////////////////////////////////////////////
function f_COAP_step_loadTemplate_byIntIdx(in EPTF_LGenBase_TestStepArgs pl_ptr)
runs on EPTF_COAP_LGen_CT
{
f_EPTF_COAP_Logging_DEBUG(log2str(%definitionId));
if (not f_EPTF_COAP_setStepCtx(pl_ptr, v_COAP_ctx)) { return; }
var integer vl_templateIdx := -1;
f_EPTF_COAP_getIntValue(pl_ptr.refContext.fRefArgs, 0, vl_templateIdx);
f_EPTF_COAP_templateDB_get(vl_templateIdx, v_COAP_msgToSend.pdu);
}
///////////////////////////////////////////////////////////
// Function: f_COAP_step_loadTemplate_byStringId
//
// Purpose:
// Test step to load a <CoAP_Template> from <tsp_EPTF_COAP_LGen_templates> into *v_COAP_msgToSend*
// (which can be sent using the send test step). String parameter required.
//
// Parameters:
// pl_ptr - *in* <EPTF_LGenBase_TestStepArgs> - test step args
// contextArgs.charstringVal - *charstring* - ID the template to load into *v_COAP_msgToSend*
//
// Related Constants:
// - <c_COAP_stepIdx_loadTemplate_byStringId>
// - <c_COAP_stepName_loadTemplate_byStringId>
//
// Related Steps:
// <f_COAP_step_send>
///////////////////////////////////////////////////////////
function f_COAP_step_loadTemplate_byStringId(in EPTF_LGenBase_TestStepArgs pl_ptr)
runs on EPTF_COAP_LGen_CT
{
f_EPTF_COAP_Logging_DEBUG(log2str(%definitionId));
if (not f_EPTF_COAP_setStepCtx(pl_ptr, v_COAP_ctx)) { return; }
var charstring vl_templateId := f_EPTF_LGenBase_charstringValOfStep(pl_ptr);
var integer vl_templateIdx := f_EPTF_COAP_templateDB_lookUp(vl_templateId);
if (vl_templateIdx >= 0)
{
f_EPTF_COAP_templateDB_get(vl_templateIdx, v_COAP_msgToSend.pdu);
}
else
{
f_EPTF_COAP_Logging_WARNING(log2str(%definitionId," Couldn't find template with id: ", vl_templateId));
}
}
///////////////////////////////////////////////////////////
// Function: f_COAP_step_send
//
// Purpose:
// Test step to send out a COAP message from *v_COAP_msgToSend*.
// The message will be processed by the Applib's COAP stack
// The step expects the localAddress and the remoteAddress to be configured
//
// Parameters:
// pl_ptr - *in* <EPTF_LGenBase_TestStepArgs> - test step args
//
// Related Constants:
// - <c_COAP_stepIdx_send>
// - <c_COAP_stepName_send>
//
// Related Steps:
// - <f_COAP_step_loadTemplate_byIntIdx>
// - <f_COAP_step_loadTemplate_byStringId>
//
// Related functions:
// <f_EPTF_COAP_stack_fromApp>
///////////////////////////////////////////////////////////
function f_COAP_step_send(in EPTF_LGenBase_TestStepArgs pl_ptr)
runs on EPTF_COAP_LGen_CT
{
f_EPTF_COAP_Logging_DEBUG(log2str(%definitionId," ",pl_ptr));
if (not f_EPTF_COAP_setStepCtx(pl_ptr, v_COAP_ctx)) { return; }
f_EPTF_COAP_transportEndpointDB_get(v_COAP_transportEndpoint, v_COAP_EntityCtxDB.data[v_COAP_ctx.eCtxIdx].localAddressIdx);
v_COAP_msgToSend.transportParams.localAddress := v_COAP_transportEndpoint.socket;
if (v_COAP_FsmCtxDB.data[v_COAP_ctx.fsmCtxIdx].rrIdx == -1)
{
// If there is no ongoing RR, we will send to the remote address
f_EPTF_COAP_transportEndpointDB_get(v_COAP_transportEndpoint, v_COAP_FsmCtxDB.data[v_COAP_ctx.fsmCtxIdx].remoteAddressIdx);
v_COAP_msgToSend.transportParams.remoteAddress := v_COAP_transportEndpoint.socket;
}
v_COAP_msgToSend.transportParams.transport := v_COAP_transportEndpoint.proto;
v_COAP_msgToSend.eIdx := v_COAP_ctx.eIdx;
v_COAP_msgToSend.fsmIdx := v_COAP_ctx.fsmIdx;
f_EPTF_COAP_Logging_DEBUG(log2str(%definitionId," msg to send: ",v_COAP_msgToSend));
f_EPTF_COAP_stack_fromApp(v_COAP_msgToSend, v_COAP_ctx);
f_EPTF_SchedulerComp_refreshSnapshotTime();
}
///////////////////////////////////////////////////////////
// Function: f_COAP_step_handleRequest
//
// Purpose:
// The test step can be called from an FSM to handle a reported COAP request.
// The test step will bind the current request to the caller FSM.
//
// Parameters:
// pl_ptr - *in* <EPTF_LGenBase_TestStepArgs> - test step args
//
// Related Constants:
// - <c_COAP_stepIdx_handleRequest>
// - <c_COAP_stepName_handleRequest>
///////////////////////////////////////////////////////////
function f_COAP_step_handleRequest(in EPTF_LGenBase_TestStepArgs pl_ptr)
runs on EPTF_COAP_LGen_CT
{
f_EPTF_COAP_Logging_DEBUG(log2str(%definitionId));
if (not f_EPTF_COAP_setStepCtx(pl_ptr, v_COAP_ctx)) { return; }
// New RR
var COAP_RR vl_rr := c_COAP_RR_init;
vl_rr.eIdx := v_COAP_ctx.eIdx;
vl_rr.fsmIdx := v_COAP_ctx.fsmIdx;
vl_rr.fsmCtxIdx := v_COAP_ctx.fsmCtxIdx;
vl_rr.addrIdx := v_COAP_EntityCtxDB.data[v_COAP_ctx.eCtxIdx].localAddressIdx;
vl_rr.token := v_COAP_msgToProcess.pdu.token;
vl_rr.state.server := IDLE;
var integer vl_rrIdx := f_EPTF_COAP_rrDB_add(vl_rr);
v_COAP_FsmCtxDB.data[v_COAP_ctx.fsmCtxIdx].rrIdx := vl_rrIdx;
// Get TR
var integer vl_trIdx := f_EPTF_COAP_trDB_lookUp(v_COAP_msgToProcess.transportParams.localAddress, v_COAP_msgToProcess.pdu.header.message_id, INCOMING);
if (vl_trIdx < 0)
{
f_EPTF_COAP_Logging_WARNING(log2str(%definitionId, " couldn't find incoming transaction"));
}
v_COAP_trDB.data[vl_trIdx].rrIdx := vl_rrIdx;
v_COAP_rrDB.data[vl_rrIdx].trIdx := vl_trIdx;
f_EPTF_COAP_rr_handleMsg(v_COAP_msgToProcess, vl_rrIdx);
}
///////////////////////////////////////////////////////////
// Function: f_COAP_step_sendResponse
//
// Purpose:
// The test step expects an ongoing request bound to the FSM by <f_COAP_step_handleRequest>
// and a response message loaded into *v_COAP_msgToSend* by <f_COAP_step_loadTemplate_byIntIdx>
// The test step will take the template and process it in the applib's stack that will fill in
// the necessary id (e.g. mid, token) and will match the message type to the request the following way:
// - req.NON -> rsp.NON
// - req.CON && state.SERVING -> rsp.ACK
// - req.CON && state.SEPARATE -> rsp.CON
//
// Parameters:
// pl_ptr - *in* <EPTF_LGenBase_TestStepArgs> - test step args
//
// Related Constants:
// - <c_COAP_stepIdx_sendResponse>
// - <c_COAP_stepName_sendResponse>
//
// Related Steps:
// - <f_COAP_step_handleRequest>
// - <f_COAP_step_loadTemplate_byIntIdx>
///////////////////////////////////////////////////////////
function f_COAP_step_sendResponse(in EPTF_LGenBase_TestStepArgs pl_ptr)
runs on EPTF_COAP_LGen_CT
{
f_EPTF_COAP_Logging_DEBUG(log2str(%definitionId));
// Matches the msg_Type of response to the incoming request and the current state
// That is:
// - req.NON -> rsp.NON
// - req.CON && state.SERVING -> rsp.ACK
// - req.CON && state.SEPARATE -> rsp.CON
if (not f_EPTF_COAP_setStepCtx(pl_ptr, v_COAP_ctx)) { return; }
// We need an ongoing RR!
if (v_COAP_FsmCtxDB.data[v_COAP_ctx.fsmCtxIdx].rrIdx != -1)
{
var integer vl_rrIdx := v_COAP_FsmCtxDB.data[v_COAP_ctx.fsmCtxIdx].rrIdx;
if (ischosen(v_COAP_rrDB.data[vl_rrIdx].state.server))
{
if (ispresent(v_COAP_rrDB.data[vl_rrIdx].request))
{
if (v_COAP_rrDB.data[vl_rrIdx].request.pdu.header.msg_type == NON_CONFIRMABLE) {
v_COAP_msgToSend.pdu.header.msg_type := NON_CONFIRMABLE;
}
else //if (v_COAP_rrDB.data[vl_rrIdx].request.pdu.header.msg_type == CONFIRMABLE)
{
if (v_COAP_rrDB.data[vl_rrIdx].state.server == SERVING) {
v_COAP_msgToSend.pdu.header.msg_type := ACKNOWLEDGEMENT;
}
else if (v_COAP_rrDB.data[vl_rrIdx].state.server == SEPARATE) {
v_COAP_msgToSend.pdu.header.msg_type := CONFIRMABLE;
}
else {
f_EPTF_COAP_Logging_ERROR(log2str(%definitionId, " unrecognized state"));
}
}
f_EPTF_COAP_transportEndpointDB_get(v_COAP_transportEndpoint, v_COAP_EntityCtxDB.data[v_COAP_ctx.eCtxIdx].localAddressIdx);
v_COAP_msgToSend.transportParams.localAddress := v_COAP_transportEndpoint.socket;
v_COAP_msgToSend.transportParams.transport := v_COAP_transportEndpoint.proto;
v_COAP_msgToSend.eIdx := v_COAP_ctx.eIdx;
v_COAP_msgToSend.fsmIdx := v_COAP_ctx.fsmIdx;
f_EPTF_COAP_stack_fromApp(v_COAP_msgToSend, v_COAP_ctx);
}
else {
f_EPTF_COAP_Logging_WARNING(log2str(%definitionId, " there is no request received, therefore response cannot be sent!"));
}
}
else {
f_EPTF_COAP_Logging_WARNING(log2str(%definitionId, " ongoing rr must be a server, in a client rr no response can be sent!"));
}
}
else {
f_EPTF_COAP_Logging_WARNING(log2str(%definitionId, " there is no ongoing RR, therefore response cannot be sent!"));
}
f_EPTF_SchedulerComp_refreshSnapshotTime();
}
///////////////////////////////////////////////////////////
// Function: f_COAP_step_sendAccept
//
// Purpose:
// The test step expects an ongoing request bound to the FSM by <f_COAP_step_handleRequest>
// The test step will send an accept (eg. ACK to a CON) without the body thus indicating to
// the client, that the request is accepted, but time is needed to produce the content. This
// accept will make the client cease its request retranmissions
//
// Parameters:
// pl_ptr - *in* <EPTF_LGenBase_TestStepArgs> - test step args
//
// Related Constants:
// - <c_COAP_stepIdx_sendAccept>
// - <c_COAP_stepName_sendAccept>
//
// Related Steps:
// - <f_COAP_step_handleRequest>
///////////////////////////////////////////////////////////
function f_COAP_step_sendAccept(in EPTF_LGenBase_TestStepArgs pl_ptr)
runs on EPTF_COAP_LGen_CT
{
f_EPTF_COAP_Logging_DEBUG(log2str(%definitionId));
if (not f_EPTF_COAP_setStepCtx(pl_ptr, v_COAP_ctx)) { return; }
// We need an ongoing RR!
if (v_COAP_FsmCtxDB.data[v_COAP_ctx.fsmCtxIdx].rrIdx != -1)
{
var integer vl_rrIdx := v_COAP_FsmCtxDB.data[v_COAP_ctx.fsmCtxIdx].rrIdx;
if (ischosen(v_COAP_rrDB.data[vl_rrIdx].state.server) and v_COAP_rrDB.data[vl_rrIdx].state.server == SERVING)
{
if (ispresent(v_COAP_rrDB.data[vl_rrIdx].request))
{
v_COAP_msgToSend.pdu := valueof(t_CoAP_EmptyAck);
f_EPTF_COAP_transportEndpointDB_get(v_COAP_transportEndpoint, v_COAP_EntityCtxDB.data[v_COAP_ctx.eCtxIdx].localAddressIdx);
v_COAP_msgToSend.transportParams.localAddress := v_COAP_transportEndpoint.socket;
v_COAP_msgToSend.transportParams.transport := v_COAP_transportEndpoint.proto;
v_COAP_msgToSend.eIdx := v_COAP_ctx.eIdx;
v_COAP_msgToSend.fsmIdx := v_COAP_ctx.fsmIdx;
f_EPTF_COAP_stack_fromApp(v_COAP_msgToSend, v_COAP_ctx);
}
else {
f_EPTF_COAP_Logging_WARNING(log2str(%definitionId, " there is no request received, therefore empty ack response cannot be sent!"));
}
}
else {
f_EPTF_COAP_Logging_WARNING(log2str(%definitionId, " ongoing rr must be a server, and the rr must be in SERVING state!"));
}
}
else {
f_EPTF_COAP_Logging_WARNING(log2str(%definitionId, " there is no ongoing RR, therefore empty ack response cannot be sent!"));
}
f_EPTF_SchedulerComp_refreshSnapshotTime();
}
///////////////////////////////////////////////////////////
// Function: f_COAP_step_startListening
//
// Purpose:
// The test step expects that a transport endpoint is set in the entity context: <COAP_EntityCtx> as a local address
// The step will initiate allocating the local address using the transport layer and eventually
// it will report back if it was successful or it failed
//
// Parameters:
// pl_ptr - *in* <EPTF_LGenBase_TestStepArgs> - test step args
//
// Related Constants:
// - <c_COAP_stepIdx_startListening>
// - <c_COAP_stepName_startListening>
//
// Related Events:
// - <c_COAP_eventIdx_transportSucc>
// - <c_COAP_eventIdx_transportFail>
//
// Related Steps:
// - <f_COAP_step_setLocalAddress>
///////////////////////////////////////////////////////////
function f_COAP_step_startListening(in EPTF_LGenBase_TestStepArgs pl_ptr)
runs on EPTF_COAP_LGen_CT
{
if (not f_EPTF_COAP_setStepCtx(pl_ptr, v_COAP_ctx)) { return; }
var EPTF_COAP_Transport_Request vl_req := c_EPTF_COAP_Transport_Request_init;
vl_req.eIdx := v_COAP_ctx.eIdx;
vl_req.fsmIdx := v_COAP_ctx.fsmIdx;
f_EPTF_COAP_transportEndpointDB_get(v_COAP_transportEndpoint, v_COAP_EntityCtxDB.data[v_COAP_ctx.eCtxIdx].localAddressIdx);
if (ischosen(v_COAP_transportEndpoint.proto.ip))
{
vl_req.params.startListening.localAddress := v_COAP_transportEndpoint.socket;
vl_req.params.startListening.protocol := v_COAP_transportEndpoint.proto.ip;
vf_EPTF_COAP_Transport_apiRequest.apply(vl_req);
}
else
{
f_EPTF_COAP_Logging_WARNING(log2str(%definitionId, " listening is only for IP transport!"));
}
}
///////////////////////////////////////////////////////////
// Function: f_COAP_step_startDTLS
//
// Purpose:
// The test step expects that a transport endpoint is set in the entity context as a local address
// and a remote address is set in the FSM context.
// The step will use PSK for authentication in case the PSK identity and key is set in the FSM context: <COAP_FsmCtx>
// The step will initiate creating a DTLS connection and
// it will report back if it was successful or it failed
//
// Parameters:
// pl_ptr - *in* <EPTF_LGenBase_TestStepArgs> - test step args
//
// Related Constants:
// - <c_COAP_stepIdx_startDTLS>
// - <c_COAP_stepName_startDTLS>
//
// Related Events:
// - <c_COAP_eventIdx_transportSucc>
// - <c_COAP_eventName_transportSucc>
// - <c_COAP_eventIdx_transportFail>
// - <c_COAP_eventName_transportFail>
///////////////////////////////////////////////////////////
function f_COAP_step_startDTLS(in EPTF_LGenBase_TestStepArgs pl_ptr)
runs on EPTF_COAP_LGen_CT
{
if (not f_EPTF_COAP_setStepCtx(pl_ptr, v_COAP_ctx)) { return; }
var EPTF_COAP_Transport_Request vl_req := c_EPTF_COAP_Transport_Request_init;
vl_req.eIdx := v_COAP_ctx.eIdx;
vl_req.fsmIdx := v_COAP_ctx.fsmIdx;
f_EPTF_COAP_transportEndpointDB_get(v_COAP_transportEndpoint, v_COAP_EntityCtxDB.data[v_COAP_ctx.eCtxIdx].localAddressIdx);
vl_req.params.startDTLS.localAddress := v_COAP_transportEndpoint.socket;
f_EPTF_COAP_transportEndpointDB_get(v_COAP_transportEndpoint, v_COAP_FsmCtxDB.data[v_COAP_ctx.fsmCtxIdx].remoteAddressIdx);
vl_req.params.startDTLS.remoteAddress := v_COAP_transportEndpoint.socket;
vl_req.params.startDTLS.pskIdentity := omit;
vl_req.params.startDTLS.pskKey := omit;
if (ispresent(v_COAP_FsmCtxDB.data[v_COAP_ctx.fsmCtxIdx].psk))
{
vl_req.params.startDTLS.pskIdentity := v_COAP_FsmCtxDB.data[v_COAP_ctx.fsmCtxIdx].psk.identity;
vl_req.params.startDTLS.pskKey := v_COAP_FsmCtxDB.data[v_COAP_ctx.fsmCtxIdx].psk.key;
}
vf_EPTF_COAP_Transport_apiRequest.apply(vl_req);
}
///////////////////////////////////////////////////////////
// Function: f_COAP_step_startDTLS_byVarIds
//
// Purpose:
// The test step expects that a transport endpoint is set in the entity context as a local address
// and a remote address is set in the FSM context.
// The step will use PSK for authentication. The PSK identity and key will be taken from the steps parameters
// and loaded into the FSM context: <COAP_FsmCtx>
// The step will initiate creating a DTLS connection and
// it will report back if it was successful or it failed
//
// Parameters:
// pl_ptr - *in* <EPTF_LGenBase_TestStepArgs> - test step args
// contextArgs.varNames[0] - *charstring variable* - PSK identity
// contextArgs.varNames[1] - *charstring variable* - PSK key
//
// Related Constants:
// - <c_COAP_stepIdx_startDTLS_byVarIds>
// - <c_COAP_stepName_startDTLS_byVarIds>
//
// Related Events:
// - <c_COAP_eventIdx_transportSucc>
// - <c_COAP_eventName_transportSucc>
// - <c_COAP_eventIdx_transportFail>
// - <c_COAP_eventName_transportFail>
///////////////////////////////////////////////////////////
function f_COAP_step_startDTLS_byVarIds(in EPTF_LGenBase_TestStepArgs pl_ptr)
runs on EPTF_COAP_LGen_CT
{
if (not f_EPTF_COAP_setStepCtx(pl_ptr, v_COAP_ctx)) { return; }
// 1st param: psk id: charstring
// 2nd param: psk key: charstring
var EPTF_IntegerList vl_varIds := {};
f_EPTF_LGenBase_fsmVarIdListFromStep(pl_ptr, vl_varIds);
var EPTF_COAP_Transport_Request vl_req := c_EPTF_COAP_Transport_Request_init;
vl_req.eIdx := v_COAP_ctx.eIdx;
vl_req.fsmIdx := v_COAP_ctx.fsmIdx;
f_EPTF_COAP_transportEndpointDB_get(v_COAP_transportEndpoint, v_COAP_EntityCtxDB.data[v_COAP_ctx.eCtxIdx].localAddressIdx);
vl_req.params.startDTLS.localAddress := v_COAP_transportEndpoint.socket;
f_EPTF_COAP_transportEndpointDB_get(v_COAP_transportEndpoint, v_COAP_FsmCtxDB.data[v_COAP_ctx.fsmCtxIdx].remoteAddressIdx);
vl_req.params.startDTLS.remoteAddress := v_COAP_transportEndpoint.socket;
vl_req.params.startDTLS.pskIdentity := omit;
vl_req.params.startDTLS.pskKey := omit;
if (sizeof(vl_varIds)==2)
{
var EPTF_Var_DirectContent vl_id, vl_key;
f_EPTF_Var_getContent(vl_varIds[0], vl_id);
f_EPTF_Var_getContent(vl_varIds[1], vl_key);
if (not ischosen(vl_id.charstringVal)) {
f_EPTF_COAP_Logging_WARNING(log2str(%definitionId, " first param is not charstring variable!"));
return;
}
if (not ischosen(vl_key.charstringVal)) {
f_EPTF_COAP_Logging_WARNING(log2str(%definitionId, " second param is not charstring variable!"));
return;
}
vl_req.params.startDTLS.pskIdentity := vl_id.charstringVal;
vl_req.params.startDTLS.pskKey := vl_key.charstringVal;
}
else if (ispresent(v_COAP_FsmCtxDB.data[v_COAP_ctx.fsmCtxIdx].psk))
{
vl_req.params.startDTLS.pskIdentity := v_COAP_FsmCtxDB.data[v_COAP_ctx.fsmCtxIdx].psk.identity;
vl_req.params.startDTLS.pskKey := v_COAP_FsmCtxDB.data[v_COAP_ctx.fsmCtxIdx].psk.key;
}
vf_EPTF_COAP_Transport_apiRequest.apply(vl_req);
}
///////////////////////////////////////////////////////////
// Function: f_COAP_step_startDTLS_byIntIdx
//
// Purpose:
// The test step expects that a transport endpoint is set in the entity context as a local address
// and a remote address is set in the FSM context.
// The step will use PSK for authentication. The PSK identity and key will be taken from the step's parameters
// and loaded into the FSM context: <COAP_FsmCtx>
// The step will initiate creating a DTLS connection and
// it will report back if it was successful or it failed
//
// Parameters:
// pl_ptr - *in* <EPTF_LGenBase_TestStepArgs> - test step args
// pl_ptr.refContext.fRefArgs[0] - *charstring variable* - integer idx of the PSK parameters in <tsp_EPTF_COAP_LGen_psks>
//
// Related Constants:
// - <c_COAP_stepIdx_startDTLS_byIntIdx>
// - <c_COAP_stepName_startDTLS_byIntIdx>
//
// Related Events:
// - <c_COAP_eventIdx_transportSucc>
// - <c_COAP_eventName_transportSucc>
// - <c_COAP_eventIdx_transportFail>
// - <c_COAP_eventName_transportFail>
///////////////////////////////////////////////////////////
function f_COAP_step_startDTLS_byIntIdx(in EPTF_LGenBase_TestStepArgs pl_ptr)
runs on EPTF_COAP_LGen_CT
{
if (not f_EPTF_COAP_setStepCtx(pl_ptr, v_COAP_ctx)) { return; }
// idx param: psk idx in tsp_EPTF_COAP_LGen_psks
var integer vl_pskIdx;
if (f_EPTF_COAP_getIntValue(pl_ptr.refContext.fRefArgs, 0, vl_pskIdx))
{
if (sizeof(tsp_EPTF_COAP_LGen_psks)>0 and vl_pskIdx < sizeof(tsp_EPTF_COAP_LGen_psks))
{
var EPTF_COAP_Transport_Request vl_req := c_EPTF_COAP_Transport_Request_init;
vl_req.eIdx := v_COAP_ctx.eIdx;
vl_req.fsmIdx := v_COAP_ctx.fsmIdx;
f_EPTF_COAP_transportEndpointDB_get(v_COAP_transportEndpoint, v_COAP_EntityCtxDB.data[v_COAP_ctx.eCtxIdx].localAddressIdx);
vl_req.params.startDTLS.localAddress := v_COAP_transportEndpoint.socket;
f_EPTF_COAP_transportEndpointDB_get(v_COAP_transportEndpoint, v_COAP_FsmCtxDB.data[v_COAP_ctx.fsmCtxIdx].remoteAddressIdx);
vl_req.params.startDTLS.remoteAddress := v_COAP_transportEndpoint.socket;
v_COAP_FsmCtxDB.data[v_COAP_ctx.fsmCtxIdx].psk := tsp_EPTF_COAP_LGen_psks[vl_pskIdx];
vl_req.params.startDTLS.pskIdentity := tsp_EPTF_COAP_LGen_psks[vl_pskIdx].identity;
vl_req.params.startDTLS.pskKey := tsp_EPTF_COAP_LGen_psks[vl_pskIdx].key;
vf_EPTF_COAP_Transport_apiRequest.apply(vl_req);
}
else {f_EPTF_COAP_Logging_WARNING(log2str(%definitionId, " element idx",vl_pskIdx ,"is invalid in tsp_EPTF_COAP_LGen_psks modulepar!")); }
}
else { f_EPTF_COAP_Logging_WARNING(log2str(%definitionId, " an integer is needed as param!")); }
}
///////////////////////////////////////////////////////////
// Function: f_COAP_step_setRemoteAddress_byVars
//
// Purpose:
// Test step to set the remote address by variable parameters in the FSM context <COAP_FsmCtx>.
//
// Parameters:
// pl_ptr - *in* <EPTF_LGenBase_TestStepArgs> - test step args
// contextArgs.varNames[0] - *charstring variable* - remoteHost
// contextArgs.varNames[1] - *integer variable* - remotePort
//
// Related Constants:
// - <c_COAP_stepIdx_setRemoteAddress_byVars>
// - <c_COAP_stepName_setRemoteAddress_byVars>
///////////////////////////////////////////////////////////
function f_COAP_step_setRemoteAddress_byVars(in EPTF_LGenBase_TestStepArgs pl_ptr)
runs on EPTF_COAP_LGen_CT
{
f_EPTF_COAP_Logging_DEBUG(log2str(%definitionId));
if (not f_EPTF_COAP_setStepCtx(pl_ptr, v_COAP_ctx)) { return; }
// 1st param: remoteHost: charstring
// 2nd param: remotePort: integer
var EPTF_IntegerList vl_varIds := {};
f_EPTF_LGenBase_fsmVarIdListFromStep(pl_ptr, vl_varIds);
if (sizeof(vl_varIds)==2)
{
var EPTF_Var_DirectContent vl_host, vl_port;
f_EPTF_Var_getContent(vl_varIds[0], vl_host);
f_EPTF_Var_getContent(vl_varIds[1], vl_port);
if (not ischosen(vl_host.charstringVal)) {
f_EPTF_COAP_Logging_WARNING(log2str(%definitionId, " first param is not charstring variable!"));
return;
}
if (not ischosen(vl_port.intVal)) {
f_EPTF_COAP_Logging_WARNING(log2str(%definitionId, " second param is not integer variable!"));
return;
}
v_COAP_transportEndpoint := c_COAP_TransportEndpoint_empty;
v_COAP_transportEndpoint.socket.hostName := vl_host.charstringVal;
v_COAP_transportEndpoint.socket.portNumber := vl_port.intVal;
f_EPTF_COAP_transportEndpointDB_add(
v_COAP_transportEndpoint,
v_COAP_FsmCtxDB.data[v_COAP_ctx.fsmCtxIdx].remoteAddressIdx
);
}
else {
f_EPTF_COAP_Logging_WARNING(log2str(%definitionId, " two variables are needed as params!"));
}
}
///////////////////////////////////////////////////////////
// Function: f_COAP_step_reportCoapEventForEntity
//
// Purpose:
// The test step will turn on/off the COAP event reporting for the entity in the entity context <COAP_EntityCtx>
// It is recommended to turn the reporting off, when the COAP applib is used as a transport for the LWM2M applib
//
// Parameters:
// pl_ptr - *in* <EPTF_LGenBase_TestStepArgs> - test step args
// pl_ptr.refContext.fRefArgs[0] - 0: false, 1: true
//
// Related Constants:
// - <c_COAP_stepIdx_reportCoapEventForEntity>
// - <c_COAP_stepName_reportCoapEventForEntity>
///////////////////////////////////////////////////////////
function f_COAP_step_reportCoapEventForEntity(in EPTF_LGenBase_TestStepArgs pl_ptr)
runs on EPTF_COAP_LGen_CT
{
f_EPTF_COAP_Logging_DEBUG(log2str(%definitionId));
if (not f_EPTF_COAP_setStepCtx(pl_ptr, v_COAP_ctx)) { return; }
var integer vl_paramValue := -1;
if (f_EPTF_COAP_getIntValue(pl_ptr.refContext.fRefArgs, 0, vl_paramValue))
{
if (vl_paramValue == c_COAP_stepParam_true) {
v_COAP_EntityCtxDB.data[v_COAP_ctx.eCtxIdx].reportCoapEvent := true;
}
else {
v_COAP_EntityCtxDB.data[v_COAP_ctx.eCtxIdx].reportCoapEvent := false;
}
}
}
///////////////////////////////////////////////////////////
// Function: f_COAP_step_confirmableNotificationForEntity
//
// Purpose:
// The test step will turn on/off the COAP CON notifications for the entity in the entity context <COAP_EntityCtx>
//
// Parameters:
// pl_ptr - *in* <EPTF_LGenBase_TestStepArgs> - test step args
// pl_ptr.refContext.fRefArgs[0] - 0: NON notifications, 1: CON notifications
//
// Related Constants:
// - <c_COAP_stepIdx_confirmableNotificationForEntity>
// - <c_COAP_stepName_confirmableNotificationForEntity>
///////////////////////////////////////////////////////////
function f_COAP_step_confirmableNotificationForEntity(in EPTF_LGenBase_TestStepArgs pl_ptr)
runs on EPTF_COAP_LGen_CT
{
f_EPTF_COAP_Logging_DEBUG(log2str(%definitionId));
if (not f_EPTF_COAP_setStepCtx(pl_ptr, v_COAP_ctx)) { return; }
var integer vl_paramValue := -1;
if (f_EPTF_COAP_getIntValue(pl_ptr.refContext.fRefArgs, 0, vl_paramValue))
{
if (vl_paramValue == c_COAP_stepParam_true) {
v_COAP_EntityCtxDB.data[v_COAP_ctx.eCtxIdx].confirmableNotification := true;
}
else {
v_COAP_EntityCtxDB.data[v_COAP_ctx.eCtxIdx].confirmableNotification := false;
}
}
}
///////////////////////////////////////////////////////////
// Function: f_COAP_step_sendNotification_byIntIdx
//
// Purpose:
// The test step send notifications to the observers of the observed resource pointed by the idx parameter
//
// Parameters:
// pl_ptr - *in* <EPTF_LGenBase_TestStepArgs> - test step args
// pl_ptr.refContext.fRefArgs[0] - *integer* - observed resource idx in the entity context <COAP_EntityCtx>
//
// Related Constants:
// - <c_COAP_stepIdx_sendNotification_byIntIdx>
// - <c_COAP_stepName_sendNotification_byIntIdx>
///////////////////////////////////////////////////////////
function f_COAP_step_sendNotification_byIntIdx(in EPTF_LGenBase_TestStepArgs pl_ptr)
runs on EPTF_COAP_LGen_CT
{
f_EPTF_COAP_Logging_DEBUG(log2str(%definitionId));
if (not f_EPTF_COAP_setStepCtx(pl_ptr, v_COAP_ctx)) { return; }
// 1st param: integer, the index of the resource of the given entity
var integer vl_observedResourceIdx_Idx := -1;
if (f_EPTF_COAP_getIntValue(pl_ptr.refContext.fRefArgs, 0, vl_observedResourceIdx_Idx))
{
var integer vl_observedResourceIdx := -1;
if (f_EPTF_COAP_getIntValue(v_COAP_EntityCtxDB.data[v_COAP_ctx.eCtxIdx].observedResourceIndices, vl_observedResourceIdx_Idx, vl_observedResourceIdx))
{
f_EPTF_COAP_ObservedResource_sendNotification(vl_observedResourceIdx, v_COAP_msgToSend);
}
else { f_EPTF_COAP_Logging_WARNING(log2str(%definitionId, " it was not possible to fetch the referred observedResourceIdx")); }
}
else { f_EPTF_COAP_Logging_WARNING(log2str(%definitionId, " an integer is needed as param!")); }
}
///////////////////////////////////////////////////////////
// Function: f_COAP_step_sendNotification_byStringId
//
// Purpose:
// The test step send notifications to the observers of the observed resource identified by the string uri given as parameter
//
// Parameters:
// pl_ptr - *in* <EPTF_LGenBase_TestStepArgs> - test step args
// contextArgs.charstringValue - *charstring* - observed resource uri
//
// Related Constants:
// - <c_COAP_stepIdx_sendNotification_byStringId>
// - <c_COAP_stepName_sendNotification_byStringId>
///////////////////////////////////////////////////////////
function f_COAP_step_sendNotification_byStringId(in EPTF_LGenBase_TestStepArgs pl_ptr)
runs on EPTF_COAP_LGen_CT
{
f_EPTF_COAP_Logging_DEBUG(log2str(%definitionId));
if (not f_EPTF_COAP_setStepCtx(pl_ptr, v_COAP_ctx)) { return; }
// 1st param: charstring, the URI of the observed resource
var charstring vl_observedResourceId := f_EPTF_LGenBase_charstringValOfStep(pl_ptr);
f_EPTF_COAP_transportEndpointDB_get(v_COAP_transportEndpoint, v_COAP_EntityCtxDB.data[v_COAP_ctx.eCtxIdx].localAddressIdx);
var integer vl_observedResourceIdx := f_EPTF_COAP_observedResourceDB_lookUp(
v_COAP_transportEndpoint.socket.hostName,
v_COAP_transportEndpoint.socket.portNumber,
vl_observedResourceId
);
if (vl_observedResourceIdx != -1)
{
f_EPTF_COAP_ObservedResource_sendNotification(vl_observedResourceIdx, v_COAP_msgToSend);
}
else { f_EPTF_COAP_Logging_WARNING(log2str(%definitionId, " it was not possible to fetch the referred observedResourceIdx")); }
}
///////////////////////////////////////////////////////////
// Function: f_COAP_step_sendNotification_internal
//
// Purpose:
// This function sends notifications to the observers of the observed resource identified by the string uri given as parameter
//
// Parameters:
// pl_ptr - *in* <EPTF_LGenBase_TestStepArgs> - test step args
// contextArgs.charstringValue - *charstring* - observed resource uri
//
// Related Types:
// <EPTF_COAP_LGen_CT>
///////////////////////////////////////////////////////////
function f_COAP_step_sendNotification_internal(in EPTF_LGenBase_TestStepArgs pl_ptr, in charstring p_observedResourceId)
runs on EPTF_COAP_LGen_CT
{
f_EPTF_COAP_Logging_DEBUG(log2str(%definitionId,":",p_observedResourceId));
if (not f_EPTF_COAP_setStepCtx(pl_ptr, v_COAP_ctx)) { return; }
f_EPTF_COAP_transportEndpointDB_get(v_COAP_transportEndpoint, v_COAP_EntityCtxDB.data[v_COAP_ctx.eCtxIdx].localAddressIdx);
var integer vl_observedResourceIdx := f_EPTF_COAP_observedResourceDB_lookUp(
v_COAP_transportEndpoint.socket.hostName,
v_COAP_transportEndpoint.socket.portNumber,
p_observedResourceId
);
if (vl_observedResourceIdx != -1)
{
f_EPTF_COAP_ObservedResource_sendNotification(vl_observedResourceIdx, v_COAP_msgToSend);
}
else { f_EPTF_COAP_Logging_WARNING(log2str(%definitionId, " it was not possible to fetch the referred observedResourceIdx")); }
}
///////////////////////////////////////////////////////////
// Function: f_COAP_step_removeResourceObservations_byIntIdx
//
// Purpose:
// The test step removes the observers of the observed resource pointed by the idx parameter
//
// Parameters:
// pl_ptr - *in* <EPTF_LGenBase_TestStepArgs> - test step args
// pl_ptr.refContext.fRefArgs[0] - *integer* - observed resource idx in the entity context <COAP_EntityCtx>
//
// Related Constants:
// - <c_COAP_stepIdx_removeResourceObservations_byIntIdx>
// - <c_COAP_stepName_removeResourceObservations_byIntIdx>
///////////////////////////////////////////////////////////
function f_COAP_step_removeResourceObservations_byIntIdx(in EPTF_LGenBase_TestStepArgs pl_ptr)
runs on EPTF_COAP_LGen_CT
{
f_EPTF_COAP_Logging_DEBUG(log2str(%definitionId));
if (not f_EPTF_COAP_setStepCtx(pl_ptr, v_COAP_ctx)) { return; }
// 1st param: integer, the index of the resource of the given entity
var integer vl_observedResourceIdx_Idx := -1;
if (f_EPTF_COAP_getIntValue(pl_ptr.refContext.fRefArgs, 0, vl_observedResourceIdx_Idx))
{
var integer vl_observedResourceIdx := -1;
if (f_EPTF_COAP_getIntValue(v_COAP_EntityCtxDB.data[v_COAP_ctx.eCtxIdx].observedResourceIndices, vl_observedResourceIdx_Idx, vl_observedResourceIdx))
{
f_EPTF_COAP_EntityCtx_removeObservedResource(v_COAP_ctx.eCtxIdx, vl_observedResourceIdx);
}
else { f_EPTF_COAP_Logging_WARNING(log2str(%definitionId, " it was not possible to fetch the referred observedResourceIdx")); }
}
else { f_EPTF_COAP_Logging_WARNING(log2str(%definitionId, " an integer is needed as param!")); }
}
///////////////////////////////////////////////////////////
// Function: f_COAP_step_removeResourceObservations_byStringId
//
// Purpose:
// The test step removes the observers of the observed resource identified by the string uri given as parameter
//
// Parameters:
// pl_ptr - *in* <EPTF_LGenBase_TestStepArgs> - test step args
// contextArgs.charstringValue - *charstring* - observed resource uri
//
// Related Constants:
// - <c_COAP_stepIdx_removeResourceObservations_byStringId>
// - <c_COAP_stepName_removeResourceObservations_byStringId>
///////////////////////////////////////////////////////////
function f_COAP_step_removeResourceObservations_byStringId(in EPTF_LGenBase_TestStepArgs pl_ptr)
runs on EPTF_COAP_LGen_CT
{
f_EPTF_COAP_Logging_DEBUG(log2str(%definitionId));
if (not f_EPTF_COAP_setStepCtx(pl_ptr, v_COAP_ctx)) { return; }
// 1st param: charstring, the URI of the observed resource
var charstring vl_observedResourceId := f_EPTF_LGenBase_charstringValOfStep(pl_ptr);
f_EPTF_COAP_transportEndpointDB_get(v_COAP_transportEndpoint, v_COAP_EntityCtxDB.data[v_COAP_ctx.eCtxIdx].localAddressIdx);
var integer vl_observedResourceIdx := f_EPTF_COAP_observedResourceDB_lookUp(
v_COAP_transportEndpoint.socket.hostName,
v_COAP_transportEndpoint.socket.portNumber,
vl_observedResourceId
);
if (vl_observedResourceIdx != -1)
{
f_EPTF_COAP_EntityCtx_removeObservedResource(v_COAP_ctx.eCtxIdx, vl_observedResourceIdx);
}
else { f_EPTF_COAP_Logging_WARNING(log2str(%definitionId, " it was not possible to fetch the referred observedResourceIdx")); }
}
///////////////////////////////////////////////////////////
// Function: f_COAP_step_setPreferredBlocksize
//
// Purpose:
// Test step to set the preferred blocksize (szx) in the entity context. Integer parameter required.
//
// Parameters:
// pl_ptr - *in* <EPTF_LGenBase_TestStepArgs> - test step args
// pl_ptr.refContext.fRefArgs[0] - *integer* - SZX value to be set. 0 will set to omit.
//
// Related Constants:
// - <c_COAP_stepIdx_setPreferredBlocksize>
// - <c_COAP_stepName_setPreferredBlocksize>
///////////////////////////////////////////////////////////
function f_COAP_step_setPreferredBlocksize(in EPTF_LGenBase_TestStepArgs pl_ptr)
runs on EPTF_COAP_LGen_CT
{
f_EPTF_COAP_Logging_DEBUG(log2str(%definitionId));
if (not f_EPTF_COAP_setStepCtx(pl_ptr, v_COAP_ctx)) { return; }
// 1st param: integer with the szx
var integer vl_szx := 1;
if (f_EPTF_COAP_getIntValue(pl_ptr.refContext.fRefArgs, 0, vl_szx))
{
if (vl_szx == 0)
{
v_COAP_EntityCtxDB.data[v_COAP_ctx.eCtxIdx].preferredBlocksize := omit;
}
else
{
v_COAP_EntityCtxDB.data[v_COAP_ctx.eCtxIdx].preferredBlocksize := vl_szx;
}
}
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_setStepCtx
//
// Purpose:
// This sets the instance pointers of <COAP_StepCtx> to the related instances of a simulated device (entity)
// calculated from the test step args <EPTF_LGenBase_TestStepArgs>
//
// Parameters:
// pl_ptr - *in* <EPTF_LGenBase_TestStepArgs> - test step args
// p_ctx - <COAP_StepCtx> - step context with pointers to the related instances
//
// Related Types:
// - <COAP_EntityCtx>
// - <COAP_StepCtx>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_setStepCtx(in EPTF_LGenBase_TestStepArgs pl_ptr, inout COAP_StepCtx p_ctx)
runs on EPTF_COAP_LGen_CT
return boolean
{
if (not f_EPTF_COAP_isFsmInitialized(pl_ptr.eIdx, pl_ptr.refContext.fCtxIdx, p_ctx.fsmCtxIdx))
{
f_EPTF_COAP_Logging_WARNING(%definitionId &
": FSM has not been initialized. The f_COAP_step_init function must be called as first step in the FSMs using COAP.");
return false;
}
p_ctx.eIdx := pl_ptr.eIdx;
p_ctx.fsmIdx := pl_ptr.refContext.fCtxIdx;
p_ctx.eCtxIdx := f_EPTF_LGenBase_getBehaviorCtxItem(pl_ptr.eIdx, v_COAP_bIdx, 0);
return true;
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_setCtx
//
// Purpose:
// This sets the instance pointers of <COAP_StepCtx> to the related instances of a simulated device (entity)
// calculated from the test step args <EPTF_LGenBase_TestStepArgs>
//
// Parameters:
// p_eIdx - *in* *integer* - entity index
// p_fsmIdx - *in* *integer* - fsm instace index
//
// Returns:
// p_ctx - <COAP_StepCtx> - step context with pointers to the related instances
//
// Related Types:
// - <COAP_EntityCtx>
// - <COAP_StepCtx>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_setCtx(in integer p_eIdx, in integer p_fsmIdx, inout COAP_StepCtx p_ctx)
runs on EPTF_COAP_LGen_CT
return boolean
{
if (not f_EPTF_COAP_isFsmInitialized(p_eIdx, p_fsmIdx, p_ctx.fsmCtxIdx))
{
f_EPTF_COAP_Logging_WARNING(%definitionId &
": FSM has not been initialized. The f_COAP_step_init function must be called as first step in the FSMs using COAP.");
return false;
}
p_ctx.eIdx := p_eIdx;
p_ctx.fsmIdx := p_fsmIdx;
p_ctx.eCtxIdx := f_EPTF_LGenBase_getBehaviorCtxItem(p_eIdx, v_COAP_bIdx, 0);
return true;
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_isFsmInitialized
//
// Purpose:
// Checks if the <COAP_FsmCtx> instace was created for an FSM instance and returns with a pointer to it
//
// Parameters:
// p_eIdx - *in* *integer* - entity index
// p_fsmIdx - *in* *integer* - fsm instace index
//
// Returns:
// pl_fsmCtxIdx - *inout* *integer* - index of the <COAP_FsmCtx> instance in the <COAP_FsmCtx_DB>
//
// Related Types:
// <COAP_FsmCtx>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_isFsmInitialized(in integer pl_eIdx, in integer pl_fsmIdx, inout integer pl_fsmCtxIdx)
runs on EPTF_COAP_LGen_CT
return boolean
{
pl_fsmCtxIdx := -1;
var EPTF_IntegerList vl_appData := f_EPTF_LGenBase_getAppDataListOfFsmCtx(pl_eIdx, pl_fsmIdx, v_COAP_bIdx);
if (c_COAP_AppData_fsmCtxIdx < sizeof(vl_appData))
{
pl_fsmCtxIdx := vl_appData[c_COAP_AppData_fsmCtxIdx];
}
return -1 < pl_fsmCtxIdx and sizeof(v_COAP_FsmCtxDB.data) > pl_fsmCtxIdx;
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_getIntValue
//
// Purpose:
// Retreives an element of an <EPTF_IntegerList> if it exists
//
// Parameters:
// pl_intList - *in* <EPTF_IntegerList> - list of integers
// pl_number - *in* *integer* - index of the integer to be retrieved
//
// Returns:
// pl_value - *inout* *integer* - value of the retrieved integer
// *boolean* - true if the element existed in the integer list
///////////////////////////////////////////////////////////
function f_EPTF_COAP_getIntValue(
in EPTF_IntegerList pl_intList,
in integer pl_number,
inout integer pl_value)
return boolean
{
if (sizeof(pl_intList) > pl_number)
{
pl_value := pl_intList[pl_number];
return true;
}
return false;
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_CodeToEventIdx
//
// Purpose:
// Converts the <Code> ot a COAP PDU to an integer number
//
// Parameters:
// p_code - *in* <Code> - code of a COAP PDU
//
// Returns:
// *integer* - the returned id
///////////////////////////////////////////////////////////
function f_EPTF_COAP_CodeToEventIdx(in Code p_code)
return integer
{
return p_code.class*100+p_code.detail;
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_isCoapReportEnabledForEntity
//
// Purpose:
// Checks if the COAP event reporting is enabled for a particular entity
//
// Parameters:
// pl_eIdx - *in* *integer* - the index of the entity
//
// Returns:
// *boolean* - *true* if COAP event reporting is enabled, *false* otherwise
//
// Related Types:
// <COAP_EntityCtx>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_isCoapReportEnabledForEntity(in integer pl_eIdx)
runs on EPTF_COAP_LGen_CT
return boolean
{
var integer vl_eCtxIdx := f_EPTF_LGenBase_getBehaviorCtxItem(pl_eIdx, v_COAP_bIdx, 0);
return v_COAP_EntityCtxDB.data[v_COAP_ctx.eCtxIdx].reportCoapEvent;
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_dispatchEventForObserve_ifExists
//
// Purpose:
// Dispatches the <c_COAP_eventIdx_OBSERVE> event to an entity/fsm if the COAP message has an OBSERVE option
//
// Parameters:
// p_pdu - *in* <CoAP_ReqResp> - the COAP PDU
// pl_eIdx - *in* *integer* - the index of the entity
// pl_fsmCtx - *in* *integer* - the index of FSM
//
// Related Types:
// <EPTF_COAP_LGen_CT>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_dispatchEventForObserve_ifExists(in CoAP_ReqResp p_pdu, in integer pl_eIdx, in integer pl_fsmCtx)
runs on EPTF_COAP_LGen_CT
{
if (not f_EPTF_COAP_isCoapReportEnabledForEntity(pl_eIdx) ) { return; }
var integer i:= f_EPTF_COAP_hasObserve(p_pdu);
if (i >= 0)
{
if (p_pdu.options[i].observe == 0) {
f_EPTF_COAP_dispatchEvent(c_COAP_eventIdx_OBSERVE, pl_eIdx, pl_fsmCtx, {});
}
}
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_dispatchEventForBlock1
//
// Purpose:
// Dispatches the <c_COAP_eventIdx_BLOCK1_init> event to an entity/fsm if the COAP message has an block1 option
//
// Parameters:
// p_pdu - *in* <CoAP_ReqResp> - the COAP PDU
// pl_eIdx - *in* *integer* - the index of the entity
// pl_fsmCtx - *in* *integer* - the index of FSM
//
// Related Types:
// <EPTF_COAP_LGen_CT>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_dispatchEventForBlock1(in BlockOption p_block1, in integer pl_eIdx, in integer pl_fsmCtx)
runs on EPTF_COAP_LGen_CT
{
if (not f_EPTF_COAP_isCoapReportEnabledForEntity(pl_eIdx) ) { return; }
f_EPTF_COAP_dispatchEvent(c_COAP_eventIdx_BLOCK1_block, pl_eIdx, pl_fsmCtx, {});
if (p_block1.num == 0) {
f_EPTF_COAP_dispatchEvent(c_COAP_eventIdx_BLOCK1_init, pl_eIdx, pl_fsmCtx, {});
}
else if (p_block1.m == false) {
f_EPTF_COAP_dispatchEvent(c_COAP_eventIdx_BLOCK1_last, pl_eIdx, pl_fsmCtx, {});
}
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_dispatchEventsForCode
//
// Purpose:
// Dispatches events to an entity/fsm based on the COAP PDU's code
//
// Parameters:
// pl_code - *in* <Code> - the COAP PDU's code
// pl_eIdx - *in* *integer* - the index of the entity
// pl_fsmCtx - *in* *integer* - the index of FSM
// pl_reportedArgs - *in* <EPTF_IntegerList> - additional arguments to be reported to the entity/FSM
//
// Related Types:
// <EPTF_COAP_LGen_CT>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_dispatchEventsForCode(in Code pl_code, in integer pl_eIdx, in integer pl_fsmCtx, in EPTF_IntegerList pl_reportedArgs)
runs on EPTF_COAP_LGen_CT
{
if (not f_EPTF_COAP_isCoapReportEnabledForEntity(pl_eIdx) ) { return; }
var integer vl_eventIdx := f_EPTF_COAP_CodeToEventIdx(pl_code);
f_EPTF_COAP_dispatchEvent(vl_eventIdx, pl_eIdx, pl_fsmCtx, {});
if (100 <= vl_eventIdx and vl_eventIdx <= 199)
{
f_EPTF_COAP_dispatchEvent(c_COAP_eventIdx_1xx, pl_eIdx, pl_fsmCtx, {});
}
else if (200 <= vl_eventIdx and vl_eventIdx <= 299)
{
f_EPTF_COAP_dispatchEvent(c_COAP_eventIdx_2xx, pl_eIdx, pl_fsmCtx, {});
}
else if (300 <= vl_eventIdx and vl_eventIdx <= 699)
{
if (300 <= vl_eventIdx and vl_eventIdx <= 399)
{
f_EPTF_COAP_dispatchEvent(c_COAP_eventIdx_3xx, pl_eIdx, pl_fsmCtx, {});
}
else if (400 <= vl_eventIdx and vl_eventIdx <= 499)
{
f_EPTF_COAP_dispatchEvent(c_COAP_eventIdx_4xx, pl_eIdx, pl_fsmCtx, {});
}
else if (500 <= vl_eventIdx and vl_eventIdx <= 599)
{
f_EPTF_COAP_dispatchEvent(c_COAP_eventIdx_4xx, pl_eIdx, pl_fsmCtx, {});
}
f_EPTF_COAP_dispatchEvent(c_COAP_eventIdx_3xxto6xx, pl_eIdx, pl_fsmCtx, {});
}
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_dispatchEvent
//
// Purpose:
// Wrapper for CLL's <f_EPTF_LGenBase_postEvent> to handle multi level event (generic, entity, FSM) reporting
//
// Parameters:
// pl_eventIdx - *in* *integer* - index of the vent to be reported
// pl_eIdx - *in* *integer* - the index of the entity, in case it's -1 the reported event will be *generic* level
// pl_fsmCtx - *in* *integer* - the index of FSM, , in case it's -1 the reported event will be *entity* level
// pl_reportedArgs - *in* <EPTF_IntegerList> - additional arguments to be reported to the entity/FSM
//
// Related Types:
// <EPTF_COAP_LGen_CT>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_dispatchEvent(in integer pl_eventIdx, in integer pl_eIdx, in integer pl_fsmCtx, in EPTF_IntegerList pl_reportedArgs)
runs on EPTF_COAP_LGen_CT
{
if (pl_eIdx < 0)
{
f_EPTF_LGenBase_postEvent(
{
{
v_COAP_bIdx,
pl_eventIdx,
omit,
omit
},
pl_reportedArgs
});
}
else
{
if (pl_fsmCtx < 0)
{
f_EPTF_LGenBase_postEvent(
{
{
v_COAP_bIdx,
pl_eventIdx,
{
pl_eIdx,
omit
}, omit
},
pl_reportedArgs
});
}
else
{
f_EPTF_LGenBase_postEvent(
{
{
v_COAP_bIdx,
pl_eventIdx,
{
pl_eIdx,
pl_fsmCtx
}, omit
},
pl_reportedArgs
});
}
}
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_isEmpty
//
// Purpose:
// Checks if the COAP PDU is empty
//
// Parameters:
// p_pdu - *in* <CoAP_ReqResp> - COAP PDU to be checked
//
// Returns:
// *boolean* - true in case the COAP PDU is empty
///////////////////////////////////////////////////////////
function f_EPTF_COAP_isEmpty(in CoAP_ReqResp p_pdu)
return boolean
{
if (p_pdu.header.code.class == 0 and
p_pdu.header.code.detail == 0) {
return true;
}
return false;
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_isRequest
//
// Purpose:
// Checks if the COAP PDU is a request
//
// Parameters:
// p_pdu - *in* <CoAP_ReqResp> - COAP PDU to be checked
//
// Returns:
// *boolean* - true in case the COAP PDU is a request
///////////////////////////////////////////////////////////
function f_EPTF_COAP_isRequest(in CoAP_ReqResp p_pdu)
return boolean
{
if (p_pdu.header.code.class == 0 and
p_pdu.header.code.detail > 0) {
return true;
}
return false;
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_isResponse
//
// Purpose:
// Checks if the COAP PDU is a response
//
// Parameters:
// p_pdu - *in* <CoAP_ReqResp> - COAP PDU to be checked
//
// Returns:
// *boolean* - true in case the COAP PDU is a response
///////////////////////////////////////////////////////////
function f_EPTF_COAP_isResponse(in CoAP_ReqResp p_pdu)
return boolean
{
if (p_pdu.header.code.class > 0) {
return true;
}
return false;
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_hasObserve
//
// Purpose:
// Checks if the COAP PDU has an OBSERVE option
//
// Parameters:
// p_pdu - *in* <CoAP_ReqResp> - COAP PDU to be checked
//
// Returns:
// *integer* - index of the observe option in case the COAP PDU has an OBSERVE option
///////////////////////////////////////////////////////////
function f_EPTF_COAP_hasObserve(in CoAP_ReqResp p_pdu)
return integer
{
for (var integer i:=0; i<sizeof(p_pdu.options); i:=i+1) {
if (ischosen(p_pdu.options[i].observe)) {
return i;
}
}
return -1;
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_hasBlock1
//
// Purpose:
// Checks if the COAP PDU has a BLOCK1 option
//
// Parameters:
// p_pdu - *in* <CoAP_ReqResp> - COAP PDU to be checked
//
// Returns:
// *integer* - index of the block1 option in case the COAP PDU has a BLOCK1 option
///////////////////////////////////////////////////////////
function f_EPTF_COAP_hasBlock1(in CoAP_ReqResp p_pdu)
return integer
{
for (var integer i:=0; i<sizeof(p_pdu.options); i:=i+1) {
if (ischosen(p_pdu.options[i].block1)) {
return i;
}
}
return -1;
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_isReset
//
// Purpose:
// Checks if the COAP PDU is a RST
//
// Parameters:
// p_pdu - *in* <CoAP_ReqResp> - COAP PDU to be checked
//
// Returns:
// *boolean* - true in case the COAP PDU is a RST
///////////////////////////////////////////////////////////
function f_EPTF_COAP_isReset(in CoAP_ReqResp p_pdu)
return boolean
{
if (p_pdu.header.msg_type == RESET) {
return true;
}
return false;
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_uriPathToString
//
// Purpose:
// Converts the uri path of the COAP PDU into one string using "/" as delimiter
//
// Parameters:
// p_pdu - *in* <CoAP_ReqResp> - COAP PDU
//
// Returns:
// *charstring* - uri path of the COAP PDU in one string using "/" as delimiter
///////////////////////////////////////////////////////////
function f_EPTF_COAP_uriPathToString(in CoAP_ReqResp p_pdu)
return charstring
{
var charstring v_ret := "";
for (var integer i:=0; i<sizeof(p_pdu.options); i:=i+1)
{
if (ischosen(p_pdu.options[i].uri_path)) {
v_ret := v_ret & "/" & oct2char(unichar2oct(p_pdu.options[i].uri_path));
}
}
return v_ret;
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_fetchUriPath
//
// Purpose:
// Fetches the uri path of the COAP PDU
//
// Parameters:
// p_pdu - *in* <CoAP_ReqResp> - COAP PDU
//
// Returns:
// *charstring* - uri path of the COAP PDU in one string using "/" as delimiter
///////////////////////////////////////////////////////////
function f_EPTF_COAP_fetchUriPath(in CoAP_ReqResp p_pdu)
return UriPath_List
{
var UriPath_List v_ret := {};
for (var integer i:=0; i<sizeof(p_pdu.options); i:=i+1)
{
if (ischosen(p_pdu.options[i].uri_path)) {
v_ret[sizeof(v_ret)] := p_pdu.options[i].uri_path;
}
}
return v_ret;
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_fetchContentFormat
//
// Purpose:
// Fetches the content format of the COAP PDU
//
// Parameters:
// p_pdu - *in* <CoAP_ReqResp> - COAP PDU
//
// Returns:
// *integer* - content format of the COAP PDU
///////////////////////////////////////////////////////////
function f_EPTF_COAP_fetchContentFormat(in CoAP_ReqResp p_pdu)
return integer
{
for (var integer i:=0; i<sizeof(p_pdu.options); i:=i+1)
{
if (ischosen(p_pdu.options[i].content_format)) {
return p_pdu.options[i].content_format;
}
}
return -1;
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_addOption
//
// Purpose:
// Adds <CoAP_Options> options to a the COAP PDU
//
// Parameters:
// p_pdu - *inout* <CoAP_ReqResp> - COAP PDU
// p_option - *in* <CoAP_Options> - COAP options to be added
///////////////////////////////////////////////////////////
function f_EPTF_COAP_addOption(inout CoAP_ReqResp p_coap, in CoAP_Options p_option)
{
if (not ispresent(p_coap.options)) { p_coap.options := {} }
p_coap.options[sizeof(p_coap.options)] := p_option;
}
function f_EPTF_COAP_updateMessageStatistics(inout EPTF_COAP_Message_Statistics p_stats, in EPTF_COAP_PDU p_pdu)
{
// request
if (p_pdu.pdu.header.code.class == 0)
{
// empty
if (p_pdu.pdu.header.code.detail == 0) { p_stats.noEMPTY := p_stats.noEMPTY + 1; }
// GET
else if (p_pdu.pdu.header.code.detail == 1) { p_stats.noGET := p_stats.noGET + 1; }
// POST
else if (p_pdu.pdu.header.code.detail == 2) { p_stats.noPOST := p_stats.noPOST + 1; }
// PUT
else if (p_pdu.pdu.header.code.detail == 3) { p_stats.noPUT := p_stats.noPUT + 1; }
// DELETE
else if (p_pdu.pdu.header.code.detail == 4) { p_stats.noDELETE := p_stats.noDELETE + 1; }
}
// positive response
else if (p_pdu.pdu.header.code.class == 2) { p_stats.noPosResp := p_stats.noPosResp + 1; }
// negative response
else if (p_pdu.pdu.header.code.class >= 3) { p_stats.noNegResp := p_stats.noNegResp + 1; }
if (p_pdu.pdu.header.msg_type == CONFIRMABLE) { p_stats.noCON := p_stats.noCON + 1; }
else if (p_pdu.pdu.header.msg_type == NON_CONFIRMABLE) { p_stats.noNON := p_stats.noNON + 1; }
else if (p_pdu.pdu.header.msg_type == ACKNOWLEDGEMENT) { p_stats.noACK := p_stats.noACK + 1; }
else if (p_pdu.pdu.header.msg_type == RESET) { p_stats.noRST := p_stats.noRST + 1; }
}
template CoAP_ReqResp t_CoAP_EmptyAck :=
{
header :=
{
version := 1,
msg_type := ACKNOWLEDGEMENT,
code := EMPTY_MESSAGE,
message_id := 0
},
token := ''O,
options := omit,
payload := omit
}
}