| /////////////////////////////////////////////////////////////////////////////// |
| // |
| // Copyright (c) 2000-2017 Ericsson Telecom AB |
| // |
| // All rights reserved. This program and the accompanying materials |
| // are made available under the terms of the Eclipse Public License v1.0 |
| // which accompanies this distribution, and is available at |
| // http://www.eclipse.org/legal/epl-v10.html |
| /////////////////////////////////////////////////////////////////////////////// |
| // File: EPTF_COAP_LGen_Functions.ttcn |
| // Description: |
| // Rev: R1A |
| // Prodnr: CNL 113 858 |
| // Updated: 2017-09-01 |
| // Contact: http://ttcn.ericsson.se |
| /////////////////////////////////////////////////////////////////////////////// |
| module EPTF_COAP_LGen_Functions |
| { |
| import from EPTF_COAP_LGen_Definitions all; |
| import from EPTF_COAP_Transport_Definitions all; |
| |
| import from EPTF_CLL_Base_Functions all; |
| import from EPTF_CLL_Common_Definitions all; |
| import from EPTF_CLL_Variable_Definitions all; |
| import from EPTF_CLL_Variable_Functions all; |
| import from EPTF_CLL_LGenBase_Definitions all; |
| import from EPTF_CLL_LGenBase_ConfigFunctions all; |
| import from EPTF_CLL_LGenBase_Functions all; |
| import from EPTF_CLL_LGenBase_EventHandlingFunctions all; |
| import from EPTF_CLL_Logging_Definitions all; |
| import from EPTF_CLL_Logging_Functions all; |
| import from EPTF_CLL_FBQ_Functions all; |
| import from EPTF_CLL_HashMapStr2Int_Functions all; |
| import from EPTF_CLL_Scheduler_Definitions all; |
| import from EPTF_CLL_RBTScheduler_Functions all; |
| |
| import from CoAP_Types all; |
| import from IPL4asp_Types all; |
| |
| modulepar integer tsp_EPTF_COAP_maxToken := 65535; |
| modulepar float tsp_EPTF_COAP_NON_LIFETIME := 145.0; |
| modulepar float tsp_EPTF_COAP_EXCHANGE_LIFETIME := 247.0; |
| |
| function f_EPTF_COAP_LGen_init(in charstring pl_name) |
| runs on EPTF_COAP_LGen_CT |
| { |
| if (v_COAP_initialized){return;} |
| |
| f_EPTF_LGenBase_init(pl_name, 0, pl_name); |
| f_EPTF_Logging_init_CT(pl_name); |
| f_EPTF_str2int_HashMap_Init(); |
| |
| v_COAP_bIdx := f_EPTF_LGenBase_declareBehaviorType( |
| c_COAP_behaviorType, |
| tsp_EPTF_COAP_LGen_maxBindableCtx, |
| refers(f_COAP_eCtxReset), |
| refers(f_COAP_eCtxBind), |
| refers(f_COAP_eCtxUnbind) |
| ); |
| |
| v_COAP_loggingMaskId := |
| f_EPTF_Logging_registerComponentMasks( |
| "COAP_Logging", |
| {"WARNING", "DEBUG", "DEBUGV", "ERROR" }, |
| EPTF_Logging_CLL); |
| |
| f_EPTF_COAP_Logging_DEBUG(log2str(%definitionId,": my behavior idx is ", v_COAP_bIdx)); |
| |
| f_EPTF_COAP_EntityCtxDB_init(); |
| f_EPTF_COAP_FsmCtxDB_init(); |
| f_EPTF_COAP_addressDB_init(); |
| f_EPTF_COAP_trDB_init(); |
| f_EPTF_COAP_rrDB_init(); |
| f_EPTF_COAP_templateDB_init(); |
| |
| f_EPTF_COAP_declareSteps(); |
| f_EPTF_COAP_declareEvents(); |
| |
| f_EPTF_Base_registerCleanup(refers(f_COAP_cleanUp)); |
| |
| v_COAP_initialized := true; |
| } |
| |
| function f_EPTF_COAP_LGen_initLogging() |
| runs on EPTF_COAP_LGen_CT |
| { |
| f_EPTF_Logging_init_CT("COAP_LGen"); |
| v_COAP_loggingMaskId := |
| f_EPTF_Logging_registerComponentMasks( |
| "COAP_LGen_Logging", |
| {"WARNING", "DEBUG", "DEBUGV", "ERROR"}, |
| EPTF_Logging_CLL |
| ); |
| |
| if(tsp_EPTF_COAP_LGen_debug){ |
| f_EPTF_Logging_enableLocalMask(v_COAP_loggingMaskId, c_COAP_LGen_Logging_DEBUG); |
| } |
| else { |
| f_EPTF_Logging_disableLocalMask(v_COAP_loggingMaskId, c_COAP_LGen_Logging_DEBUG); |
| } |
| |
| if(tsp_EPTF_COAP_LGen_debugVerbose) { |
| f_EPTF_Logging_enableLocalMask(v_COAP_loggingMaskId, c_COAP_LGen_Logging_DEBUGV); |
| } |
| else { |
| f_EPTF_Logging_disableLocalMask(v_COAP_loggingMaskId, c_COAP_LGen_Logging_DEBUGV); |
| } |
| } |
| |
| function f_COAP_cleanUp() |
| runs on EPTF_COAP_LGen_CT |
| { |
| f_EPTF_COAP_EntityCtxDB_cleanUp(); |
| f_EPTF_COAP_FsmCtxDB_cleanUp(); |
| f_EPTF_COAP_addressDB_cleanUp(); |
| f_EPTF_COAP_trDB_cleanUp(); |
| f_EPTF_COAP_rrDB_cleanUp(); |
| f_EPTF_COAP_templateDB_cleanUp(); |
| vf_COAP_msgReceived := null; |
| |
| v_COAP_initialized := false; |
| } |
| |
| function f_COAP_eCtxBind(in integer pl_eIdx) |
| runs on EPTF_COAP_LGen_CT |
| return EPTF_IntegerList |
| { |
| var integer vl_eCtxIdx := f_EPTF_FBQ_getOrCreateFreeSlot(v_COAP_EntityCtxDB.queue); |
| f_EPTF_FBQ_moveFromFreeHeadToBusyTail(v_COAP_EntityCtxDB.queue); |
| |
| v_COAP_EntityCtxDB.data[vl_eCtxIdx] := c_COAP_EntityCtx_init; |
| v_COAP_EntityCtxDB.data[vl_eCtxIdx].eIdx := pl_eIdx; |
| v_COAP_EntityCtxDB.data[vl_eCtxIdx].nextToken := float2int(int2float(tsp_EPTF_COAP_maxToken)*rnd()); |
| v_COAP_EntityCtxDB.data[vl_eCtxIdx].nextMID := float2int(int2float(65535)*rnd()); |
| |
| return {vl_eCtxIdx}; |
| } |
| |
| function f_COAP_eCtxUnbind(in integer pl_eIdx) |
| runs on EPTF_COAP_LGen_CT |
| { |
| if (not v_COAP_initialized) {return;} |
| |
| var integer vl_eCtxIdx:= f_EPTF_LGenBase_getBehaviorCtxItem(pl_eIdx, v_COAP_bIdx, 0); |
| |
| f_EPTF_FBQ_moveFromBusyToFreeTail(vl_eCtxIdx, v_COAP_EntityCtxDB.queue); |
| } |
| |
| function f_COAP_eCtxReset(in integer pl_eIdx) |
| runs on EPTF_COAP_LGen_CT |
| { |
| var integer vl_eCtxIdx:= f_EPTF_LGenBase_getBehaviorCtxItem(pl_eIdx, v_COAP_bIdx, 0); |
| |
| v_COAP_EntityCtxDB.data[vl_eCtxIdx] := c_COAP_EntityCtx_init; |
| } |
| |
| function f_EPTF_COAP_EntityCtxDB_init() |
| runs on EPTF_COAP_LGen_CT |
| { |
| f_EPTF_FBQ_initFreeBusyQueue(v_COAP_EntityCtxDB.queue); |
| v_COAP_EntityCtxDB.data := {}; |
| v_COAP_EntityCtxDB.hashRef := f_EPTF_str2int_HashMap_New("EPTF_COAP_EnityCtxDB_Hash"); |
| } |
| |
| function f_EPTF_COAP_EntityCtxDB_cleanUp() |
| runs on EPTF_COAP_LGen_CT |
| { |
| f_EPTF_FBQ_initFreeBusyQueue(v_COAP_EntityCtxDB.queue); |
| v_COAP_EntityCtxDB.data :={} |
| f_EPTF_str2int_HashMap_Delete("EPTF_COAP_EnityCtxDB_Hash"); |
| } |
| |
| function f_EPTF_COAP_FsmCtxDB_init() |
| runs on EPTF_COAP_LGen_CT |
| { |
| f_EPTF_FBQ_initFreeBusyQueue(v_COAP_FsmCtxDB.queue); |
| v_COAP_FsmCtxDB.data := {}; |
| v_COAP_FsmCtxDB.hashRef := f_EPTF_str2int_HashMap_New("EPTF_COAP_FsmCtxDB_Hash"); |
| } |
| |
| function f_EPTF_COAP_FsmCtxDB_cleanUp() |
| runs on EPTF_COAP_LGen_CT |
| { |
| f_EPTF_FBQ_initFreeBusyQueue(v_COAP_FsmCtxDB.queue); |
| v_COAP_FsmCtxDB.data :={} |
| f_EPTF_str2int_HashMap_Delete("EPTF_COAP_FsmCtxDB_Hash"); |
| } |
| |
| function f_EPTF_COAP_addressDB_init() |
| runs on EPTF_COAP_LGen_CT |
| { |
| f_EPTF_FBQ_initFreeBusyQueue(v_COAP_addressDB.queue); |
| v_COAP_addressDB.data := {}; |
| v_COAP_addressDB.hashRef := f_EPTF_str2int_HashMap_New("EPTF_COAP_addressDB_Hash"); |
| } |
| |
| function f_EPTF_COAP_addressDB_cleanUp() |
| runs on EPTF_COAP_LGen_CT |
| { |
| f_EPTF_FBQ_initFreeBusyQueue(v_COAP_addressDB.queue); |
| v_COAP_addressDB.data := {}; |
| f_EPTF_str2int_HashMap_Delete("EPTF_COAP_addressDB_Hash"); |
| } |
| |
| function f_EPTF_COAP_addressDB_add(in Socket p_addr, inout integer p_idx) |
| runs on EPTF_COAP_LGen_CT |
| { |
| p_idx := f_EPTF_COAP_addressDB_lookUp(p_addr); |
| |
| if (p_idx == -1) |
| { |
| p_idx := f_EPTF_FBQ_getOrCreateFreeSlot(v_COAP_addressDB.queue); |
| f_EPTF_FBQ_moveFromFreeHeadToBusyTail(v_COAP_addressDB.queue); |
| f_EPTF_COAP_Logging_DEBUG(log2str(": "," adding target address ", p_idx, " ", p_addr)); |
| f_EPTF_str2int_HashMap_Insert(v_COAP_addressDB.hashRef, f_EPTF_COAP_addressDB_Socket2String(p_addr), p_idx); |
| v_COAP_addressDB.data[p_idx] := p_addr; |
| } |
| } |
| |
| function f_EPTF_COAP_addressDB_get(inout Socket p_addr, in integer p_idx) |
| runs on EPTF_COAP_LGen_CT |
| { |
| if (p_idx < sizeof(v_COAP_addressDB.data)) |
| { |
| p_addr := v_COAP_addressDB.data[p_idx]; |
| } |
| } |
| |
| function f_EPTF_COAP_addressDB_lookUp(in Socket p_sock) |
| runs on EPTF_COAP_LGen_CT |
| return integer |
| { |
| var integer vl_idx := -1; |
| f_EPTF_str2int_HashMap_Find(v_COAP_addressDB.hashRef, f_EPTF_COAP_addressDB_Socket2String(p_sock), vl_idx); |
| return vl_idx; |
| } |
| |
| function f_EPTF_COAP_addressDB_Socket2String(Socket p_sock) |
| return charstring |
| { |
| return p_sock.hostName&":"&int2str(p_sock.portNumber); |
| } |
| |
| function f_EPTF_COAP_rrDB_init() |
| runs on EPTF_COAP_LGen_CT |
| { |
| f_EPTF_FBQ_initFreeBusyQueue(v_COAP_rrDB.queue); |
| v_COAP_rrDB.data := {}; |
| v_COAP_rrDB.hashRef := f_EPTF_str2int_HashMap_New("v_COAP_rrDB"); |
| } |
| |
| function f_EPTF_COAP_rrDB_add(in COAP_RR p_rr) |
| runs on EPTF_COAP_LGen_CT |
| return integer |
| { |
| var Socket v_addr; |
| f_EPTF_COAP_addressDB_get(v_addr, p_rr.addrIdx); |
| |
| var integer v_idx := f_EPTF_FBQ_getOrCreateFreeSlot(v_COAP_rrDB.queue); |
| f_EPTF_FBQ_moveFromFreeHeadToBusyTail(v_COAP_rrDB.queue); |
| f_EPTF_COAP_Logging_DEBUG(log2str(": "," adding rr ", v_idx, " ", p_rr)); |
| f_EPTF_str2int_HashMap_Insert(v_COAP_rrDB.hashRef, f_EPTF_COAP_rrDB_tokenHash(v_addr, p_rr.token), v_idx); |
| |
| v_COAP_rrDB.data[v_idx] := p_rr; |
| |
| return v_idx; |
| } |
| |
| function f_EPTF_COAP_rrDB_lookUp(in Socket p_sock, in octetstring p_token) |
| runs on EPTF_COAP_LGen_CT |
| return integer |
| { |
| var integer vl_idx := -1; |
| f_EPTF_str2int_HashMap_Find(v_COAP_rrDB.hashRef, f_EPTF_COAP_rrDB_tokenHash(p_sock, p_token), vl_idx); |
| return vl_idx; |
| } |
| |
| function f_EPTF_COAP_rrDB_get(in integer p_idx, inout COAP_RR p_rr) |
| runs on EPTF_COAP_LGen_CT |
| { |
| if (p_idx < sizeof(v_COAP_rrDB.data)) |
| { |
| p_rr := v_COAP_rrDB.data[p_idx]; |
| } |
| } |
| |
| function f_EPTF_COAP_rrDB_remove(in integer p_idx) |
| runs on EPTF_COAP_LGen_CT |
| { |
| var Socket v_addr; |
| f_EPTF_COAP_addressDB_get(v_addr, v_COAP_rrDB.data[p_idx].addrIdx); |
| f_EPTF_str2int_HashMap_Erase(v_COAP_rrDB.hashRef, f_EPTF_COAP_rrDB_tokenHash(v_addr, v_COAP_rrDB.data[p_idx].token)); |
| v_COAP_rrDB.data[p_idx] := c_COAP_RR_init; |
| f_EPTF_FBQ_moveFromBusyToFreeTail(p_idx, v_COAP_rrDB.queue); |
| } |
| |
| function f_EPTF_COAP_rrDB_cleanUp() |
| runs on EPTF_COAP_LGen_CT |
| { |
| f_EPTF_FBQ_initFreeBusyQueue(v_COAP_rrDB.queue); |
| v_COAP_rrDB.data := {}; |
| f_EPTF_str2int_HashMap_Delete("v_COAP_rrDB"); |
| } |
| |
| function f_EPTF_COAP_rrDB_tokenHash(in Socket p_sock, in octetstring p_token) |
| return charstring |
| { |
| return oct2str(p_token)&":"&p_sock.hostName&":"&int2str(p_sock.portNumber); |
| } |
| |
| function f_EPTF_COAP_trDB_init() |
| runs on EPTF_COAP_LGen_CT |
| { |
| f_EPTF_FBQ_initFreeBusyQueue(v_COAP_trDB.queue); |
| v_COAP_trDB.data := {}; |
| v_COAP_trDB.hashRefOutgoing := f_EPTF_str2int_HashMap_New("v_COAP_outTrDB"); |
| v_COAP_trDB.hashRefIncoming := f_EPTF_str2int_HashMap_New("v_COAP_incTrDB"); |
| } |
| |
| function f_EPTF_COAP_trDB_add(in COAP_Transaction p_tr) |
| runs on EPTF_COAP_LGen_CT |
| return integer |
| { |
| var Socket v_addr; |
| f_EPTF_COAP_addressDB_get(v_addr, p_tr.addrIdx); |
| var integer v_idx := f_EPTF_FBQ_getOrCreateFreeSlot(v_COAP_trDB.queue); |
| f_EPTF_FBQ_moveFromFreeHeadToBusyTail(v_COAP_trDB.queue); |
| f_EPTF_COAP_Logging_DEBUG(log2str(": "," adding tr ", v_idx, " ", p_tr)); |
| if (p_tr.direction == OUTGOING) |
| { |
| f_EPTF_str2int_HashMap_Insert(v_COAP_trDB.hashRefOutgoing, f_EPTF_COAP_trDB_midHash(v_addr, p_tr.mid), v_idx); |
| } |
| else |
| { |
| f_EPTF_COAP_Logging_DEBUG(log2str("adding tr ", v_idx, " ", f_EPTF_COAP_trDB_midHash(v_addr, p_tr.mid))); |
| f_EPTF_str2int_HashMap_Insert(v_COAP_trDB.hashRefIncoming, f_EPTF_COAP_trDB_midHash(v_addr, p_tr.mid), v_idx); |
| } |
| v_COAP_trDB.data[v_idx] := p_tr; |
| |
| return v_idx; |
| } |
| |
| function f_EPTF_COAP_trDB_lookUp(in Socket p_sock, in integer p_mid, COAP_Transaction_Direction p_dir) |
| runs on EPTF_COAP_LGen_CT |
| return integer |
| { |
| var integer vl_idx := -1; |
| if (p_dir == OUTGOING) |
| { |
| f_EPTF_str2int_HashMap_Find(v_COAP_trDB.hashRefOutgoing, f_EPTF_COAP_trDB_midHash(p_sock, p_mid), vl_idx); |
| } |
| else |
| { |
| f_EPTF_COAP_Logging_VERBOSE(log2str("look up tr ", f_EPTF_COAP_trDB_midHash(p_sock, p_mid))); |
| f_EPTF_str2int_HashMap_Find(v_COAP_trDB.hashRefIncoming, f_EPTF_COAP_trDB_midHash(p_sock, p_mid), vl_idx); |
| } |
| |
| return vl_idx; |
| } |
| |
| function f_EPTF_COAP_trDB_get(in integer p_idx, inout COAP_Transaction p_tr) |
| runs on EPTF_COAP_LGen_CT |
| { |
| if (p_idx < sizeof(v_COAP_trDB.data)) |
| { |
| p_tr := v_COAP_trDB.data[p_idx]; |
| } |
| } |
| |
| function f_EPTF_COAP_trDB_remove(in integer p_idx) |
| runs on EPTF_COAP_LGen_CT |
| { |
| var Socket v_addr; |
| f_EPTF_COAP_addressDB_get(v_addr, v_COAP_trDB.data[p_idx].addrIdx); |
| if (v_COAP_trDB.data[p_idx].direction == OUTGOING) |
| { |
| f_EPTF_str2int_HashMap_Erase(v_COAP_trDB.hashRefOutgoing, f_EPTF_COAP_trDB_midHash(v_addr, v_COAP_trDB.data[p_idx].mid)); |
| } |
| else |
| { |
| f_EPTF_str2int_HashMap_Erase(v_COAP_trDB.hashRefIncoming, f_EPTF_COAP_trDB_midHash(v_addr, v_COAP_trDB.data[p_idx].mid)); |
| } |
| v_COAP_trDB.data[p_idx] := c_COAP_Transaction_init; |
| f_EPTF_FBQ_moveFromBusyToFreeTail(p_idx, v_COAP_trDB.queue); |
| } |
| |
| function f_EPTF_COAP_trDB_cleanUp() |
| runs on EPTF_COAP_LGen_CT |
| { |
| f_EPTF_FBQ_initFreeBusyQueue(v_COAP_trDB.queue); |
| v_COAP_trDB.data := {}; |
| f_EPTF_str2int_HashMap_Delete("v_COAP_outTrDB"); |
| f_EPTF_str2int_HashMap_Delete("v_COAP_incTrDB"); |
| } |
| |
| function f_EPTF_COAP_trDB_midHash(in Socket p_sock, in integer p_mid) |
| return charstring |
| { |
| return int2str(p_mid)&":"&p_sock.hostName&":"&int2str(p_sock.portNumber); |
| } |
| |
| function f_EPTF_COAP_templateDB_init() |
| runs on EPTF_COAP_LGen_CT |
| { |
| v_COAP_templateDB.data := {}; |
| v_COAP_templateDB.hashRef := f_EPTF_str2int_HashMap_New("EPTF_COAP_templateDB_Hash"); |
| |
| for (var integer i:=0; i<sizeof(tsp_EPTF_COAP_LGen_templates); i:=i+1) { |
| f_EPTF_COAP_templateDB_add(tsp_EPTF_COAP_LGen_templates[i]); |
| } |
| } |
| |
| function f_EPTF_COAP_templateDB_add(in CoAP_Template p_template) |
| runs on EPTF_COAP_LGen_CT |
| return integer |
| { |
| if (f_EPTF_COAP_templateDB_lookUp(p_template.id)!=-1) |
| { |
| f_EPTF_COAP_Logging_WARNING(log2str(%definitionId, " template is already added with id: ", p_template.id)); |
| return -1; |
| } |
| |
| var integer v_idx := sizeof(v_COAP_templateDB.data); |
| v_COAP_templateDB.data[v_idx] := p_template; |
| f_EPTF_str2int_HashMap_Insert(v_COAP_templateDB.hashRef, p_template.id, v_idx); |
| |
| f_EPTF_COAP_Logging_VERBOSE(log2str(%definitionId, " template was added with id: ", p_template.id, " at idx: ",v_idx)); |
| |
| return v_idx; |
| } |
| |
| function f_EPTF_COAP_templateDB_lookUp(in charstring p_id) |
| runs on EPTF_COAP_LGen_CT |
| return integer |
| { |
| var integer vl_idx := -1; |
| if (not f_EPTF_str2int_HashMap_Find(v_COAP_templateDB.hashRef, p_id, vl_idx)) |
| { |
| vl_idx := -1; |
| } |
| |
| return vl_idx; |
| } |
| |
| function f_EPTF_COAP_templateDB_get(in integer p_idx, inout CoAP_ReqResp p_pdu) |
| runs on EPTF_COAP_LGen_CT |
| { |
| if (p_idx < sizeof(v_COAP_templateDB.data) and p_idx >= 0) |
| { |
| f_EPTF_COAP_Logging_VERBOSE(log2str(%definitionId, " template is fetched with idx: ", p_idx)); |
| p_pdu := v_COAP_templateDB.data[p_idx].msg; |
| } |
| } |
| |
| function f_EPTF_COAP_templateDB_cleanUp() |
| runs on EPTF_COAP_LGen_CT |
| { |
| v_COAP_templateDB.data := {}; |
| f_EPTF_str2int_HashMap_Delete("EPTF_COAP_templateDB_Hash"); |
| } |
| |
| function f_EPTF_COAP_getNextMID(in COAP_StepCtx p_ctx) |
| runs on EPTF_COAP_LGen_CT |
| return integer |
| { |
| if (v_COAP_EntityCtxDB.data[p_ctx.eCtxIdx].nextMID < 65535) |
| { |
| v_COAP_EntityCtxDB.data[p_ctx.eCtxIdx].nextMID := v_COAP_EntityCtxDB.data[p_ctx.eCtxIdx].nextMID + 1; |
| } |
| else |
| { |
| v_COAP_EntityCtxDB.data[p_ctx.eCtxIdx].nextMID := 0; |
| } |
| return v_COAP_EntityCtxDB.data[p_ctx.eCtxIdx].nextMID; |
| } |
| |
| function f_EPTF_COAP_getNextToken(in COAP_StepCtx p_ctx) |
| runs on EPTF_COAP_LGen_CT |
| return octetstring |
| { |
| if (v_COAP_EntityCtxDB.data[p_ctx.eCtxIdx].nextToken < tsp_EPTF_COAP_maxToken) |
| { |
| v_COAP_EntityCtxDB.data[p_ctx.eCtxIdx].nextToken := v_COAP_EntityCtxDB.data[p_ctx.eCtxIdx].nextToken + 1; |
| } |
| else |
| { |
| v_COAP_EntityCtxDB.data[p_ctx.eCtxIdx].nextToken := 0; |
| } |
| return int2oct(v_COAP_EntityCtxDB.data[p_ctx.eCtxIdx].nextToken, 4); |
| } |
| |
| function f_EPTF_COAP_LGen_receiveMessage(in EPTF_COAP_PDU pl_message) |
| runs on EPTF_COAP_LGen_CT |
| { |
| f_EPTF_COAP_Logging_VERBOSE(log2str(%definitionId, " ", pl_message)); |
| |
| v_COAP_msgToProcess := pl_message; |
| |
| var boolean v_duplicate := not f_EPTF_COAP_stack_fromEnv(v_COAP_msgToProcess); |
| |
| if (vf_COAP_msgReceived != null) |
| { |
| vf_COAP_msgReceived.apply(v_COAP_msgToProcess, v_duplicate); |
| } |
| } |
| |
| function f_EPTF_COAP_LGen_receiveEvent(in ASP_Event p_event) |
| runs on EPTF_COAP_LGen_CT |
| { |
| f_EPTF_COAP_Logging_VERBOSE(log2str(%definitionId, " ", p_event)); |
| } |
| |
| function f_EPTF_COAP_LGen_transportApiResponse(in EPTF_COAP_Transport_Response pl_rsp) |
| runs on EPTF_COAP_LGen_CT |
| { |
| f_EPTF_COAP_Logging_VERBOSE(log2str("api response: ", pl_rsp)); |
| if (pl_rsp.succ) |
| { |
| f_EPTF_COAP_dispatchEvent(c_COAP_eventIdx_transportSucc, pl_rsp.eIdx, pl_rsp.fsmIdx, {}); |
| } |
| else |
| { |
| f_EPTF_COAP_dispatchEvent(c_COAP_eventIdx_transportFail, pl_rsp.eIdx, pl_rsp.fsmIdx, {}); |
| } |
| } |
| |
| function f_EPTF_COAP_stack_fromApp(inout EPTF_COAP_PDU p_msg, in COAP_StepCtx p_ctx) |
| runs on EPTF_COAP_LGen_CT |
| { |
| // New Req-Resp |
| if (v_COAP_FsmCtxDB.data[p_ctx.fsmCtxIdx].rrIdx == -1) |
| { |
| f_EPTF_COAP_Logging_VERBOSE(log2str(%definitionId, " new request response")); |
| |
| var COAP_RR vl_rr := c_COAP_RR_init; |
| vl_rr.eIdx := p_ctx.eIdx; |
| vl_rr.fsmIdx := p_ctx.fsmIdx; |
| vl_rr.fsmCtxIdx := p_ctx.fsmCtxIdx; |
| vl_rr.addrIdx := v_COAP_EntityCtxDB.data[p_ctx.eCtxIdx].localAddressIdx; |
| vl_rr.token := f_EPTF_COAP_getNextToken(p_ctx); |
| vl_rr.state.client := IDLE; |
| p_msg.pdu.token := vl_rr.token; |
| var integer vl_rrIdx := f_EPTF_COAP_rrDB_add(vl_rr); |
| f_EPTF_COAP_rr_setState(vl_rrIdx, {client := IDLE}); |
| |
| v_COAP_FsmCtxDB.data[p_ctx.fsmCtxIdx].rrIdx := vl_rrIdx; |
| |
| f_EPTF_COAP_rr_handleMsg(p_msg, v_COAP_FsmCtxDB.data[p_ctx.fsmCtxIdx].rrIdx); |
| } |
| // Ongoing Req-Resp |
| else |
| { |
| f_EPTF_COAP_Logging_VERBOSE(log2str(%definitionId, " ongoing request response")); |
| f_EPTF_COAP_rr_handleMsg(p_msg, v_COAP_FsmCtxDB.data[p_ctx.fsmCtxIdx].rrIdx); |
| } |
| } |
| |
| function f_EPTF_COAP_stack_fromEnv(inout EPTF_COAP_PDU p_msg) |
| runs on EPTF_COAP_LGen_CT |
| return boolean |
| { |
| // Answer for an ongoing tr |
| var integer vl_trIdx := f_EPTF_COAP_trDB_lookUp(p_msg.transportParams.localAddress, p_msg.pdu.header.message_id, OUTGOING); |
| if (vl_trIdx >= 0) |
| { |
| f_EPTF_COAP_Logging_VERBOSE(log2str(%definitionId, " answer for ongoing tr")); |
| f_EPTF_COAP_tr_fromEnv(p_msg, vl_trIdx); |
| return true; |
| } |
| else |
| { |
| vl_trIdx := f_EPTF_COAP_trDB_lookUp(p_msg.transportParams.localAddress, p_msg.pdu.header.message_id, INCOMING); |
| |
| // Deduplication. Already ongoing tr for a request |
| if (vl_trIdx != -1 and (p_msg.pdu.header.msg_type == CONFIRMABLE or p_msg.pdu.header.msg_type == NON_CONFIRMABLE)) |
| { |
| f_EPTF_COAP_Logging_VERBOSE(log2str(%definitionId, " duplicate received ", p_msg)); |
| if (ispresent(v_COAP_trDB.data[vl_trIdx].cache)) |
| { |
| f_EPTF_COAP_tr_send(v_COAP_trDB.data[vl_trIdx].cache, vl_trIdx); |
| } |
| return false; |
| } |
| // New incoming request |
| else |
| { |
| f_EPTF_COAP_Logging_VERBOSE(log2str(%definitionId, " new incoming request ", p_msg)); |
| |
| // Create new tr |
| var integer vl_eCtxIdx := f_EPTF_LGenBase_getBehaviorCtxItem(p_msg.eIdx, v_COAP_bIdx, 0); |
| var COAP_Transaction vl_tr := c_COAP_Transaction_init; |
| vl_tr.mid := p_msg.pdu.header.message_id; |
| vl_tr.eIdx := p_msg.eIdx; |
| vl_tr.addrIdx := v_COAP_EntityCtxDB.data[vl_eCtxIdx].localAddressIdx; |
| vl_tr.state := CLOSED; |
| vl_tr.direction := INCOMING; |
| |
| vl_trIdx := f_EPTF_COAP_trDB_add(vl_tr); |
| f_EPTF_COAP_tr_setState(vl_trIdx, CLOSED); |
| |
| f_EPTF_COAP_tr_fromEnv(v_COAP_msgToProcess, vl_trIdx); |
| return true; |
| } |
| } |
| } |
| |
| function f_EPTF_COAP_rr_handleMsg(inout EPTF_COAP_PDU p_msg, in integer p_rrIdx) |
| runs on EPTF_COAP_LGen_CT |
| { |
| f_EPTF_COAP_Logging_VERBOSE(log2str(%definitionId, " rr [",v_COAP_rrDB.data[p_rrIdx].token,"] current state: ",v_COAP_rrDB.data[p_rrIdx].state)); |
| |
| f_EPTF_COAP_setCtx(v_COAP_rrDB.data[p_rrIdx].eIdx, v_COAP_rrDB.data[p_rrIdx].fsmIdx, v_COAP_ctx); |
| |
| // RR: Client |
| if (ischosen(v_COAP_rrDB.data[p_rrIdx].state.client)) |
| { |
| // State: IDLE |
| if (v_COAP_rrDB.data[p_rrIdx].state.client == IDLE) |
| { |
| // appIn: request |
| if (f_EPTF_COAP_isRequest(p_msg.pdu)) |
| { |
| // Create new TR |
| var COAP_Transaction vl_tr := c_COAP_Transaction_init; |
| vl_tr.mid := f_EPTF_COAP_getNextMID(v_COAP_ctx); |
| vl_tr.eIdx := v_COAP_ctx.eIdx; |
| vl_tr.rrIdx := p_rrIdx; |
| vl_tr.addrIdx := v_COAP_EntityCtxDB.data[v_COAP_ctx.eCtxIdx].localAddressIdx; |
| vl_tr.state := CLOSED; |
| vl_tr.direction := OUTGOING; |
| p_msg.pdu.header.message_id := vl_tr.mid; |
| var integer vl_trIdx := f_EPTF_COAP_trDB_add(vl_tr); |
| f_EPTF_COAP_tr_setState(vl_trIdx, CLOSED); |
| |
| v_COAP_rrDB.data[p_rrIdx].trIdx := vl_trIdx; |
| |
| // trOut.send |
| v_COAP_rrDB.data[p_rrIdx].request := p_msg; |
| f_EPTF_COAP_tr_fromRR(p_msg, v_COAP_ctx, p_rrIdx, v_COAP_rrDB.data[p_rrIdx].trIdx); |
| |
| // next state: WAITING |
| f_EPTF_COAP_rr_setState(p_rrIdx, {client := WAITING}); |
| } |
| else |
| { |
| f_EPTF_COAP_Logging_WARNING(log2str(%definitionId, " only request can be handled in rr::client::IDLE. Ignoring:", p_msg)); |
| } |
| } |
| // State: WAITING |
| else if (v_COAP_rrDB.data[p_rrIdx].state.client == WAITING) |
| { |
| // trIn: response |
| if (f_EPTF_COAP_isResponse(p_msg.pdu)) |
| { |
| v_COAP_rrDB.data[p_rrIdx].response := p_msg; |
| |
| // If response is CON then immediatelly answer with empty ack |
| if (p_msg.pdu.header.msg_type == CONFIRMABLE and |
| v_COAP_rrDB.data[p_rrIdx].trIdx != -1 and |
| ispresent(v_COAP_rrDB.data[p_rrIdx].request) |
| ) { |
| var EPTF_COAP_PDU vl_empty_ack := v_COAP_rrDB.data[p_rrIdx].request; |
| vl_empty_ack.pdu := valueof(t_CoAP_EmptyAck); |
| //vl_empty_ack.pdu.token := int2oct(v_COAP_rrDB.data[p_rrIdx].token, 4); |
| |
| f_EPTF_COAP_tr_fromRR(vl_empty_ack, v_COAP_ctx, p_rrIdx, v_COAP_rrDB.data[p_rrIdx].trIdx); |
| } |
| |
| // report to app |
| f_EPTF_COAP_dispatchEventsForCode( |
| p_msg.pdu.header.code, |
| v_COAP_rrDB.data[p_rrIdx].eIdx, |
| v_COAP_rrDB.data[p_rrIdx].fsmIdx, |
| {} |
| ); |
| p_msg.fsmIdx := v_COAP_rrDB.data[p_rrIdx].fsmIdx; |
| // finish |
| f_EPTF_COAP_rr_remove(p_rrIdx); |
| } |
| else |
| { |
| f_EPTF_COAP_Logging_WARNING(log2str(%definitionId," only response can be handled in rr::client::WAITING. Ignoring: ", p_msg)); |
| } |
| } |
| else |
| { |
| f_EPTF_COAP_Logging_WARNING(log2str(%definitionId," rr: unknown client state ", v_COAP_rrDB.data[p_rrIdx].state.client)); |
| } |
| } |
| // RR: Server |
| else |
| { |
| // State: IDLE |
| if (v_COAP_rrDB.data[p_rrIdx].state.server == IDLE) |
| { |
| v_COAP_rrDB.data[p_rrIdx].remoteAddress := p_msg.transportParams.remoteAddress; |
| v_COAP_rrDB.data[p_rrIdx].request := p_msg; |
| |
| // appIn: request && CON |
| if (p_msg.pdu.header.msg_type == CONFIRMABLE) |
| { |
| // next state: SERVING |
| f_EPTF_COAP_rr_setState(p_rrIdx, {server := SERVING}); |
| } |
| // appIn: request && NON |
| else if (p_msg.pdu.header.msg_type == NON_CONFIRMABLE) |
| { |
| // next state: SEPARATE |
| f_EPTF_COAP_rr_setState(p_rrIdx, {server := SEPARATE}); |
| } |
| else |
| { |
| f_EPTF_COAP_Logging_WARNING(log2str(%definitionId, " message type not handled in rr:server::IDLE ", p_msg)); |
| } |
| } |
| // State: SEPARATE |
| else if (v_COAP_rrDB.data[p_rrIdx].state.server == SEPARATE) |
| { |
| // appIn: response |
| if (f_EPTF_COAP_isResponse(p_msg.pdu)) |
| { |
| p_msg.pdu.token := v_COAP_rrDB.data[p_rrIdx].token; |
| |
| // create new TR |
| var COAP_Transaction vl_tr := c_COAP_Transaction_init; |
| vl_tr.mid := f_EPTF_COAP_getNextMID(v_COAP_ctx); |
| vl_tr.eIdx := v_COAP_ctx.eIdx; |
| vl_tr.rrIdx := p_rrIdx; |
| vl_tr.addrIdx := v_COAP_EntityCtxDB.data[v_COAP_ctx.eCtxIdx].localAddressIdx; |
| vl_tr.state := CLOSED; |
| vl_tr.direction := OUTGOING; |
| p_msg.pdu.header.message_id := vl_tr.mid; |
| var integer vl_trIdx := f_EPTF_COAP_trDB_add(vl_tr); |
| f_EPTF_COAP_tr_setState(vl_trIdx, CLOSED); |
| |
| v_COAP_rrDB.data[p_rrIdx].trIdx := vl_trIdx; |
| |
| if (ispresent(v_COAP_rrDB.data[p_rrIdx].remoteAddress)) |
| { |
| p_msg.transportParams.remoteAddress := v_COAP_rrDB.data[p_rrIdx].remoteAddress; |
| } |
| |
| // trOut.send |
| v_COAP_rrDB.data[p_rrIdx].response := p_msg; |
| f_EPTF_COAP_tr_fromRR(p_msg, v_COAP_ctx, p_rrIdx, v_COAP_rrDB.data[p_rrIdx].trIdx); |
| |
| // finish |
| f_EPTF_COAP_rr_remove(p_rrIdx); |
| } |
| else |
| { |
| f_EPTF_COAP_Logging_WARNING(log2str(%definitionId," only response can be handled in rr::server::SEPARATE. Ignoring: ", p_msg)); |
| } |
| } |
| // State: SERVING |
| else if (v_COAP_rrDB.data[p_rrIdx].state.server == SERVING) |
| { |
| // appIn: response |
| if (f_EPTF_COAP_isResponse(p_msg.pdu) and p_msg.pdu.header.msg_type == ACKNOWLEDGEMENT) |
| { |
| // Get the TR |
| if (v_COAP_rrDB.data[p_rrIdx].trIdx != -1) |
| { |
| p_msg.pdu.token := v_COAP_rrDB.data[p_rrIdx].token; |
| |
| if (ispresent(v_COAP_rrDB.data[p_rrIdx].remoteAddress)) |
| { |
| p_msg.transportParams.remoteAddress := v_COAP_rrDB.data[p_rrIdx].remoteAddress; |
| } |
| |
| // trOut.send |
| v_COAP_rrDB.data[p_rrIdx].response := p_msg; |
| f_EPTF_COAP_tr_fromRR(p_msg, v_COAP_ctx, p_rrIdx, v_COAP_rrDB.data[p_rrIdx].trIdx); |
| |
| f_EPTF_COAP_rr_remove(p_rrIdx); |
| } |
| else |
| { |
| f_EPTF_COAP_Logging_WARNING(log2str(%definitionId," couldn't find ongoing transaction in rr::server::SERVING. Ignoring: ", p_msg)); |
| } |
| } |
| // appIn: empty ACK |
| else if (f_EPTF_COAP_isEmpty(p_msg.pdu) and p_msg.pdu.header.msg_type == ACKNOWLEDGEMENT) |
| { |
| // Get the TR |
| if (v_COAP_rrDB.data[p_rrIdx].trIdx != -1) |
| { |
| // Empty ACK has no token |
| //p_msg.pdu.token := int2oct(v_COAP_rrDB.data[p_rrIdx].token, 4); |
| |
| if (ispresent(v_COAP_rrDB.data[p_rrIdx].remoteAddress)) |
| { |
| p_msg.transportParams.remoteAddress := v_COAP_rrDB.data[p_rrIdx].remoteAddress; |
| } |
| |
| // trOut.send |
| f_EPTF_COAP_tr_fromRR(p_msg, v_COAP_ctx, p_rrIdx, v_COAP_rrDB.data[p_rrIdx].trIdx); |
| |
| f_EPTF_COAP_rr_setState(p_rrIdx, {server := SEPARATE}); |
| } |
| else |
| { |
| f_EPTF_COAP_Logging_WARNING(log2str(%definitionId," couldn't find ongoing transaction in rr::server::SERVING. Ignoring: ", p_msg)); |
| } |
| } |
| else |
| { |
| f_EPTF_COAP_Logging_WARNING(log2str(%definitionId," response must be an ACK, message cannot be handled in rr::server::SERVING. Ignoring: ", p_msg)); |
| } |
| } |
| else |
| { |
| f_EPTF_COAP_Logging_WARNING(log2str(%definitionId, "unknown server state ", v_COAP_rrDB.data[p_rrIdx].state.server)); |
| } |
| } |
| } |
| |
| function f_EPTF_COAP_rr_reset(in integer p_rrIdx) |
| runs on EPTF_COAP_LGen_CT |
| { |
| // RR: Client |
| if (ischosen(v_COAP_rrDB.data[p_rrIdx].state.client)) |
| { |
| // State: WAITING |
| if (v_COAP_rrDB.data[p_rrIdx].state.client == WAITING) |
| { |
| f_EPTF_COAP_dispatchEvent( |
| c_COAP_eventIdx_trRST, |
| v_COAP_rrDB.data[p_rrIdx].eIdx, |
| v_COAP_rrDB.data[p_rrIdx].fsmIdx, |
| {} |
| ); |
| f_EPTF_COAP_rr_remove(p_rrIdx); |
| } |
| else |
| { |
| f_EPTF_COAP_Logging_WARNING(log2str(%definitionId, " reset only handled rr:client::WAITING")); |
| } |
| } |
| else |
| { |
| f_EPTF_COAP_Logging_WARNING(log2str(%definitionId, " reset not handled in rr:server")); |
| } |
| } |
| |
| function f_EPTF_COAP_rr_timeout(in integer p_rrIdx) |
| runs on EPTF_COAP_LGen_CT |
| { |
| // RR: Client |
| if (ischosen(v_COAP_rrDB.data[p_rrIdx].state.client)) |
| { |
| // State: WAITING |
| if (v_COAP_rrDB.data[p_rrIdx].state.client == WAITING) |
| { |
| f_EPTF_COAP_dispatchEvent( |
| c_COAP_eventIdx_trTimeout, |
| v_COAP_rrDB.data[p_rrIdx].eIdx, |
| v_COAP_rrDB.data[p_rrIdx].fsmIdx, |
| {} |
| ); |
| f_EPTF_COAP_rr_remove(p_rrIdx); |
| } |
| else |
| { |
| f_EPTF_COAP_Logging_WARNING(log2str(%definitionId, " reset only handled rr:client::WAITING")); |
| } |
| } |
| else |
| { |
| f_EPTF_COAP_Logging_WARNING(log2str(%definitionId, " reset not handled in rr:server")); |
| } |
| } |
| |
| function f_EPTF_COAP_rr_cancel(in integer p_rrIdx) |
| runs on EPTF_COAP_LGen_CT |
| { |
| // RR: Client |
| if (ischosen(v_COAP_rrDB.data[p_rrIdx].state.client)) |
| { |
| // State: WAITING |
| if (v_COAP_rrDB.data[p_rrIdx].state.client == WAITING) |
| { |
| if (v_COAP_rrDB.data[p_rrIdx].trIdx != -1) |
| { |
| f_EPTF_COAP_tr_cancel(v_COAP_rrDB.data[p_rrIdx].trIdx); |
| |
| f_EPTF_COAP_rr_remove(p_rrIdx); |
| } |
| else |
| { |
| f_EPTF_COAP_Logging_WARNING(log2str(%definitionId, " there is no ongoing transaction to handle cancel")); |
| } |
| } |
| else |
| { |
| f_EPTF_COAP_Logging_WARNING(log2str(%definitionId, " cancel only handled rr:client::WAITING")); |
| } |
| } |
| else |
| { |
| f_EPTF_COAP_Logging_WARNING(log2str(%definitionId, " cance; not handled in rr:server")); |
| } |
| } |
| |
| function f_EPTF_COAP_rr_remove(in integer p_rrIdx) |
| runs on EPTF_COAP_LGen_CT |
| { |
| if (ischosen(v_COAP_rrDB.data[p_rrIdx].state.client)) |
| { |
| f_EPTF_COAP_rr_setState(p_rrIdx, {client := REMOVING}); |
| } |
| else |
| { |
| f_EPTF_COAP_rr_setState(p_rrIdx, {server := REMOVING}); |
| } |
| //action(%definitionId, " rr: (rrIdx: ",p_rrIdx,") ",v_COAP_rrDB.data[p_rrIdx]); |
| |
| if (v_COAP_rrDB.data[p_rrIdx].trIdx != -1) |
| { |
| if (v_COAP_trDB.data[v_COAP_rrDB.data[p_rrIdx].trIdx].rrIdx == p_rrIdx) |
| { |
| v_COAP_trDB.data[v_COAP_rrDB.data[p_rrIdx].trIdx].rrIdx := -1; |
| } |
| } |
| |
| if (v_COAP_rrDB.data[p_rrIdx].fsmCtxIdx != -1) |
| { |
| //action(%definitionId, " fsm: ",v_COAP_FsmCtxDB.data[v_COAP_rrDB.data[p_rrIdx].fsmCtxIdx]); |
| if (v_COAP_FsmCtxDB.data[v_COAP_rrDB.data[p_rrIdx].fsmCtxIdx].rrIdx == p_rrIdx) |
| { |
| v_COAP_FsmCtxDB.data[v_COAP_rrDB.data[p_rrIdx].fsmCtxIdx].rrIdx := -1; |
| } |
| } |
| |
| f_EPTF_COAP_rrDB_remove(p_rrIdx); |
| } |
| |
| function f_EPTF_COAP_rr_setState(in integer p_rrIdx, in COAP_RR_State p_nextState) |
| runs on EPTF_COAP_LGen_CT |
| { |
| 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_tr_fromRR(inout EPTF_COAP_PDU p_msg, in COAP_StepCtx p_ctx, in integer p_rrIdx, in integer p_trIdx) |
| runs on EPTF_COAP_LGen_CT |
| { |
| f_EPTF_COAP_Logging_DEBUG(log2str("current state: ", v_COAP_trDB.data[p_trIdx].state)); |
| // State: CLOSED |
| if (v_COAP_trDB.data[p_trIdx].state == CLOSED) |
| { |
| // rrIn: CON |
| if (p_msg.pdu.header.msg_type == CONFIRMABLE) |
| { |
| f_EPTF_COAP_tr_startT_retransmit(p_trIdx); |
| // start EXCHANGE_LIFETIME |
| f_EPTF_COAP_tr_startT_lifetime(p_trIdx, tsp_EPTF_COAP_EXCHANGE_LIFETIME); |
| // send to env |
| f_EPTF_COAP_tr_send(p_msg, p_trIdx); |
| // next state: RELIABLE_TX |
| f_EPTF_COAP_tr_setState(p_trIdx, RELIABLE_TX); |
| } |
| // rrIn: NON |
| else if (p_msg.pdu.header.msg_type == NON_CONFIRMABLE) |
| { |
| // out.send |
| f_EPTF_COAP_tr_send(p_msg, p_trIdx); |
| // finish |
| f_EPTF_COAP_tr_remove(p_trIdx); |
| } |
| // rrIn: ACK |
| else if (p_msg.pdu.header.msg_type == ACKNOWLEDGEMENT) |
| { |
| // out.send |
| f_EPTF_COAP_tr_send(p_msg, p_trIdx); |
| // finish |
| f_EPTF_COAP_tr_remove(p_trIdx); |
| } |
| else |
| { |
| f_EPTF_COAP_Logging_WARNING(log2str(%definitionId, "cannot handle msg type ",p_msg.pdu.header.msg_type," in state ",v_COAP_trDB.data[p_trIdx].state)); |
| } |
| } |
| // State: ACK_PENDING |
| else if (v_COAP_trDB.data[p_trIdx].state == ACK_PENDING) |
| { |
| // rrIn: ACK |
| if (p_msg.pdu.header.msg_type == ACKNOWLEDGEMENT) |
| { |
| p_msg.pdu.header.message_id := v_COAP_trDB.data[p_trIdx].mid; |
| // store in cache |
| v_COAP_trDB.data[p_trIdx].cache := p_msg; |
| // out.send |
| f_EPTF_COAP_tr_send(p_msg, p_trIdx); |
| // next state: CLOSED |
| f_EPTF_COAP_tr_setState(p_trIdx, CLOSED); |
| } |
| // rrIn: RST |
| else if (p_msg.pdu.header.msg_type == RESET) |
| { |
| p_msg.pdu.header.message_id := v_COAP_trDB.data[p_trIdx].mid; |
| // store in cache |
| v_COAP_trDB.data[p_trIdx].cache := p_msg; |
| // out.send |
| f_EPTF_COAP_tr_send(p_msg, p_trIdx); |
| // next state: CLOSED |
| f_EPTF_COAP_tr_setState(p_trIdx, CLOSED); |
| } |
| else |
| { |
| f_EPTF_COAP_Logging_WARNING(log2str(%definitionId, "cannot handle msg type ",p_msg.pdu.header.msg_type," in state ",v_COAP_trDB.data[p_trIdx].state)); |
| } |
| } |
| else |
| { |
| f_EPTF_COAP_Logging_ERROR(log2str(%definitionId, "unknown state ", p_msg)); |
| } |
| } |
| |
| function f_EPTF_COAP_tr_fromEnv(inout EPTF_COAP_PDU p_msg, in integer p_trIdx) |
| runs on EPTF_COAP_LGen_CT |
| { |
| f_EPTF_COAP_Logging_VERBOSE(log2str(%definitionId, "current state: ", v_COAP_trDB.data[p_trIdx].state)); |
| // State: CLOSED |
| if (v_COAP_trDB.data[p_trIdx].state == CLOSED) |
| { |
| // envIn: NON |
| if (p_msg.pdu.header.msg_type == NON_CONFIRMABLE) |
| { |
| // start NON_LIFETIME |
| f_EPTF_COAP_tr_startT_lifetime(p_trIdx, tsp_EPTF_COAP_NON_LIFETIME); |
| // next state: CLOSED |
| f_EPTF_COAP_tr_setState(p_trIdx, CLOSED); |
| // rrOut.send |
| if (v_COAP_trDB.data[p_trIdx].rrIdx == -1) |
| { |
| // |
| var integer vl_rrIdx := f_EPTF_COAP_rrDB_lookUp(p_msg.transportParams.localAddress, p_msg.pdu.token); |
| if (vl_rrIdx >= 0) |
| { |
| v_COAP_trDB.data[p_trIdx].rrIdx := vl_rrIdx; |
| v_COAP_rrDB.data[vl_rrIdx].trIdx := p_trIdx; |
| f_EPTF_COAP_rr_handleMsg(p_msg, vl_rrIdx); |
| } |
| else |
| { |
| f_EPTF_COAP_dispatchEventsForCode( |
| p_msg.pdu.header.code, |
| p_msg.eIdx, |
| -1, |
| {} |
| ); |
| } |
| } |
| else |
| { |
| f_EPTF_COAP_rr_handleMsg(p_msg, v_COAP_trDB.data[p_trIdx].rrIdx); |
| } |
| } |
| // envIn: CON |
| else if (p_msg.pdu.header.msg_type == CONFIRMABLE) |
| { |
| // start EXCHANGE_LIFETIME |
| f_EPTF_COAP_tr_startT_lifetime(p_trIdx, tsp_EPTF_COAP_EXCHANGE_LIFETIME); |
| // next state: ACK_PENDING |
| f_EPTF_COAP_tr_setState(p_trIdx, ACK_PENDING); |
| // rrOut.send |
| if (v_COAP_trDB.data[p_trIdx].rrIdx == -1) |
| { |
| // |
| var integer vl_rrIdx := f_EPTF_COAP_rrDB_lookUp(p_msg.transportParams.localAddress, p_msg.pdu.token); |
| if (vl_rrIdx >= 0) |
| { |
| v_COAP_trDB.data[p_trIdx].rrIdx := vl_rrIdx; |
| v_COAP_rrDB.data[vl_rrIdx].trIdx := p_trIdx; |
| f_EPTF_COAP_rr_handleMsg(p_msg, vl_rrIdx); |
| } |
| else |
| { |
| f_EPTF_COAP_dispatchEventsForCode( |
| p_msg.pdu.header.code, |
| p_msg.eIdx, |
| -1, |
| {} |
| ); |
| } |
| } |
| else |
| { |
| f_EPTF_COAP_rr_handleMsg(p_msg, v_COAP_trDB.data[p_trIdx].rrIdx); |
| } |
| } |
| else |
| { |
| f_EPTF_COAP_Logging_WARNING(log2str(%definitionId, "cannot handle msg type ",p_msg.pdu.header.msg_type," in state ",v_COAP_trDB.data[p_trIdx].state)); |
| } |
| } |
| // State: RELIABLE_TX |
| else if (v_COAP_trDB.data[p_trIdx].state == RELIABLE_TX) |
| { |
| if (p_msg.pdu.header.msg_type == ACKNOWLEDGEMENT) |
| { |
| // cancel T retransmission |
| f_EPTF_COAP_tr_cancelT_retransmit(p_trIdx); |
| if (not f_EPTF_COAP_isEmpty(p_msg.pdu)) |
| { |
| f_EPTF_COAP_rr_handleMsg(p_msg, v_COAP_trDB.data[p_trIdx].rrIdx); |
| } |
| // next state: CLOSED |
| f_EPTF_COAP_tr_setState(p_trIdx, CLOSED); |
| } |
| else if (p_msg.pdu.header.msg_type == RESET) |
| { |
| // cancel T retransmission |
| f_EPTF_COAP_tr_cancelT_retransmit(p_trIdx); |
| // report reset |
| f_EPTF_COAP_rr_reset(v_COAP_trDB.data[p_trIdx].rrIdx); |
| // next state: CLOSED |
| f_EPTF_COAP_tr_setState(p_trIdx, CLOSED); |
| } |
| else |
| { |
| f_EPTF_COAP_Logging_WARNING(log2str(%definitionId, "cannot handle msg type ",p_msg.pdu.header.msg_type," in state ",v_COAP_trDB.data[p_trIdx].state)); |
| } |
| } |
| else if (v_COAP_trDB.data[p_trIdx].state == ACK_PENDING) |
| { |
| f_EPTF_COAP_Logging_WARNING(log2str(%definitionId, " messages from environment in ACK_PENDING are not expected")); |
| } |
| else |
| { |
| f_EPTF_COAP_Logging_ERROR(log2str(%definitionId, " unknown state")); |
| } |
| } |
| |
| function f_EPTF_COAP_tr_cancel(in integer p_trIdx) |
| runs on EPTF_COAP_LGen_CT |
| { |
| if (v_COAP_trDB.data[p_trIdx].state == RELIABLE_TX) |
| { |
| // cancel T retransmission |
| f_EPTF_COAP_tr_cancelT_retransmit(p_trIdx); |
| // next state: CLOSED |
| f_EPTF_COAP_tr_setState(p_trIdx, CLOSED); |
| } |
| else |
| { |
| f_EPTF_COAP_Logging_WARNING(log2str(%definitionId, " cancel only handled in RELIABLE_ACK state")); |
| } |
| } |
| |
| function f_EPTF_COAP_tr_lifetime(in EPTF_ScheduledAction pl_action, in integer pl_eventIndex) |
| runs on EPTF_COAP_LGen_CT |
| return boolean |
| { |
| var integer vl_trIdx := pl_action.actionId[0]; |
| v_COAP_trDB.data[vl_trIdx].lifetimeTimer := -1; |
| |
| if (v_COAP_trDB.data[vl_trIdx].state == RELIABLE_TX) |
| { |
| // cancel T retransmission |
| f_EPTF_COAP_tr_cancelT_retransmit(vl_trIdx); |
| // report trTimeout event |
| f_EPTF_COAP_rr_timeout(v_COAP_trDB.data[vl_trIdx].rrIdx); |
| // next state: CLOSED |
| f_EPTF_COAP_tr_setState(vl_trIdx, CLOSED); |
| } |
| |
| f_EPTF_COAP_tr_remove(vl_trIdx); |
| |
| return true; |
| } |
| |
| function f_EPTF_COAP_tr_retransmit(in EPTF_ScheduledAction pl_action, in integer pl_eventIndex) |
| runs on EPTF_COAP_LGen_CT |
| return boolean |
| { |
| var integer vl_trIdx := pl_action.actionId[0]; |
| v_COAP_trDB.data[vl_trIdx].retransmitTimer := -1; |
| |
| if (ispresent(v_COAP_trDB.data[vl_trIdx].cache)) |
| { |
| f_EPTF_COAP_tr_startT_retransmit(vl_trIdx); |
| f_EPTF_COAP_tr_send(v_COAP_trDB.data[vl_trIdx].cache, vl_trIdx); |
| } |
| else |
| { |
| f_EPTF_COAP_Logging_WARNING(log2str(%definitionId, " cannot retransmit empty cache")); |
| } |
| |
| return true; |
| } |
| |
| function f_EPTF_COAP_tr_startT_retransmit(in integer pl_trIdx) |
| runs on EPTF_COAP_LGen_CT |
| return boolean |
| { |
| var boolean retval; |
| var EPTF_ActionId vl_actionId; |
| var float vl_time := v_COAP_trDB.data[pl_trIdx].retransmitTimerValue; |
| |
| vl_actionId[0] := pl_trIdx; |
| |
| retval := f_EPTF_SchedulerComp_scheduleAction( |
| f_EPTF_SchedulerComp_snapshotTime() + vl_time, |
| refers(f_EPTF_COAP_tr_retransmit), |
| vl_actionId, |
| v_COAP_trDB.data[pl_trIdx].retransmitTimer |
| ); |
| |
| // start retransTimeout (TODO calculate next rentransmission) |
| v_COAP_trDB.data[pl_trIdx].retransmitTimerValue := v_COAP_trDB.data[pl_trIdx].retransmitTimerValue * 2.0; |
| |
| return retval; |
| } |
| |
| function f_EPTF_COAP_tr_cancelT_retransmit(in integer pl_trIdx) |
| runs on EPTF_COAP_LGen_CT |
| { |
| if (v_COAP_trDB.data[pl_trIdx].retransmitTimer >= 0) |
| { |
| if(not f_EPTF_SchedulerComp_CancelEvent(v_COAP_trDB.data[pl_trIdx].retransmitTimer)) |
| { |
| f_EPTF_COAP_Logging_WARNING(log2str(%definitionId,": could not cancel timer")); |
| } |
| v_COAP_trDB.data[pl_trIdx].retransmitTimer := -1; |
| } |
| } |
| |
| function f_EPTF_COAP_tr_startT_lifetime(in integer pl_trIdx, in float pl_time) |
| runs on EPTF_COAP_LGen_CT |
| return boolean |
| { |
| var boolean retval; |
| var EPTF_ActionId vl_actionId; |
| |
| vl_actionId[0] := pl_trIdx; |
| |
| retval := f_EPTF_SchedulerComp_scheduleAction( |
| f_EPTF_SchedulerComp_snapshotTime() + pl_time, |
| refers(f_EPTF_COAP_tr_lifetime), |
| vl_actionId, |
| v_COAP_trDB.data[pl_trIdx].lifetimeTimer |
| ); |
| |
| return retval; |
| } |
| |
| function f_EPTF_COAP_tr_cancelT_lifetime(in integer pl_trIdx) |
| runs on EPTF_COAP_LGen_CT |
| { |
| if (v_COAP_trDB.data[pl_trIdx].lifetimeTimer >= 0) |
| { |
| if(not f_EPTF_SchedulerComp_CancelEvent(v_COAP_trDB.data[pl_trIdx].lifetimeTimer)) |
| { |
| f_EPTF_COAP_Logging_WARNING(log2str(%definitionId,": could not cancel timer")); |
| } |
| v_COAP_trDB.data[pl_trIdx].lifetimeTimer := -1; |
| } |
| } |
| |
| function f_EPTF_COAP_tr_send(inout EPTF_COAP_PDU p_msg, in integer p_trIdx) |
| runs on EPTF_COAP_LGen_CT |
| { |
| v_COAP_trDB.data[p_trIdx].cache := p_msg; |
| vf_EPTF_COAP_Transport_send.apply(p_msg); |
| } |
| |
| function f_EPTF_COAP_tr_remove(in integer p_trIdx) |
| runs on EPTF_COAP_LGen_CT |
| { |
| f_EPTF_COAP_tr_setState(p_trIdx, REMOVING); |
| |
| f_EPTF_COAP_tr_cancelT_lifetime(p_trIdx); |
| f_EPTF_COAP_tr_cancelT_retransmit(p_trIdx); |
| |
| if (v_COAP_trDB.data[p_trIdx].rrIdx != -1) |
| { |
| if (v_COAP_rrDB.data[v_COAP_trDB.data[p_trIdx].rrIdx].trIdx == p_trIdx) |
| { |
| v_COAP_rrDB.data[v_COAP_trDB.data[p_trIdx].rrIdx].trIdx := -1; |
| } |
| } |
| f_EPTF_COAP_trDB_remove(p_trIdx); |
| } |
| |
| function f_EPTF_COAP_tr_setState(in integer p_trIdx, in COAP_Transaction_State p_nextState) |
| runs on EPTF_COAP_LGen_CT |
| { |
| 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_Logging_VERBOSE(in @lazy charstring pl_message) |
| runs on EPTF_COAP_LGen_CT |
| { |
| if (c_EPTF_Common_debugSwitch) { |
| f_EPTF_Logging_debugV2(pl_message, v_COAP_loggingMaskId, {c_COAP_LGen_Logging_DEBUGV}); |
| } |
| } |
| |
| function f_EPTF_COAP_Logging_DEBUG(in @lazy charstring pl_message) |
| runs on EPTF_COAP_LGen_CT |
| { |
| if (c_EPTF_Common_debugSwitch) { |
| f_EPTF_Logging_debugV2(pl_message, v_COAP_loggingMaskId, {c_COAP_LGen_Logging_DEBUG}); |
| } |
| } |
| |
| function f_EPTF_COAP_Logging_WARNING(in @lazy charstring pl_message) |
| runs on EPTF_COAP_LGen_CT |
| { |
| if (c_EPTF_Common_debugSwitch) { |
| f_EPTF_Logging_debugV2(pl_message, v_COAP_loggingMaskId, {c_COAP_LGen_Logging_WARNING}); |
| } |
| } |
| |
| function f_EPTF_COAP_Logging_ERROR(in @lazy charstring pl_message) |
| runs on EPTF_COAP_LGen_CT |
| { |
| if (c_EPTF_Common_debugSwitch) { |
| f_EPTF_Logging_debugV2(pl_message, v_COAP_loggingMaskId, {c_COAP_LGen_Logging_ERROR}); |
| } |
| } |
| |
| function f_EPTF_COAP_declareEvents() |
| runs on EPTF_COAP_LGen_CT |
| { |
| var integer vl_dummy; |
| |
| if ( |
| c_COAP_eventIdx_EMPTY != f_EPTF_LGenBase_declareFsmEvent(c_COAP_behaviorType, c_COAP_eventName_EMPTY) or |
| c_COAP_eventIdx_GET != f_EPTF_LGenBase_declareFsmEvent(c_COAP_behaviorType, c_COAP_eventName_GET) or |
| c_COAP_eventIdx_POST != f_EPTF_LGenBase_declareFsmEvent(c_COAP_behaviorType, c_COAP_eventName_POST) or |
| c_COAP_eventIdx_PUT != f_EPTF_LGenBase_declareFsmEvent(c_COAP_behaviorType, c_COAP_eventName_PUT) or |
| c_COAP_eventIdx_DELETE != f_EPTF_LGenBase_declareFsmEvent(c_COAP_behaviorType, c_COAP_eventName_DELETE) |
| ){ |
| f_EPTF_LGenBase_log(); |
| log("error"); mtc.stop |
| } |
| |
| for (var integer i:=5; i<700; i:=i+1) |
| { |
| vl_dummy := f_EPTF_LGenBase_declareFsmEvent(c_COAP_behaviorType, "COAP rsp: "&int2str(i)); |
| } |
| |
| if ( |
| c_COAP_eventIdx_1xx != f_EPTF_LGenBase_declareFsmEvent(c_COAP_behaviorType, c_COAP_eventName_1xx) or |
| c_COAP_eventIdx_2xx != f_EPTF_LGenBase_declareFsmEvent(c_COAP_behaviorType, c_COAP_eventName_2xx) or |
| c_COAP_eventIdx_3xx != f_EPTF_LGenBase_declareFsmEvent(c_COAP_behaviorType, c_COAP_eventName_3xx) or |
| c_COAP_eventIdx_4xx != f_EPTF_LGenBase_declareFsmEvent(c_COAP_behaviorType, c_COAP_eventName_4xx) or |
| c_COAP_eventIdx_5xx != f_EPTF_LGenBase_declareFsmEvent(c_COAP_behaviorType, c_COAP_eventName_5xx) or |
| c_COAP_eventIdx_6xx != f_EPTF_LGenBase_declareFsmEvent(c_COAP_behaviorType, c_COAP_eventName_6xx) or |
| c_COAP_eventIdx_3xxto6xx != f_EPTF_LGenBase_declareFsmEvent(c_COAP_behaviorType, c_COAP_eventName_3xxto6xx) or |
| c_COAP_eventIdx_transportSucc != f_EPTF_LGenBase_declareFsmEvent(c_COAP_behaviorType, c_COAP_eventName_transportSucc) or |
| c_COAP_eventIdx_transportFail != f_EPTF_LGenBase_declareFsmEvent(c_COAP_behaviorType, c_COAP_eventName_transportFail) or |
| c_COAP_eventIdx_trRST != f_EPTF_LGenBase_declareFsmEvent(c_COAP_behaviorType, c_COAP_eventName_trRST) or |
| c_COAP_eventIdx_trTimeout != f_EPTF_LGenBase_declareFsmEvent(c_COAP_behaviorType, c_COAP_eventName_trTimeout) |
| ){ |
| f_EPTF_LGenBase_log(); |
| log("error"); mtc.stop |
| } |
| } |
| |
| function f_EPTF_COAP_declareSteps() |
| runs on EPTF_COAP_LGen_CT |
| { |
| if ( |
| c_COAP_stepIdx_init != f_EPTF_LGenBase_declareStep(c_COAP_behaviorType,{c_COAP_stepName_init, refers(f_COAP_step_init)}) or |
| c_COAP_stepIdx_cleanUp != f_EPTF_LGenBase_declareStep(c_COAP_behaviorType,{c_COAP_stepName_cleanUp, refers(f_COAP_step_cleanUp) }) or |
| c_COAP_stepIdx_setLocalAddress != f_EPTF_LGenBase_declareStep(c_COAP_behaviorType,{c_COAP_stepName_setLocalAddress, refers(f_COAP_step_setLocalAddress)}) or |
| c_COAP_stepIdx_setRemoteAddress_byIntIdx != f_EPTF_LGenBase_declareStep(c_COAP_behaviorType,{c_COAP_stepName_setRemoteAddress_byIntIdx, refers(f_COAP_step_setRemoteAddress_byIntIdx)}) or |
| c_COAP_stepIdx_send != f_EPTF_LGenBase_declareStep(c_COAP_behaviorType,{c_COAP_stepName_send, refers(f_COAP_step_send)}) or |
| c_COAP_stepIdx_loadTemplate_byIntIdx != f_EPTF_LGenBase_declareStep(c_COAP_behaviorType,{c_COAP_stepName_loadTemplate_byIntIdx, refers(f_COAP_step_loadTemplate_byIntIdx)}) or |
| c_COAP_stepIdx_handleRequest != f_EPTF_LGenBase_declareStep(c_COAP_behaviorType,{c_COAP_stepName_handleRequest, refers(f_COAP_step_handleRequest)}) or |
| c_COAP_stepIdx_sendResponse != f_EPTF_LGenBase_declareStep(c_COAP_behaviorType,{c_COAP_stepName_sendResponse, refers(f_COAP_step_sendResponse)}) or |
| c_COAP_stepIdx_sendAccept != f_EPTF_LGenBase_declareStep(c_COAP_behaviorType,{c_COAP_stepName_sendAccept, refers(f_COAP_step_sendAccept)}) or |
| c_COAP_stepIdx_startListening != f_EPTF_LGenBase_declareStep(c_COAP_behaviorType,{c_COAP_stepName_startListening, refers(f_COAP_step_startListening)}) or |
| c_COAP_stepIdx_reportCoapEventForEntity != f_EPTF_LGenBase_declareStep(c_COAP_behaviorType,{c_COAP_stepName_reportCoapEventForEntity, refers(f_COAP_step_reportCoapEventForEntity)}) or |
| c_COAP_stepIdx_loadTemplate_byStringId != f_EPTF_LGenBase_declareStep(c_COAP_behaviorType,{c_COAP_stepName_loadTemplate_byStringId, refers(f_COAP_step_loadTemplate_byStringId)}) or |
| c_COAP_stepIdx_setRemoteAddress_byVars != f_EPTF_LGenBase_declareStep(c_COAP_behaviorType,{c_COAP_stepName_setRemoteAddress_byVars, refers(f_COAP_step_setRemoteAddress_byVars)}) |
| ) |
| { |
| f_EPTF_LGenBase_log(); |
| log("EPTF_COAP_LGen declaration error"); mtc.stop |
| } |
| } |
| |
| function f_COAP_step_init(in EPTF_LGenBase_TestStepArgs pl_ptr) |
| runs on EPTF_COAP_LGen_CT |
| { |
| f_EPTF_COAP_Logging_DEBUG(log2str(%definitionId)); |
| |
| var integer vl_eIdx := pl_ptr.eIdx; |
| var integer vl_fsmIdx := pl_ptr.refContext.fCtxIdx; |
| var integer vl_newFsmCtxIdx := -1; |
| |
| if (f_EPTF_COAP_isFsmInitialized(vl_eIdx, vl_fsmIdx, vl_newFsmCtxIdx)) { return } |
| |
| vl_newFsmCtxIdx := f_EPTF_FBQ_getOrCreateFreeSlot(v_COAP_FsmCtxDB.queue); |
| f_EPTF_FBQ_moveFromFreeHeadToBusyTail(v_COAP_FsmCtxDB.queue); |
| |
| f_EPTF_COAP_Logging_DEBUG(log2str(%definitionId, ": initializing fsm ", vl_fsmIdx, " for entity ",vl_eIdx)); |
| |
| f_EPTF_LGenBase_setAppDataItemOfFsmCtx(vl_eIdx, vl_fsmIdx, v_COAP_bIdx, c_COAP_AppData_fsmCtxIdx, vl_newFsmCtxIdx); |
| |
| v_COAP_FsmCtxDB.data[vl_newFsmCtxIdx] := c_COAP_FsmCtx_init; |
| v_COAP_FsmCtxDB.data[vl_newFsmCtxIdx].eIdx := vl_eIdx; |
| } |
| |
| function f_COAP_step_cleanUp(in EPTF_LGenBase_TestStepArgs pl_ptr) |
| runs on EPTF_COAP_LGen_CT |
| { |
| f_EPTF_COAP_Logging_DEBUG(log2str(%definitionId)); |
| |
| var integer vl_eIdx:=pl_ptr.eIdx; |
| var integer vl_fsmIdx := pl_ptr.refContext.fCtxIdx; |
| var integer vl_fsmCtxIdx := -1; |
| |
| if (not f_EPTF_COAP_isFsmInitialized(vl_eIdx, vl_fsmIdx, vl_fsmCtxIdx)) |
| { |
| f_EPTF_COAP_Logging_DEBUG(%definitionId&": FSM has not been initialized"); |
| return; |
| } |
| |
| var integer vl_eCtxIdx := f_EPTF_LGenBase_getBehaviorCtxItem(vl_eIdx, v_COAP_bIdx, 0); |
| |
| f_EPTF_COAP_Logging_DEBUG(log2str(%definitionId,": FSM database: ",v_COAP_FsmCtxDB.data[vl_fsmCtxIdx])); |
| |
| //f_EPTF_SIP_CancelAllTimers_FSM(vl_userIdx, vl_FSMIdx); |
| |
| v_COAP_FsmCtxDB.data[vl_fsmCtxIdx] := c_COAP_FsmCtx_init; |
| |
| f_EPTF_FBQ_moveFromBusyToFreeTail(vl_fsmCtxIdx, v_COAP_FsmCtxDB.queue); |
| |
| f_EPTF_LGenBase_setAppDataItemOfFsmCtx(vl_eIdx, vl_fsmIdx, v_COAP_bIdx, c_COAP_AppData_fsmCtxIdx, -1); |
| } |
| |
| function f_COAP_step_setLocalAddress(in EPTF_LGenBase_TestStepArgs pl_ptr) |
| runs on EPTF_COAP_LGen_CT |
| { |
| f_EPTF_COAP_Logging_DEBUG(log2str(%definitionId)); |
| |
| if (not f_EPTF_COAP_setStepCtx(pl_ptr, v_COAP_ctx)) { return; } |
| |
| f_EPTF_COAP_getIntValue(pl_ptr.refContext.fRefArgs, 0, v_COAP_EntityCtxDB.data[v_COAP_ctx.eCtxIdx].localAddressIdx); |
| } |
| |
| function f_COAP_step_setRemoteAddress_byIntIdx(in EPTF_LGenBase_TestStepArgs pl_ptr) |
| runs on EPTF_COAP_LGen_CT |
| { |
| f_EPTF_COAP_Logging_DEBUG(log2str(%definitionId)); |
| |
| if (not f_EPTF_COAP_setStepCtx(pl_ptr, v_COAP_ctx)) { return; } |
| |
| f_EPTF_COAP_getIntValue(pl_ptr.refContext.fRefArgs, 0, v_COAP_FsmCtxDB.data[v_COAP_ctx.fsmCtxIdx].remoteAddressIdx); |
| } |
| |
| function f_COAP_step_loadTemplate_byIntIdx(in EPTF_LGenBase_TestStepArgs pl_ptr) |
| runs on EPTF_COAP_LGen_CT |
| { |
| f_EPTF_COAP_Logging_DEBUG(log2str(%definitionId)); |
| |
| if (not f_EPTF_COAP_setStepCtx(pl_ptr, v_COAP_ctx)) { return; } |
| |
| var integer vl_templateIdx := -1; |
| f_EPTF_COAP_getIntValue(pl_ptr.refContext.fRefArgs, 0, vl_templateIdx); |
| |
| f_EPTF_COAP_templateDB_get(vl_templateIdx, v_COAP_msgToSend.pdu); |
| } |
| |
| function f_COAP_step_loadTemplate_byStringId(in EPTF_LGenBase_TestStepArgs pl_ptr) |
| runs on EPTF_COAP_LGen_CT |
| { |
| f_EPTF_COAP_Logging_DEBUG(log2str(%definitionId)); |
| |
| if (not f_EPTF_COAP_setStepCtx(pl_ptr, v_COAP_ctx)) { return; } |
| |
| var charstring vl_templateId := f_EPTF_LGenBase_charstringValOfStep(pl_ptr); |
| var integer vl_templateIdx := f_EPTF_COAP_templateDB_lookUp(vl_templateId); |
| |
| if (vl_templateIdx >= 0) |
| { |
| f_EPTF_COAP_templateDB_get(vl_templateIdx, v_COAP_msgToSend.pdu); |
| } |
| else |
| { |
| f_EPTF_COAP_Logging_WARNING(log2str(%definitionId," Couldn't find template with id: ", vl_templateId)); |
| } |
| } |
| |
| function f_COAP_step_send(in EPTF_LGenBase_TestStepArgs pl_ptr) |
| runs on EPTF_COAP_LGen_CT |
| { |
| f_EPTF_COAP_Logging_DEBUG(log2str(%definitionId," ",pl_ptr)); |
| |
| if (not f_EPTF_COAP_setStepCtx(pl_ptr, v_COAP_ctx)) { return; } |
| |
| f_EPTF_COAP_addressDB_get(v_COAP_msgToSend.transportParams.localAddress, v_COAP_EntityCtxDB.data[v_COAP_ctx.eCtxIdx].localAddressIdx); |
| if (v_COAP_FsmCtxDB.data[v_COAP_ctx.fsmCtxIdx].rrIdx == -1) |
| { |
| // If there is no ongoing RR, we will send to the remote address |
| f_EPTF_COAP_addressDB_get(v_COAP_msgToSend.transportParams.remoteAddress, v_COAP_FsmCtxDB.data[v_COAP_ctx.fsmCtxIdx].remoteAddressIdx); |
| } |
| v_COAP_msgToSend.transportParams.proto := {udp := {}}; |
| v_COAP_msgToSend.eIdx := v_COAP_ctx.eIdx; |
| |
| f_EPTF_COAP_Logging_DEBUG(log2str(%definitionId," msg to send: ",v_COAP_msgToSend)); |
| |
| f_EPTF_COAP_stack_fromApp(v_COAP_msgToSend, v_COAP_ctx); |
| |
| f_EPTF_SchedulerComp_refreshSnapshotTime(); |
| } |
| |
| function f_COAP_step_handleRequest(in EPTF_LGenBase_TestStepArgs pl_ptr) |
| runs on EPTF_COAP_LGen_CT |
| { |
| f_EPTF_COAP_Logging_DEBUG(log2str(%definitionId)); |
| |
| if (not f_EPTF_COAP_setStepCtx(pl_ptr, v_COAP_ctx)) { return; } |
| |
| // New RR |
| var COAP_RR vl_rr := c_COAP_RR_init; |
| vl_rr.eIdx := v_COAP_ctx.eIdx; |
| vl_rr.fsmIdx := v_COAP_ctx.fsmIdx; |
| vl_rr.fsmCtxIdx := v_COAP_ctx.fsmCtxIdx; |
| vl_rr.addrIdx := v_COAP_EntityCtxDB.data[v_COAP_ctx.eCtxIdx].localAddressIdx; |
| vl_rr.token := v_COAP_msgToProcess.pdu.token; |
| vl_rr.state.server := IDLE; |
| |
| var integer vl_rrIdx := f_EPTF_COAP_rrDB_add(vl_rr); |
| v_COAP_FsmCtxDB.data[v_COAP_ctx.fsmCtxIdx].rrIdx := vl_rrIdx; |
| |
| // Get TR |
| var integer vl_trIdx := f_EPTF_COAP_trDB_lookUp(v_COAP_msgToProcess.transportParams.localAddress, v_COAP_msgToProcess.pdu.header.message_id, INCOMING); |
| if (vl_trIdx < 0) |
| { |
| f_EPTF_COAP_Logging_WARNING(log2str(%definitionId, " couldn't find incoming transaction")); |
| } |
| v_COAP_trDB.data[vl_trIdx].rrIdx := vl_rrIdx; |
| v_COAP_rrDB.data[vl_rrIdx].trIdx := vl_trIdx; |
| |
| f_EPTF_COAP_rr_handleMsg(v_COAP_msgToProcess, vl_rrIdx); |
| } |
| |
| // Matches the msg_Type of response to the incoming request and the current state |
| // That is: |
| // - req.NON -> rsp.NON |
| // - req.CON && state.SERVING -> rsp.ACK |
| // - req.CON && state.SEPARATE -> rsp.CON |
| function f_COAP_step_sendResponse(in EPTF_LGenBase_TestStepArgs pl_ptr) |
| runs on EPTF_COAP_LGen_CT |
| { |
| f_EPTF_COAP_Logging_DEBUG(log2str(%definitionId)); |
| |
| if (not f_EPTF_COAP_setStepCtx(pl_ptr, v_COAP_ctx)) { return; } |
| |
| // We need an ongoing RR! |
| if (v_COAP_FsmCtxDB.data[v_COAP_ctx.fsmCtxIdx].rrIdx != -1) |
| { |
| var integer vl_rrIdx := v_COAP_FsmCtxDB.data[v_COAP_ctx.fsmCtxIdx].rrIdx; |
| if (ischosen(v_COAP_rrDB.data[vl_rrIdx].state.server)) |
| { |
| if (ispresent(v_COAP_rrDB.data[vl_rrIdx].request)) |
| { |
| if (v_COAP_rrDB.data[vl_rrIdx].request.pdu.header.msg_type == NON_CONFIRMABLE) { |
| v_COAP_msgToSend.pdu.header.msg_type := NON_CONFIRMABLE; |
| } |
| else //if (v_COAP_rrDB.data[vl_rrIdx].request.pdu.header.msg_type == CONFIRMABLE) |
| { |
| if (v_COAP_rrDB.data[vl_rrIdx].state.server == SERVING) { |
| v_COAP_msgToSend.pdu.header.msg_type := ACKNOWLEDGEMENT; |
| } |
| else if (v_COAP_rrDB.data[vl_rrIdx].state.server == SEPARATE) { |
| v_COAP_msgToSend.pdu.header.msg_type := CONFIRMABLE; |
| } |
| else { |
| f_EPTF_COAP_Logging_ERROR(log2str(%definitionId, " unrecognized state")); |
| } |
| } |
| f_EPTF_COAP_addressDB_get(v_COAP_msgToSend.transportParams.localAddress, v_COAP_EntityCtxDB.data[v_COAP_ctx.eCtxIdx].localAddressIdx); |
| v_COAP_msgToSend.transportParams.proto := {udp := {}}; |
| v_COAP_msgToSend.eIdx := v_COAP_ctx.eIdx; |
| |
| f_EPTF_COAP_stack_fromApp(v_COAP_msgToSend, v_COAP_ctx); |
| } |
| else { |
| f_EPTF_COAP_Logging_WARNING(log2str(%definitionId, " there is no request received, therefore response cannot be sent!")); |
| } |
| } |
| else { |
| f_EPTF_COAP_Logging_WARNING(log2str(%definitionId, " ongoing rr must be a server, in a client rr no response can be sent!")); |
| } |
| } |
| else { |
| f_EPTF_COAP_Logging_WARNING(log2str(%definitionId, " there is no ongoing RR, therefore response cannot be sent!")); |
| } |
| |
| f_EPTF_SchedulerComp_refreshSnapshotTime(); |
| } |
| |
| function f_COAP_step_sendAccept(in EPTF_LGenBase_TestStepArgs pl_ptr) |
| runs on EPTF_COAP_LGen_CT |
| { |
| f_EPTF_COAP_Logging_DEBUG(log2str(%definitionId)); |
| |
| if (not f_EPTF_COAP_setStepCtx(pl_ptr, v_COAP_ctx)) { return; } |
| |
| // We need an ongoing RR! |
| if (v_COAP_FsmCtxDB.data[v_COAP_ctx.fsmCtxIdx].rrIdx != -1) |
| { |
| var integer vl_rrIdx := v_COAP_FsmCtxDB.data[v_COAP_ctx.fsmCtxIdx].rrIdx; |
| if (ischosen(v_COAP_rrDB.data[vl_rrIdx].state.server) and v_COAP_rrDB.data[vl_rrIdx].state.server == SERVING) |
| { |
| if (ispresent(v_COAP_rrDB.data[vl_rrIdx].request)) |
| { |
| v_COAP_msgToSend.pdu := valueof(t_CoAP_EmptyAck); |
| |
| f_EPTF_COAP_addressDB_get(v_COAP_msgToSend.transportParams.localAddress, v_COAP_EntityCtxDB.data[v_COAP_ctx.eCtxIdx].localAddressIdx); |
| v_COAP_msgToSend.transportParams.proto := {udp := {}}; |
| v_COAP_msgToSend.eIdx := v_COAP_ctx.eIdx; |
| |
| f_EPTF_COAP_stack_fromApp(v_COAP_msgToSend, v_COAP_ctx); |
| } |
| else { |
| f_EPTF_COAP_Logging_WARNING(log2str(%definitionId, " there is no request received, therefore empty ack response cannot be sent!")); |
| } |
| } |
| else { |
| f_EPTF_COAP_Logging_WARNING(log2str(%definitionId, " ongoing rr must be a server, and the rr must be in SERVING state!")); |
| } |
| } |
| else { |
| f_EPTF_COAP_Logging_WARNING(log2str(%definitionId, " there is no ongoing RR, therefore empty ack response cannot be sent!")); |
| } |
| |
| f_EPTF_SchedulerComp_refreshSnapshotTime(); |
| } |
| |
| function f_COAP_step_startListening(in EPTF_LGenBase_TestStepArgs pl_ptr) |
| runs on EPTF_COAP_LGen_CT |
| { |
| if (not f_EPTF_COAP_setStepCtx(pl_ptr, v_COAP_ctx)) { return; } |
| |
| var EPTF_COAP_Transport_Request vl_req := c_EPTF_COAP_Transport_Request_init; |
| vl_req.eIdx := v_COAP_ctx.eIdx; |
| vl_req.fsmIdx := v_COAP_ctx.fsmIdx; |
| |
| f_EPTF_COAP_addressDB_get(vl_req.params.startListening.localAddress, v_COAP_EntityCtxDB.data[v_COAP_ctx.eCtxIdx].localAddressIdx); |
| |
| vf_EPTF_COAP_Transport_apiRequest.apply(vl_req); |
| } |
| |
| |
| // 1st param: remoteHost: charstring |
| // 2nd param: remotePort: integer |
| function f_COAP_step_setRemoteAddress_byVars(in EPTF_LGenBase_TestStepArgs pl_ptr) |
| runs on EPTF_COAP_LGen_CT |
| { |
| f_EPTF_COAP_Logging_DEBUG(log2str(%definitionId)); |
| |
| if (not f_EPTF_COAP_setStepCtx(pl_ptr, v_COAP_ctx)) { return; } |
| |
| var EPTF_IntegerList vl_varIds := {}; |
| f_EPTF_LGenBase_fsmVarIdListFromStep(pl_ptr, vl_varIds); |
| |
| if (sizeof(vl_varIds)==2) |
| { |
| var EPTF_Var_DirectContent vl_host, vl_port; |
| f_EPTF_Var_getContent(vl_varIds[0], vl_host); |
| f_EPTF_Var_getContent(vl_varIds[1], vl_port); |
| |
| if (not ischosen(vl_host.charstringVal)) { |
| f_EPTF_COAP_Logging_WARNING(log2str(%definitionId, " first param is not charstring variable!")); |
| return; |
| } |
| if (not ischosen(vl_port.intVal)) { |
| f_EPTF_COAP_Logging_WARNING(log2str(%definitionId, " second param is not integer variable!")); |
| return; |
| } |
| |
| f_EPTF_COAP_addressDB_add( |
| { |
| hostName := vl_host.charstringVal, |
| portNumber := vl_port.intVal |
| }, |
| v_COAP_FsmCtxDB.data[v_COAP_ctx.fsmCtxIdx].remoteAddressIdx |
| ); |
| } |
| else { |
| f_EPTF_COAP_Logging_WARNING(log2str(%definitionId, " two variables are needed as params!")); |
| } |
| } |
| |
| function f_COAP_step_reportCoapEventForEntity(in EPTF_LGenBase_TestStepArgs pl_ptr) |
| runs on EPTF_COAP_LGen_CT |
| { |
| f_EPTF_COAP_Logging_DEBUG(log2str(%definitionId)); |
| |
| if (not f_EPTF_COAP_setStepCtx(pl_ptr, v_COAP_ctx)) { return; } |
| |
| var integer vl_paramValue := -1; |
| f_EPTF_COAP_getIntValue(pl_ptr.refContext.fRefArgs, 0, vl_paramValue); |
| |
| if (vl_paramValue == c_COAP_stepParam_true) { |
| v_COAP_EntityCtxDB.data[v_COAP_ctx.eCtxIdx].reportCoapEvent := true; |
| } |
| else { |
| v_COAP_EntityCtxDB.data[v_COAP_ctx.eCtxIdx].reportCoapEvent := false; |
| } |
| } |
| |
| function f_EPTF_COAP_setStepCtx(in EPTF_LGenBase_TestStepArgs pl_ptr, inout COAP_StepCtx p_ctx) |
| runs on EPTF_COAP_LGen_CT |
| return boolean |
| { |
| if (not f_EPTF_COAP_isFsmInitialized(pl_ptr.eIdx, pl_ptr.refContext.fCtxIdx, p_ctx.fsmCtxIdx)) |
| { |
| f_EPTF_COAP_Logging_WARNING(%definitionId & |
| ": FSM has not been initialized. The f_COAP_step_init function must be called as first step in the FSMs using COAP."); |
| return false; |
| } |
| |
| p_ctx.eIdx := pl_ptr.eIdx; |
| p_ctx.fsmIdx := pl_ptr.refContext.fCtxIdx; |
| p_ctx.eCtxIdx := f_EPTF_LGenBase_getBehaviorCtxItem(pl_ptr.eIdx, v_COAP_bIdx, 0); |
| |
| return true; |
| } |
| |
| function f_EPTF_COAP_setCtx(in integer p_eIdx, in integer p_fsmIdx, inout COAP_StepCtx p_ctx) |
| runs on EPTF_COAP_LGen_CT |
| return boolean |
| { |
| if (not f_EPTF_COAP_isFsmInitialized(p_eIdx, p_fsmIdx, p_ctx.fsmCtxIdx)) |
| { |
| f_EPTF_COAP_Logging_WARNING(%definitionId & |
| ": FSM has not been initialized. The f_COAP_step_init function must be called as first step in the FSMs using COAP."); |
| return false; |
| } |
| |
| p_ctx.eIdx := p_eIdx; |
| p_ctx.fsmIdx := p_fsmIdx; |
| p_ctx.eCtxIdx := f_EPTF_LGenBase_getBehaviorCtxItem(p_eIdx, v_COAP_bIdx, 0); |
| |
| return true; |
| } |
| |
| function f_EPTF_COAP_isFsmInitialized(in integer pl_eIdx, in integer pl_fsmIdx, inout integer pl_fsmCtxIdx) |
| runs on EPTF_COAP_LGen_CT |
| return boolean |
| { |
| pl_fsmCtxIdx := -1; |
| |
| var EPTF_IntegerList vl_appData := f_EPTF_LGenBase_getAppDataListOfFsmCtx(pl_eIdx, pl_fsmIdx, v_COAP_bIdx); |
| |
| if (c_COAP_AppData_fsmCtxIdx < sizeof(vl_appData)) |
| { |
| pl_fsmCtxIdx := vl_appData[c_COAP_AppData_fsmCtxIdx]; |
| } |
| |
| return -1 < pl_fsmCtxIdx and sizeof(v_COAP_FsmCtxDB.data) > pl_fsmCtxIdx; |
| } |
| |
| function f_EPTF_COAP_getIntValue( |
| in EPTF_IntegerList pl_intList, |
| in integer pl_number, |
| inout integer pl_value) |
| return boolean |
| { |
| if (sizeof(pl_intList) > pl_number) |
| { |
| pl_value := pl_intList[pl_number]; |
| return true; |
| } |
| return false; |
| } |
| |
| function f_EPTF_COAP_CodeToEventIdx(in Code p_code) |
| return integer |
| { |
| return p_code.class*100+p_code.detail; |
| } |
| |
| function f_EPTF_COAP_isCoapReportEnabledForEntity(in integer pl_eIdx) |
| runs on EPTF_COAP_LGen_CT |
| return boolean |
| { |
| var integer vl_eCtxIdx := f_EPTF_LGenBase_getBehaviorCtxItem(pl_eIdx, v_COAP_bIdx, 0); |
| |
| return v_COAP_EntityCtxDB.data[v_COAP_ctx.eCtxIdx].reportCoapEvent; |
| } |
| |
| function f_EPTF_COAP_dispatchEventsForCode(in Code pl_code, in integer pl_eIdx, in integer pl_fsmCtx, in EPTF_IntegerList pl_reportedArgs) |
| runs on EPTF_COAP_LGen_CT |
| { |
| if (not f_EPTF_COAP_isCoapReportEnabledForEntity(pl_eIdx) ) { return; } |
| |
| var integer vl_eventIdx := f_EPTF_COAP_CodeToEventIdx(pl_code); |
| |
| f_EPTF_COAP_dispatchEvent(vl_eventIdx, pl_eIdx, pl_fsmCtx, {}); |
| |
| if (100 <= vl_eventIdx and vl_eventIdx <= 199) |
| { |
| f_EPTF_COAP_dispatchEvent(c_COAP_eventIdx_1xx, pl_eIdx, pl_fsmCtx, {}); |
| } |
| else if (200 <= vl_eventIdx and vl_eventIdx <= 299) |
| { |
| f_EPTF_COAP_dispatchEvent(c_COAP_eventIdx_2xx, pl_eIdx, pl_fsmCtx, {}); |
| } |
| else if (300 <= vl_eventIdx and vl_eventIdx <= 699) |
| { |
| if (300 <= vl_eventIdx and vl_eventIdx <= 399) |
| { |
| f_EPTF_COAP_dispatchEvent(c_COAP_eventIdx_3xx, pl_eIdx, pl_fsmCtx, {}); |
| } |
| else if (400 <= vl_eventIdx and vl_eventIdx <= 499) |
| { |
| f_EPTF_COAP_dispatchEvent(c_COAP_eventIdx_4xx, pl_eIdx, pl_fsmCtx, {}); |
| } |
| else if (500 <= vl_eventIdx and vl_eventIdx <= 599) |
| { |
| f_EPTF_COAP_dispatchEvent(c_COAP_eventIdx_4xx, pl_eIdx, pl_fsmCtx, {}); |
| } |
| f_EPTF_COAP_dispatchEvent(c_COAP_eventIdx_3xxto6xx, pl_eIdx, pl_fsmCtx, {}); |
| } |
| } |
| |
| function f_EPTF_COAP_dispatchEvent(in integer pl_eventIdx, in integer pl_eIdx, in integer pl_fsmCtx, in EPTF_IntegerList pl_reportedArgs) |
| runs on EPTF_COAP_LGen_CT |
| { |
| if (pl_eIdx < 0) |
| { |
| f_EPTF_LGenBase_postEvent( |
| { |
| { |
| v_COAP_bIdx, |
| pl_eventIdx, |
| omit, |
| omit |
| }, |
| pl_reportedArgs |
| }); |
| } |
| else |
| { |
| if (pl_fsmCtx < 0) |
| { |
| f_EPTF_LGenBase_postEvent( |
| { |
| { |
| v_COAP_bIdx, |
| pl_eventIdx, |
| { |
| pl_eIdx, |
| omit |
| }, omit |
| }, |
| pl_reportedArgs |
| }); |
| } |
| else |
| { |
| f_EPTF_LGenBase_postEvent( |
| { |
| { |
| v_COAP_bIdx, |
| pl_eventIdx, |
| { |
| pl_eIdx, |
| pl_fsmCtx |
| }, omit |
| }, |
| pl_reportedArgs |
| }); |
| } |
| } |
| } |
| |
| function f_EPTF_COAP_isEmpty(in CoAP_ReqResp p_pdu) |
| return boolean |
| { |
| if (p_pdu.header.code.class == 0 and |
| p_pdu.header.code.detail == 0) { |
| return true; |
| } |
| return false; |
| } |
| |
| function f_EPTF_COAP_isRequest(in CoAP_ReqResp p_pdu) |
| return boolean |
| { |
| if (p_pdu.header.code.class == 0 and |
| p_pdu.header.code.detail > 0) { |
| return true; |
| } |
| return false; |
| } |
| |
| function f_EPTF_COAP_isResponse(in CoAP_ReqResp p_pdu) |
| return boolean |
| { |
| if (p_pdu.header.code.class > 0) { |
| return true; |
| } |
| return false; |
| } |
| |
| template CoAP_ReqResp t_CoAP_EmptyAck := |
| { |
| header := |
| { |
| version := 1, |
| msg_type := ACKNOWLEDGEMENT, |
| code := EMPTY_MESSAGE, |
| message_id := 0 |
| }, |
| token := ''O, |
| options := omit, |
| payload := omit |
| } |
| } |