libsua/sualibrary/sua/sua_co.cpp

2071 lines
63 KiB
C++

/***************************************************************************
sua_co.cpp - description
-------------------
begin : Tue Jan 8 2002
copyright : (C) 2002 by Lode Coene
email : lode.coene@siemens.atea.be
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
/*
* $Id: sua_co.cpp,v 1.5 2003/02/17 14:38:08 p82609 Exp $
*
* SUA implementation according to SUA draft issue 6.
*
* Author(s): Lode Coene
*
*
* Copyright (C) 2001 by Siemens Atea, Herentals, Belgium.
*
* Realized in co-operation between Siemens Atea and
* Siemens AG, Munich, Germany.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* Contact: gery.verwimp@siemens.atea.be
* lode.coene@siemens.atea.be
*
* The alternative comment
* inspiration : Virginie
* "This code was written using the KISS methodology. (Yes, we kissed a "
* "lot of beautifull girls) We always use this method."
*
* Purpose: This code-file defines the SUA connection-oriented message
* handling:
* - send a COnnect REquest msg to remote node
* - send a COnnect RESPonse msg to remote node
* - send a CO DATA msg to remote node
* - send a CO RELease REQuest msg to remote node
* - send a CO RELease COnfirm msg to remote node
* - Process a COnnect REquest msg
* - Process a COnnect RESPonse msg
* - Process a CO DATA msg
* - Process a CO RELease REQuest msg
* - Process a CO RELease COnfirm msg
* - Process a COnnect REFuse msg
*/
#include "sua_debug.h"
#include "sua_syntax.h"
#include "sua_database.h"
#include "sua_distribution.h"
#include "sua_logging.h"
#include "sua_tcb.h"
#include "sua_cl.h"
#include "sua_co.h"
#ifdef LINUX
#include <unistd.h>
#endif
#include <cstdio>
#include <iostream>
#include <cstdlib>
#include <string>
#include <vector>
#include <netinet/in_systm.h>
#include <netinet/ip.h> /* includes <netinet/in.h> also ! */
#include <netinet/ip_icmp.h>
#include <netdb.h>
#include <arpa/inet.h>
using namespace std;
// import the dataobjects of SUA
extern db_Sua_DatabaseList sua;
// import the TCB pool of SUA
extern tcb_Sua_TCB_arr tcb_pool;
extern tcb_Sua_msgqueue_pool msg_store;
// import the received msg pool
extern vector<sua_save_str> rec_msg_pool;
/***********************************************************************/
/* Send sua connection-oriented request primitive to remote side */
/***********************************************************************/
/***********************************************************************/
/* sua_send_CORE */
/***********************************************************************/
int sua_send_CORE( sccp_QOS_str &QOS,
sccp_addr_str &called_pty_address,
sccp_addr_str &calling_pty_address,
char *buffer,
unsigned int len,
unsigned int &Sua_ConnId,
tcb_Sua_TCB_str *tcb_ptr
)
{
Sua_container msg;
Sua_syntax_error_struct error;
int error_value;
int i, string_size, datalen;
signed int SCTP_assoc_id;
int sua_assoc_id;
signed int sctp_loadshare = SCTP_USE_PRIMARY;
short sctp_stream_id = 0;
int sctp_delivery_type, result;
tcb_Sua_msg_elem sua_msg;
// init the message
msg.sua_init();
// fill in the main sua header
msg.sua_prim.hdr_msg_class = sua_co;
msg.sua_prim.hdr_msg_type.co = co_core;
msg.sua_prim.rout_con_pres = TRUE;
msg.sua_prim.rout_con = 1;
msg.sua_prim.importance_pres = TRUE;
msg.sua_prim.importance = 5;
msg.sua_prim.hop_count_pres = TRUE;
msg.sua_prim.hop_count = 15;
// QOS choice
switch (QOS.prot_class)
{
case(class2): // connectionless transport, non-sequenced
msg.sua_prim.prot_class_pres = TRUE;
msg.sua_prim.prot_class.pcl = prot_class_2;
msg.sua_prim.seq_control_pres = TRUE;
msg.sua_prim.seq_control = 1;
sctp_delivery_type = SCTP_UNORDERED_DELIVERY;
break;
case(class3):
return(PROTOCOL_CLASS_NOT_SPECIFIED);
break;
default:
return(PROTOCOL_CLASS_NOT_SPECIFIED);
break;
}
if (QOS.return_msg_on_error)
msg.sua_prim.prot_class.return_option = TRUE;
else
msg.sua_prim.prot_class.return_option = FALSE;
// fill in the source address (=local sua address/CLG)
switch (calling_pty_address.routing_ind)
{
case (route_on_ssn):
if (calling_pty_address.address_fields_present.pc == ipvx_pc_present)
{
msg.sua_prim.source_addr.ip_addr_pres = TRUE;
msg.sua_prim.source_addr.pc_pres = FALSE;
if (calling_pty_address.pc.ipvx.sa.sa_family == AF_INET)
{
msg.sua_prim.source_addr.ip_addr_type = ip_v4;
msg.sua_prim.source_addr.ip_addr.ipv4 = calling_pty_address.pc.ipvx.sin;
}
else if (calling_pty_address.pc.ipvx.sa.sa_family == AF_INET6)
{
msg.sua_prim.source_addr.ip_addr_type = ip_v6;
msg.sua_prim.source_addr.ip_addr.ipv6 = calling_pty_address.pc.ipvx.sin6;
}
else
cout << "error filling in CLG IP address \n";
msg.sua_prim.source_addr_pres = TRUE;
msg.sua_prim.source_addr.rout_ind = ri_route_IP_SSN;
msg.sua_prim.source_addr.ssn_incl = TRUE;
msg.sua_prim.source_addr.pc_incl = FALSE;
msg.sua_prim.source_addr.gt_incl = FALSE;
msg.sua_prim.source_addr.ssn = calling_pty_address.ssn;
}
else if (calling_pty_address.address_fields_present.pc == ss7_pc_present)
{
msg.sua_prim.source_addr_pres = TRUE;
msg.sua_prim.source_addr.ip_addr_pres = FALSE;
msg.sua_prim.source_addr.pc_pres = TRUE;
msg.sua_prim.source_addr.pc = calling_pty_address.pc.ss7.ITU24.pc;
msg.sua_prim.source_addr.rout_ind = ri_route_PC_SSN;
msg.sua_prim.source_addr.ssn_incl = TRUE;
msg.sua_prim.source_addr.pc_incl = TRUE;
msg.sua_prim.source_addr.gt_incl = FALSE;
msg.sua_prim.source_addr.ssn = calling_pty_address.ssn;
cout << "SS7 PC in CLG address \n";
}
else
cout << "unsupported CLG address option\n";
break;
case(route_on_name_gt):
msg.sua_prim.source_addr.ip_addr_pres = FALSE;
msg.sua_prim.source_addr.pc_pres = FALSE;
if (calling_pty_address.address_fields_present.name_gt == hostname_present){
msg.sua_prim.source_addr_pres = TRUE;
msg.sua_prim.source_addr.rout_ind = ri_route_hostname;
msg.sua_prim.source_addr.hostname_pres = TRUE;
msg.sua_prim.source_addr.gt_pres = FALSE;
msg.sua_prim.source_addr.hostname = calling_pty_address.name.HostName;
}
else if (calling_pty_address.address_fields_present.name_gt == GT_present){
msg.sua_prim.source_addr_pres = TRUE;
msg.sua_prim.source_addr.rout_ind = ri_route_GT;
msg.sua_prim.source_addr.hostname_pres = FALSE;
msg.sua_prim.source_addr.gt_pres = TRUE;
msg.sua_prim.source_addr.gt.translation_type = calling_pty_address.name.GT.Translation_Type;
msg.sua_prim.source_addr.gt.num_plan = calling_pty_address.name.GT.Numbering_Plan;
msg.sua_prim.source_addr.gt.nat_addr = calling_pty_address.name.GT.Nature_of_Address;
msg.sua_prim.source_addr.gt.nr_of_digits = calling_pty_address.name.GT.nr_of_digits;
for (i=0; i < calling_pty_address.name.GT.nr_of_digits; i++)
msg.sua_prim.source_addr.gt.digits[i] = calling_pty_address.name.GT.digits[i];
}
else
cout << "unsupported CLG name/GT address option\n";
msg.sua_prim.source_addr.ssn_incl = TRUE;
msg.sua_prim.source_addr.pc_incl = FALSE;
msg.sua_prim.source_addr.gt_incl = TRUE;
msg.sua_prim.source_addr.ssn = called_pty_address.ssn;
break;
case(route_on_name_gt_next_office):
break;
default:
return(INVALID_CLG_ADDRESS);
break;
}
// fill in the destination address(=remote sua address/CLD)
switch (called_pty_address.routing_ind)
{
case (route_on_ssn):
if (called_pty_address.address_fields_present.pc == ipvx_pc_present)
{
msg.sua_prim.dest_addr.ip_addr_pres = TRUE;
msg.sua_prim.dest_addr.pc_pres = FALSE;
if (called_pty_address.pc.ipvx.sa.sa_family == AF_INET)
{
msg.sua_prim.dest_addr.ip_addr_type = ip_v4;
msg.sua_prim.dest_addr.ip_addr.ipv4 = called_pty_address.pc.ipvx.sin;
}
else if (called_pty_address.pc.ipvx.sa.sa_family == AF_INET6)
{
msg.sua_prim.dest_addr.ip_addr_type = ip_v6;
msg.sua_prim.dest_addr.ip_addr.ipv6 = called_pty_address.pc.ipvx.sin6;
}
else
cout << "error filling in CLD IP address \n";
msg.sua_prim.dest_addr_pres = TRUE;
msg.sua_prim.dest_addr.rout_ind = ri_route_IP_SSN;
msg.sua_prim.dest_addr.ssn_incl = TRUE;
msg.sua_prim.dest_addr.pc_incl = FALSE;
msg.sua_prim.dest_addr.gt_incl = FALSE;
msg.sua_prim.dest_addr.ssn = called_pty_address.ssn;
}
else if (called_pty_address.address_fields_present.pc == ss7_pc_present)
{
msg.sua_prim.dest_addr_pres = TRUE;
msg.sua_prim.dest_addr.ip_addr_pres = FALSE;
msg.sua_prim.dest_addr.pc_pres = TRUE;
msg.sua_prim.dest_addr.pc = called_pty_address.pc.ss7.ITU24.pc;
msg.sua_prim.dest_addr.rout_ind = ri_route_PC_SSN;
msg.sua_prim.dest_addr.ssn_incl = TRUE;
msg.sua_prim.dest_addr.pc_incl = TRUE;
msg.sua_prim.dest_addr.gt_incl = FALSE;
msg.sua_prim.dest_addr.ssn = called_pty_address.ssn;
cout << "SS7 PC in CLD address \n";
}
else
cout << "unsupported CLD address option\n";
break;
case(route_on_name_gt):
msg.sua_prim.dest_addr.ip_addr_pres = FALSE;
msg.sua_prim.dest_addr.pc_pres = FALSE;
if (called_pty_address.address_fields_present.name_gt == hostname_present){
msg.sua_prim.dest_addr_pres = TRUE;
msg.sua_prim.dest_addr.rout_ind = ri_route_hostname;
msg.sua_prim.dest_addr.hostname_pres = TRUE;
msg.sua_prim.dest_addr.gt_pres = FALSE;
msg.sua_prim.dest_addr.hostname = called_pty_address.name.HostName;
}
else if (called_pty_address.address_fields_present.name_gt == GT_present){
msg.sua_prim.dest_addr_pres = TRUE;
msg.sua_prim.dest_addr.rout_ind = ri_route_GT;
msg.sua_prim.dest_addr.hostname_pres = FALSE;
msg.sua_prim.dest_addr.gt_pres = TRUE;
msg.sua_prim.dest_addr.gt.translation_type = called_pty_address.name.GT.Translation_Type;
msg.sua_prim.dest_addr.gt.num_plan = called_pty_address.name.GT.Numbering_Plan;
msg.sua_prim.dest_addr.gt.nat_addr = called_pty_address.name.GT.Nature_of_Address;
msg.sua_prim.dest_addr.gt.nr_of_digits = called_pty_address.name.GT.nr_of_digits;
for (i=0; i < called_pty_address.name.GT.nr_of_digits; i++)
msg.sua_prim.dest_addr.gt.digits[i] = called_pty_address.name.GT.digits[i];
}
else
cout << "unsupported CLG name/GT address option\n";
msg.sua_prim.dest_addr.ssn_incl = TRUE;
msg.sua_prim.dest_addr.pc_incl = FALSE;
msg.sua_prim.dest_addr.gt_incl = TRUE;
msg.sua_prim.dest_addr.ssn = called_pty_address.ssn;
break;
case(route_on_name_gt_next_office):
break;
default:
return(INVALID_CLD_ADDRESS);
break;
}
// fill in the connection-oriented specific data of the msg
msg.sua_prim.source_ref_pres = TRUE;
msg.sua_prim.source_ref = Sua_ConnId;
msg.sua_prim.dest_ref = FALSE;
// fill in the user data
msg.sua_prim.data_pres = TRUE;
string stemp(buffer,len);
msg.sua_prim.data_string = stemp;
#ifdef DEBUG
cout << "Data = " << stemp << "\n";
cout << "Source LR = " << Sua_ConnId << "\n";
#endif
// encode the SUA unitdata message
error = msg.sua_encode();
string_size = msg.sua_msg.size();
// call routing to figure out which association to take for sending
// out the message
#ifdef DEBUG
cout << "call routing function\n";
#endif
SCTP_assoc_id = sua.route_msg( called_pty_address,
calling_pty_address,
sua_assoc_id
);
#ifdef DEBUG
cout << "routed to SCTP assoc " << SCTP_assoc_id << "/SUA association " << sua_assoc_id << "\n";
#endif
// fill in the TCB
tcb_ptr->Source_LR = Sua_ConnId;
tcb_ptr->User_ref_id = 1;
tcb_ptr->sctp_Association_id = SCTP_assoc_id;
tcb_ptr->state = scoc_outgoing;
tcb_ptr->remote_address = called_pty_address;
tcb_ptr->seq_number = Sua_ConnId % 256 ;
/* does association exist? */
if (SCTP_assoc_id > 0)
{
/* copy data into buffer, then finally... */
char* databuf = new char[msg.sua_msg.length()];
msg.sua_msg.copy(databuf, msg.sua_msg.length());
datalen = msg.sua_msg.length();
// send data to SCTP
result = sua_send_Message( SCTP_assoc_id,
sctp_stream_id,
sctp_delivery_type,
sctp_loadshare,
databuf,
datalen
);
delete databuf;
error_value = 0;
#ifdef DEBUG
cout << "sua_co.c:result sctp send = "<< result << "\n";
#endif
}
else if (SCTP_assoc_id < 0)
{
#ifdef DEBUG
cout << "sua_co.c:sending msg prohibited \n";
#endif
error_value = -1;
}
else
{
/* NO it does NOT exist. */
/* - Try to set up the association */
sua_assoc_id = sua.Dynamic_Associate ( called_pty_address,
calling_pty_address,
1,
1,
1
);
/* save newly assigned SCTP association id in SCOC TCB */
tcb_ptr->sctp_Association_id = sua.AssocDB.instance[sua_assoc_id].SCTP_assoc_id;
/* - save the msg till the association is setup or */
/* association setup fails -> drop saved msg */
sua_msg.byte = msg.sua_msg;
sua_msg.delivery_type = sctp_delivery_type;
sua_msg.stream_id = sctp_stream_id;
sua_msg.valid = true;
msg_store.add_msg ( sua_assoc_id,
sua_msg
);
error_value = -1;
}
return(error_value);
}
/***********************************************************************/
/* sua_send_CORESP */
/***********************************************************************/
int sua_send_CORESP( sccp_QOS_str &QOS,
char *buffer,
unsigned int len,
unsigned int &Sua_ConnId,
tcb_Sua_TCB_str *tcb_ptr
)
{
Sua_container msg;
Sua_syntax_error_struct error;
int error_value;
int string_size, datalen;
unsigned int SCTP_assoc_id;
unsigned int sua_assoc_id;
unsigned int local_sua_id,remote_sua_id;
signed int sctp_loadshare = SCTP_USE_PRIMARY;
short sctp_stream_id = 0;
int sctp_delivery_type, result = 0;
// init the message
msg.sua_init();
// fill in the main sua header
msg.sua_prim.hdr_msg_class = sua_co;
msg.sua_prim.hdr_msg_type.co = co_coak;
msg.sua_prim.rout_con_pres = TRUE;
msg.sua_prim.rout_con = 1;
msg.sua_prim.importance_pres = TRUE;
msg.sua_prim.importance = 5;
msg.sua_prim.hop_count_pres = TRUE;
msg.sua_prim.hop_count = 15;
// QOS choice
switch (QOS.prot_class)
{
case(class2): // connection-oriented transport, non-sequenced
msg.sua_prim.prot_class_pres = TRUE;
msg.sua_prim.prot_class.pcl = prot_class_2;
msg.sua_prim.seq_control_pres = TRUE;
msg.sua_prim.seq_control = tcb_ptr->seq_number ;
sctp_delivery_type = SCTP_UNORDERED_DELIVERY;
break;
case(class3):
return(PROTOCOL_CLASS_NOT_SPECIFIED);
break;
default:
return(PROTOCOL_CLASS_NOT_SPECIFIED);
break;
}
if (QOS.return_msg_on_error)
msg.sua_prim.prot_class.return_option = TRUE;
else
msg.sua_prim.prot_class.return_option = FALSE;
// fill in the connection-oriented specific data of the msg
msg.sua_prim.source_ref_pres = TRUE;
msg.sua_prim.source_ref = tcb_ptr->Source_LR ;
msg.sua_prim.dest_ref_pres = TRUE;
msg.sua_prim.dest_ref = tcb_ptr->Dest_LR ;
tcb_ptr->state = scoc_active;
#ifdef DEBUG
cout << "TCB source_LR = " << tcb_ptr->Source_LR << "\n";
cout << "TCB Dest_LR = " << tcb_ptr->Dest_LR << "\n";
cout << "TCB Association Id = " << tcb_ptr->sctp_Association_id << "\n";
cout << "TCB state = " << tcb_ptr->state << "\n";
#endif
// fill in the user data
if (len > 0)
{
msg.sua_prim.data_pres = TRUE;
string stemp(buffer,len);
msg.sua_prim.data_string = stemp;
}
else
msg.sua_prim.data_pres = FALSE;
// encode the SUA unitdata message
error = msg.sua_encode();
string_size = msg.sua_msg.size();
SCTP_assoc_id = tcb_ptr->sctp_Association_id;
#ifdef DEBUG
cout << "routed to SCTP assoc " << SCTP_assoc_id << "\n";
#endif
#ifdef SUA_MANAGEMENT
sua_assoc_id = sua.AssocDB.Find_association( SCTP_assoc_id,
local_sua_id,
remote_sua_id
);
if (sua.AssocDB.instance[sua_assoc_id].asp.status == asp_active)
{
#endif
/* copy data into buffer, then finally... */
char* databuf = new char[msg.sua_msg.length()];
msg.sua_msg.copy(databuf, msg.sua_msg.length());
datalen = msg.sua_msg.length();
// send data to SCTP
result = sua_send_Message( SCTP_assoc_id,
sctp_stream_id,
sctp_delivery_type,
sctp_loadshare,
databuf,
datalen
);
delete databuf;
error_value = 0;
#ifdef SUA_MANAGEMENT
}
else
{
#ifdef DEBUG
cout << "sua_co.c:message sending prohibited\n";
#endif
error_value = -1;
}
#endif
#ifdef DEBUG
cout << "sua_co.c:result sctp send = "<< result << "\n";
#endif
return(error_value);
}
/***********************************************************************/
/* sua_send_CODATA */
/***********************************************************************/
int sua_send_CODATA( sccp_QOS_str &QOS,
char *buffer,
unsigned int len,
unsigned int &Sua_ConnId,
tcb_Sua_TCB_str *tcb_ptr
)
{
Sua_container msg;
Sua_syntax_error_struct error;
int error_value;
int string_size, datalen;
unsigned int SCTP_assoc_id;
unsigned int sua_assoc_id;
unsigned int local_sua_id,remote_sua_id;
signed int sctp_loadshare = SCTP_USE_PRIMARY;
short sctp_stream_id = 0;
int sctp_delivery_type, result = 0;
// init the message
msg.sua_init();
// fill in the main sua header
msg.sua_prim.hdr_msg_class = sua_co;
msg.sua_prim.hdr_msg_type.co = co_data;
msg.sua_prim.rout_con_pres = TRUE;
msg.sua_prim.rout_con = 1;
msg.sua_prim.importance_pres = TRUE;
msg.sua_prim.importance = 5;
msg.sua_prim.hop_count_pres = TRUE;
msg.sua_prim.hop_count = 15;
// QOS choice
switch (QOS.prot_class)
{
case(class2): // connectionless transport, non-sequenced
msg.sua_prim.prot_class_pres = TRUE;
msg.sua_prim.prot_class.pcl = prot_class_2;
msg.sua_prim.seq_control_pres = TRUE;
msg.sua_prim.seq_control = tcb_ptr->seq_number ;
sctp_delivery_type = SCTP_UNORDERED_DELIVERY;
break;
case(class3):
return(PROTOCOL_CLASS_NOT_SPECIFIED);
break;
default:
return(PROTOCOL_CLASS_NOT_SPECIFIED);
break;
}
if (QOS.return_msg_on_error)
msg.sua_prim.prot_class.return_option = TRUE;
else
msg.sua_prim.prot_class.return_option = FALSE;
// fill in the connection-oriented specific data of the msg
msg.sua_prim.source_ref_pres = FALSE;
msg.sua_prim.dest_ref_pres = TRUE;
msg.sua_prim.dest_ref = tcb_ptr->Dest_LR ;
msg.sua_prim.seq_nr_pres = TRUE;
msg.sua_prim.seq_nr.more_data = FALSE;
#ifdef DEBUG
cout << "TCB source_LR = " << tcb_ptr->Source_LR << "\n";
cout << "TCB Dest_LR = " << tcb_ptr->Dest_LR << "\n";
cout << "TCB Association Id = " << tcb_ptr->sctp_Association_id << "\n";
cout << "TCB state = " << tcb_ptr->state << "\n";
#endif
// fill in the user data
msg.sua_prim.data_pres = TRUE;
string stemp(buffer,len);
msg.sua_prim.data_string = stemp;
// encode the SUA unitdata message
error = msg.sua_encode();
string_size = msg.sua_msg.size();
SCTP_assoc_id = tcb_ptr->sctp_Association_id;
#ifdef DEBUG
cout << "routed to SCTP assoc " << SCTP_assoc_id << "\n";
#endif
#ifdef SUA_MANAGEMENT
sua_assoc_id = sua.AssocDB.Find_association( SCTP_assoc_id,
local_sua_id,
remote_sua_id
);
if (sua.AssocDB.instance[sua_assoc_id].asp.status == asp_active)
{
#endif
/* copy data into buffer, then finally... */
char* databuf = new char[msg.sua_msg.length()];
msg.sua_msg.copy(databuf, msg.sua_msg.length());
datalen = msg.sua_msg.length();
// send data to SCTP
result = sua_send_Message( SCTP_assoc_id,
sctp_stream_id,
sctp_delivery_type,
sctp_loadshare,
databuf,
datalen
);
delete databuf;
error_value = 0;
#ifdef SUA_MANAGEMENT
}
else
{
#ifdef DEBUG
cout << "sua_co.c:message sending prohibited\n";
#endif
error_value = -1;
}
#endif
#ifdef DEBUG
cout << "sua_co.c:result sctp send = "<< result << "\n";
#endif
return(error_value);
}
/***********************************************************************/
/* sua_send_CO Release request */
/***********************************************************************/
int sua_send_CORELRQ( sccp_QOS_str &QOS,
char *buffer,
unsigned int len,
unsigned int &Sua_ConnId,
tcb_Sua_TCB_str *tcb_ptr
)
{
Sua_container msg;
Sua_syntax_error_struct error;
int error_value;
int string_size, datalen;
unsigned int SCTP_assoc_id;
unsigned int sua_assoc_id;
unsigned int local_sua_id,remote_sua_id;
signed int sctp_loadshare = SCTP_USE_PRIMARY;
short sctp_stream_id = 0;
int sctp_delivery_type, result = 0;
// init the message
msg.sua_init();
// fill in the main sua header
msg.sua_prim.hdr_msg_class = sua_co;
msg.sua_prim.hdr_msg_type.co = co_relre;
msg.sua_prim.rout_con_pres = TRUE;
msg.sua_prim.rout_con = 1;
msg.sua_prim.importance_pres = TRUE;
msg.sua_prim.importance = 5;
msg.sua_prim.hop_count_pres = TRUE;
msg.sua_prim.hop_count = 15;
// QOS choice
switch (QOS.prot_class)
{
case(class2): // connectionless transport, non-sequenced
msg.sua_prim.prot_class_pres = TRUE;
msg.sua_prim.prot_class.pcl = prot_class_2;
msg.sua_prim.seq_control_pres = TRUE;
msg.sua_prim.seq_control = tcb_ptr->seq_number ;
sctp_delivery_type = SCTP_UNORDERED_DELIVERY;
break;
case(class3):
return(PROTOCOL_CLASS_NOT_SPECIFIED);
break;
default:
return(PROTOCOL_CLASS_NOT_SPECIFIED);
break;
}
if (QOS.return_msg_on_error)
msg.sua_prim.prot_class.return_option = TRUE;
else
msg.sua_prim.prot_class.return_option = FALSE;
// fill in the connection-oriented specific data of the msg
msg.sua_prim.source_ref_pres = TRUE;
msg.sua_prim.source_ref = tcb_ptr->Source_LR ;
msg.sua_prim.dest_ref_pres = TRUE;
msg.sua_prim.dest_ref = tcb_ptr->Dest_LR ;
msg.sua_prim.SCCP_cause_pres = TRUE;
msg.sua_prim.SCCP_cause.cause_type = ctp_release_cause;
msg.sua_prim.SCCP_cause.cause_value = 3;
tcb_ptr->state = scoc_disconnect;
#ifdef DEBUG
cout << "TCB source_LR = " << tcb_ptr->Source_LR << "\n";
cout << "TCB Dest_LR = " << tcb_ptr->Dest_LR << "\n";
cout << "TCB Association Id = " << tcb_ptr->sctp_Association_id << "\n";
cout << "TCB state = " << tcb_ptr->state << "\n";
#endif
// fill in the user data
msg.sua_prim.data_pres = TRUE;
string stemp(buffer,len);
msg.sua_prim.data_string = stemp;
// encode the SUA unitdata message
error = msg.sua_encode();
string_size = msg.sua_msg.size();
SCTP_assoc_id = tcb_ptr->sctp_Association_id;
#ifdef DEBUG
cout << "routed to SCTP assoc " << SCTP_assoc_id << "\n";
#endif
#ifdef SUA_MANAGEMENT
sua_assoc_id = sua.AssocDB.Find_association( SCTP_assoc_id,
local_sua_id,
remote_sua_id
);
if (sua.AssocDB.instance[sua_assoc_id].asp.status == asp_active)
{
#endif
/* copy data into buffer, then finally... */
char* databuf = new char[msg.sua_msg.length()];
msg.sua_msg.copy(databuf, msg.sua_msg.length());
datalen = msg.sua_msg.length();
// send data to SCTP
result = sua_send_Message( SCTP_assoc_id,
sctp_stream_id,
sctp_delivery_type,
sctp_loadshare,
databuf,
datalen
);
delete databuf;
error_value = 0;
#ifdef SUA_MANAGEMENT
}
else
{
#ifdef DEBUG
cout << "sua_co.c:message sending prohibited\n";
#endif
error_value = -1;
}
#endif
#ifdef DEBUG
cout << "sua_co.c:result sctp send = "<< result << "\n";
#endif
return(error_value);
}
/***********************************************************************/
/* sua_send_CO Release Confirm */
/***********************************************************************/
int sua_send_CORELCO( sccp_QOS_str &QOS,
char *buffer,
unsigned int len,
unsigned int &Sua_ConnId,
tcb_Sua_TCB_str *tcb_ptr
)
{
Sua_container msg;
Sua_syntax_error_struct error;
int error_value;
int string_size, datalen;
unsigned int SCTP_assoc_id;
unsigned int sua_assoc_id;
unsigned int local_sua_id,remote_sua_id;
signed int sctp_loadshare = SCTP_USE_PRIMARY;
short sctp_stream_id = 0;
int sctp_delivery_type, result = 0;
// init the message
msg.sua_init();
// fill in the main sua header
msg.sua_prim.hdr_msg_class = sua_co;
msg.sua_prim.hdr_msg_type.co = co_relco;
msg.sua_prim.rout_con_pres = TRUE;
msg.sua_prim.rout_con = 1;
msg.sua_prim.importance_pres = TRUE;
msg.sua_prim.importance = 7;
msg.sua_prim.hop_count_pres = TRUE;
msg.sua_prim.hop_count = 15;
// QOS choice
switch (QOS.prot_class)
{
case(class2): // connectionless transport, non-sequenced
msg.sua_prim.prot_class_pres = TRUE;
msg.sua_prim.prot_class.pcl = prot_class_2;
msg.sua_prim.seq_control_pres = TRUE;
msg.sua_prim.seq_control = tcb_ptr->seq_number ;
sctp_delivery_type = SCTP_UNORDERED_DELIVERY;
break;
case(class3):
return(PROTOCOL_CLASS_NOT_SPECIFIED);
break;
default:
return(PROTOCOL_CLASS_NOT_SPECIFIED);
break;
}
if (QOS.return_msg_on_error)
msg.sua_prim.prot_class.return_option = TRUE;
else
msg.sua_prim.prot_class.return_option = FALSE;
// fill in the connection-oriented specific data of the msg
msg.sua_prim.source_ref_pres = TRUE;
msg.sua_prim.source_ref = tcb_ptr->Source_LR ;
msg.sua_prim.dest_ref_pres = TRUE;
msg.sua_prim.dest_ref = tcb_ptr->Dest_LR ;
msg.sua_prim.SCCP_cause_pres = TRUE;
msg.sua_prim.SCCP_cause.cause_type = ctp_release_cause;
msg.sua_prim.SCCP_cause.cause_value = 3;
// fill in the user data
msg.sua_prim.data_pres = TRUE;
string stemp(buffer,len);
msg.sua_prim.data_string = stemp;
// encode the SUA unitdata message
error = msg.sua_encode();
string_size = msg.sua_msg.size();
SCTP_assoc_id = tcb_ptr->sctp_Association_id;
tcb_ptr->state = scoc_idle;
#ifdef DEBUG
cout << "TCB source_LR = " << tcb_ptr->Source_LR << "\n";
cout << "TCB Dest_LR = " << tcb_ptr->Dest_LR << "\n";
cout << "TCB Association Id = " << tcb_ptr->sctp_Association_id << "\n";
cout << "TCB state = " << tcb_ptr->state << "\n";
#endif
#ifdef SUA_MANAGEMENT
sua_assoc_id = sua.AssocDB.Find_association( SCTP_assoc_id,
local_sua_id,
remote_sua_id
);
if (sua.AssocDB.instance[sua_assoc_id].asp.status == asp_active)
{
#endif
/* copy data into buffer, then finally... */
char* databuf = new char[msg.sua_msg.length()];
msg.sua_msg.copy(databuf, msg.sua_msg.length());
datalen = msg.sua_msg.length();
// send data to SCTP
result = sua_send_Message( SCTP_assoc_id,
sctp_stream_id,
sctp_delivery_type,
sctp_loadshare,
databuf,
datalen
);
delete databuf;
error_value = 0;
#ifdef SUA_MANAGEMENT
}
else
{
#ifdef DEBUG
cout << "sua_co.c:message sending prohibited\n";
#endif
error_value = -1;
}
#endif
#ifdef DEBUG
cout << "sua_co.c:result sctp send = "<< result << "\n";
#endif
// release the TCB of this connection
tcb_pool.release_TCB(Sua_ConnId);
return(error_value);
}
/***********************************************************************/
/* sua_send_CO Connection Refused */
/***********************************************************************/
int sua_send_COREF( sccp_QOS_str &QOS,
char *buffer,
unsigned int len,
unsigned int &Sua_ConnId,
tcb_Sua_TCB_str *tcb_ptr
)
{
Sua_container msg;
Sua_syntax_error_struct error;
int error_value;
int string_size, datalen;
unsigned int SCTP_assoc_id;
unsigned int sua_assoc_id;
unsigned int local_sua_id,remote_sua_id;
signed int sctp_loadshare = SCTP_USE_PRIMARY;
short sctp_stream_id = 0;
int sctp_delivery_type, result = 0;
sccp_addr_str called_pty_address;
// init the message
msg.sua_init();
// fill in the main sua header
msg.sua_prim.hdr_msg_class = sua_co;
msg.sua_prim.hdr_msg_type.co = co_coref;
msg.sua_prim.rout_con_pres = TRUE;
msg.sua_prim.rout_con = 1;
msg.sua_prim.importance_pres = TRUE;
msg.sua_prim.importance = 5;
msg.sua_prim.hop_count_pres = TRUE;
msg.sua_prim.hop_count = 15;
// QOS choice
switch (QOS.prot_class)
{
case(class2): // connectionless transport, non-sequenced
msg.sua_prim.prot_class_pres = TRUE;
msg.sua_prim.prot_class.pcl = prot_class_2;
msg.sua_prim.seq_control_pres = TRUE;
msg.sua_prim.seq_control = tcb_ptr->seq_number ;
sctp_delivery_type = SCTP_UNORDERED_DELIVERY;
break;
case(class3):
return(PROTOCOL_CLASS_NOT_SPECIFIED);
break;
default:
return(PROTOCOL_CLASS_NOT_SPECIFIED);
break;
}
if (QOS.return_msg_on_error)
msg.sua_prim.prot_class.return_option = TRUE;
else
msg.sua_prim.prot_class.return_option = FALSE;
called_pty_address = tcb_ptr->remote_address;
// fill in the destination address(=remote sua address/CLD)
switch (called_pty_address.routing_ind)
{
case (route_on_ssn):
if (called_pty_address.address_fields_present.pc == ipvx_pc_present)
{
msg.sua_prim.dest_addr.ip_addr_pres = TRUE;
if (called_pty_address.pc.ipvx.sa.sa_family == AF_INET)
{
msg.sua_prim.dest_addr.ip_addr_type = ip_v4;
msg.sua_prim.dest_addr.ip_addr.ipv4 = called_pty_address.pc.ipvx.sin;
}
else if (called_pty_address.pc.ipvx.sa.sa_family == AF_INET6)
{
msg.sua_prim.dest_addr.ip_addr_type = ip_v6;
msg.sua_prim.dest_addr.ip_addr.ipv6 = called_pty_address.pc.ipvx.sin6;
}
else
cout << "error filling in CLD IP address \n";
}
else
cout << "unsupported CLD address option\n";
msg.sua_prim.dest_addr_pres = TRUE;
msg.sua_prim.dest_addr.rout_ind = ri_route_IP_SSN;
msg.sua_prim.dest_addr.ssn_incl = TRUE;
msg.sua_prim.dest_addr.pc_incl = FALSE;
msg.sua_prim.dest_addr.gt_incl = FALSE;
msg.sua_prim.dest_addr.ssn = called_pty_address.ssn;
break;
case(route_on_name_gt):
break;
case(route_on_name_gt_next_office):
break;
default:
return(INVALID_CLD_ADDRESS);
break;
}
// fill in the connection-oriented specific data of the msg
msg.sua_prim.source_ref_pres = FALSE;
msg.sua_prim.dest_ref_pres = TRUE;
msg.sua_prim.dest_ref = tcb_ptr->Dest_LR ;
msg.sua_prim.SCCP_cause_pres = TRUE;
msg.sua_prim.SCCP_cause.cause_type = ctp_refusal_cause;
msg.sua_prim.SCCP_cause.cause_value = 3;
// fill in the user data
msg.sua_prim.data_pres = TRUE;
string stemp(buffer,len);
msg.sua_prim.data_string = stemp;
// encode the SUA unitdata message
error = msg.sua_encode();
string_size = msg.sua_msg.size();
SCTP_assoc_id = tcb_ptr->sctp_Association_id;
tcb_ptr->state = scoc_idle;
#ifdef DEBUG
cout << "TCB source_LR = " << tcb_ptr->Source_LR << "\n";
cout << "TCB Dest_LR = " << tcb_ptr->Dest_LR << "\n";
cout << "TCB Association Id = " << tcb_ptr->sctp_Association_id << "\n";
cout << "TCB state = " << tcb_ptr->state << "\n";
#endif
#ifdef SUA_MANAGEMENT
sua_assoc_id = sua.AssocDB.Find_association( SCTP_assoc_id,
local_sua_id,
remote_sua_id
);
if (sua.AssocDB.instance[sua_assoc_id].asp.status == asp_active)
{
#endif
/* copy data into buffer, then finally... */
char* databuf = new char[msg.sua_msg.length()];
msg.sua_msg.copy(databuf, msg.sua_msg.length());
datalen = msg.sua_msg.length();
// send data to SCTP
result = sua_send_Message( SCTP_assoc_id,
sctp_stream_id,
sctp_delivery_type,
sctp_loadshare,
databuf,
datalen
);
delete databuf;
error_value = 0;
#ifdef SUA_MANAGEMENT
}
else
{
#ifdef DEBUG
cout << "sua_co.c:message sending prohibited\n";
#endif
error_value = -1;
}
#endif
#ifdef DEBUG
cout << "sua_co.c:result sctp send = "<< result << "\n";
#endif
// release the TCB of this connection
tcb_pool.release_TCB(Sua_ConnId);
return(error_value);
}
/***********************************************************************/
/* Receive a sua connection-oriented message from the remote side */
/***********************************************************************/
/***********************************************************************/
/* sua_process_CORE */
/***********************************************************************/
short process_CORE_msg ( unsigned int sua_assoc_id,
tcb_Sua_TCB_str *tcb_ptr,
unsigned int &Sua_ConnId,
Sua_container &msg
)
{
int result = 0;
unsigned int sctp_assoc_id = 0;
unsigned int local_sua_id = 0;
sua_save_str temp;
unsigned int Sua_Out_ConnId;
tcb_Sua_TCB_str *tcb_out_ptr;
char digit_char;
temp.primitive = N_CONNECT_IND;
temp.user_ref = Sua_ConnId;
if ( msg.sua_prim.prot_class_pres )
{
// QOS choice
switch ( msg.sua_prim.prot_class.pcl)
{
case(prot_class_2): // connectionoriented transport, non-sequenced
temp.QOS.prot_class = class2;
temp.QOS.in_sequence = true;
break;
case(prot_class_3):
temp.QOS.prot_class = class3;
temp.QOS.in_sequence = true;
break;
default:
return(PROTOCOL_CLASS_NOT_SPECIFIED);
break;
}
temp.QOS.return_msg_on_error = (msg.sua_prim.prot_class.return_option == TRUE);
}
temp.QOS.sequence_number = 0;
temp.QOS.importance = msg.sua_prim.importance;
// retrieve the clg(=source) address (=remote sua address)
// which types are present in the address(ip pc, SS7 pc, GT, hostname)
if (msg.sua_prim.source_addr.ip_addr_pres == TRUE)
{
temp.calling_pty_address.address_fields_present.pc = ipvx_pc_present;
if (msg.sua_prim.source_addr.ip_addr_type == ip_v4) {
temp.calling_pty_address.pc.ipvx.sin = msg.sua_prim.source_addr.ip_addr.ipv4;
temp.calling_pty_address.pc.ipvx.sa.sa_family = AF_INET;
temp.calling_pty_address.pc.ipvx.sin.sin_port = sua.AssocDB.instance[sua_assoc_id].Dest.addrs[0].sin.sin_port;
}
else if (msg.sua_prim.source_addr.ip_addr_type == ip_v6) {
temp.calling_pty_address.pc.ipvx.sin6 = msg.sua_prim.source_addr.ip_addr.ipv6;
temp.calling_pty_address.pc.ipvx.sa.sa_family = AF_INET6;
temp.calling_pty_address.pc.ipvx.sin6.sin6_port = sua.AssocDB.instance[sua_assoc_id].Dest.addrs[0].sin6.sin6_port;
}
else
cout << "Unknown IP address format\n";
}
if (msg.sua_prim.source_addr.pc_pres == TRUE)
{
temp.calling_pty_address.address_fields_present.pc = ss7_pc_present;
temp.calling_pty_address.pc.ss7.ITU24.family = sua.AssocDB.instance[sua_assoc_id].Dest.pc.ITU24.family;
temp.calling_pty_address.pc.ss7.ITU24.pc = msg.sua_prim.source_addr.pc;
}
if (msg.sua_prim.source_addr.gt_pres == TRUE)
{
temp.calling_pty_address.address_fields_present.name_gt = GT_present;
temp.calling_pty_address.name.GT.Translation_Type = msg.sua_prim.source_addr.gt.translation_type ;
temp.calling_pty_address.name.GT.Numbering_Plan = msg.sua_prim.source_addr.gt.num_plan ;
temp.calling_pty_address.name.GT.Nature_of_Address = msg.sua_prim.source_addr.gt.nat_addr ;
temp.calling_pty_address.name.GT.nr_of_digits = msg.sua_prim.source_addr.gt.nr_of_digits ;
for (int i=0; i < temp.calling_pty_address.name.GT.nr_of_digits; i++){
sprintf(&digit_char, "%d", msg.sua_prim.source_addr.gt.digits[i]);
temp.calling_pty_address.name.GT.digits[i] = digit_char;
}
temp.calling_pty_address.name.GT.digits[temp.calling_pty_address.name.GT.nr_of_digits] = '\0';
}
if (msg.sua_prim.source_addr.hostname_pres == TRUE)
{
temp.calling_pty_address.address_fields_present.name_gt = hostname_present;
msg.sua_prim.source_addr.hostname.copy( temp.calling_pty_address.name.HostName,
(msg.sua_prim.source_addr.hostname.length()+1 )
);
temp.calling_pty_address.name.HostName[msg.sua_prim.source_addr.hostname.length()] = '\0';
}
if ((msg.sua_prim.source_addr.ip_addr_pres /= TRUE) &&
(msg.sua_prim.source_addr.pc_pres /= TRUE) &&
(msg.sua_prim.source_addr.gt_pres /= TRUE) &&
(msg.sua_prim.source_addr.hostname_pres /= TRUE))
{
cout << "No valid address format found in msg\n";
}
// routing indicator
switch (msg.sua_prim.source_addr.rout_ind)
{
case(ri_route_PC_SSN):
temp.calling_pty_address.routing_ind = route_on_ssn;
break;
case(ri_route_IP_SSN):
temp.calling_pty_address.routing_ind = route_on_ssn;
break;
case (ri_route_GT):
temp.calling_pty_address.routing_ind = route_on_name_gt;
break;
case (ri_route_hostname):
temp.calling_pty_address.routing_ind = route_on_name_gt;
break;
default:
break;
}
if (msg.sua_prim.source_addr.ssn_incl == TRUE) {
temp.calling_pty_address.address_fields_present.ssn_port = ssn_present;
temp.calling_pty_address.ssn = msg.sua_prim.source_addr.ssn;
}
else
temp.calling_pty_address.address_fields_present.ssn_port = no_sap_present;
// retrieve the called(=destination) address(=should be our own local addr)
// not completely done yet
if (msg.sua_prim.dest_addr.ip_addr_pres == TRUE)
{
temp.called_pty_address.address_fields_present.pc = ipvx_pc_present;
if (msg.sua_prim.dest_addr.ip_addr_type == ip_v4) {
temp.called_pty_address.pc.ipvx.sin = msg.sua_prim.dest_addr.ip_addr.ipv4;
temp.called_pty_address.pc.ipvx.sa.sa_family = AF_INET;
temp.called_pty_address.pc.ipvx.sin.sin_port = sua.AssocDB.instance[sua_assoc_id].Dest.addrs[0].sin.sin_port;
}
else if (msg.sua_prim.dest_addr.ip_addr_type == ip_v6) {
temp.called_pty_address.pc.ipvx.sin6 = msg.sua_prim.dest_addr.ip_addr.ipv6;
temp.called_pty_address.pc.ipvx.sa.sa_family = AF_INET6;
temp.called_pty_address.pc.ipvx.sin6.sin6_port = sua.AssocDB.instance[sua_assoc_id].Dest.addrs[0].sin6.sin6_port;
}
else
cout << "Unknown IP address format\n";
}
if (msg.sua_prim.dest_addr.pc_pres == TRUE)
{
temp.called_pty_address.address_fields_present.pc = ss7_pc_present;
temp.called_pty_address.pc.ss7.ITU24.family = sua.AssocDB.instance[sua_assoc_id].Dest.pc.ITU24.family;
temp.called_pty_address.pc.ss7.ITU24.pc = msg.sua_prim.dest_addr.pc;
}
if (msg.sua_prim.dest_addr.gt_pres == TRUE)
{
temp.called_pty_address.address_fields_present.name_gt = GT_present;
temp.called_pty_address.name.GT.Translation_Type = msg.sua_prim.dest_addr.gt.translation_type;
temp.called_pty_address.name.GT.Numbering_Plan = msg.sua_prim.dest_addr.gt.num_plan;
temp.called_pty_address.name.GT.Nature_of_Address = msg.sua_prim.dest_addr.gt.nat_addr;
temp.called_pty_address.name.GT.nr_of_digits = msg.sua_prim.dest_addr.gt.nr_of_digits;
for (int i=0; i < temp.called_pty_address.name.GT.nr_of_digits; i++){
sprintf(&digit_char, "%d", msg.sua_prim.dest_addr.gt.digits[i]);
temp.called_pty_address.name.GT.digits[i] = digit_char;
}
temp.called_pty_address.name.GT.digits[temp.called_pty_address.name.GT.nr_of_digits] = '\0';
}
if (msg.sua_prim.dest_addr.hostname_pres == TRUE)
{
temp.called_pty_address.address_fields_present.name_gt = hostname_present;
msg.sua_prim.dest_addr.hostname.copy( temp.called_pty_address.name.HostName,
(msg.sua_prim.dest_addr.hostname.length()+1 )
);
temp.called_pty_address.name.HostName[msg.sua_prim.dest_addr.hostname.length()] = '\0';
}
// routing indicator
switch (msg.sua_prim.dest_addr.rout_ind)
{
case(ri_route_PC_SSN):
temp.called_pty_address.routing_ind = route_on_ssn;
break;
case (ri_route_GT):
temp.called_pty_address.routing_ind = route_on_name_gt;
break;
case (ri_route_hostname):
temp.called_pty_address.routing_ind = route_on_name_gt;
break;
default:
break;
}
temp.called_pty_address.address_fields_present.ssn_port = ssn_present;
temp.called_pty_address.ssn = msg.sua_prim.dest_addr.ssn;
// fill in the allocated TCB
tcb_ptr->Source_LR = Sua_ConnId;
tcb_ptr->Dest_LR = msg.sua_prim.source_ref;
tcb_ptr->User_ref_id = 1;
tcb_ptr->sctp_Association_id = sua.AssocDB.instance[sua_assoc_id].SCTP_assoc_id;
tcb_ptr->state = scoc_incoming;
tcb_ptr->remote_address = temp.calling_pty_address;
tcb_ptr->seq_number = Sua_ConnId % 255;
local_sua_id = sua.AssocDB.instance[sua_assoc_id].local_sua_id;
#ifdef DEBUG
cout << "TCB source_LR = " << tcb_ptr->Source_LR << "\n";
cout << "TCB Dest_LR = " << tcb_ptr->Dest_LR << "\n";
cout << "TCB Association Id = " << tcb_ptr->sctp_Association_id << "\n";
cout << "TCB state = " << tcb_ptr->state << "\n";
#endif
if (msg.sua_prim.data_pres == TRUE)
temp.userdata = msg.sua_prim.data_string;
else
cout << "sua_co.c: no sua user data in CORE msg \n";
/* Is this the final destination ? */
if ( sua.Find_local_sua ( temp.called_pty_address) > 0 )
{
/* Yes, message has arrived at its final destination -> send */
/* to upper layer */
/* store primitive in a list(is retrieve via sua_receive_msg) */
rec_msg_pool.push_back(temp);
/* call the application/user callBack function */
sua.local_sua.instance[local_sua_id].SUA_APLCallBack.ulp_ConnIndNotif
( local_sua_id,
Sua_ConnId,
temp.userdata.length()
);
}
else
{
/* No, Message has not arrived at its final destination -> */
/* route it to the next SUA node via an SCTP association nr x */
/* setup TCB linkage for CO */
tcb_out_ptr = tcb_pool.allocate_TCB(Sua_Out_ConnId);
msg.sua_prim.source_ref = Sua_Out_ConnId;
result = sua_route_Message( sctp_assoc_id,
local_sua_id,
msg,
temp.called_pty_address,
temp.calling_pty_address
);
// fill in the allocated TCB
tcb_out_ptr->Source_LR = Sua_Out_ConnId;
tcb_out_ptr->User_ref_id = 1;
tcb_out_ptr->sctp_Association_id = sctp_assoc_id;
/* fill in link from TCB_out to first TCB */
tcb_out_ptr->scoc_tcb_id = Sua_ConnId;
tcb_out_ptr->state = scoc_outgoing;
tcb_out_ptr->remote_address = temp.called_pty_address;
tcb_out_ptr->seq_number = Sua_Out_ConnId % 255;
/* fill in the link from the first TCB to the TCB_out */
tcb_ptr->scoc_tcb_id = Sua_Out_ConnId;
}
return(0);
}
/***********************************************************************/
/* sua_process_COAK */
/***********************************************************************/
short process_COAK_msg ( unsigned int sua_assoc_id,
tcb_Sua_TCB_str *tcb_ptr,
unsigned int &sua_ConnId,
Sua_container &msg
)
{
unsigned int local_sua_id = 0;
sua_save_str temp;
unsigned int Sua_Out_ConnId;
tcb_Sua_TCB_str *tcb_out_ptr;
Sua_syntax_error_struct error;
temp.primitive = N_CONNECT_CONF;
temp.user_ref = sua_ConnId;
if (msg.sua_prim.prot_class_pres)
{
// QOS choice
switch ( msg.sua_prim.prot_class.pcl)
{
case(prot_class_2): // connectionoriented transport, non-sequenced
temp.QOS.prot_class = class2;
temp.QOS.in_sequence = true;
break;
case(prot_class_3):
temp.QOS.prot_class = class3;
temp.QOS.in_sequence = true;
break;
default:
return(PROTOCOL_CLASS_NOT_SPECIFIED);
break;
}
temp.QOS.return_msg_on_error = (msg.sua_prim.prot_class.return_option == TRUE);
}
temp.QOS.sequence_number = 0;
temp.QOS.importance = msg.sua_prim.importance;
// retrieve the clg(=source) address (=remote sua address)
// retrieve the called(=destination) address(=should be our own local addr)
// fill in the allocated TCB
tcb_ptr->Dest_LR = msg.sua_prim.source_ref;
tcb_ptr->User_ref_id = 1;
tcb_ptr->state = scoc_active;
local_sua_id = sua.AssocDB.instance[sua_assoc_id].local_sua_id;
#ifdef DEBUG
cout << "TCB source_LR = " << tcb_ptr->Source_LR << "\n";
cout << "TCB Dest_LR = " << tcb_ptr->Dest_LR << "\n";
cout << "TCB Association Id = " << tcb_ptr->sctp_Association_id << "\n";
cout << "TCB state = " << tcb_ptr->state << "\n";
#endif
if (msg.sua_prim.data_pres == TRUE)
temp.userdata = msg.sua_prim.data_string;
else
cout << "sua_co.c: no sua user data in CODATA msg \n";
/* Look if this is the end or intermediate node */
Sua_Out_ConnId = tcb_ptr->scoc_tcb_id;
/* Is this the final destination ? */
if ( Sua_Out_ConnId == 0 )
{
/* Yes, message has arrived at its final destination -> send */
/* to upper layer */
// store primitive in a list(is retrieve via sua_receive_msg)
rec_msg_pool.push_back(temp);
/* call the application/user callBack function */
sua.local_sua.instance[local_sua_id].SUA_APLCallBack.ulp_ConnConfIndNotif
( local_sua_id,
sua_ConnId,
temp.userdata.length()
);
}
else
{
/* No, Message has not arrived at its final destination -> */
/* route it to the next SUA node via an SCTP association nr x */
/* get association id from SCOC TCB */
tcb_out_ptr = tcb_pool.get_tcb(Sua_Out_ConnId);
msg.sua_prim.source_ref = tcb_out_ptr->Source_LR;
msg.sua_prim.dest_ref = tcb_out_ptr->Dest_LR;
error = msg.sua_encode();
/* copy data into buffer, then finally... */
signed int sctp_loadshare = SCTP_USE_PRIMARY;
short sctp_stream_id = 0;
int sctp_delivery_type = 0 ,datalen , result = 0;
char* databuf = new char[msg.sua_msg.length()];
msg.sua_msg.copy(databuf, msg.sua_msg.length());
datalen = msg.sua_msg.length();
// send data to SCTP
result = sua_send_Message( tcb_out_ptr->sctp_Association_id,
sctp_stream_id,
sctp_delivery_type,
sctp_loadshare,
databuf,
datalen
);
delete databuf;
// set the outgoing TCB on active
tcb_out_ptr->state = scoc_active;
}
return(0);
}
/***********************************************************************/
/* sua_process_CODATA */
/***********************************************************************/
short process_CODATA_msg ( unsigned int sua_assoc_id,
tcb_Sua_TCB_str *tcb_ptr,
unsigned int &sua_ConnId,
Sua_container &msg
)
{
unsigned int local_sua_id = 0;
sua_save_str temp;
unsigned int Sua_Out_ConnId;
tcb_Sua_TCB_str *tcb_out_ptr;
Sua_syntax_error_struct error;
//temp.primitive = N_CODATA;
temp.user_ref = sua_ConnId;
temp.QOS.return_msg_on_error = (msg.sua_prim.prot_class.return_option == TRUE);
temp.QOS.sequence_number = 0;
temp.QOS.importance = msg.sua_prim.importance;
// retrieve the clg(=source) address (=remote sua address)
// not needed -> to be found in TCB
// retrieve the called(=destination) address(=should be our own local addr)
// not needed -> to be found in TCB
local_sua_id = sua.AssocDB.instance[sua_assoc_id].local_sua_id;
#ifdef DEBUG
cout << "TCB source_LR = " << tcb_ptr->Source_LR << "\n";
cout << "TCB Dest_LR = " << tcb_ptr->Dest_LR << "\n";
cout << "TCB Association Id = " << tcb_ptr->sctp_Association_id << "\n";
cout << "TCB state = " << tcb_ptr->state << "\n";
#endif
if (msg.sua_prim.data_pres == TRUE)
temp.userdata = msg.sua_prim.data_string;
else
cout << "sua_co.c: no sua user data in CODATA msg \n";
/* Look if this is the end or intermediate node */
Sua_Out_ConnId = tcb_ptr->scoc_tcb_id;
/* Is this the final destination ? */
if ( Sua_Out_ConnId == 0 )
{
// store primitive in a list(is retrieve via sua_receive_msg)
rec_msg_pool.push_back(temp);
/* call the application/user callBack function */
sua.local_sua.instance[local_sua_id].SUA_APLCallBack.ulp_ConnDataIndNotif
( local_sua_id,
sua_ConnId,
temp.userdata.length()
);
}
else
{
/* No, Message has not arrived at its final destination -> */
/* route it to the next SUA node via an SCTP association nr x */
/* get association id from SCOC TCB */
tcb_out_ptr = tcb_pool.get_tcb(Sua_Out_ConnId);
msg.sua_prim.source_ref = tcb_out_ptr->Source_LR;
msg.sua_prim.dest_ref = tcb_out_ptr->Dest_LR;
error = msg.sua_encode();
/* copy data into buffer, then finally... */
signed int sctp_loadshare = SCTP_USE_PRIMARY;
short sctp_stream_id = 0;
int sctp_delivery_type = 0 ,datalen , result = 0;
char* databuf = new char[msg.sua_msg.length()];
msg.sua_msg.copy(databuf, msg.sua_msg.length());
datalen = msg.sua_msg.length();
// send data to SCTP
result = sua_send_Message( tcb_out_ptr->sctp_Association_id,
sctp_stream_id,
sctp_delivery_type,
sctp_loadshare,
databuf,
datalen
);
delete databuf;
}
return(0);
}
/***********************************************************************/
/* sua_process_CORELRQ */
/***********************************************************************/
short process_CORELRQ_msg ( unsigned int sua_assoc_id,
tcb_Sua_TCB_str *tcb_ptr,
unsigned int &sua_ConnId,
Sua_container &msg
)
{
unsigned int local_sua_id = 0;
unsigned int release_cause = 0;
unsigned int routing_Contex = 0;
sua_save_str temp;
unsigned int Sua_Out_ConnId;
tcb_Sua_TCB_str *tcb_out_ptr;
Sua_syntax_error_struct error;
temp.primitive = N_RELEASE_REQ;
temp.user_ref = sua_ConnId;
routing_Contex = msg.sua_prim.rout_con;
temp.QOS.return_msg_on_error = (msg.sua_prim.prot_class.return_option == TRUE);
temp.QOS.sequence_number = 0;
temp.QOS.importance = msg.sua_prim.importance;
// retrieve the clg(=source) address (=remote sua address)
// retrieve the called(=destination) address(=should be our own local addr)
tcb_ptr->state = scoc_disconnect;
#ifdef DEBUG
cout << "TCB source_LR = " << tcb_ptr->Source_LR << "\n";
cout << "TCB Dest_LR = " << tcb_ptr->Dest_LR << "\n";
cout << "TCB Association Id = " << tcb_ptr->sctp_Association_id << "\n";
cout << "TCB state = " << tcb_ptr->state << "\n";
#endif
if (msg.sua_prim.data_pres == TRUE)
temp.userdata = msg.sua_prim.data_string;
else
cout << "sua_co.c: no sua user data in CODATA msg \n";
/* Look if this is the end or intermediate node */
Sua_Out_ConnId = tcb_ptr->scoc_tcb_id;
/* Is this the final destination ? */
if ( Sua_Out_ConnId == 0 )
{
// store primitive in a list(is retrieve via sua_receive_msg)
rec_msg_pool.push_back(temp);
// send a CORELCONF back to the remote node
Sua_syntax_error_struct error;
int datalen;
unsigned int assoc_id;
short stream_id = 0;
int delivery_type, result;
// init the message
msg.sua_init();
// fill in the main sua header
msg.sua_prim.hdr_msg_class = sua_co;
msg.sua_prim.hdr_msg_type.co = co_relco;
msg.sua_prim.rout_con_pres = TRUE;
msg.sua_prim.rout_con = routing_Contex;
msg.sua_prim.importance_pres = TRUE;
msg.sua_prim.importance = 7;
// QOS choice
delivery_type = SCTP_UNORDERED_DELIVERY;
// fill in the connection-oriented specific data of the msg
msg.sua_prim.source_ref_pres = TRUE;
msg.sua_prim.source_ref = tcb_ptr->Source_LR ;
msg.sua_prim.dest_ref_pres = TRUE;
msg.sua_prim.dest_ref = tcb_ptr->Dest_LR ;
msg.sua_prim.SCCP_cause_pres = FALSE;
// fill in the user data
msg.sua_prim.data_pres = FALSE;
// encode the SUA Release complete message
error = msg.sua_encode();
//string_size = msg.sua_msg.size();
assoc_id = tcb_ptr->sctp_Association_id;
local_sua_id = sua.AssocDB.instance[sua_assoc_id].local_sua_id;
#ifdef DEBUG
cout << "routed to SCTP assoc " << assoc_id << "\n";
#endif
tcb_ptr->state = scoc_idle;
// send data to SCTP
char* databuf = new char[msg.sua_msg.length()];
msg.sua_msg.copy(databuf, msg.sua_msg.length());
datalen = msg.sua_msg.length();
#ifdef DEBUG
// display byte array
display_byte_array(databuf , msg.sua_msg.length());
#endif
char logstring[100];
sprintf(logstring, "SUA encoded message, ready for being send to SCTP assoc %d", assoc_id);
event_log("sua_co.c",logstring);
log_byte_array("sua_co.c", databuf,msg.sua_msg.length());
result = sctp_send ( assoc_id,
stream_id,
(unsigned char *) databuf,
datalen,
htonl(SUA_PPI),
SCTP_USE_PRIMARY,
SCTP_NO_CONTEXT,
SCTP_INFINITE_LIFETIME,
delivery_type,
SCTP_BUNDLING_DISABLED
);
delete databuf;
// release the TCB of this connection
tcb_pool.release_TCB(sua_ConnId);
#ifdef DEBUG
cout << "local_sua_id = " << local_sua_id << "\n";
#endif
/* call the application/user callBack function */
sua.local_sua.instance[local_sua_id].SUA_APLCallBack.ulp_DisConnIndNotif
( local_sua_id,
sua_ConnId,
release_cause,
temp.userdata.length()
);
}
else
{
/* No, Message has not arrived at its final destination -> */
/* route it to the next SUA node via an SCTP association nr x */
/* get association id from SCOC TCB */
tcb_out_ptr = tcb_pool.get_tcb(Sua_Out_ConnId);
msg.sua_prim.source_ref = tcb_out_ptr->Source_LR;
msg.sua_prim.dest_ref = tcb_out_ptr->Dest_LR;
error = msg.sua_encode();
/* copy data into buffer, then finally... */
signed int sctp_loadshare = SCTP_USE_PRIMARY;
short sctp_stream_id = 0;
int sctp_delivery_type = 0 ,datalen , result = 0;
char* databuf = new char[msg.sua_msg.length()];
msg.sua_msg.copy(databuf, msg.sua_msg.length());
datalen = msg.sua_msg.length();
// send data to SCTP
result = sua_send_Message( tcb_out_ptr->sctp_Association_id,
sctp_stream_id,
sctp_delivery_type,
sctp_loadshare,
databuf,
datalen
);
delete databuf;
}
return(0);
}
/***********************************************************************/
/* sua_process_CORELCO */
/***********************************************************************/
short process_CORELCO_msg ( unsigned int sua_assoc_id,
tcb_Sua_TCB_str *tcb_ptr,
unsigned int &sua_ConnId,
Sua_container &msg
)
{
unsigned int local_sua_id = 0;
unsigned int release_cause = 0;
sua_save_str temp;
unsigned int Sua_Out_ConnId;
tcb_Sua_TCB_str *tcb_out_ptr;
Sua_syntax_error_struct error;
temp.primitive = N_RELEASE_CONF;
temp.user_ref = sua_ConnId;
temp.QOS.return_msg_on_error = (msg.sua_prim.prot_class.return_option == TRUE);
temp.QOS.sequence_number = 0;
temp.QOS.importance = msg.sua_prim.importance;
// retrieve the clg(=source) address (=remote sua address)
// retrieve the called(=destination) address(=should be our own local addr)
tcb_ptr->state = scoc_idle;
#ifdef DEBUG
cout << "TCB source_LR = " << tcb_ptr->Source_LR << "\n";
cout << "TCB Dest_LR = " << tcb_ptr->Dest_LR << "\n";
cout << "TCB Association Id = " << tcb_ptr->sctp_Association_id << "\n";
cout << "TCB state = " << tcb_ptr->state << "\n";
#endif
local_sua_id = sua.AssocDB.instance[sua_assoc_id].local_sua_id;
/* Look if this is the end or intermediate node */
Sua_Out_ConnId = tcb_ptr->scoc_tcb_id;
/* Is this the final destination ? */
if ( Sua_Out_ConnId == 0 )
{
// store primitive in a list(is retrieve via sua_receive_msg)
rec_msg_pool.push_back(temp);
// release the TCB of this connection
tcb_pool.release_TCB(sua_ConnId);
/* call the application/user callBack function */
sua.local_sua.instance[local_sua_id].SUA_APLCallBack.ulp_DisConnIndNotif
( local_sua_id,
sua_ConnId,
release_cause,
temp.userdata.length()
);
}
else
{
/* No, Message has not arrived at its final destination -> */
/* route it to the next SUA node via an SCTP association nr x */
/* get association id from SCOC TCB */
tcb_out_ptr = tcb_pool.get_tcb(Sua_Out_ConnId);
msg.sua_prim.source_ref = tcb_out_ptr->Source_LR;
msg.sua_prim.dest_ref = tcb_out_ptr->Dest_LR;
error = msg.sua_encode();
/* copy data into buffer, then finally... */
signed int sctp_loadshare = SCTP_USE_PRIMARY;
short sctp_stream_id = 0;
int sctp_delivery_type = 0 ,datalen , result = 0;
char* databuf = new char[msg.sua_msg.length()];
msg.sua_msg.copy(databuf, msg.sua_msg.length());
datalen = msg.sua_msg.length();
// send data to SCTP
result = sua_send_Message( tcb_out_ptr->sctp_Association_id,
sctp_stream_id,
sctp_delivery_type,
sctp_loadshare,
databuf,
datalen
);
delete databuf;
// release the incoming TCB of this connection
tcb_pool.release_TCB(sua_ConnId);
// release outgoing TCB of this connection
tcb_pool.release_TCB(Sua_Out_ConnId);
}
return(0);
}
/***********************************************************************/
/* sua_process_COREF */
/***********************************************************************/
short process_COREF_msg ( unsigned int sua_assoc_id,
tcb_Sua_TCB_str *tcb_ptr,
unsigned int &sua_ConnId,
Sua_container &msg
)
{
unsigned int local_sua_id = 0;
unsigned int release_cause = 0;
sua_save_str temp;
unsigned int Sua_Out_ConnId;
tcb_Sua_TCB_str *tcb_out_ptr;
Sua_syntax_error_struct error;
temp.primitive = N_CONNECT_REFUSED;
temp.user_ref = sua_ConnId;
if ( msg.sua_prim.prot_class_pres )
{
// QOS choice
switch ( msg.sua_prim.prot_class.pcl)
{
case(prot_class_2): // connectionoriented transport, non-sequenced
temp.QOS.prot_class = class2;
temp.QOS.in_sequence = true;
break;
case(prot_class_3):
temp.QOS.prot_class = class3;
temp.QOS.in_sequence = true;
break;
default:
return(PROTOCOL_CLASS_NOT_SPECIFIED);
break;
}
temp.QOS.return_msg_on_error = (msg.sua_prim.prot_class.return_option == TRUE);
}
temp.QOS.sequence_number = 0;
temp.QOS.importance = msg.sua_prim.importance;
// retrieve the clg(=source) address (=remote sua address)
// retrieve the called(=destination) address(=should be our own local addr)
tcb_ptr->state = scoc_idle;
#ifdef DEBUG
cout << "TCB source_LR = " << tcb_ptr->Source_LR << "\n";
cout << "TCB Dest_LR = " << tcb_ptr->Dest_LR << "\n";
cout << "TCB Association Id = " << tcb_ptr->sctp_Association_id << "\n";
cout << "TCB state = " << tcb_ptr->state << "\n";
#endif
if (msg.sua_prim.data_pres == TRUE)
temp.userdata = msg.sua_prim.data_string;
/* Look if this is the end or intermediate node */
Sua_Out_ConnId = tcb_ptr->scoc_tcb_id;
/* Is this the final destination ? */
if ( Sua_Out_ConnId == 0 )
{
// store primitive in a list(is retrieve via sua_receive_msg)
rec_msg_pool.push_back(temp);
// release the TCB of this connection
tcb_pool.release_TCB(sua_ConnId);
#ifdef DEBUG
cout << "local_sua_id = " << local_sua_id << "\n";
#endif
/* call the application/user callBack function */
sua.local_sua.instance[local_sua_id].SUA_APLCallBack.ulp_DisConnIndNotif
( local_sua_id,
sua_ConnId,
release_cause,
temp.userdata.length()
);
}
else
{
/* No, Message has not arrived at its final destination -> */
/* route it to the next SUA node via an SCTP association nr x */
/* get association id from SCOC TCB */
tcb_out_ptr = tcb_pool.get_tcb(Sua_Out_ConnId);
msg.sua_prim.source_ref = tcb_out_ptr->Source_LR;
msg.sua_prim.dest_ref = tcb_out_ptr->Dest_LR;
error = msg.sua_encode();
/* copy data into buffer, then finally... */
signed int sctp_loadshare = SCTP_USE_PRIMARY;
short sctp_stream_id = 0;
int sctp_delivery_type = 0 ,datalen , result = 0;
char* databuf = new char[msg.sua_msg.length()];
msg.sua_msg.copy(databuf, msg.sua_msg.length());
datalen = msg.sua_msg.length();
// send data to SCTP
result = sua_send_Message( tcb_out_ptr->sctp_Association_id,
sctp_stream_id,
sctp_delivery_type,
sctp_loadshare,
databuf,
datalen
);
delete databuf;
// release the incoming TCB of this connection
tcb_pool.release_TCB(sua_ConnId);
// release outgoing TCB of this connection
tcb_pool.release_TCB(Sua_Out_ConnId);
}
return(0);
}
// end of module sua_co.c