blob: 2483edc154df77cc4831e7f448a719bbea17575c [file] [log] [blame]
///////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2000-2018 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: SCTP_Engine_Core.ttcn
// Description: Core functions of the SCTP Engine
// Rev: <RnXnn>
// Prodnr: CNL 113 840
//
module SCTP_Engine_Core{
import from SCTP_Engine_Definition all;
import from SCTP_Engine_PortTypes all
import from SCTP_Engine_Functions all
import from SCTP_Types all
//***************************************************************************//
//
// The main function, it should be started
//
//***************************************************************************//
function SCTP_Core_main() runs on SCTP_Engine_CT {
// Start the run timer
t_run_time.start(2147482.0) // ~24 days. Can be set higher, but in that case
// the TITAN will flood the log with stupid warning
// Activate the handler altsteps
alt{
[] SCTP_core_lower_handler()
[] SCTP_Core_timer_handler()
[] SCTP_Core_upper_handler()
}
}
//***************************************************************************//
//
// Upper port event handler functions
//
//***************************************************************************//
altstep SCTP_Core_upper_handler() runs on SCTP_Engine_CT {
var SCTP_Listen_data vl_listen_data;
var SCTP_Connect_data vl_connect_data;
var SCTP_Engine_CT vl_sender;
var SCTP_MSG_data vl_send_msg_data ;
var SCTP_Shutdown_data vl_shutdown_data ;
var SCTP_Reconfiguration_req vl_reconfig;
var integer vl_assoc_id;
[] p_sctp_req_api.getcall(S_SCTP_Listen:{?}) -> param (vl_listen_data) sender vl_sender{
SCTP_api_handle_listen(vl_listen_data,vl_sender)
repeat;
}
[] p_sctp_req_api.getcall(S_SCTP_Connect:{?}) -> param (vl_connect_data) sender vl_sender{
SCTP_api_handle_connect(vl_connect_data,vl_sender)
repeat;
}
[] p_sctp_req_api.getcall(S_SCTP_Send_req:{?}) -> param (vl_send_msg_data) sender vl_sender{
SCTP_api_handle_send_msg(vl_send_msg_data,vl_sender)
repeat;
}
[] p_sctp_req_api.getcall(S_SCTP_Shutdown:{?}) -> param (vl_shutdown_data) sender vl_sender{
SCTP_api_handle_shutdown(vl_shutdown_data,vl_sender)
repeat;
}
[] p_sctp_req_api.getcall(S_SCTP_Shutdown_conf:{?}) -> param (vl_assoc_id) sender vl_sender{
SCTP_api_handle_shutdown_conf(vl_assoc_id,vl_sender)
repeat;
}
[] p_sctp_req_api.getcall(S_SCTP_reconfig:{?}) -> param (vl_reconfig) sender vl_sender{
SCTP_api_handle_reconfig(vl_reconfig,vl_sender)
repeat;
}
}
//***************************************************************************//
//
// Time event handler functions
//
//***************************************************************************//
altstep SCTP_Core_timer_handler() runs on SCTP_Engine_CT {
[] t_next_event.timeout {
// Store the event data
var integer vl_assoc_id:=v_event_db.events[v_event_db.the_sceduled_event].assoc_id
var integer vl_timer_id:=v_event_db.events[v_event_db.the_sceduled_event].timer_id
// remove the event from the queue
SCTP_event_remove(v_event_db.the_sceduled_event)
// Call the timer handler
select(vl_timer_id){
case (c_timer_T1) {
SCTP_timeout_T1_init(vl_assoc_id)
}
case (c_timer_T1_cookie) {
SCTP_timeout_T1_cookie(vl_assoc_id)
}
case (c_timer_T3_rtx) {
SCTP_timeout_T3_rtx(vl_assoc_id)
}
case (c_timer_T2_shutdown) {
SCTP_timeout_T2_shutdown(vl_assoc_id)
}
case (c_timer_heartbeat) {
SCTP_timeout_heartbeat(vl_assoc_id)
}
case (c_timer_reconfig) {
SCTP_timeout_reconfig(vl_assoc_id)
}
case (c_timer_close) {
SCTP_timeout_close(vl_assoc_id)
}
}
repeat;
}
}
//***************************************************************************//
//
// Lower port event handler functions
//
//***************************************************************************//
altstep SCTP_core_lower_handler() runs on SCTP_Engine_CT {
var SCTP_Engine_packet vl_recv_packet;
var SCTP_Packet vl_sctp_pdu;
var integer vl_decode_res;
[] p_packet_port.receive(SCTP_Engine_packet:?) -> value vl_recv_packet {
// Process the incoming sctp packet
vl_decode_res:=f_SCTP_dec(vl_recv_packet.sctp_packet,vl_sctp_pdu);
//log("received: ",vl_decode_res)
if(vl_decode_res==0){ // Decode OK
// Find the association
var integer vl_assoc_id:=SCTP_find_id_map(vl_recv_packet.transport_id,
// incoming packet, the destination port is the local port
vl_sctp_pdu.common_header.destination_port,
vl_sctp_pdu.common_header.source_port)
//log("assoc id ",vl_assoc_id)
if(vl_assoc_id != -1 ){ // we found the assoctiation
SCTP_message_incoming_handler(vl_assoc_id,vl_sctp_pdu);
repeat;
} else {
// if it is an INIT or COOKIE ECHO chunk, try to find the listening
// association
if((lengthof(vl_sctp_pdu.chunks)>0) and
(ischosen(vl_sctp_pdu.chunks[0].init)
or ischosen(vl_sctp_pdu.chunks[0].cookie_echo) )
){
// Lets find the listening association
vl_assoc_id:=SCTP_find_id_map(vl_recv_packet.transport_id,
// incoming packet, the destination port is the local port
vl_sctp_pdu.common_header.destination_port,
// the remote port is 0 for listening assoc
0)
if(vl_assoc_id == -1){
// The listening assoc_id is not found
// Look for assoc listening on all transport
vl_assoc_id:=SCTP_find_id_map(-1, // All transport
// incoming packet, the destination port is the local port
vl_sctp_pdu.common_header.destination_port,
// the remote port is 0 for listening assoc
0)
}
if(vl_assoc_id != -1 ){ // we found the assoctiation
SCTP_message_incoming_init_cookie_handler(vl_assoc_id,
vl_recv_packet.transport_id, vl_sctp_pdu);
repeat;
}
}
}
// Not processed message, Out of the blue packet
// Send abort
SCTP_message_process_oob_packet(vl_recv_packet.transport_id, vl_sctp_pdu);
} else {
// What the hell we received?
log("Undecodable packet: ", vl_recv_packet);
// just drop it
}
repeat;
}
[] p_packet_port.receive(SCTP_Addr_change_notification:?) {
repeat;
}
}
}