| /////////////////////////////////////////////////////////////////////////////// |
| // |
| // 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; |
| } |
| |
| } |