diff options
author | eantwuh | 2019-08-27 12:39:51 +0000 |
---|---|---|
committer | eantwuh | 2019-08-27 12:39:51 +0000 |
commit | aff5c15f93027f474677da02e5a439f247b12c9f (patch) | |
tree | 2a3f6cd082a49d8605c9e81399ecaae6325f187b | |
parent | bef30e21181de5c712abf21bcba60ffb2ea00e61 (diff) | |
download | titan.ApplicationLibraries.CoAP-aff5c15f93027f474677da02e5a439f247b12c9f.tar.gz titan.ApplicationLibraries.CoAP-aff5c15f93027f474677da02e5a439f247b12c9f.tar.xz titan.ApplicationLibraries.CoAP-aff5c15f93027f474677da02e5a439f247b12c9f.zip |
block1 transfer added
Signed-off-by: eantwuh <antal.wu-hen-chang@ericsson.com>
-rw-r--r-- | src/EPTF_COAP_LGen_Definitions.ttcn | 386 | ||||
-rw-r--r-- | src/EPTF_COAP_LGen_Functions.ttcn | 1036 | ||||
-rw-r--r-- | test/EPTF_COAP_Tests.cfg | 16 | ||||
-rw-r--r-- | test/EPTF_COAP_Tests.ttcn | 793 |
4 files changed, 2064 insertions, 167 deletions
diff --git a/src/EPTF_COAP_LGen_Definitions.ttcn b/src/EPTF_COAP_LGen_Definitions.ttcn index c97fe18..6e624b0 100644 --- a/src/EPTF_COAP_LGen_Definitions.ttcn +++ b/src/EPTF_COAP_LGen_Definitions.ttcn @@ -11,7 +11,7 @@ // Description: // Rev: R1A // Prodnr: CNL 113 858 -// Updated: 2017-09-01 +// Updated: 2019-08-27 // Contact: http://ttcn.ericsson.se /////////////////////////////////////////////////////////////////////////////// @@ -197,6 +197,21 @@ module EPTF_COAP_LGen_Definitions /////////////////////////////////////////////////////////// modulepar float tsp_EPTF_COAP_EXCHANGE_LIFETIME := 247.0; + /////////////////////////////////////////////////////////// + // Module parameter: tsp_EPTF_COAP_BlockwiseTransfer_collectContent + // + // Purpose: + // Enables/disables collecting the content of a blockwise transfer. + // Can casue overload in case of high traffic and large transfers when enabled + // + // Type: + // *float* + // + // Default value: + // *247.0* + /////////////////////////////////////////////////////////// + modulepar boolean tsp_EPTF_COAP_BlockwiseTransfer_collectContent := false; + const integer c_COAP_LGen_Logging_WARNING := 0; const integer c_COAP_LGen_Logging_DEBUG := 1; const integer c_COAP_LGen_Logging_DEBUGV := 2; @@ -211,6 +226,7 @@ module EPTF_COAP_LGen_Definitions const charstring c_COAP_behaviorType := "COAP Behavior"; type record of integer COAP_ObservedResourceIdx_List; + type record of integer COAP_BlockwiseIdx_List; /***************************************************************** @@ -500,6 +516,7 @@ module EPTF_COAP_LGen_Definitions // reportCoapEvent - *boolean* - COAP events (e.g. COAP GET, COAP 200 will be reported for this entity), should be false when using LwM2M applib // confirmableNotification - *boolean* - CON transactions will be used for sending nitifications when this field is set to true // observedResourceIndices - <COAP_ObservedResourceIdx_List> - pointers to all observed resources in *v_COAP_observedResourceDB* + // blockwiseIndices - <COAP_BlockwiseIdx_List> - pointers to the running blockwise FSMs in *v_COAP_blockwiseDB* // // Related Functions: // - <f_EPTF_COAP_getNextMID> (in <COAP_StepCtx> p_ctx) @@ -517,7 +534,10 @@ module EPTF_COAP_LGen_Definitions integer nextToken, boolean reportCoapEvent, boolean confirmableNotification, - COAP_ObservedResourceIdx_List observedResourceIndices // FIXME: Can be slow to update in case of larger nums + integer preferredBlocksize optional, + COAP_ObservedResourceIdx_List observedResourceIndices, // FIXME: Can be slow to update in case of larger nums + COAP_BlockwiseIdx_List blockwiseIndices // FIXME: Can be slow to update in case of larger nums + } const COAP_EntityCtx c_COAP_EntityCtx_init := @@ -528,7 +548,9 @@ module EPTF_COAP_LGen_Definitions nextToken := -1, reportCoapEvent := true, confirmableNotification := false, - observedResourceIndices := {} + preferredBlocksize := omit, + observedResourceIndices := {}, + blockwiseIndices := {} } /////////////////////////////////////////////////////////// @@ -1479,6 +1501,125 @@ module EPTF_COAP_LGen_Definitions } /////////////////////////////////////////////////////////// + // Type: COAP_Blockwise_Transfer + // + // Purpose: + // Represents a stateful blockwise transfer + // + // Class: + // (see EPTF_COAP_LGen_Definitions.COAP_Blockwise_Transfer.jpg) + // + // Elements: + // localAddress - *charstring* - local address of the resource + // localPort - *integer* - remote port of the observer + // remoteAddress - *charstring* - address of the observer + // remotePort - *integer* - remote port of the observer + // resourceId - *charstring* - id of the observed resource + // eCtxIdx - *integer* - pointer to the notifications <COAP_RR> + // lastBlock1Option - <BlockOption> - last received Block1 option + // headerCode - <Code> - the COAP header code + // contentFormat - *integer* - content format + // + // Related Functions: + // - <f_EPTF_COAP_BlockwiseTransfer_in> (in *integer* p_bsIdx, inout <EPTF_COAP_PDU> p_msg) + /////////////////////////////////////////////////////////// + type record COAP_Blockwise_Transfer + { + charstring localAddress, + integer localPort, + charstring remoteAddress, + integer remotePort, + UriPath_List uriPath, + charstring resourceId, + integer eIdx, + integer fsmIdx, + integer lifetimeTimer, + boolean ongoingBlocksizeChange, + BlockOption lastBlock1Option, + Code headerCode, + integer contentFormat, + octetstring content + } + + const COAP_Blockwise_Transfer c_COAP_Blockwise_Transfer_init := + { + localAddress := "", + localPort := -1, + remoteAddress := "", + remotePort := -1, + uriPath := {}, + resourceId := "", + eIdx := -1, + fsmIdx := -1, + lifetimeTimer := -1, + ongoingBlocksizeChange := false, + lastBlock1Option := c_BlockOption_empty, + headerCode := { 0, 2 }, + contentFormat := -1, + content := ''O + } + + const BlockOption c_BlockOption_empty := + { + num := 0, + m := false, + szx := 1 + } + + /////////////////////////////////////////////////////////// + // Type: COAP_Blockwise_Transfer_List + // + // Purpose: + // List of <COAP_Blockwise_Transfer> + /////////////////////////////////////////////////////////// + type record of COAP_Blockwise_Transfer COAP_Blockwise_Transfer_List; + + /***************************************************************** + @startuml EPTF_COAP_LGen_Definitions.COAP_Blockwise_DB.jpg + class COAP_Blockwise_DB { + EPTF_FreeBusyQueue queue, + COAP_Blockwise_Server_List data, + integer hashRef + f_EPTF_COAP_blockwiseDB_init() + f_EPTF_COAP_blockwiseDB_add(in COAP_Blockwise_Transfer p_bt) + f_EPTF_COAP_blockwiseDB_lookUp(in charstring p_remoteAddr, in integer p_remotePort, in charstring p_resId) + f_EPTF_COAP_blockwiseDB_get(in integer p_idx, inout COAP_Blockwise_Transfer p_bt) + f_EPTF_COAP_blockwiseDB_remove(in integer p_idx) + f_EPTF_COAP_blockwiseDB_cleanUp() + f_EPTF_COAP_blockwiseDB_tokenHash(in charstring p_remoteAddr, in integer p_remotePort, in charstring p_resId) + } + @enduml + ******************************************************************/ + /////////////////////////////////////////////////////////// + // Type: COAP_Blockwise_DB + // + // Purpose: + // Storing <COAP_Blockwise_Transfer> instances + // + // Class: + // (see EPTF_COAP_LGen_Definitions.COAP_Blockwise_DB.jpg) + // + // Elements: + // data - <COAP_Blockwise_Transfer_List> - elements + // + // Related Functions: + // - <f_EPTF_COAP_blockwiseDB_init> () + // - <f_EPTF_COAP_blockwiseDB_add> (in <COAP_Blockwise_Transfer> p_bt) + // - <f_EPTF_COAP_blockwiseDB_lookUp> (in *charstring* p_remoteAddr, in *integer* p_remotePort, in *charstring* p_resId) + // - <f_EPTF_COAP_blockwiseDB_get> (in *integer* p_idx, inout <COAP_Blockwise_Transfer> p_bt) + // - <f_EPTF_COAP_blockwiseDB_remove> (in *integer* p_idx) + // - <f_EPTF_COAP_blockwiseDB_cleanUp> () + // - <f_EPTF_COAP_blcokwiseDB_tokenHash> (in *charstring* p_remoteAddr, in *integer* p_remotePort, in *charstring* p_resId) + /////////////////////////////////////////////////////////// + type record COAP_Blockwise_DB + { + EPTF_FreeBusyQueue queue, + COAP_Blockwise_Transfer_List data, + integer hashRef, + boolean collectContent + } + + /////////////////////////////////////////////////////////// // Type: fcb_EPTF_COAP_messageReceived // // Purpose: @@ -1486,9 +1627,10 @@ module EPTF_COAP_LGen_Definitions // // Elements: // pl_message - *in* <EPTF_COAP_PDU> - received COAP message - // p_duplicate - *in* <EPTF_COAP_PDU> - flag, when true, indicates a duplicate message + // p_duplicate - *in* *boolean* - flag, when true, indicates a duplicate message + // p_autoHandled - *in* *boolean* - flag, when true, indicates an automatically and the - by the stack - already handled message /////////////////////////////////////////////////////////// - type function fcb_EPTF_COAP_messageReceived(in EPTF_COAP_PDU pl_message, in boolean p_duplicate) runs on self; + type function fcb_EPTF_COAP_messageReceived(in EPTF_COAP_PDU pl_message, in boolean p_duplicate, in boolean p_autoHandled) runs on self; /////////////////////////////////////////////////////////// // Type: fcb_EPTF_COAP_eventIndication @@ -1511,7 +1653,7 @@ module EPTF_COAP_LGen_Definitions // pl_rtt - *in* *float* - received round-trip time measurements /////////////////////////////////////////////////////////// type function fcb_EPTF_COAP_rttIndication(in float pl_rtt) runs on self; - + /////////////////////////////////////////////////////////// // Type: EPTF_COAP_EventDescriptor // @@ -1520,10 +1662,12 @@ module EPTF_COAP_LGen_Definitions // // Elements: // resourceNotObserved - <EPTF_COAP_ResourceNotObserved_Event> - event that indicates that a resource is not observed any more + // atomicBlock1Finished - <EPTF_COAP_AtomicBlock1Finished_Event> - event that indicates that an atomic block1 transfer is finished /////////////////////////////////////////////////////////// type union EPTF_COAP_EventDescriptor { - EPTF_COAP_ResourceNotObserved_Event resourceNotObserved + EPTF_COAP_ResourceNotObserved_Event resourceNotObserved, + EPTF_COAP_AtomicBlock1Finished_Event atomicBlock1Finished } /////////////////////////////////////////////////////////// @@ -1540,7 +1684,28 @@ module EPTF_COAP_LGen_Definitions { integer eIdx, UriPath_List uriPath - } + } + + /////////////////////////////////////////////////////////// + // Type: EPTF_COAP_AtomicBlock1Finished_Event + // + // Purpose: + // Describes an event which indicates that a particular atomic block1 operation was finished + // + // Elements: + // eIdx - *integer* - entity index + // uriPath - <UriPath_List> - the URI of the resource + // method - <Code> - COAP request code for the atomic block1 operation + // contentFormat - *integer* - content format of the block1 transfer + /////////////////////////////////////////////////////////// + type record EPTF_COAP_AtomicBlock1Finished_Event + { + integer eIdx, + UriPath_List uriPath, + Code method, + integer contentFormat, + octetstring content + } /***************************************************************** @startuml EPTF_COAP_LGen_Definitions.EPTF_COAP_LGen_Statistics.jpg @@ -1563,19 +1728,111 @@ module EPTF_COAP_LGen_Definitions // noRetransmissions - *integer* - number of COAP message retransmissions // noTransactionTimeouts - *integer* - number of timed out COAP transactions // noDuplicates - *integer* - number of duplicated messages received + // noObserves - *integer* - number of observes + // block1 - <EPTF_COAP_Block1_Statistics> - Block1 related statistics + // incoming - <EPTF_COAP_Message_Statistics> - statistics of incoming messages + // outgoing - <EPTF_COAP_Message_Statistics> - statistics of outgoing messages /////////////////////////////////////////////////////////// type record EPTF_COAP_LGen_Statistics { integer noRetransmissions, integer noTransactionTimeouts, - integer noDuplicates + integer noDuplicates, + integer noObserves, + EPTF_COAP_Block1_Statistics block1, + EPTF_COAP_Message_Statistics incoming, + EPTF_COAP_Message_Statistics outgoing } const EPTF_COAP_LGen_Statistics c_EPTF_COAP_LGen_Statistics_empty := { noRetransmissions := 0, noTransactionTimeouts := 0, - noDuplicates := 0 + noDuplicates := 0, + noObserves := 0, + block1 := c_EPTF_COAP_Block1_Statistics_empty, + incoming := c_EPTF_COAP_Message_Statistics_empty, + outgoing := c_EPTF_COAP_Message_Statistics_empty + } + + /////////////////////////////////////////////////////////// + // Type: EPTF_COAP_Block1_Statistics + // + // Purpose: + // Storing counters for block1 related statistics + // + // Elements: + // noBlocks - *integer* - number of block1 blocks received + // noAtomicSucc - *integer* - number of succesfully finished atomic blockwise transfers + // noAtomicUnsucc - *integer* - number of unsuccesfully finished atomic blockwise transfers + // noAtomicTimeouts - *integer* - number of timed out atomic blockwise transfers + /////////////////////////////////////////////////////////// + type record EPTF_COAP_Block1_Statistics + { + integer noBlocks, + integer noAtomicSucc, + integer noAtomicUnsucc, + integer noAtomicTimeouts + } + + const EPTF_COAP_Block1_Statistics c_EPTF_COAP_Block1_Statistics_empty := + { + noBlocks := 0, + noAtomicSucc := 0, + noAtomicUnsucc := 0, + noAtomicTimeouts := 0 + } + + /////////////////////////////////////////////////////////// + // Type: EPTF_COAP_Message_Statistics + // + // Purpose: + // Storing counters for message related statistics + // + // Elements: + // noGET - *integer* - number of GET requests + // noPUT - *integer* - number of PUT request + // noPOST - *integer* - number of POST request + // noDELETE - *integer* - number of DELETE requests + // noEMPTY - *integer* - number of EMPTY requests + // noPosResp - *integer* - number of positive (2.xx) repsonses + // noNegResp - *integer* - number of negative (3.xx - 6.xx) repsonses + // noCON - *integer* - number of CONFIRMABLE messages + // noNON - *integer* - number of NON CONFIRMABLE messages + // noACK - *integer* - number of ACKNOWLEDGEMENT messages + // noRST - *integer* - number of RESET messages + // noNotifications - *integer* of NOTIFICATION messages + /////////////////////////////////////////////////////////// + type record EPTF_COAP_Message_Statistics + { + integer noGET, + integer noPUT, + integer noPOST, + integer noDELETE, + integer noEMPTY, + integer noPosResp, + integer noNegResp, + integer noCON, + integer noNON, + integer noACK, + integer noRST, + integer noNotifications + } + + const EPTF_COAP_Message_Statistics c_EPTF_COAP_Message_Statistics_empty := + { + noGET := 0, + noPUT := 0, + noPOST := 0, + noDELETE := 0, + noEMPTY := 0, + noPosResp := 0, + noNegResp := 0, + noCON := 0, + noNON := 0, + noACK := 0, + noRST := 0, + noNotifications := 0 } /***************************************************************** @@ -1643,6 +1900,7 @@ module EPTF_COAP_LGen_Definitions // v_COAP_initialized - *boolean* - Flag to indicate that if init function was already called // v_COAP_bIdx - *integer* - Name of the NAS_EPS LGen component // v_COAP_loggingMaskId - *integer* - logging mask id <COAP_EntityCtx> + // v_COAP_Stack_autoHandled - *boolean* - the stack can automatically handle particular messages (e.g. Block1 requests), true when handled, false when not // // v_COAP_ctx - <COAP_StepCtx> - collection of the most important pointers // v_COAP_transportEndpoint - <COAP_TransportEndpoint> - variable for a transport endpoint @@ -1700,7 +1958,9 @@ module EPTF_COAP_LGen_Definitions var COAP_Template_DB v_COAP_templateDB := {}; var COAP_Observation_DB v_COAP_observationDB; var COAP_ObservedResource_DB v_COAP_observedResourceDB; - + var COAP_Blockwise_DB v_COAP_blockwiseDB; + var boolean v_COAP_Stack_autoHandled := false; + var COAP_StepCtx v_COAP_ctx := c_COAP_StepCtx_empty; var COAP_TransportEndpoint v_COAP_transportEndpoint := c_COAP_TransportEndpoint_empty; @@ -2041,7 +2301,87 @@ module EPTF_COAP_LGen_Definitions // Charstring constant for the COAP transport DTLS connection closed indication /////////////////////////////////////////////////////////// const charstring c_COAP_eventName_dtlsConnectionClosed := "COAP transport: DTLS connection closed"; - + + /////////////////////////////////////////////////////////// + // const: c_COAP_eventIdx_BLOCK1_init + // + // Purpose: + // Integer constant for the initial (num=0) Block1 request indication + /////////////////////////////////////////////////////////// + const integer c_COAP_eventIdx_BLOCK1_init := 714; + + /////////////////////////////////////////////////////////// + // const: c_COAP_eventName_BLOCK1_init + // + // Purpose: + // Charstring constant for the initial (num=0) Block1 request indication + /////////////////////////////////////////////////////////// + const charstring c_COAP_eventName_BLOCK1_init := "COAP block1: first block indication"; + + /////////////////////////////////////////////////////////// + // const: c_COAP_eventIdx_BLOCK1_block + // + // Purpose: + // Integer constant for Block1 request indication (not first, not last) + /////////////////////////////////////////////////////////// + const integer c_COAP_eventIdx_BLOCK1_block := 715; + + /////////////////////////////////////////////////////////// + // const: c_COAP_eventName_BLOCK1_block + // + // Purpose: + // Charstring constant for Block1 request indication + /////////////////////////////////////////////////////////// + const charstring c_COAP_eventName_BLOCK1_block := "COAP block1: block indication"; + + /////////////////////////////////////////////////////////// + // const: c_COAP_eventIdx_BLOCK1_last + // + // Purpose: + // Integer constant for the last Block1 request indication + /////////////////////////////////////////////////////////// + const integer c_COAP_eventIdx_BLOCK1_last := 716 + + /////////////////////////////////////////////////////////// + // const: c_COAP_eventName_BLOCK1_last + // + // Purpose: + // Charstring constant for the last Block1 request indication + /////////////////////////////////////////////////////////// + const charstring c_COAP_eventName_BLOCK1_last := "COAP block1: last block indication"; + + /////////////////////////////////////////////////////////// + // const: c_COAP_eventIdx_BLOCK1_atomic_succ + // + // Purpose: + // Integer constant for indicating that the atomic block1 transfer was succesfully finished + /////////////////////////////////////////////////////////// + const integer c_COAP_eventIdx_BLOCK1_atomic_succ := 717 + + /////////////////////////////////////////////////////////// + // const: c_COAP_eventName_BLOCK1_atomic_succ + // + // Purpose: + // Charstring constant for indicating that the atomic block1 transfer was succesfully finished + /////////////////////////////////////////////////////////// + const charstring c_COAP_eventName_BLOCK1_atomic_succ := "COAP block1: atomic succesfully finished"; + + /////////////////////////////////////////////////////////// + // const: c_COAP_eventIdx_BLOCK1_atomic_fail + // + // Purpose: + // Integer constant for indicating that the atomic block1 transfer was unsuccesfully finished + /////////////////////////////////////////////////////////// + const integer c_COAP_eventIdx_BLOCK1_atomic_fail := 718 + + /////////////////////////////////////////////////////////// + // const: c_COAP_eventName_BLOCK1_atomic_fail + // + // Purpose: + // Charstring constant for indicating that the atomic block1 transfer was succesfully finished + /////////////////////////////////////////////////////////// + const charstring c_COAP_eventName_BLOCK1_atomic_fail := "COAP block1: atomic unsuccesfully finished"; + // Steps /////////////////////////////////////////////////////////// @@ -2506,6 +2846,28 @@ module EPTF_COAP_LGen_Definitions /////////////////////////////////////////////////////////// const charstring c_COAP_stepName_confirmableNotificationForEntity := "COAP Applib: confirmableNotificationForEntity"; + /////////////////////////////////////////////////////////// + // const: c_COAP_stepIdx_setPreferredBlocksize + // + // Purpose: + // Integer constant for the COAP setPreferredBlocksize test step + // + // Related Function: + // - <f_COAP_step_setPreferredBlocksize> + /////////////////////////////////////////////////////////// + const integer c_COAP_stepIdx_setPreferredBlocksize := 21; + + /////////////////////////////////////////////////////////// + // const: c_COAP_stepName_setPreferredBlocksize + // + // Purpose: + // Charstring constant for the COAP setPreferredBlocksize step + // + // Related Function: + // - <f_COAP_step_setPreferredBlocksize> + /////////////////////////////////////////////////////////// + const charstring c_COAP_stepName_setPreferredBlocksize := "COAP Applib: setPreferredBlocksize"; + // Step parameters: const integer c_COAP_stepParam_true := 1; diff --git a/src/EPTF_COAP_LGen_Functions.ttcn b/src/EPTF_COAP_LGen_Functions.ttcn index 29db6a7..3e9a718 100644 --- a/src/EPTF_COAP_LGen_Functions.ttcn +++ b/src/EPTF_COAP_LGen_Functions.ttcn @@ -11,7 +11,7 @@ // Description: // Rev: R1A // Prodnr: CNL 113 858 -// Updated: 2017-09-01 +// Updated: 2019-08-27 // Contact: http://ttcn.ericsson.se /////////////////////////////////////////////////////////////////////////////// @@ -86,8 +86,9 @@ module EPTF_COAP_LGen_Functions f_EPTF_COAP_trDB_init(); f_EPTF_COAP_rrDB_init(); f_EPTF_COAP_templateDB_init(); - f_EPTF_COAP_observedResourceDB_init(); + f_EPTF_COAP_observedResourceDB_init(); f_EPTF_COAP_observationDB_init(); + f_EPTF_COAP_blockwiseDB_init(); f_EPTF_COAP_declareSteps(); f_EPTF_COAP_declareEvents(); @@ -150,8 +151,9 @@ module EPTF_COAP_LGen_Functions f_EPTF_COAP_trDB_cleanUp(); f_EPTF_COAP_rrDB_cleanUp(); f_EPTF_COAP_templateDB_cleanUp(); - f_EPTF_COAP_observedResourceDB_cleanUp(); + f_EPTF_COAP_observedResourceDB_cleanUp(); f_EPTF_COAP_observationDB_cleanUp(); + f_EPTF_COAP_blockwiseDB_cleanUp(); vf_COAP_msgReceived := null; vf_COAP_eventIndication := null; @@ -632,7 +634,7 @@ module EPTF_COAP_LGen_Functions 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), v_idx + 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; @@ -658,14 +660,14 @@ module EPTF_COAP_LGen_Functions // Related Type: // <COAP_Observation_DB> /////////////////////////////////////////////////////////// - function f_EPTF_COAP_observationDB_lookUp(in charstring p_remoteAddr, in integer p_remotePort, in charstring p_resId) + 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), vl_idx + f_EPTF_COAP_observationDB_tokenHash(p_remoteAddr, p_remotePort, p_resId, p_resIdx), vl_idx ); return vl_idx; } @@ -714,7 +716,8 @@ module EPTF_COAP_LGen_Functions 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].resourceId, + v_COAP_observationDB.data[p_idx].observedResourceIdx ) ); @@ -743,7 +746,7 @@ module EPTF_COAP_LGen_Functions // Function: f_EPTF_COAP_observationDB_tokenHash // // Purpose: - // Hash function for lookups used by the *v_COAP_rrDB* <COAP_RR_DB> database + // 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 @@ -754,12 +757,184 @@ module EPTF_COAP_LGen_Functions // *charstring* - string hash unique of a <COAP_Observation_Server> element // // Related Type: - // <COAP_RR_DB> + // <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_observationDB_tokenHash(in charstring p_remoteAddr, in integer p_remotePort, in charstring p_resId) + // 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_remoteAddr&":"&int2str(p_remotePort)&p_resId; + return p_localAddr&":"&int2str(p_localPort)&p_resId; } /////////////////////////////////////////////////////////// @@ -1319,6 +1494,8 @@ module EPTF_COAP_LGen_Functions 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) { @@ -1327,7 +1504,7 @@ module EPTF_COAP_LGen_Functions if (vf_COAP_msgReceived != null) { - vf_COAP_msgReceived.apply(v_COAP_msgToProcess, v_duplicate); + vf_COAP_msgReceived.apply(v_COAP_msgToProcess, v_duplicate, v_COAP_Stack_autoHandled); } } @@ -1481,6 +1658,9 @@ module EPTF_COAP_LGen_Functions 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) @@ -1571,7 +1751,7 @@ module EPTF_COAP_LGen_Functions 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); @@ -1686,42 +1866,10 @@ module EPTF_COAP_LGen_Functions 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); - // 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 subscribe - 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); - - // 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 - ); - - if (vl_observationIdx != -1) - { - f_EPTF_COAP_ObservationServer_cancelReceivedFromEnv(vl_observationIdx); - } - } - } + 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; @@ -1768,43 +1916,11 @@ module EPTF_COAP_LGen_Functions if (v_COAP_rrDB.data[p_rrIdx].trIdx != -1) { p_msg.pdu.token := v_COAP_rrDB.data[p_rrIdx].token; - - // 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 subscribe - 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); - - // 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 - ); - - if (vl_observationIdx != -1) - { - f_EPTF_COAP_ObservationServer_cancelReceivedFromEnv(vl_observationIdx); - } - } - } + 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; @@ -2059,11 +2175,141 @@ module EPTF_COAP_LGen_Functions 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(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(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 @@ -2226,12 +2472,15 @@ module EPTF_COAP_LGen_Functions else { f_EPTF_COAP_dispatchEventForObserve_ifExists(p_msg.pdu, p_msg.eIdx, -1); - f_EPTF_COAP_dispatchEventsForCode( - p_msg.pdu.header.code, - 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 @@ -2259,12 +2508,15 @@ module EPTF_COAP_LGen_Functions else { f_EPTF_COAP_dispatchEventForObserve_ifExists(p_msg.pdu, p_msg.eIdx, -1); - f_EPTF_COAP_dispatchEventsForCode( - p_msg.pdu.header.code, - 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 @@ -2336,6 +2588,40 @@ module EPTF_COAP_LGen_Functions } } + 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 // @@ -2617,8 +2903,11 @@ module EPTF_COAP_LGen_Functions 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); + vf_EPTF_COAP_Transport_send.apply(p_msg); } @@ -2671,11 +2960,215 @@ module EPTF_COAP_LGen_Functions 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(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(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 // @@ -2774,16 +3267,16 @@ module EPTF_COAP_LGen_Functions { // 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) { @@ -2793,13 +3286,15 @@ module EPTF_COAP_LGen_Functions 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; } /////////////////////////////////////////////////////////// @@ -2818,7 +3313,9 @@ module EPTF_COAP_LGen_Functions /////////////////////////////////////////////////////////// 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, @@ -2826,9 +3323,9 @@ module EPTF_COAP_LGen_Functions -1, {} ); } - + var COAP_ObservedResourceIdx_List vl_newList := {}; - + if (p_lastObserver) { // Indicate event to the COAP user layer @@ -2838,7 +3335,7 @@ module EPTF_COAP_LGen_Functions {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) { @@ -2847,10 +3344,10 @@ module EPTF_COAP_LGen_Functions } } 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, @@ -2859,6 +3356,8 @@ module EPTF_COAP_LGen_Functions ); } } + + v_COAP_stats.noObserves := v_COAP_stats.noObserves - 1; } /////////////////////////////////////////////////////////// @@ -2878,10 +3377,10 @@ module EPTF_COAP_LGen_Functions 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) { @@ -2890,10 +3389,111 @@ module EPTF_COAP_LGen_Functions } } 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_cleanUp @@ -2938,12 +3538,13 @@ module EPTF_COAP_LGen_Functions 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 + v_COAP_observedResourceDB.data[p_obsResIdx].resourceId, + p_obsResIdx ); // If we haven't found it, then we need to add this observation @@ -2982,6 +3583,8 @@ module EPTF_COAP_LGen_Functions 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 := {}; @@ -3022,7 +3625,13 @@ module EPTF_COAP_LGen_Functions function f_EPTF_COAP_ObservedResource_sendNotification(in integer p_obsResIdx, inout EPTF_COAP_PDU p_msg) runs on EPTF_COAP_LGen_CT { - if (p_obsResIdx < 0 or p_obsResIdx >= sizeof(v_COAP_observedResourceDB.data)) { return } + 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) { @@ -3072,8 +3681,14 @@ module EPTF_COAP_LGen_Functions function f_EPTF_COAP_ObservationServer_sendNotification(in integer p_obsIdx, inout EPTF_COAP_PDU p_msg) runs on EPTF_COAP_LGen_CT { - if (p_obsIdx < 0 or p_obsIdx >= sizeof(v_COAP_observationDB.data)) { return } - + 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! @@ -3082,29 +3697,29 @@ module EPTF_COAP_LGen_Functions // 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.proto := 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.proto := 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); @@ -3117,12 +3732,14 @@ module EPTF_COAP_LGen_Functions 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!")); @@ -3144,6 +3761,8 @@ module EPTF_COAP_LGen_Functions 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) { @@ -3196,7 +3815,12 @@ module EPTF_COAP_LGen_Functions 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) + 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) ){ f_EPTF_LGenBase_log(); log("f_EPTF_COAP_declareEvents() error at responses"); mtc.stop @@ -3236,7 +3860,8 @@ module EPTF_COAP_LGen_Functions 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)}) + 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(); @@ -4109,7 +4734,7 @@ module EPTF_COAP_LGen_Functions 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)); + f_EPTF_COAP_Logging_DEBUG(log2str(%definitionId,":",p_observedResourceId)); if (not f_EPTF_COAP_setStepCtx(pl_ptr, v_COAP_ctx)) { return; } @@ -4184,26 +4809,63 @@ module EPTF_COAP_LGen_Functions 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_setLocalAddress + // + // 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_setLocalAddress> + // - <c_COAP_stepName_setLocalAddress> + /////////////////////////////////////////////////////////// + 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 // @@ -4402,6 +5064,34 @@ module EPTF_COAP_LGen_Functions } } } + + /////////////////////////////////////////////////////////// + // 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 @@ -4594,7 +5284,7 @@ module EPTF_COAP_LGen_Functions // p_pdu - *in* <CoAP_ReqResp> - COAP PDU to be checked // // Returns: - // *boolean* - true in case the COAP PDU has an OBSERVE option + // *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 @@ -4608,6 +5298,29 @@ module EPTF_COAP_LGen_Functions } /////////////////////////////////////////////////////////// + // 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: @@ -4676,6 +5389,30 @@ module EPTF_COAP_LGen_Functions } } 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; } /////////////////////////////////////////////////////////// @@ -4691,10 +5428,37 @@ module EPTF_COAP_LGen_Functions 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 := diff --git a/test/EPTF_COAP_Tests.cfg b/test/EPTF_COAP_Tests.cfg index 7d0999f..1e0231f 100644 --- a/test/EPTF_COAP_Tests.cfg +++ b/test/EPTF_COAP_Tests.cfg @@ -4,17 +4,17 @@ tsp_addresses := { id := "tester", hostName := "127.0.0.1", - portNumber := 31000 + portNumber := 30000 }, { id := "tester2", hostName := "127.0.0.1", - portNumber := 31001 + portNumber := 30001 }, { id := "sut", hostName := "127.0.0.1", - portNumber := 41000 + portNumber := 40000 } } @@ -44,7 +44,7 @@ LogEntityName := Yes #EndTestCase := "/home/eantwuh/iotsim/cfg/stopTcpDump" [MAIN_CONTROLLER] -TCPPort := 9877 +TCPPort := 9777 KillTimer := 30.0 [TESTPORT_PARAMETERS] @@ -85,3 +85,11 @@ EPTF_COAP_Tests.control //EPTF_COAP_Tests.tc_recv_CON_OBS_send_ACK_200OK_send_Notification_recv_RST //EPTF_COAP_Tests.tc_recv_CON_OBS_send_ACK_200OK_send_Notification_withTwoObservers_recv_RST //EPTF_COAP_Tests.tc_recv_CON_OBS_send_ACK_200OK_send_Notification_recv_Obs1 +// Block1 server +//EPTF_COAP_Tests.tc_recv_CON_block1_send_ACK_404NotFound +//EPTF_COAP_Tests.tc_recv_CON_block1_send_ACK_204Changed_stateless +//EPTF_COAP_Tests.tc_recv_CON_block1_send_ACK_231Continue_atomic_succ +//EPTF_COAP_Tests.tc_recv_CON_block1_send_ACK_231Continue_atomic_fail +//EPTF_COAP_Tests.tc_recv_CON_block1_send_ACK_231Continue_atomic_timeout +//EPTF_COAP_Tests.tc_recv_CON_block1_send_ACK_231Continue_atomic_smaller_blocksize +//EPTF_COAP_Tests.tc_block1_fwug diff --git a/test/EPTF_COAP_Tests.ttcn b/test/EPTF_COAP_Tests.ttcn index a874b1a..0c87bdf 100644 --- a/test/EPTF_COAP_Tests.ttcn +++ b/test/EPTF_COAP_Tests.ttcn @@ -11,7 +11,7 @@ // Description: // Rev: R1A // Prodnr: CNL 113 858 -// Updated: 2017-09-01 +// Updated: 2019-08-27 // Contact: http://ttcn.ericsson.se /////////////////////////////////////////////////////////////////////////////// @@ -121,6 +121,8 @@ module EPTF_COAP_Tests v_tempIdx := f_EPTF_COAP_templateDB_add({id:="t_reg_CON_GET", msg:=valueof(t_reg_CON_GET)}); v_tempIdx := f_EPTF_COAP_templateDB_add({id:="t_reg_Content", msg:=valueof(t_reg_Content)}); v_tempIdx := f_EPTF_COAP_templateDB_add({id:="t_reg_NotFound", msg:=valueof(t_reg_NotFound)}); + v_tempIdx := f_EPTF_COAP_templateDB_add({id:="t_reg_Changed", msg:=valueof(t_reg_Changed)}); + v_tempIdx := f_EPTF_COAP_templateDB_add({id:="t_reg_Continue", msg:=valueof(t_reg_Continue)}); f_EPTF_MBT_initLGenFsm(null, null); EPTF_MBT_PCO.send(EPTF_MBT_CommandResponse:{ ready := {}}) to mtc; @@ -188,7 +190,7 @@ module EPTF_COAP_Tests }, payload := omit } - + template CoAP_ReqResp t_CON_GET_Obs1 := { header := @@ -206,6 +208,110 @@ module EPTF_COAP_Tests }, payload := omit } + + template CoAP_ReqResp t_CON_PUT_Block1(template BlockOption p_block1) := + { + header := + { + version := 1, + msg_type := CONFIRMABLE, + code := METHOD_PUT, + message_id := 0 + }, + token := ''O, + options := + { + { uri_path := "test" }, + { content_format := 11542 }, + { block1 := p_block1 }, + { size1 := 8863 } + }, + payload := 'D000229B504B03041400000008008DA0A64E479244B258010000F0040000130000005B436F6E74656E745F54797065735D2E786D6CAD944D4EC3301085F79C22F216256E5920849A7641610995280730F6A4B1EAD89667FA777B26690B088940D56E6245F67BDFF879ECD164DBB86C0D096DF0A51816039181D7C158BF28C5DBFC29BF131992F246B9E0A1143B4031195F8DE6BB0898B1D863296AA2782F25EA1A1A854588E079A60AA951C4BF6921A3D24BB500793318DC4A1D3C81A79C5A0F311EBD303F5903D94C257A560D63E4D6496237D87F8705FB89EC612F6CD9A550313AAB1571E172EDCD0F6A1EAACA6A3041AF1A96149DCD75EB227F0522ED1CE0D9288C0994C11A801A57EC4D8FE429546AE5287BDCB2FB3EF3040E4FE31DC22C58D9ADC1DAC63E42FF867ED7ADCF0C82F5D3A436DC4A3DA16F425ABE87B0BC74ECED5834CAFABE4367F12C858892516717006D72064C1ED91212D9AF63EF65EB90E074F8B1095AF53F8987B4BB685076C3F0C2B17FFAFF75D56A95C0BC52E2E6B8F88DFBEE7DAC43760FD6F803504B03041400000008008DA0A64E17B63738E90000004B0200000B0000005F72656C732F2E72656C73AD92CD6AC3300C80EF7B0AA37BA3B48531469D5ECAA0B732B207D06CE5872496B1BD2D7DFB7987B105BAD2C38E96A54F9F8476FB791AD53B87D88BD3B02E4A50EC8CD8DEB51A5EEAA7D5'O + } + + template CoAP_ReqResp t_CON_PUT_Block1_FwUg_num0 := + { + header := + { + version := 1, + msg_type := CONFIRMABLE, + code := { class := 0, detail := 3 }, + message_id := 42919 + }, + token := '088042E55D354B17'O, + options := + { + { uri_path := "5" }, + { uri_path := "0" }, + { uri_path := "0" }, + { content_format := 11542 }, + { block1 := { num := 0, m := true, szx := 5 } }, + { size1 := 1889 } + }, + payload := 'D000075D2E8ADE9A2A6CBA6768968AEC8AD6A67AD7289EC79CB5EB6EADA762A62B1C8A781E962B4C6AEAE2B2D8A772276E9ED9A296282E95AB1E76F7ACB626EE96E99EB2D6E26DE9DDBA6AAE8AC36E9656A29EC6A989E9EC7A6A5EADD8A09E2B2C8A6A1D8A87AD8A6A5EADD89EB677AAB9E4AEB297A7762B2C7AEB5DA25A2B76E885BAC71E8A785E9DDADEAE2B5DA25A2B328ADB89AB6EAE98ACB5E9A9BAC96E72DBAC9EE96569EB5F7AE8226AD7A58AD36E9DC7AB6ADBAB9DA7A57A27DE9DDBE2B5A7A2A6CBA6BE2B5A79E95E89F7A776B8689DCBAC7ACB5279D96E72DBAC6E56A7762B5E95E89F7A774F7A595E9ED7ACAAE79EB5CBABB2EB1DA25A2B328ADB8A7BA595A99A8276AD7A6A6EB2779C6AE72DA2BA6569C7AB6AD9A89658ACB22B5A99EB6B8ACBAC0AB6ACBAD99EB6EB1CA27B1E72D7ADBABB2896589C8ADB9D8A79EE9DC69D8A09E2B2C8A68EEB2DA157ACB626EE96E9A275A71CBA6B1A9DDBA2AAE8AC9A895EB2D89EB6EAE98AC0AB6AC89A72E962B2DA2BB68ADEB9EC6F6AB8AEB28AE76AB79279DB1A822B6D8ACA68AEDB62B68AE7BA77229EF7A189CBA56A66A09DA6E26DE9DDBA6B22B5A99EB44B626A69686E8AED8ACB1E99A72589B7ABA1FAE29E08A595A8A6A5EADD89EB42ADAB2779CA6EAEEB2789B8407A779A9EEB5E7DF89C8ADBAB6AB72E3EB69EB1E9EDBDE96F7A58ADAAE8AC6A7B5E7AE8AC9A'O + } + + template CoAP_ReqResp t_CON_PUT_Block1_FwUg_num1 := + { + header := + { + version := 1, + msg_type := CONFIRMABLE, + code := { class := 0, detail := 3 }, + message_id := 42920 + }, + token := '088042E55D354B17'O, + options := + { + { uri_path := "5" }, + { uri_path := "0" }, + { uri_path := "0" }, + { content_format := 11542 }, + { block1 := { num := 1, m := true, szx := 5 } } + }, + payload := '876995A71EADAB42ADAB2D7A6A6EB2F8AF7ABADA99AB2C6ABBADAEE9AD8A772276E9ED7ABA2CB2875A95EB22750BA2B2AB9E7AE8AC9A8769BABBACAAE8AC7A78A6A6E96F8A76ABBAD75AA626EEB268AC71E95EAE2B2AB9E35A9AABA2B2579CB6EB2F7A576E8AE96DAE27227AC95AA2B79EB54B5DBA295EA1CA269A87689E89DEAE8B2779C89A72E962B229ED7AB76E9ADA2BB68AC2ADAB2779C7DAB9C89BBAC95EA05BAC71EA6569C7AB6AD95AA2B79EB68762A27A27BEE969BAD6AD7AC7A68A7B5EADDBA689D42E8ACAAE7A9A2BB6D8ADA2BBA595A99CA2BA5EAE569CBACB22B5A99EB666B18A6BAC9EE9656AD7A6A6EB2C8AD6A67AD0EE8AC7289DD8A67A7B6E9A78AC96C8AD6A67AD7289DD8A67A7B6E99FAE29E08A595A7626A67A58ADA68B2E7AB79AADCBAC8AD6A67ADB5E9A9A2BB1AA627A7B1E99EB666ACB1A4AEB297A7762B2C7A789B85E9E29AF8AF7ABADA7AE99AC629AEB2C79D69C72E9AC6A79E89EDA2BB68AD57ACB626EE96E9A29DEAE8B1CBABB2EB2E9656A6728AE97AB9E26E1BDE95CA27BDA9658AC96282E95A12D89A9A66B18A6BACB2896589C8ADB9D8A77ACB5F8A789BBAC79F7E2722B6EACC6AEAE2B1EB9B95A9DD8AD99AB2C69279DA68AED6A78AC9629E78AC969A2CB9EADE7AEBDAAE2BAC9A27DAB9C89BBAC36E9656AE96DAE27227ACBDAAE2BAC99A82769AA6E96F8A76AB96282E95A9A8965'O + } + + template CoAP_ReqResp t_CON_PUT_Block1_FwUg_num2 := + { + header := + { + version := 1, + msg_type := CONFIRMABLE, + code := { class := 0, detail := 3 }, + message_id := 42921 + }, + token := '088042E55D354B17'O, + options := { + { uri_path := "5" }, + { uri_path := "0" }, + { uri_path := "0" }, + { content_format := 11542 }, + { block1 := { num := 2, m := true, szx := 5 } } + }, + payload := '8AC7DA722962B22B05BAC71EBDE86272E95A99AC629AEB229A97AB7627AD49E76E9656A6728AE97AB8A7B5EADDBA67ABA2C7AE8AC9A876E9656A6728AE97AB31ABAB8ACAAE8ACA6E96F8A76AB7ACB6C79DA2B9DAADE95EA089DEBAD7A6A68AE57A831ABAB8AC69C72E9AC6A795E72DBAC89D6AE82E7A29ED7AB76E99E81EB5E7DF89C8ADBAB99ABAB8AC9686E8AED8AC3E16AC7A596EB1A962AAE6A6A6E96F8A76ABBDE86272E95A4AEB297A7762B2C79F69C8A58AC8AC8A6A5EADD89EB5ABA0B9EB22B5A99EB5A962AAE7AD562BDA9AEB2985AADEB6B69EB678AC89E81EB66A257ACB6278D6A699A82769EAE8B2C7A6A5EAEF7A57A07ACB5AB2779CBDEB2D89BBA5BA67AE76E8889ED7A07ABB2EB1C8A98AD9EE9DC9DE71CA27B1EAAE6AD96E72DBAC31A79C7A76ACB6EAE98AC99A8276A269CBA58ACBADBAB9DA8A77289EC7AAB9AB5F7AE8226AD76E88C6AEAE2B2ABA2B1EC6F8AD69E8A9B2E99CBABB2EB2985AADEB6B6957ACB626EE96E99AB6EAE98AC89DBDE962B617A776B7AB8AD7DEAE67A7B6E98CA2B6E2AE1A2772EB1CA269A876899AB2C6889E9A2BB6D8ADA2B95A72EB2EB5B89B7A776E99A71CBA6B1A9D4B67A279626DEAE8B1E7657A89A895EB2D89E7289EF6A5962B10BA2B2AB9E6E26DE9DDBA6B5E965BAC89DAAE6A67289EC7AAB9AB69A2BB5A36E9656A58A0BA56AB8ACBACB2EB1C8A98ADBAD99ABAB8'O + } + + template CoAP_ReqResp t_CON_PUT_Block1_FwUg_num3 := + { + header := + { + version := 1, + msg_type := CONFIRMABLE, + code := { class := 0, detail := 3 }, + message_id := 42922 + }, + token := '088042E55D354B17'O, + options := + { + { uri_path := "5" }, + { uri_path := "0" }, + { uri_path := "0" }, + { content_format := 11542 }, + { block1 := { num := 3, m := false, szx := 5 } } + }, + payload := 'ACB22B5A99EB5D8A09E2B2C8A6AEEB6BBA6B6EAE98AC328ADB89EB9E962B5A95E72DBACA68B2E7AB79E95E99E9EDBA67AEB1E767BA7703A2779CBEE969BAD6AD79A962AAE6A699A8276AF7A58A6A5EADD89EB40962AAE6A6B1A822B6D8AC7A58ADB1E75FAE29E08A595A7289EC7AAB9AB4FADA7AC7A7B666A57ACB9A75A7A78A6B5E9A9A2B9A28A7B5EADDBA6AEEB6BBA6A5E9657A7B5EB2AB9E9A2A6E96F8A76AB0AEADA6E2B6EAE56A8ADE7AD76272DBA67AE8AC9A874DBA595A89D9A89658AC95A72EB229E985AADEB6B69DA25A2B562BDA9AEB27A27AEEB6BBA69626DEAE8328ADB8A29DD89A99F7AE8226ADBE2BDEAEB6A589B7ABA1A7229ED7AB76E99D89A98D6A6A68AEDB62B68AEC7A67A07AD9A895EB2D89EB629DC89DBA7B489EF8AD69E8A6A5EADD89EB6688EADC8AF6AB8AEB276ADA2AB9EA5E9DAB626EEB1EB666A09E2B1D8ACA5AAEDBAB89E9ED9A89ED7AC9DAB1C7ADBABAE276272E96EB26BA'O + } template CoAP_ReqResp t_reg_Content := { @@ -244,7 +350,39 @@ module EPTF_COAP_Tests }, payload := omit } - + + template CoAP_ReqResp t_reg_Changed := + { + header := + { + version := 1, + msg_type := NON_CONFIRMABLE, + code := RESPONSE_CODE_Changed, + message_id := 0 + }, + token := ''O, + options := + { + }, + payload := omit + } + + template CoAP_ReqResp t_reg_Continue := + { + header := + { + version := 1, + msg_type := NON_CONFIRMABLE, + code := { class := 2, detail := 31 }, + message_id := 0 + }, + token := ''O, + options := + { + }, + payload := omit + } + template CoAP_ReqResp tr_NON_GET := { header := @@ -403,6 +541,56 @@ module EPTF_COAP_Tests }, payload := omit } + + template CoAP_ReqResp tr_Incomplete(Type p_msgType) := + { + header := + { + version := 1, + msg_type := p_msgType, + code := { class := 4, detail := 8}, + message_id := ? + }, + token := ?, + options := + { + }, + payload := omit + } + + template CoAP_ReqResp tr_Changed_withBlock1(Type p_msgType, template BlockOption p_block1) := + { + header := + { + version := 1, + msg_type := p_msgType, + code := RESPONSE_CODE_Changed, + message_id := ? + }, + token := ?, + options := + { + { block1 := p_block1 } + }, + payload := omit + } + + template CoAP_ReqResp tr_Continue_withBlock1(Type p_msgType, template BlockOption p_block1) := + { + header := + { + version := 1, + msg_type := p_msgType, + code := { class := 2, detail := 31}, + message_id := ? + }, + token := ?, + options := + { + { block1 := p_block1 } + }, + payload := omit + } template EPTF_MBT_LGen_Definitions.FsmAddr t_addr(integer eIdx, integer fIdx := 0) := { @@ -425,7 +613,9 @@ module EPTF_COAP_Tests const integer c_t_CON_GET := 1; const integer c_t_Content := 2; const integer c_t_NotFound := 3; - + const integer c_t_Changed := 4; + const integer c_t_Continue := 5; + /////////////////////////////////////////////////////////// // @@ -2153,38 +2343,602 @@ module EPTF_COAP_Tests f_IFW_CoapPeer_setMessageToSend(peer, valueof(t_CON_OBSERVE), GENERATE_NEW_MID, GENERATE_NEW_TOKEN); f_IFW_CoapPeer_send(peer); - + f_handleVerdict(f_MBT_waitFor(c_COAP_behaviorType, c_COAP_eventName_OBSERVE, valueof(t_addr(0, -1)), 3.0)); f_handleVerdict(f_MBT_waitFor(c_COAP_behaviorType, c_COAP_eventName_GET, valueof(t_addr(0, -1)), 3.0)); f_MBT_execute(c_COAP_stepName_handleRequest, valueof(t_addr(0, 0)), {}, false); f_MBT_execute(c_COAP_stepName_loadTemplate_byIntIdx, valueof(t_addr(0, 0)), {c_t_Content}, false); f_MBT_execute(c_COAP_stepName_sendResponse, valueof(t_addr(0, 0)), {}, false); - + f_IFW_CoapPeer_receive(peer); f_handleVerdict(f_IFW_CoapPeer_check(peer, tr_Content_withObserve(ACKNOWLEDGEMENT, 2))); - + f_MBT_execute(c_COAP_stepName_loadTemplate_byIntIdx, valueof(t_addr(0, 0)), {c_t_Content}, false); f_MBT_execute(c_COAP_stepName_sendNotification_byIntIdx, valueof(t_addr(0, 0)), {0}, false); - + f_IFW_CoapPeer_receive(peer); f_handleVerdict(f_IFW_CoapPeer_check(peer, tr_Content_withObserve(NON_CONFIRMABLE, 3))); - + f_IFW_CoapPeer_setMessageToSend(peer, valueof(t_CON_GET_Obs1), GENERATE_NEW_MID, GENERATE_NEW_TOKEN); f_IFW_CoapPeer_send(peer); - + f_handleVerdict(f_MBT_waitFor(c_COAP_behaviorType, c_COAP_eventName_GET, valueof(t_addr(0, -1)), 3.0)); - + f_MBT_execute(c_COAP_stepName_handleRequest, valueof(t_addr(0, 0)), {}, false); f_MBT_execute(c_COAP_stepName_loadTemplate_byIntIdx, valueof(t_addr(0, 0)), {c_t_Content}, false); f_MBT_execute(c_COAP_stepName_sendResponse, valueof(t_addr(0, 0)), {}, false); - + f_handleVerdict(f_MBT_waitFor(c_COAP_behaviorType, c_COAP_eventName_observeCanceled, valueof(t_addr(0, -1)), 3.0)); f_handleVerdict(f_MBT_waitFor(c_COAP_behaviorType, c_COAP_eventName_resourceNotObservedIndication, valueof(t_addr(0, -1)), 3.0)); - + f_IFW_CoapPeer_receive(peer); f_handleVerdict(f_IFW_CoapPeer_check(peer, tr_Content(ACKNOWLEDGEMENT))); - + + f_COAP_Tests_end(); + } + +/* + SUT: Block1 server + - recv: CON(block1,size1), send: ACK(404), resource not found + (- recv: CON(block1,size1), send: ACK(408), num != 0) + - recv: CON(block1,size1), send: ACK(204, block1 m=false) state-less + - recv: CON(block1,size1), send: ACK(231, block1 m=true) atomic, succesful 204 + - recv: CON(block1,size1), send: ACK(231, block1 m=true) atomic, not in sequence block, 408 + (- recv: CON(block1,size1), send: ACK(231, block1 m=true) atomic, missing block after last block, 408) + - recv: CON(block1,size1), send: ACK(231, block1 m=true) atomic, LIFETIME timeout before next block, 408 + - recv: CON(block1,size1), send: ACK(231, block1 m=true, szx smaller) atomic, smaller block size + + device.blockwiseOptions: + - atomic/stateless + - szx +*/ + + /////////////////////////////////////////////////////////// + // + // Testcase: tc_recv_CON_block1_send_ACK_404NotFound + // + // Purpose: + // Testcase for checking that a a request with the block1 option + // is reported as an BLOCK1 request and can be answered with a 404 + // negative response + // + // Action: + // (see EPTF_COAP_Tests.tc_recv_CON_block1_send_ACK_404NotFound.jpg) + /////////////////////////////////////////////////////////// + /***************************************************************** + * Call flow: + * @startuml EPTF_COAP_Tests.tc_recv_CON_block1_send_ACK_404NotFound.jpg + * FSM -> Applib: c_COAP_stepName_init() + * FSM -> Applib: c_COAP_stepName_setLocalAddress(c_localAddr) + * FSM -> Applib: c_COAP_stepName_startListening() + * FSM <- Applib: c_COAP_eventName_transportSucc + * Peer -> Applib: CON-PUT with Block1:({num=0, m=true, szx=5}), size1:8863 + * FSM <- Applib: c_COAP_eventName_BLOCK1_init + * FSM -> Applib: c_COAP_stepName_handleRequest() + * FSM -> Applib: c_COAP_stepName_loadTemplate_byIntIdx(c_t_NotFound) + * FSM -> Applib: c_COAP_stepName_sendResponse() + * Peer <- Applib: ACK-404NotFound + * @enduml + ******************************************************************/ + testcase tc_recv_CON_block1_send_ACK_404NotFound() runs on Tester_CT + { + f_COAP_Tests_begin(); + + var integer peer := f_IFW_addComponent(COAP_PEER, "tester"); + f_IFW_CoapPeer_setRemote(peer, "sut"); + f_IFW_initComponents(); + + f_MBT_execute(c_COAP_stepName_init, valueof(t_addr(0, 0)), {}, false); + f_MBT_execute(c_COAP_stepName_setLocalAddress, valueof(t_addr(0, 0)), {c_localAddr}, false); + f_MBT_execute(c_COAP_stepName_startListening, valueof(t_addr(0, 0)), {}, false); + f_handleVerdict(f_MBT_waitFor(c_COAP_behaviorType, c_COAP_eventName_transportSucc, valueof(t_addr(0, 0)), 3.0)); + + f_IFW_CoapPeer_setMessageToSend(peer, valueof(t_CON_PUT_Block1({ num := 0, m := true, szx := 5 })), GENERATE_NEW_MID, GENERATE_NEW_TOKEN); + f_IFW_CoapPeer_send(peer); + + f_handleVerdict(f_MBT_waitFor(c_COAP_behaviorType, c_COAP_eventName_BLOCK1_block, valueof(t_addr(0, -1)), 3.0)); + f_handleVerdict(f_MBT_waitFor(c_COAP_behaviorType, c_COAP_eventName_BLOCK1_init, valueof(t_addr(0, -1)), 3.0)); + + f_MBT_execute(c_COAP_stepName_handleRequest, valueof(t_addr(0, 0)), {}, false); + f_MBT_execute(c_COAP_stepName_loadTemplate_byIntIdx, valueof(t_addr(0, 0)), {c_t_NotFound}, false); + f_MBT_execute(c_COAP_stepName_sendResponse, valueof(t_addr(0, 0)), {}, false); + + f_IFW_CoapPeer_receive(peer); + f_handleVerdict(f_IFW_CoapPeer_check(peer, tr_NotFound(ACKNOWLEDGEMENT))); + + f_COAP_Tests_end(); + } + + /////////////////////////////////////////////////////////// + // + // Testcase: tc_recv_CON_block1_send_ACK_204Changed_stateless + // + // Purpose: + // Testcase for checking that a a request with the block1 option + // is reported as an BLOCK1 request and can be answered with a 204 + // postivie response to receive the BLOCK1 transfer in stateless mode + // + // Action: + // (see EPTF_COAP_Tests.tc_recv_CON_block1_send_ACK_204Changed_stateless.jpg) + /////////////////////////////////////////////////////////// + /***************************************************************** + * Call flow: + * @startuml EPTF_COAP_Tests.tc_recv_CON_block1_send_ACK_204Changed_stateless.jpg + * FSM -> Applib: c_COAP_stepName_init() + * FSM -> Applib: c_COAP_stepName_setLocalAddress(c_localAddr) + * FSM -> Applib: c_COAP_stepName_startListening() + * FSM <- Applib: c_COAP_eventName_transportSucc + * Peer -> Applib: CON-PUT with Block1:({num=0, m=true, szx=5}), size1:8863 + * FSM <- Applib: c_COAP_eventName_BLOCK1_block + * FSM <- Applib: c_COAP_eventName_BLOCK1_init + * FSM -> Applib: c_COAP_stepName_handleRequest() + * FSM -> Applib: c_COAP_stepName_loadTemplate_byIntIdx(c_t_Content_204) + * FSM -> Applib: c_COAP_stepName_sendResponse() + * Peer <- Applib: ACK-204OK with with Block1:({num=0, m=false, szx=5}) + * Peer -> Applib: CON-PUT with Block1:({num=1, m=true, szx=5}) + * FSM <- Applib: c_COAP_eventName_BLOCK1_block + * FSM -> Applib: c_COAP_stepName_handleRequest() + * FSM -> Applib: c_COAP_stepName_loadTemplate_byIntIdx(c_t_Content_204) + * FSM -> Applib: c_COAP_stepName_sendResponse() + * Peer <- Applib: ACK-204OK with with Block1:({num=1, m=false, szx=5}) + * Peer -> Applib: CON-PUT with Block1:({num=2, m=false, szx=5}) + * FSM <- Applib: c_COAP_eventName_BLOCK1_last + * FSM -> Applib: c_COAP_stepName_handleRequest() + * FSM -> Applib: c_COAP_stepName_loadTemplate_byIntIdx(c_t_Content_204) + * FSM -> Applib: c_COAP_stepName_sendResponse() + * Peer <- Applib: ACK-204OK with with Block1:({num=2, m=false, szx=5}) + * @enduml + ******************************************************************/ + testcase tc_recv_CON_block1_send_ACK_204Changed_stateless() runs on Tester_CT + { + f_COAP_Tests_begin(); + + var integer peer := f_IFW_addComponent(COAP_PEER, "tester"); + f_IFW_CoapPeer_setRemote(peer, "sut"); + f_IFW_initComponents(); + + f_MBT_execute(c_COAP_stepName_init, valueof(t_addr(0, 0)), {}, false); + f_MBT_execute(c_COAP_stepName_setLocalAddress, valueof(t_addr(0, 0)), {c_localAddr}, false); + f_MBT_execute(c_COAP_stepName_startListening, valueof(t_addr(0, 0)), {}, false); + f_handleVerdict(f_MBT_waitFor(c_COAP_behaviorType, c_COAP_eventName_transportSucc, valueof(t_addr(0, 0)), 3.0)); + + // Block1 num=0 (first) + f_IFW_CoapPeer_setMessageToSend(peer, valueof(t_CON_PUT_Block1({ num := 0, m := true, szx := 5 })), GENERATE_NEW_MID, GENERATE_NEW_TOKEN); + f_IFW_CoapPeer_send(peer); + + f_handleVerdict(f_MBT_waitFor(c_COAP_behaviorType, c_COAP_eventName_BLOCK1_block, valueof(t_addr(0, -1)), 3.0)); + f_handleVerdict(f_MBT_waitFor(c_COAP_behaviorType, c_COAP_eventName_BLOCK1_init, valueof(t_addr(0, -1)), 3.0)); + + f_MBT_execute(c_COAP_stepName_handleRequest, valueof(t_addr(0, 0)), {}, false); + f_MBT_execute(c_COAP_stepName_loadTemplate_byIntIdx, valueof(t_addr(0, 0)), {c_t_Changed}, false); + f_MBT_execute(c_COAP_stepName_sendResponse, valueof(t_addr(0, 0)), {}, false); + + f_IFW_CoapPeer_receive(peer); + f_handleVerdict(f_IFW_CoapPeer_check(peer, tr_Changed_withBlock1(ACKNOWLEDGEMENT, {num:=0, m:=false, szx:=5}))); + + // Block1 num=1 + f_IFW_CoapPeer_setMessageToSend(peer, valueof(t_CON_PUT_Block1({ num := 1, m := true, szx := 5 })), GENERATE_NEW_MID, GENERATE_NEW_TOKEN); + f_IFW_CoapPeer_send(peer); + + f_handleVerdict(f_MBT_waitFor(c_COAP_behaviorType, c_COAP_eventName_BLOCK1_block, valueof(t_addr(0, -1)), 3.0)); + + f_MBT_execute(c_COAP_stepName_handleRequest, valueof(t_addr(0, 0)), {}, false); + f_MBT_execute(c_COAP_stepName_loadTemplate_byIntIdx, valueof(t_addr(0, 0)), {c_t_Changed}, false); + f_MBT_execute(c_COAP_stepName_sendResponse, valueof(t_addr(0, 0)), {}, false); + + f_IFW_CoapPeer_receive(peer); + f_handleVerdict(f_IFW_CoapPeer_check(peer, tr_Changed_withBlock1(ACKNOWLEDGEMENT, {num:=1, m:=false, szx:=5}))); + + // Block1 num=2 (last) + f_IFW_CoapPeer_setMessageToSend(peer, valueof(t_CON_PUT_Block1({ num := 2, m := false, szx := 5 })), GENERATE_NEW_MID, GENERATE_NEW_TOKEN); + f_IFW_CoapPeer_send(peer); + + f_handleVerdict(f_MBT_waitFor(c_COAP_behaviorType, c_COAP_eventName_BLOCK1_block, valueof(t_addr(0, -1)), 3.0)); + f_handleVerdict(f_MBT_waitFor(c_COAP_behaviorType, c_COAP_eventName_BLOCK1_last, valueof(t_addr(0, -1)), 3.0)); + + f_MBT_execute(c_COAP_stepName_handleRequest, valueof(t_addr(0, 0)), {}, false); + f_MBT_execute(c_COAP_stepName_loadTemplate_byIntIdx, valueof(t_addr(0, 0)), {c_t_Changed}, false); + f_MBT_execute(c_COAP_stepName_sendResponse, valueof(t_addr(0, 0)), {}, false); + + f_IFW_CoapPeer_receive(peer); + f_handleVerdict(f_IFW_CoapPeer_check(peer, tr_Changed_withBlock1(ACKNOWLEDGEMENT, {num:=2, m:=false, szx:=5}))); + + f_COAP_Tests_end(); + } + + /////////////////////////////////////////////////////////// + // + // Testcase: tc_recv_CON_block1_send_ACK_231Continue_atomic_succ + // + // Purpose: + // Testcase for checking that a a request with the block1 option + // is reported as an BLOCK1 request and can be answered with a 231 + // postivie response to receive the BLOCK1 transfer in atomic mode + // The following blocks are automatically handled by the applib until + // the last block is received and the transfer is finished succesfully + // + // Action: + // (see EPTF_COAP_Tests.tc_recv_CON_block1_send_ACK_231Continue_atomic_succ.jpg) + /////////////////////////////////////////////////////////// + /***************************************************************** + * Call flow: + * @startuml EPTF_COAP_Tests.tc_recv_CON_block1_send_ACK_231Continue_atomic_succ.jpg + * FSM -> Applib: c_COAP_stepName_init() + * FSM -> Applib: c_COAP_stepName_setLocalAddress(c_localAddr) + * FSM -> Applib: c_COAP_stepName_startListening() + * FSM <- Applib: c_COAP_eventName_transportSucc + * Peer -> Applib: CON-PUT with Block1:({num=0, m=true, szx=5}), size1:8863 + * FSM <- Applib: c_COAP_eventName_BLOCK1_block + * FSM <- Applib: c_COAP_eventName_BLOCK1_init + * FSM -> Applib: c_COAP_stepName_handleRequest() + * FSM -> Applib: c_COAP_stepName_loadTemplate_byIntIdx(c_t_Continue_231) + * FSM -> Applib: c_COAP_stepName_sendResponse() + * Peer <- Applib: ACK-231Continue with with Block1:({num=0, m=true, szx=5}) + * Peer -> Applib: CON-PUT with Block1:({num=1, m=true, szx=5}) + * Peer <- Applib: ACK-231Continue with with Block1:({num=1, m=true, szx=5}) + * Peer -> Applib: CON-PUT with Block1:({num=2, m=false, szx=5}) + * Peer <- Applib: ACK-204Changed with with Block1:({num=2, m=false, szx=5}) + * FSM <- Applib: c_COAP_eventName_BLOCK1_atomic_succ + * @enduml + ******************************************************************/ + testcase tc_recv_CON_block1_send_ACK_231Continue_atomic_succ() runs on Tester_CT + { + f_COAP_Tests_begin(); + + var integer peer := f_IFW_addComponent(COAP_PEER, "tester"); + f_IFW_CoapPeer_setRemote(peer, "sut"); + f_IFW_initComponents(); + + f_MBT_execute(c_COAP_stepName_init, valueof(t_addr(0, 0)), {}, false); + f_MBT_execute(c_COAP_stepName_setLocalAddress, valueof(t_addr(0, 0)), {c_localAddr}, false); + f_MBT_execute(c_COAP_stepName_startListening, valueof(t_addr(0, 0)), {}, false); + f_handleVerdict(f_MBT_waitFor(c_COAP_behaviorType, c_COAP_eventName_transportSucc, valueof(t_addr(0, 0)), 3.0)); + + // Block1 num=0 (first) + f_IFW_CoapPeer_setMessageToSend(peer, valueof(t_CON_PUT_Block1({ num := 0, m := true, szx := 5 })), GENERATE_NEW_MID, GENERATE_NEW_TOKEN); + f_IFW_CoapPeer_send(peer); + + f_handleVerdict(f_MBT_waitFor(c_COAP_behaviorType, c_COAP_eventName_BLOCK1_block, valueof(t_addr(0, -1)), 3.0)); + f_handleVerdict(f_MBT_waitFor(c_COAP_behaviorType, c_COAP_eventName_BLOCK1_init, valueof(t_addr(0, -1)), 3.0)); + + f_MBT_execute(c_COAP_stepName_handleRequest, valueof(t_addr(0, 0)), {}, false); + f_MBT_execute(c_COAP_stepName_loadTemplate_byIntIdx, valueof(t_addr(0, 0)), {c_t_Continue}, false); + f_MBT_execute(c_COAP_stepName_sendResponse, valueof(t_addr(0, 0)), {}, false); + + f_IFW_CoapPeer_receive(peer); + f_handleVerdict(f_IFW_CoapPeer_check(peer, tr_Continue_withBlock1(ACKNOWLEDGEMENT, {num:=0, m:= true, szx:=5}))); + + // Block1 num=1 + f_IFW_CoapPeer_setMessageToSend(peer, valueof(t_CON_PUT_Block1({ num := 1, m := true, szx := 5 })), GENERATE_NEW_MID, GENERATE_NEW_TOKEN); + f_IFW_CoapPeer_send(peer); + + f_IFW_CoapPeer_receive(peer); + f_handleVerdict(f_IFW_CoapPeer_check(peer, tr_Continue_withBlock1(ACKNOWLEDGEMENT, {num:=1, m:=true, szx:=5}))); + + // Block1 num=2 (last) + f_IFW_CoapPeer_setMessageToSend(peer, valueof(t_CON_PUT_Block1({ num := 2, m := false, szx := 5 })), GENERATE_NEW_MID, GENERATE_NEW_TOKEN); + f_IFW_CoapPeer_send(peer); + + f_handleVerdict(f_MBT_waitFor(c_COAP_behaviorType, c_COAP_eventName_BLOCK1_atomic_succ, valueof(t_addr(0, -1)), 3.0)); + + f_IFW_CoapPeer_receive(peer); + f_handleVerdict(f_IFW_CoapPeer_check(peer, tr_Changed_withBlock1(ACKNOWLEDGEMENT, {num:=2, m:=false, szx:=5}))); + + f_COAP_Tests_end(); + } + + /////////////////////////////////////////////////////////// + // + // Testcase: tc_recv_CON_block1_send_ACK_231Continue_atomic_fail + // + // Purpose: + // Testcase for checking that a a request with the block1 option + // is reported as an BLOCK1 request and can be answered with a 231 + // postivie response to receive the BLOCK1 transfer in atomic mode + // The following blocks are automatically handled by the applib until + // the last block is received but the transfer is finished unsuccessfully + // due to not sending the second block + // + // Action: + // (see EPTF_COAP_Tests.tc_recv_CON_block1_send_ACK_231Continue_atomic_fail.jpg) + /////////////////////////////////////////////////////////// + /***************************************************************** + * Call flow: + * @startuml EPTF_COAP_Tests.tc_recv_CON_block1_send_ACK_231Continue_atomic_fail.jpg + * FSM -> Applib: c_COAP_stepName_init() + * FSM -> Applib: c_COAP_stepName_setLocalAddress(c_localAddr) + * FSM -> Applib: c_COAP_stepName_startListening() + * FSM <- Applib: c_COAP_eventName_transportSucc + * Peer -> Applib: CON-PUT with Block1:({num=0, m=true, szx=5}), size1:8863 + * FSM <- Applib: c_COAP_eventName_BLOCK1_block + * FSM <- Applib: c_COAP_eventName_BLOCK1_init + * FSM -> Applib: c_COAP_stepName_handleRequest() + * FSM -> Applib: c_COAP_stepName_loadTemplate_byIntIdx(c_t_Continue_231) + * FSM -> Applib: c_COAP_stepName_sendResponse() + * Peer <- Applib: ACK-231Continue with with Block1:({num=0, m=true, szx=5}) + * Peer -> Applib: CON-PUT with Block1:({num=2, m=false, szx=5}) + * Peer <- Applib: ACK-408Incomplete with with Block1:({num=2, m=false, szx=5}) + * FSM <- Applib: c_COAP_eventName_BLOCK1_atomic_fail + * @enduml + ******************************************************************/ + testcase tc_recv_CON_block1_send_ACK_231Continue_atomic_fail() runs on Tester_CT + { + f_COAP_Tests_begin(); + + var integer peer := f_IFW_addComponent(COAP_PEER, "tester"); + f_IFW_CoapPeer_setRemote(peer, "sut"); + f_IFW_initComponents(); + + f_MBT_execute(c_COAP_stepName_init, valueof(t_addr(0, 0)), {}, false); + f_MBT_execute(c_COAP_stepName_setLocalAddress, valueof(t_addr(0, 0)), {c_localAddr}, false); + f_MBT_execute(c_COAP_stepName_startListening, valueof(t_addr(0, 0)), {}, false); + f_handleVerdict(f_MBT_waitFor(c_COAP_behaviorType, c_COAP_eventName_transportSucc, valueof(t_addr(0, 0)), 3.0)); + + // Block1 num=0 (first) + f_IFW_CoapPeer_setMessageToSend(peer, valueof(t_CON_PUT_Block1({ num := 0, m := true, szx := 5 })), GENERATE_NEW_MID, GENERATE_NEW_TOKEN); + f_IFW_CoapPeer_send(peer); + + f_handleVerdict(f_MBT_waitFor(c_COAP_behaviorType, c_COAP_eventName_BLOCK1_block, valueof(t_addr(0, -1)), 3.0)); + f_handleVerdict(f_MBT_waitFor(c_COAP_behaviorType, c_COAP_eventName_BLOCK1_init, valueof(t_addr(0, -1)), 3.0)); + + f_MBT_execute(c_COAP_stepName_handleRequest, valueof(t_addr(0, 0)), {}, false); + f_MBT_execute(c_COAP_stepName_loadTemplate_byIntIdx, valueof(t_addr(0, 0)), {c_t_Continue}, false); + f_MBT_execute(c_COAP_stepName_sendResponse, valueof(t_addr(0, 0)), {}, false); + + f_IFW_CoapPeer_receive(peer); + f_handleVerdict(f_IFW_CoapPeer_check(peer, tr_Continue_withBlock1(ACKNOWLEDGEMENT, {num:=0, m:= true, szx:=5}))); + + // Block1 num=1 not sent + + // Block1 num=2 (last) + f_IFW_CoapPeer_setMessageToSend(peer, valueof(t_CON_PUT_Block1({ num := 2, m := false, szx := 5 })), GENERATE_NEW_MID, GENERATE_NEW_TOKEN); + f_IFW_CoapPeer_send(peer); + + f_handleVerdict(f_MBT_waitFor(c_COAP_behaviorType, c_COAP_eventName_BLOCK1_atomic_fail, valueof(t_addr(0, -1)), 3.0)); + + f_IFW_CoapPeer_receive(peer); + f_handleVerdict(f_IFW_CoapPeer_check(peer, tr_Incomplete(ACKNOWLEDGEMENT))); + + f_COAP_Tests_end(); + } + + /////////////////////////////////////////////////////////// + // + // Testcase: tc_recv_CON_block1_send_ACK_231Continue_atomic_timeout + // + // Purpose: + // Testcase for checking that a a request with the block1 option + // is reported as an BLOCK1 request and can be answered with a 231 + // postivie response to receive the BLOCK1 transfer in atomic mode + // The following blocks are automatically handled by the applib until + // the last block is received but the transfer is finished unsuccessfully + // due to not sending the second block in time + // + // Action: + // (see EPTF_COAP_Tests.tc_recv_CON_block1_send_ACK_231Continue_atomic_timeout.jpg) + /////////////////////////////////////////////////////////// + /***************************************************************** + * Call flow: + * @startuml EPTF_COAP_Tests.tc_recv_CON_block1_send_ACK_231Continue_atomic_timeout.jpg + * FSM -> Applib: c_COAP_stepName_init() + * FSM -> Applib: c_COAP_stepName_setLocalAddress(c_localAddr) + * FSM -> Applib: c_COAP_stepName_startListening() + * FSM <- Applib: c_COAP_eventName_transportSucc + * Peer -> Applib: CON-PUT with Block1:({num=0, m=true, szx=5}), size1:8863 + * FSM <- Applib: c_COAP_eventName_BLOCK1_block + * FSM <- Applib: c_COAP_eventName_BLOCK1_init + * FSM -> Applib: c_COAP_stepName_handleRequest() + * FSM -> Applib: c_COAP_stepName_loadTemplate_byIntIdx(c_t_Continue_231) + * FSM -> Applib: c_COAP_stepName_sendResponse() + * Peer <- Applib: ACK-231Continue with with Block1:({num=0, m=true, szx=5}) + * ...after EXCHANGE_LIFETIME... + * FSM <- Applib: c_COAP_eventName_BLOCK1_atomic_fail + * @enduml + ******************************************************************/ + testcase tc_recv_CON_block1_send_ACK_231Continue_atomic_timeout() runs on Tester_CT + { + f_COAP_Tests_begin(); + + var integer peer := f_IFW_addComponent(COAP_PEER, "tester"); + f_IFW_CoapPeer_setRemote(peer, "sut"); + f_IFW_initComponents(); + + f_MBT_execute(c_COAP_stepName_init, valueof(t_addr(0, 0)), {}, false); + f_MBT_execute(c_COAP_stepName_setLocalAddress, valueof(t_addr(0, 0)), {c_localAddr}, false); + f_MBT_execute(c_COAP_stepName_startListening, valueof(t_addr(0, 0)), {}, false); + f_handleVerdict(f_MBT_waitFor(c_COAP_behaviorType, c_COAP_eventName_transportSucc, valueof(t_addr(0, 0)), 3.0)); + + // Block1 num=0 (first) + f_IFW_CoapPeer_setMessageToSend(peer, valueof(t_CON_PUT_Block1({ num := 0, m := true, szx := 5 })), GENERATE_NEW_MID, GENERATE_NEW_TOKEN); + f_IFW_CoapPeer_send(peer); + + f_handleVerdict(f_MBT_waitFor(c_COAP_behaviorType, c_COAP_eventName_BLOCK1_block, valueof(t_addr(0, -1)), 3.0)); + f_handleVerdict(f_MBT_waitFor(c_COAP_behaviorType, c_COAP_eventName_BLOCK1_init, valueof(t_addr(0, -1)), 3.0)); + + f_MBT_execute(c_COAP_stepName_handleRequest, valueof(t_addr(0, 0)), {}, false); + f_MBT_execute(c_COAP_stepName_loadTemplate_byIntIdx, valueof(t_addr(0, 0)), {c_t_Continue}, false); + f_MBT_execute(c_COAP_stepName_sendResponse, valueof(t_addr(0, 0)), {}, false); + + f_IFW_CoapPeer_receive(peer); + f_handleVerdict(f_IFW_CoapPeer_check(peer, tr_Continue_withBlock1(ACKNOWLEDGEMENT, {num:=0, m:= true, szx:=5}))); + + // Block1 num=1 not sent in ECHANGE_LIFETIME + f_handleVerdict(f_MBT_waitFor(c_COAP_behaviorType, c_COAP_eventName_BLOCK1_atomic_fail, valueof(t_addr(0, -1)), tsp_EPTF_COAP_EXCHANGE_LIFETIME+3.0)); + + f_COAP_Tests_end(); + } + + /////////////////////////////////////////////////////////// + // + // Testcase: tc_recv_CON_block1_send_ACK_231Continue_atomic_smaller_blocksize + // + // Purpose: + // Testcase for checking that a a request with the block1 option + // is reported as an BLOCK1 request and can be answered with a 231 + // postivie response to receive the BLOCK1 transfer in atomic mode + // The following blocks are automatically handled by the applib until + // the last block is received and the transfer is finished succesfully + // + // Action: + // (see EPTF_COAP_Tests.tc_recv_CON_block1_send_ACK_231Continue_atomic_smaller_blocksize.jpg) + /////////////////////////////////////////////////////////// + /***************************************************************** + * Call flow: + * @startuml EPTF_COAP_Tests.tc_recv_CON_block1_send_ACK_231Continue_atomic_succ.jpg + * FSM -> Applib: c_COAP_stepName_init() + * FSM -> Applib: c_COAP_stepName_setPreferredBlocksize(4) + * FSM -> Applib: c_COAP_stepName_setLocalAddress(c_localAddr) + * FSM -> Applib: c_COAP_stepName_startListening() + * FSM <- Applib: c_COAP_eventName_transportSucc + * Peer -> Applib: CON-PUT with Block1:({num=0, m=true, szx=5}), size1:8863 + * FSM <- Applib: c_COAP_eventName_BLOCK1_block + * FSM <- Applib: c_COAP_eventName_BLOCK1_init + * FSM -> Applib: c_COAP_stepName_handleRequest() + * FSM -> Applib: c_COAP_stepName_loadTemplate_byIntIdx(c_t_Continue_231) + * FSM -> Applib: c_COAP_stepName_sendResponse() + * Peer <- Applib: ACK-231Continue with with Block1:({num=0, m=true, szx=4}) + * Peer -> Applib: CON-PUT with Block1:({num=4, m=true, szx=4}) + * Peer <- Applib: ACK-231Continue with with Block1:({num=4, m=true, szx=4}) + * Peer -> Applib: CON-PUT with Block1:({num=5, m=false, szx=4}) + * Peer <- Applib: ACK-204Changed with with Block1:({num=5, m=false, szx=4}) + * FSM <- Applib: c_COAP_eventName_BLOCK1_atomic_succ + * @enduml + ******************************************************************/ + + testcase tc_recv_CON_block1_send_ACK_231Continue_atomic_smaller_blocksize() runs on Tester_CT + { + f_COAP_Tests_begin(); + + var integer peer := f_IFW_addComponent(COAP_PEER, "tester"); + f_IFW_CoapPeer_setRemote(peer, "sut"); + f_IFW_initComponents(); + + f_MBT_execute(c_COAP_stepName_init, valueof(t_addr(0, 0)), {}, false); + f_MBT_execute(c_COAP_stepName_setPreferredBlocksize, valueof(t_addr(0, 0)), {4}, false); + f_MBT_execute(c_COAP_stepName_setLocalAddress, valueof(t_addr(0, 0)), {c_localAddr}, false); + f_MBT_execute(c_COAP_stepName_startListening, valueof(t_addr(0, 0)), {}, false); + f_handleVerdict(f_MBT_waitFor(c_COAP_behaviorType, c_COAP_eventName_transportSucc, valueof(t_addr(0, 0)), 3.0)); + + // Block1 num=0 (first) + f_IFW_CoapPeer_setMessageToSend(peer, valueof(t_CON_PUT_Block1({ num := 0, m := true, szx := 5 })), GENERATE_NEW_MID, GENERATE_NEW_TOKEN); + f_IFW_CoapPeer_send(peer); + + f_handleVerdict(f_MBT_waitFor(c_COAP_behaviorType, c_COAP_eventName_BLOCK1_block, valueof(t_addr(0, -1)), 3.0)); + f_handleVerdict(f_MBT_waitFor(c_COAP_behaviorType, c_COAP_eventName_BLOCK1_init, valueof(t_addr(0, -1)), 3.0)); + + f_MBT_execute(c_COAP_stepName_handleRequest, valueof(t_addr(0, 0)), {}, false); + f_MBT_execute(c_COAP_stepName_loadTemplate_byIntIdx, valueof(t_addr(0, 0)), {c_t_Continue}, false); + f_MBT_execute(c_COAP_stepName_sendResponse, valueof(t_addr(0, 0)), {}, false); + + f_IFW_CoapPeer_receive(peer); + f_handleVerdict(f_IFW_CoapPeer_check(peer, tr_Continue_withBlock1(ACKNOWLEDGEMENT, {num:=0, m:= true, szx:=4}))); + + // Block1 num=1 + f_IFW_CoapPeer_setMessageToSend(peer, valueof(t_CON_PUT_Block1({ num := 4, m := true, szx := 4 })), GENERATE_NEW_MID, GENERATE_NEW_TOKEN); + f_IFW_CoapPeer_send(peer); + + f_IFW_CoapPeer_receive(peer); + f_handleVerdict(f_IFW_CoapPeer_check(peer, tr_Continue_withBlock1(ACKNOWLEDGEMENT, {num:=4, m:=true, szx:=4}))); + + // Block1 num=2 (last) + f_IFW_CoapPeer_setMessageToSend(peer, valueof(t_CON_PUT_Block1({ num := 5, m := false, szx := 4 })), GENERATE_NEW_MID, GENERATE_NEW_TOKEN); + f_IFW_CoapPeer_send(peer); + + f_handleVerdict(f_MBT_waitFor(c_COAP_behaviorType, c_COAP_eventName_BLOCK1_atomic_succ, valueof(t_addr(0, -1)), 3.0)); + + f_IFW_CoapPeer_receive(peer); + f_handleVerdict(f_IFW_CoapPeer_check(peer, tr_Changed_withBlock1(ACKNOWLEDGEMENT, {num:=5, m:=false, szx:=4}))); + + f_COAP_Tests_end(); + } + + + + /////////////////////////////////////////////////////////// + // + // Testcase: tc_block1_fwug + // + // Purpose: + // Testcase for checking that a coap block1 write to /5/0/0 package + // resource (firmware upgrade) can be handled by the coap applib + // + // Action: + // (see EPTF_COAP_Tests.tc_block1_fwug.jpg) + /////////////////////////////////////////////////////////// + /***************************************************************** + * Call flow: + * @startuml EPTF_COAP_Tests.tc_block1_fwug.jpg + * FSM -> Applib: c_COAP_stepName_init() + * FSM -> Applib: c_COAP_stepName_setLocalAddress(c_localAddr) + * FSM -> Applib: c_COAP_stepName_startListening() + * FSM <- Applib: c_COAP_eventName_transportSucc + * Peer -> Applib: CON-PUT with Block1:({num=0, m=true, szx=5}), size1:1889 + * FSM <- Applib: c_COAP_eventName_BLOCK1_block + * FSM <- Applib: c_COAP_eventName_BLOCK1_init + * FSM -> Applib: c_COAP_stepName_handleRequest() + * FSM -> Applib: c_COAP_stepName_loadTemplate_byIntIdx(c_t_Continue_231) + * FSM -> Applib: c_COAP_stepName_sendResponse() + * Peer <- Applib: ACK-231Continue with with Block1:({num=0, m=true, szx=5}) + * Peer -> Applib: CON-PUT with Block1:({num=1, m=true, szx=5}) + * Peer <- Applib: ACK-231Continue with with Block1:({num=1, m=true, szx=5}) + * Peer -> Applib: CON-PUT with Block1:({num=2, m=false, szx=5}) + * Peer <- Applib: ACK-204Changed with with Block1:({num=2, m=false, szx=5}) + * Peer -> Applib: CON-PUT with Block1:({num=3, m=false, szx=5}) + * Peer <- Applib: ACK-204Changed with with Block1:({num=3, m=false, szx=5}) + * FSM <- Applib: c_COAP_eventName_BLOCK1_atomic_succ + * @enduml + ******************************************************************/ + testcase tc_block1_fwug() runs on Tester_CT + { + f_COAP_Tests_begin(); + + var integer peer := f_IFW_addComponent(COAP_PEER, "tester"); + f_IFW_CoapPeer_setRemote(peer, "sut"); + f_IFW_initComponents(); + + f_MBT_execute(c_COAP_stepName_init, valueof(t_addr(0, 0)), {}, false); + f_MBT_execute(c_COAP_stepName_setLocalAddress, valueof(t_addr(0, 0)), {c_localAddr}, false); + f_MBT_execute(c_COAP_stepName_startListening, valueof(t_addr(0, 0)), {}, false); + f_handleVerdict(f_MBT_waitFor(c_COAP_behaviorType, c_COAP_eventName_transportSucc, valueof(t_addr(0, 0)), 3.0)); + + // Block1 num=0 (first) + f_IFW_CoapPeer_setMessageToSend(peer, valueof(t_CON_PUT_Block1_FwUg_num0), GENERATE_NEW_MID, GENERATE_NEW_TOKEN); + f_IFW_CoapPeer_send(peer); + + f_handleVerdict(f_MBT_waitFor(c_COAP_behaviorType, c_COAP_eventName_BLOCK1_block, valueof(t_addr(0, -1)), 3.0)); + f_handleVerdict(f_MBT_waitFor(c_COAP_behaviorType, c_COAP_eventName_BLOCK1_init, valueof(t_addr(0, -1)), 3.0)); + + f_MBT_execute(c_COAP_stepName_handleRequest, valueof(t_addr(0, 0)), {}, false); + f_MBT_execute(c_COAP_stepName_loadTemplate_byIntIdx, valueof(t_addr(0, 0)), {c_t_Continue}, false); + f_MBT_execute(c_COAP_stepName_sendResponse, valueof(t_addr(0, 0)), {}, false); + + f_IFW_CoapPeer_receive(peer); + f_handleVerdict(f_IFW_CoapPeer_check(peer, tr_Continue_withBlock1(ACKNOWLEDGEMENT, {num:=0, m:= true, szx:=5}))); + + // Block1 num=1 + f_IFW_CoapPeer_setMessageToSend(peer, valueof(t_CON_PUT_Block1_FwUg_num1), GENERATE_NEW_MID, GENERATE_NEW_TOKEN); + f_IFW_CoapPeer_send(peer); + + f_IFW_CoapPeer_receive(peer); + f_handleVerdict(f_IFW_CoapPeer_check(peer, tr_Continue_withBlock1(ACKNOWLEDGEMENT, {num:=1, m:=true, szx:=5}))); + + // Block1 num=2 + f_IFW_CoapPeer_setMessageToSend(peer, valueof(t_CON_PUT_Block1_FwUg_num2), GENERATE_NEW_MID, GENERATE_NEW_TOKEN); + f_IFW_CoapPeer_send(peer); + + f_IFW_CoapPeer_receive(peer); + f_handleVerdict(f_IFW_CoapPeer_check(peer, tr_Continue_withBlock1(ACKNOWLEDGEMENT, {num:=2, m:=true, szx:=5}))); + + // Block1 num=3 (last) + f_IFW_CoapPeer_setMessageToSend(peer, valueof(t_CON_PUT_Block1_FwUg_num3), GENERATE_NEW_MID, GENERATE_NEW_TOKEN); + f_IFW_CoapPeer_send(peer); + + f_handleVerdict(f_MBT_waitFor(c_COAP_behaviorType, c_COAP_eventName_BLOCK1_atomic_succ, valueof(t_addr(0, -1)), 3.0)); + + f_IFW_CoapPeer_receive(peer); + f_handleVerdict(f_IFW_CoapPeer_check(peer, tr_Changed_withBlock1(ACKNOWLEDGEMENT, {num:=3, m:=false, szx:=5}))); + f_COAP_Tests_end(); } @@ -2214,7 +2968,7 @@ module EPTF_COAP_Tests execute(tc_recv_CON_send_ACK_recv_Duplicate_retransmit_ACK()); execute(tc_recv_CON_send_emptyACK()); execute(tc_recv_CON_send_emptyACK_send_CON_recv_ACK()); - + // SUT: Observe Server execute(tc_recv_CON_OBS_send_ACK_200OK()); execute(tc_recv_CON_OBS_send_ACK_404NotFound()); @@ -2224,6 +2978,15 @@ module EPTF_COAP_Tests execute(tc_recv_CON_OBS_send_ACK_200OK_send_Notification_recv_RST()); execute(tc_recv_CON_OBS_send_ACK_200OK_send_Notification_withTwoObservers_recv_RST()); execute(tc_recv_CON_OBS_send_ACK_200OK_send_Notification_recv_Obs1()); + + // SUT: Block1 server + execute(tc_recv_CON_block1_send_ACK_404NotFound()); + execute(tc_recv_CON_block1_send_ACK_204Changed_stateless()); + execute(tc_recv_CON_block1_send_ACK_231Continue_atomic_succ()); + execute(tc_recv_CON_block1_send_ACK_231Continue_atomic_fail()); + execute(tc_recv_CON_block1_send_ACK_231Continue_atomic_timeout()); + execute(tc_recv_CON_block1_send_ACK_231Continue_atomic_smaller_blocksize()); + execute(tc_block1_fwug()); } } |