blob: 156dc6b6d557fb3780664530f98f51ecba027538 [file] [log] [blame]
///////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2000-2020 Ericsson Telecom AB
//
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v2.0
// which accompanies this distribution, and is available at
// https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html
///////////////////////////////////////////////////////////////////////////////
// File: EPTF_COAP_LocalTransport_Functions.ttcn
// Description:
// Rev: R1A
// Prodnr: CNL 113 858
// Updated: 2020-03-04
// Contact: http://ttcn.ericsson.se
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////
// Module: EPTF_COAP_LocalTransport_Functions
//
// Purpose:
// This module contains the functions of the COAP local transport component
//
// See also:
// <EPTF_COAP_LocalTransport_Definitions>
///////////////////////////////////////////////////////////////
module EPTF_COAP_LocalTransport_Functions
{
import from IPL4asp_Types all;
import from EPTF_CLL_Base_Functions all;
import from EPTF_CLL_Common_Definitions all;
import from EPTF_CLL_Logging_Definitions all;
import from EPTF_CLL_Logging_Functions all;
import from EPTF_CLL_HashMapStr2Int_Functions all;
import from EPTF_CLL_HashMapInt2Int_Functions all;
import from EPTF_CLL_FBQ_Functions all;
import from EPTF_CLL_RBTScheduler_Functions all;
import from EPTF_CLL_TransportIPL4_Functions all;
import from EPTF_CLL_Transport_CommonDefinitions all;
import from EPTF_COAP_LocalTransport_Definitions all;
import from EPTF_COAP_Transport_Definitions all;
import from CoAP_Types all;
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_LocalTransport_init
//
// Purpose:
// The main initialization function of the <EPTF_COAP_LocalTransport_CT> component type
//
// Related Type:
// <EPTF_COAP_LocalTransport_CT>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_LocalTransport_init()
runs on EPTF_COAP_LocalTransport_CT
{
if (v_EPTF_COAP_LocalTransport_initialized) {return;}
f_EPTF_COAP_LocalTransport_initLogging();
f_EPTF_Transport_init(IPL4, "EPTF_COAP_LocalTransport", {}, false);
f_EPTF_Transport_registerMsgCallback(
IPL4,
c_COAP_Transport_LGenType,
refers(f_EPTF_COAP_IPL4asp_handleMessage),
refers(f_EPTF_COAP_IPL4asp_handleEvent)
);
v_EPTF_COAP_Transport_stats := c_EPTF_COAP_Transport_Statistics_empty;
f_EPTF_COAP_LocalTransport_socketDB_init();
f_EPTF_Base_registerCleanup(refers(f_EPTF_COAP_LocalTransport_cleanup));
v_EPTF_COAP_LocalTransport_initialized := true;
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_LocalTransport_initLogging
//
// Purpose:
// Initializing CLL's logging feature on the <EPTF_COAP_LocalTransport_CT> component type
//
// Related Type:
// <EPTF_COAP_LocalTransport_CT>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_LocalTransport_initLogging()
runs on EPTF_COAP_LocalTransport_CT
{
f_EPTF_Logging_init_CT("COAP_Transport");
v_EPTF_COAP_LocalTransport_loggingMaskId :=
f_EPTF_Logging_registerComponentMasks(
"COAP_LocalTransport_Logging",
{"WARNING", "DEBUG", "DEBUGV", "ERROR"},
EPTF_Logging_CLL
);
if(tsp_EPTF_COAP_LocalTransport_debug){
f_EPTF_Logging_enableLocalMask(v_EPTF_COAP_LocalTransport_loggingMaskId, c_COAP_LocalTransport_Logging_DEBUG);
}
else {
f_EPTF_Logging_disableLocalMask(v_EPTF_COAP_LocalTransport_loggingMaskId, c_COAP_LocalTransport_Logging_DEBUG);
}
if(tsp_EPTF_COAP_LocalTransport_debugVerbose) {
f_EPTF_Logging_enableLocalMask(v_EPTF_COAP_LocalTransport_loggingMaskId, c_COAP_LocalTransport_Logging_DEBUGV);
}
else {
f_EPTF_Logging_disableLocalMask(v_EPTF_COAP_LocalTransport_loggingMaskId, c_COAP_LocalTransport_Logging_DEBUGV);
}
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_LocalTransport_cleanup
//
// Purpose:
// The main clean up function for the <EPTF_COAP_LocalTransport_CT> component type
//
// Related Type:
// <EPTF_COAP_LocalTransport_CT>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_LocalTransport_cleanup()
runs on EPTF_COAP_LocalTransport_CT
{
// Reset DBs, close connections
f_EPTF_COAP_LocalTransport_socketDB_cleanUp();
vf_EPTF_COAP_Transport_receiveMessage := null;
vf_EPTF_COAP_Transport_receiveEvent := null;
v_EPTF_COAP_LocalTransport_initialized := false;
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_IPL4asp_getMsgLen
//
// Purpose:
// Framing function to be regisitered into the IPL4 transport layer <EPTF_CLL_TransportIPL4_Functions>.
// It is used to determine the length of a (partially) received PDU so that the transport layer knows,
// how much more must be received before attempting to decode it.
//
// Parameters:
// stream - *in* *octetstring* - the content received so far
// args - *inout* <ro_integer> - various parameters
//
// Returns:
// *integer* - The expected length of the next PDU
//
// Related Type:
// <EPTF_COAP_LocalTransport_CT>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_IPL4asp_getMsgLen
(
in octetstring stream,
inout ro_integer args
)
return integer
{
return lengthof(stream);
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_IPL4asp_handleEvent
//
// Purpose:
// Handler function to be regisitered into the IPL4 transport layer <EPTF_CLL_TransportIPL4_Functions>.
// It is used to receieve transport events from the underlying IPL4 transport layer.
// The function currently handles the connection closed event and forwards every event to the load generator
// layer's handler function.
//
// Parameters:
// pl_transportType - *in* <EPTF_Transport_TransportType> - transport type
// pl_connId - *in* <ConnectionId> - the connection id the event is received on
// pl_event - *in* <PortEvent> - the event descriptor
//
// Related Type:
// <EPTF_COAP_LocalTransport_CT>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_IPL4asp_handleEvent(
in EPTF_Transport_TransportType pl_transportType,
in ConnectionId pl_connId,
in PortEvent pl_event)
runs on EPTF_COAP_LocalTransport_CT
{
f_COAP_Transport_Logging_VERBOSE(log2str(": incoming event: ", pl_event));
if (tsp_EPTF_COAP_LocalTransport_debug) { action("COAP transport event: \n", pl_event); }
if (vf_EPTF_COAP_Transport_receiveEvent != null) {
vf_EPTF_COAP_Transport_receiveEvent.apply(pl_event);
}
if (ischosen(pl_event.connClosed))
{
var integer vl_sockIdx := f_EPTF_COAP_LocalTransport_socketDB_lookUp_connId(pl_event.connClosed.connId);
if (vl_sockIdx >=0)
{
var EPTF_COAP_Transport_Response vl_rsp := c_EPTF_COAP_Transport_Response_init;
vl_rsp.eIdx := v_COAP_LocalTransport_localSocketDB.data[vl_sockIdx].eIdx;
vl_rsp.succ := false;
vl_rsp.params.dtlsConnectionClosed := true;
vf_EPTF_COAP_Transport_apiResponse.apply(vl_rsp);
f_EPTF_COAP_LocalTransport_socketDB_remove(vl_sockIdx);
}
}
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_IPL4asp_handleMessage
//
// Purpose:
// Handler function to be regisitered into the IPL4 transport layer <EPTF_CLL_TransportIPL4_Functions>.
// It is used to receieve COAP messages from the underlying IPL4 transport layer.
// The function looks up the entity that owns the particular connection and forwards the message and the
// entity information to the load generator layer
//
// Parameters:
// pl_transportType - *in* <EPTF_Transport_TransportType> - transport type
// pl_connId - *in* <ConnectionId> - the connection id the event is received on
// pl_remHost - *in* <HostName> - remote host name
// pl_remPort - *in* <PortNumber> - remote port number
// pl_locHost - *in* <HostName> - local host name
// pl_locPort - *in* <PortNumber> - local port number
// pl_proto - *in* <ProtoTuple> - transport protocol descriptor
// pl_userData - *in* *integer* - user data registered to the socket
// pl_msg - *in* *octetstring* - incoming message
//
// Related Type:
// <EPTF_COAP_LocalTransport_CT>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_IPL4asp_handleMessage(
in EPTF_Transport_TransportType pl_transportType,
in ConnectionId pl_connId,
in HostName pl_remHost,
in PortNumber pl_remPort,
in HostName pl_locHost,
in PortNumber pl_locPort,
in ProtoTuple pl_proto,
in integer pl_userData,
in octetstring pl_msg)
runs on EPTF_COAP_LocalTransport_CT
{
f_COAP_Transport_Logging_VERBOSE(log2str(%definitionId, " ", pl_msg));
var CoAP_Message vl_COAP_MSG;
var EPTF_COAP_PDU vl_EPTF_COAP_PDU;
f_EPTF_SchedulerComp_refreshSnapshotTime();
f_CoAP_dec(pl_msg, vl_COAP_MSG);
if (tsp_EPTF_COAP_LocalTransport_debug) { action("COAP transport receiving: \n", vl_COAP_MSG); }
if (ischosen(vl_COAP_MSG.msg))
{
vl_EPTF_COAP_PDU.pdu := vl_COAP_MSG.msg;
vl_EPTF_COAP_PDU.transportParams.localAddress.hostName := pl_locHost;
vl_EPTF_COAP_PDU.transportParams.localAddress.portNumber := pl_locPort;
vl_EPTF_COAP_PDU.transportParams.remoteAddress.hostName := pl_remHost;
vl_EPTF_COAP_PDU.transportParams.remoteAddress.portNumber := pl_remPort;
vl_EPTF_COAP_PDU.transportParams.transport.ip := pl_proto;
var SocketEntry vl_entry := c_SocketEntry_init;
var integer vl_sockIdx := f_EPTF_COAP_LocalTransport_socketDB_lookUp_connId(pl_connId);
f_EPTF_COAP_LocalTransport_socketDB_get(vl_sockIdx, vl_entry);
vl_EPTF_COAP_PDU.eIdx := vl_entry.eIdx;
vl_EPTF_COAP_PDU.fsmIdx := -1;
if (tsp_EPTF_COAP_LocalTransport_debug) { action("COAP transport receiving: eIdx: ", vl_EPTF_COAP_PDU.eIdx); }
if (tsp_EPTF_COAP_LocalTransport_debug) { action("COAP transport receiving: PDU: ", vl_EPTF_COAP_PDU); }
v_EPTF_COAP_Transport_stats.nofReceivedMessages :=
v_EPTF_COAP_Transport_stats.nofReceivedMessages + 1.0;
v_EPTF_COAP_Transport_stats.nofReceivedBytes :=
v_EPTF_COAP_Transport_stats.nofReceivedBytes + int2float(lengthof(pl_msg));
if (vf_EPTF_COAP_Transport_receiveMessage != null) {
vf_EPTF_COAP_Transport_receiveMessage.apply(vl_EPTF_COAP_PDU);
}
}
else
{
f_COAP_Transport_Logging_WARNING(
log2str(%definitionId, " Couldn't decode msg: ",pl_msg, " decoded: ", vl_COAP_MSG)
);
}
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_LocalTransport_send
//
// Purpose:
// Function to send out a <EPTF_COAP_PDU> message using the local transport. It automatically
// looks up the corresponding <Socket> or creates it on the fly if it doesn't exist yet
//
// Parameters:
// pl_msg - *in* <EPTF_COAP_PDU> - message to be sent
//
// Related Type:
// <EPTF_COAP_LocalTransport_CT>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_LocalTransport_send(in EPTF_COAP_PDU pl_msg)
runs on EPTF_COAP_LocalTransport_CT
{
f_COAP_Transport_Logging_VERBOSE(log2str(%definitionId, " ", pl_msg));
if (not ischosen(pl_msg.transportParams.transport.ip))
{
f_COAP_Transport_Logging_WARNING("Only IP transport is handled.");
return;
}
if (ischosen(pl_msg.transportParams.transport.ip.udp))
{
var integer vl_sockIdx := f_EPTF_COAP_LocalTransport_socketDB_lookUp_localAddr(pl_msg.transportParams.localAddress);
if (vl_sockIdx < 0)
{
if (not f_EPTF_COAP_LocalTransport_startSocket(pl_msg.transportParams.localAddress, pl_msg.transportParams.transport.ip, pl_msg.eIdx, vl_sockIdx))
{
f_COAP_Transport_Logging_WARNING(log2str(": couldn't create socket: ", pl_msg.transportParams.localAddress));
return;
}
}
f_EPTF_COAP_LocalTransport_socketDB_get(vl_sockIdx, v_COAP_LocalTransport_currentSocket);
if (tsp_EPTF_COAP_LocalTransport_debug) { action("COAP transport sending: \n", pl_msg); }
var octetstring v_encoded;
f_CoAP_enc(CoAP_Message: {msg := pl_msg.pdu}, v_encoded);
f_EPTF_COAP_LocalTransport_IPL4_sendTo
(
v_COAP_LocalTransport_currentSocket.connId,
pl_msg.transportParams.remoteAddress.hostName,
pl_msg.transportParams.remoteAddress.portNumber,
pl_msg.transportParams.transport.ip,
v_encoded
);
}
else if (ischosen(pl_msg.transportParams.transport.ip.dtls))
{
var integer vl_dtlsIdx := f_EPTF_COAP_LocalTransport_socketDB_lookUp_dtlsConnection(pl_msg.transportParams.localAddress, pl_msg.transportParams.remoteAddress);
if (vl_dtlsIdx < 0)
{
if (not f_EPTF_COAP_LocalTransport_startDTLS(
{
localAddress := pl_msg.transportParams.localAddress,
remoteAddress := pl_msg.transportParams.remoteAddress,
pskIdentity := omit,
pskKey := omit
},
pl_msg.eIdx,
vl_dtlsIdx
)
)
{
var EPTF_COAP_Transport_Response vl_rsp := c_EPTF_COAP_Transport_Response_init;
vl_rsp.succ := false;
vl_rsp.params.transportError := "Couldn't connect DTLS";
vf_EPTF_COAP_Transport_apiResponse.apply(vl_rsp);
f_COAP_Transport_Logging_WARNING(log2str(": couldn't connect DTLS: ", pl_msg.transportParams.localAddress,"->", pl_msg.transportParams.remoteAddress));
return;
}
}
f_EPTF_COAP_LocalTransport_socketDB_get(vl_dtlsIdx, v_COAP_LocalTransport_currentSocket);
if (tsp_EPTF_COAP_LocalTransport_debug) { action("COAP transport sending: \n", pl_msg.pdu); }
var octetstring v_encoded;
f_CoAP_enc(CoAP_Message: {msg := pl_msg.pdu}, v_encoded);
f_EPTF_COAP_LocalTransport_IPL4_send
(
v_COAP_LocalTransport_currentSocket.connId,
pl_msg.transportParams.transport.ip,
v_encoded
);
}
else
{
f_COAP_Transport_Logging_WARNING(log2str("Protocol not handled: ", pl_msg.transportParams.transport.ip));
}
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_LocalTransport_transportApiRequest
//
// Purpose:
// Function to handle incoming transport API requests
//
// Parameters:
// pl_req - *in* <EPTF_COAP_Transport_Request> - transport API request
//
// Related Type:
// <EPTF_COAP_LocalTransport_CT>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_LocalTransport_transportApiRequest(EPTF_COAP_Transport_Request pl_req)
runs on EPTF_COAP_LocalTransport_CT
{
f_COAP_Transport_Logging_VERBOSE(log2str(%definitionId, " ", pl_req));
if (ischosen(pl_req.params.startListening))
{
var EPTF_COAP_Transport_Response vl_rsp := c_EPTF_COAP_Transport_Response_init;
vl_rsp.eIdx := pl_req.eIdx;
vl_rsp.fsmIdx := pl_req.fsmIdx;
var integer vl_sockIdx := f_EPTF_COAP_LocalTransport_socketDB_lookUp_localAddr(pl_req.params.startListening.localAddress);
if (vl_sockIdx < 0)
{
if (not f_EPTF_COAP_LocalTransport_startSocket(
pl_req.params.startListening.localAddress,
pl_req.params.startListening.protocol,
pl_req.eIdx,
vl_sockIdx)
)
{
f_COAP_Transport_Logging_WARNING(log2str(": couldn't create socket: ", pl_req.params.startListening.localAddress));
}
else { vl_rsp.succ := true; }
}
else { vl_rsp.succ := false; }
vf_EPTF_COAP_Transport_apiResponse.apply(vl_rsp);
}
if (ischosen(pl_req.params.startDTLS))
{
var EPTF_COAP_Transport_Response vl_rsp := c_EPTF_COAP_Transport_Response_init;
vl_rsp.eIdx := pl_req.eIdx;
vl_rsp.fsmIdx := pl_req.fsmIdx;
var integer vl_connIdx := f_EPTF_COAP_LocalTransport_socketDB_lookUp_dtlsConnection(
pl_req.params.startDTLS.localAddress,
pl_req.params.startDTLS.remoteAddress
);
if (vl_connIdx < 0)
{
if (not f_EPTF_COAP_LocalTransport_startDTLS(
pl_req.params.startDTLS,
pl_req.eIdx,
vl_connIdx)
)
{
f_COAP_Transport_Logging_WARNING(log2str(": couldn't start dtls: ", pl_req.params));
}
else { vl_rsp.succ := true; }
}
else { vl_rsp.succ := false; }
vf_EPTF_COAP_Transport_apiResponse.apply(vl_rsp);
}
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_LocalTransport_startSocket
//
// Purpose:
// Internal (private) function to create and initialize a <Socket>
//
// Parameters:
// p_sock - *in* <Socket> - local host andm port of the socket
// p_proto - *in* <ProtoTuple> - transport protocol descriptor of the socket
// p_eIdx - *in* *integer* - entity index that owns the socket
//
// Returns:
// p_idx - *inout* *integer* - index of the <SocketEntry> in the <SocketDB>
//
// Related Type:
// <EPTF_COAP_LocalTransport_CT>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_LocalTransport_startSocket(
in Socket p_sock,
in ProtoTuple p_proto,
in integer p_eIdx,
inout integer p_idx
)
runs on EPTF_COAP_LocalTransport_CT
return boolean
{
var Result vl_result;
var SocketEntry vl_socketEntry := c_SocketEntry_init;
f_EPTF_Transport_listen(
pl_transportType := IPL4,
pl_proto := p_proto,
pl_hostName := p_sock.hostName,
pl_portNumber := p_sock.portNumber,
pl_LGenType := c_COAP_Transport_LGenType,
pl_result := vl_result,
pl_automaticBuffering := false,
pl_options := {}
);
if (f_EPTF_COAP_IPL4asp_handleResult(vl_result)) // Everything went OK
{
vl_socketEntry.addr := p_sock;
vl_socketEntry.proto := p_proto;
vl_socketEntry.connId := vl_result.connId;
vl_socketEntry.eIdx := p_eIdx;
vl_socketEntry.state := OPENED;
}
else
{ return false;}
p_idx := f_EPTF_COAP_LocalTransport_socketDB_add(vl_socketEntry);
return true;
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_LocalTransport_startDTLS
//
// Purpose:
// Internal (private) function to create and initialize a DTLS connection
//
// Parameters:
// p_params - *in* <EPTF_COAP_Transport_dtlsConnect> - DTLS parameters
// p_eIdx - *in* *integer* - entity index that owns the socket
//
// Returns:
// p_idx - *inout* *integer* - index of the <SocketEntry> in the <SocketDB>
//
// Related Type:
// <EPTF_COAP_LocalTransport_CT>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_LocalTransport_startDTLS(
in EPTF_COAP_Transport_dtlsConnect p_params,
in integer p_eIdx,
inout integer p_idx)
runs on EPTF_COAP_LocalTransport_CT
return boolean
{
var Result vl_result;
var OptionList v_options := {};
if (ispresent(p_params.pskIdentity) and ispresent(p_params.pskKey))
{
v_options[sizeof(v_options)] :=
{
psk_options := {
psk_identity := p_params.pskIdentity,
psk_identity_hint := omit,
psk_key := p_params.pskKey
}
}
}
f_COAP_Transport_Logging_DEBUG(log2str("ipl4 options: ", v_options));
f_EPTF_Transport_connect(
pl_transportType := IPL4,
pl_proto := { dtls := { udp := {} } },
pl_localHost := p_params.localAddress.hostName,
pl_localPort := p_params.localAddress.portNumber,
pl_remoteHost := p_params.remoteAddress.hostName,
pl_remotePort := p_params.remoteAddress.portNumber,
pl_LGenType := c_COAP_Transport_LGenType,
pl_result := vl_result,
pl_automaticBuffering := true,
pl_options := v_options
);
if (f_EPTF_COAP_IPL4asp_handleResult(vl_result)) // Everything went OK
{
v_COAP_LocalTransport_currentSocket := c_SocketEntry_init;
v_COAP_LocalTransport_currentSocket.dtls := c_DTLSConnection_init;
v_COAP_LocalTransport_currentSocket.addr := p_params.localAddress;
v_COAP_LocalTransport_currentSocket.dtls.remoteAddr := p_params.remoteAddress;
if (ispresent(p_params.pskIdentity) and ispresent(p_params.pskKey))
{
v_COAP_LocalTransport_currentSocket.dtls.pskIndetity := p_params.pskIdentity;
v_COAP_LocalTransport_currentSocket.dtls.pskKey := p_params.pskKey;
}
v_COAP_LocalTransport_currentSocket.connId := vl_result.connId;
v_COAP_LocalTransport_currentSocket.eIdx := p_eIdx;
v_COAP_LocalTransport_currentSocket.state := OPENED;
v_COAP_LocalTransport_currentSocket.proto := { dtls := { udp := {} } };
f_EPTF_COAP_LocalTransport_socketDB_add(v_COAP_LocalTransport_currentSocket);
}
else
{ return false;}
return true;
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_LocalTransport_IPL4_sendTo
//
// Purpose:
// Internal (private) wrapper function of the <f_EPTF_Transport_sendTo> function
//
// Related Type:
// <EPTF_COAP_LocalTransport_CT>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_LocalTransport_IPL4_sendTo(
in integer pl_connId,
in charstring pl_remName,
in integer pl_remPort,
in ProtoTuple pl_proto,
in octetstring pl_msg)
runs on EPTF_COAP_LocalTransport_CT
{
var Result v_res;
f_EPTF_Transport_sendTo(
pl_transportType := IPL4,
pl_connId := pl_connId,
pl_remHost := pl_remName,
pl_remotePort := pl_remPort,
pl_msg := pl_msg,
pl_result := v_res,
pl_needBuffering := false
);
if (ispresent(v_res.errorCode))
{
f_COAP_Transport_Logging_WARNING(log2str(": message could not be sent."));
}
v_EPTF_COAP_Transport_stats.nofSentMessages := v_EPTF_COAP_Transport_stats.nofSentMessages + 1.0;
v_EPTF_COAP_Transport_stats.nofSentBytes := v_EPTF_COAP_Transport_stats.nofSentBytes + int2float(lengthof(pl_msg));
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_LocalTransport_IPL4_send
//
// Purpose:
// Internal (private) wrapper function of the <f_EPTF_Transport_send> function
//
// Related Type:
// <EPTF_COAP_LocalTransport_CT>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_LocalTransport_IPL4_send(
in integer pl_connId,
in ProtoTuple pl_proto,
in octetstring pl_msg)
runs on EPTF_COAP_LocalTransport_CT
{
var Result v_res;
f_EPTF_Transport_send(
pl_transportType := IPL4,
pl_connId := pl_connId,
pl_msg := pl_msg,
pl_result := v_res,
pl_needBuffering := false
);
if (ispresent(v_res.errorCode))
{
f_COAP_Transport_Logging_WARNING(log2str(": message could not be sent."));
}
v_EPTF_COAP_Transport_stats.nofSentMessages := v_EPTF_COAP_Transport_stats.nofSentMessages + 1.0;
v_EPTF_COAP_Transport_stats.nofSentBytes := v_EPTF_COAP_Transport_stats.nofSentBytes + int2float(lengthof(pl_msg));
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_LocalTransport_socketDB_init
//
// Purpose:
// Initializes the *v_COAP_LocalTransport_localSocketDB* <SocketDB> database
//
// Related Type:
// <SocketDB>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_LocalTransport_socketDB_init()
runs on EPTF_COAP_LocalTransport_CT
{
f_EPTF_FBQ_initFreeBusyQueue(v_COAP_LocalTransport_localSocketDB.queue);
v_COAP_LocalTransport_localSocketDB.data := {};
v_COAP_LocalTransport_localSocketDB.hashRef := f_EPTF_str2int_HashMap_New(c_EPTF_COAP_LocalTransport_SocketDB);
v_COAP_LocalTransport_localSocketDB.connId2eIdx_hashRef := f_EPTF_int2int_HashMap_New(c_EPTF_COAP_LocalTransport_SocketDB_connId2eIdx_hashRef);
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_LocalTransport_socketDB_cleanUp
//
// Purpose:
// Cleans up the reserved resources of the *v_COAP_LocalTransport_localSocketDB* <SocketDB> database
//
// Related Type:
// <SocketDB>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_LocalTransport_socketDB_cleanUp()
runs on EPTF_COAP_LocalTransport_CT
{
f_EPTF_FBQ_initFreeBusyQueue(v_COAP_LocalTransport_localSocketDB.queue);
v_COAP_LocalTransport_localSocketDB.data := {};
f_EPTF_str2int_HashMap_Delete(c_EPTF_COAP_LocalTransport_SocketDB);
f_EPTF_int2int_HashMap_Delete(c_EPTF_COAP_LocalTransport_SocketDB_connId2eIdx_hashRef);
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_LocalTransport_socketDB_add
//
// Purpose:
// Adds a new element to the *v_COAP_LocalTransport_localSocketDB* <SocketDB> database
//
// Parameters:
// p_entry - *in* <SocketEntry> - the element to be added
//
// Returns:
// *integer* - the index of the added element in the database
//
// Related Type:
// <SocketDB>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_LocalTransport_socketDB_add(in SocketEntry p_entry)
runs on EPTF_COAP_LocalTransport_CT
return integer
{
var integer v_idx := -1;
if (ispresent(p_entry.dtls))
{
v_idx := f_EPTF_COAP_LocalTransport_socketDB_lookUp_dtlsConnection(p_entry.addr, p_entry.dtls.remoteAddr);
}
else
{
v_idx := f_EPTF_COAP_LocalTransport_socketDB_lookUp_localAddr(p_entry.addr);
}
if (v_idx == -1)
{
v_idx := f_EPTF_FBQ_getOrCreateFreeSlot(v_COAP_LocalTransport_localSocketDB.queue);
f_EPTF_FBQ_moveFromFreeHeadToBusyTail(v_COAP_LocalTransport_localSocketDB.queue);
f_COAP_Transport_Logging_DEBUG(log2str(": "," adding socket ", v_idx, " ", p_entry));
v_EPTF_COAP_Transport_stats.nofOpenSockets :=
v_EPTF_COAP_Transport_stats.nofOpenSockets + 1;
if (ispresent(p_entry.dtls))
{
f_EPTF_str2int_HashMap_Insert(v_COAP_LocalTransport_localSocketDB.hashRef, f_EPTF_COAP_DTLSConnection_hash(p_entry.addr, p_entry.dtls.remoteAddr), v_idx);
}
else
{
f_EPTF_str2int_HashMap_Insert(v_COAP_LocalTransport_localSocketDB.hashRef, f_EPTF_COAP_Socket_hash(p_entry.addr), v_idx);
}
f_EPTF_int2int_HashMap_Insert(v_COAP_LocalTransport_localSocketDB.connId2eIdx_hashRef, p_entry.connId, v_idx);
v_COAP_LocalTransport_localSocketDB.data[v_idx] := p_entry;
}
return v_idx;
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_LocalTransport_socketDB_lookUp_localAddr
//
// Purpose:
// Gets the index of an <SocketEntry> element in *v_COAP_LocalTransport_localSocketDB* <SocketDB> database
// based on its local address
//
// Parameters:
// p_localAddr - *in* <Socket> - the local address
//
// Returns:
// *integer* - the index of the element, or -1 if not found
//
// Related Type:
// <SocketDB>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_LocalTransport_socketDB_lookUp_localAddr(in Socket p_localAddr)
runs on EPTF_COAP_LocalTransport_CT
return integer
{
var integer vl_idx := -1;
f_EPTF_str2int_HashMap_Find(v_COAP_LocalTransport_localSocketDB.hashRef, f_EPTF_COAP_Socket_hash(p_localAddr), vl_idx);
return vl_idx;
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_LocalTransport_socketDB_lookUp_dtlsConnection
//
// Purpose:
// Gets the index of an <SocketEntry> element in *v_COAP_LocalTransport_localSocketDB* <SocketDB> database
// based on its DTLS connection's local address
//
// Parameters:
// p_localAddr - *in* <Socket> - the local address
//
// Returns:
// *integer* - the index of the element, or -1 if not found
//
// Related Type:
// <SocketDB>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_LocalTransport_socketDB_lookUp_dtlsConnection(in Socket p_local, in Socket p_remote)
runs on EPTF_COAP_LocalTransport_CT
return integer
{
var integer vl_idx := -1;
f_EPTF_str2int_HashMap_Find(v_COAP_LocalTransport_localSocketDB.hashRef, f_EPTF_COAP_DTLSConnection_hash(p_local, p_remote), vl_idx);
return vl_idx;
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_LocalTransport_socketDB_lookUp_connId
//
// Purpose:
// Gets the index of an <SocketEntry> element in *v_COAP_LocalTransport_localSocketDB* <SocketDB> database
// based on its connection id
//
// Parameters:
// p_connId - *in* *integer* - the connection id
//
// Returns:
// *integer* - the index of the element, or -1 if not found
//
// Related Type:
// <SocketDB>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_LocalTransport_socketDB_lookUp_connId(in integer p_connId)
runs on EPTF_COAP_LocalTransport_CT
return integer
{
var integer vl_idx := -1;
f_EPTF_int2int_HashMap_Find(v_COAP_LocalTransport_localSocketDB.connId2eIdx_hashRef, p_connId, vl_idx);
return vl_idx;
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_LocalTransport_socketDB_get
//
// Purpose:
// Retrieves an element from the *v_COAP_LocalTransport_localSocketDB* <SocketDB> database
//
// Parameters:
// p_idx - *in* *integer* - the index of the element to retrieved
//
// Returns:
// p_sock - *inout* <SocketEntry> - the retrieved element
//
// Related Type:
// <SocketDB>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_LocalTransport_socketDB_get(in integer p_idx, inout SocketEntry p_sock)
runs on EPTF_COAP_LocalTransport_CT
{
if (p_idx < sizeof(v_COAP_LocalTransport_localSocketDB.data) and p_idx >= 0)
{
p_sock := v_COAP_LocalTransport_localSocketDB.data[p_idx];
}
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_LocalTransport_socketDB_remove
//
// Purpose:
// Removes an element from the *v_COAP_LocalTransport_localSocketDB* <SocketDB> database and frees up its reserved resources
//
// Parameters:
// p_idx - *in* *integer* - the index of the element to be removed
//
// Related Type:
// <SocketDB>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_LocalTransport_socketDB_remove(in integer p_idx)
runs on EPTF_COAP_LocalTransport_CT
{
if (p_idx < sizeof(v_COAP_LocalTransport_localSocketDB.data) and p_idx >= 0)
{
f_COAP_Transport_Logging_DEBUG(log2str(": "," removing socket ", p_idx, " ", v_COAP_LocalTransport_localSocketDB.data[p_idx]));
f_EPTF_int2int_HashMap_Erase(
v_COAP_LocalTransport_localSocketDB.connId2eIdx_hashRef,
v_COAP_LocalTransport_localSocketDB.data[p_idx].connId
);
f_EPTF_str2int_HashMap_Erase(
v_COAP_LocalTransport_localSocketDB.hashRef,
f_EPTF_COAP_SocketEntry_hash(v_COAP_LocalTransport_localSocketDB.data[p_idx])
);
v_COAP_LocalTransport_localSocketDB.data[p_idx] := c_SocketEntry_init;
f_EPTF_FBQ_moveFromBusyToFreeTail(p_idx, v_COAP_LocalTransport_localSocketDB.queue);
}
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_SocketEntry_hash
//
// Purpose:
// Hash function for lookups used by the *v_COAP_LocalTransport_localSocketDB* <SocketDB> database
//
// Parameters:
// p_entry - *in* <SocketEntry> - the socket entry to get a hash of
//
// Returns:
// *charstring* - string hash unique of a <SocketEntry> element
//
// Related Type:
// <SocketDB>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_SocketEntry_hash(in SocketEntry p_entry)
return charstring
{
if (ispresent(p_entry.dtls))
{
return f_EPTF_COAP_DTLSConnection_hash(p_entry.addr, p_entry.dtls.remoteAddr);
}
// else
return f_EPTF_COAP_Socket_hash(p_entry.addr);
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_Socket_hash
//
// Purpose:
// Hash function for lookups used by the *v_COAP_LocalTransport_localSocketDB* <SocketDB> database
//
// Parameters:
// p_sock - *in* <Socket> - the socket to get a hash of
//
// Returns:
// *charstring* - string hash unique of a <Socket> element
//
// Related Type:
// <SocketDB>, <Socket>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_Socket_hash(Socket p_sock)
return charstring
{
return p_sock.hostName&":"&int2str(p_sock.portNumber);
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_DTLSConnection_hash
//
// Purpose:
// Hash function for lookups used by the *v_COAP_LocalTransport_localSocketDB* <SocketDB> database
//
// Parameters:
// p_local - *in* <Socket> - the local socket of the DTLS connection
// p_remote - *in* <Socket> - the remote socket of the DTLS connection
//
// Returns:
// *charstring* - string hash unique of a <DTLSConnection> element
//
// Related Type:
// <SocketDB>, <DTLSConnection>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_DTLSConnection_hash(in Socket p_local, in Socket p_remote)
return charstring
{
return f_EPTF_COAP_Socket_hash(p_local)&"-"&f_EPTF_COAP_Socket_hash(p_remote);
}
///////////////////////////////////////////////////////////
// Function: f_COAP_Transport_Logging_VERBOSE
//
// Purpose:
// Logging functions for the VERBOSE log level
//
// Parameters:
// pl_message - *in* *charstring* - string to be logged
//
// Related Types:
// <EPTF_COAP_LocalTransport_CT>
///////////////////////////////////////////////////////////
function f_COAP_Transport_Logging_VERBOSE(in @lazy charstring pl_message)
runs on EPTF_COAP_LocalTransport_CT
{
if (c_EPTF_Common_debugSwitch) {
f_EPTF_Logging_debugV2(pl_message, v_EPTF_COAP_LocalTransport_loggingMaskId, {c_COAP_LocalTransport_Logging_DEBUGV});
}
}
///////////////////////////////////////////////////////////
// Function: f_COAP_Transport_Logging_DEBUG
//
// Purpose:
// Logging functions for the DEBUG log level
//
// Parameters:
// pl_message - *in* *charstring* - string to be logged
//
// Related Types:
// <EPTF_COAP_LocalTransport_CT>
///////////////////////////////////////////////////////////
function f_COAP_Transport_Logging_DEBUG(in @lazy charstring pl_message)
runs on EPTF_COAP_LocalTransport_CT
{
if (c_EPTF_Common_debugSwitch) {
f_EPTF_Logging_debugV2(pl_message, v_EPTF_COAP_LocalTransport_loggingMaskId, {c_COAP_LocalTransport_Logging_DEBUG});
}
}
///////////////////////////////////////////////////////////
// Function: f_COAP_Transport_Logging_WARNING
//
// Purpose:
// Logging functions for the WARNING log level
//
// Parameters:
// pl_message - *in* *charstring* - string to be logged
//
// Related Types:
// <EPTF_COAP_LocalTransport_CT>
///////////////////////////////////////////////////////////
function f_COAP_Transport_Logging_WARNING(in @lazy charstring pl_message)
runs on EPTF_COAP_LocalTransport_CT
{
if (c_EPTF_Common_debugSwitch) {
f_EPTF_Logging_debugV2(pl_message, v_EPTF_COAP_LocalTransport_loggingMaskId, {c_COAP_LocalTransport_Logging_WARNING});
}
v_EPTF_COAP_Transport_stats.nofTransportWarnings := v_EPTF_COAP_Transport_stats.nofTransportWarnings + 1;
}
///////////////////////////////////////////////////////////
// Function: f_COAP_Transport_Logging_ERROR
//
// Purpose:
// Logging functions for the ERROR log level
//
// Parameters:
// pl_message - *in* *charstring* - string to be logged
//
// Related Types:
// <EPTF_COAP_LocalTransport_CT>
///////////////////////////////////////////////////////////
function f_COAP_Transport_Logging_ERROR(in @lazy charstring pl_message)
runs on EPTF_COAP_LocalTransport_CT
{
if (c_EPTF_Common_debugSwitch) {
f_EPTF_Logging_debugV2(pl_message, v_EPTF_COAP_LocalTransport_loggingMaskId, {c_COAP_LocalTransport_Logging_ERROR});
}
v_EPTF_COAP_Transport_stats.nofTransportWarnings := v_EPTF_COAP_Transport_stats.nofTransportWarnings + 1;
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_COAP_IPL4asp_handleResult
//
// Purpose:
// Inernal (private) function to handle the results of the underlying IPL4 transport layer
//
// Parameters:
// p_res - *inout* *Result* - result of an IPL4 transport operation
//
// Related Types:
// <EPTF_COAP_LocalTransport_CT>
///////////////////////////////////////////////////////////
function f_EPTF_COAP_IPL4asp_handleResult(inout Result p_res)
runs on EPTF_COAP_LocalTransport_CT
return boolean
{
if (ispresent(p_res.errorCode) and (p_res.errorCode != IPL4_ERROR_TEMPORARILY_UNAVAILABLE))
{
f_COAP_Transport_Logging_WARNING(log2str("Warning: f_EPTF_COAP_IPL4asp_handleResult: IPL4 error: ", p_res));
return false;
}
return true;
}
}