2044 lines
67 KiB
C
2044 lines
67 KiB
C
|
|
/************************************************************************/
|
|||
|
|
/* SISCO SOFTWARE MODULE HEADER *****************************************/
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* (c) Copyright Systems Integration Specialists Company, Inc., */
|
|||
|
|
/* 1997-2005, All Rights Reserved */
|
|||
|
|
/* */
|
|||
|
|
/* PROPRIETARY AND CONFIDENTIAL */
|
|||
|
|
/* */
|
|||
|
|
/* MODULE NAME : cospmain.c */
|
|||
|
|
/* PRODUCT(S) : MOSI Stack (over TP4) */
|
|||
|
|
/* */
|
|||
|
|
/* MODULE DESCRIPTION : */
|
|||
|
|
/* This file implements functions common to CALLING and */
|
|||
|
|
/* CALLED side of the COSP protocol. */
|
|||
|
|
/* */
|
|||
|
|
/* For information see the: */
|
|||
|
|
/* ISO 8326 "Information processing systems - Open Systems */
|
|||
|
|
/* Interconnection - Basic connection oriented session service */
|
|||
|
|
/* definition. */
|
|||
|
|
/* ISO 8327 "Information processing systems - Open Systems */
|
|||
|
|
/* Interconnection - Basic connection oriented session protocol */
|
|||
|
|
/* specification. */
|
|||
|
|
/* ISO 8327/ADD.2 (Draft for Version2). */
|
|||
|
|
/* */
|
|||
|
|
/* */
|
|||
|
|
/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */
|
|||
|
|
/* */
|
|||
|
|
/* cosp_bind */
|
|||
|
|
/* cosp_unbind */
|
|||
|
|
/* */
|
|||
|
|
/* cosp_con_req */
|
|||
|
|
/* cosp_con_rsp_pos */
|
|||
|
|
/* cosp_con_rsp_neg */
|
|||
|
|
/* */
|
|||
|
|
/* cosp_rel_req */
|
|||
|
|
/* cosp_rel_rsp_pos */
|
|||
|
|
/* */
|
|||
|
|
/* cosp_u_abort_req */
|
|||
|
|
/* */
|
|||
|
|
/* cosp_data_req */
|
|||
|
|
/* */
|
|||
|
|
/* tp4_bind_cnf */
|
|||
|
|
/* tp4_unbind_cnf */
|
|||
|
|
/* */
|
|||
|
|
/* tp4_connect_ind */
|
|||
|
|
/* tp4_connect_cnf */
|
|||
|
|
/* tp4_disconnect_ind */
|
|||
|
|
/* tp4_data_ind */
|
|||
|
|
/* tp4_expdata_ind */
|
|||
|
|
/* */
|
|||
|
|
/* */
|
|||
|
|
/* MODIFICATION LOG : */
|
|||
|
|
/* Date Who Rev Comments */
|
|||
|
|
/* -------- --- ------ ------------------------------------------- */
|
|||
|
|
/* 07/30/08 JRB 21 Chg log msg from ERR to ENC. */
|
|||
|
|
/* 04/28/08 GLB 20 Removed CALLED_ONLY and CALLING_ONLY */
|
|||
|
|
/* 04/09/08 JRB 19 Fix log message for unsupported SPDU. */
|
|||
|
|
/* 05/05/05 EJV 18 cosp_con_req: copy new port param. */
|
|||
|
|
/* 09/17/04 JRB 17 cosp_con_req: save tp4_conn_id returned from */
|
|||
|
|
/* modified tp4_connect (need for abort fix). */
|
|||
|
|
/* cosp_u_abort_req: if waiting for T-CONNECT.cnf,*/
|
|||
|
|
/* call tp4_disconnect (correct ISO 8327 action).*/
|
|||
|
|
/* 01/20/04 EJV 16 acse_free_con: add a_free_part_security_info.*/
|
|||
|
|
/* 11/14/03 JRB 15 Save encrypt_ctrl ONLY for TP0 (not for TP4).*/
|
|||
|
|
/* 08/25/03 EJV 14 Added param to tp4_connect(). */
|
|||
|
|
/* tp4_connect_ind, cnf: save encrypt_ctrl */
|
|||
|
|
/* 06/20/02 JRB 13 Chg addr args to tp4_connect_ind & */
|
|||
|
|
/* copy them to ACSE_CONN. */
|
|||
|
|
/* 06/05/02 JRB 12 Allow Called SSEL=NULL (0 length) on conn req*/
|
|||
|
|
/* 09/10/01 JRB 11 Remove last change but fix cosp_cn_ptr free. */
|
|||
|
|
/* 08/01/01 JRB 10 Del rem_addr from cosp_enc_cn_ac calls. */
|
|||
|
|
/* Del use of cosp_cn_ptr, cosp_cn_len. */
|
|||
|
|
/* 05/09/01 JRB 09 On S-CONNECT.ind, save SSELs in ACSE_CONN. */
|
|||
|
|
/* 03/14/01 JRB 08 Use new SMEM allocation functions. */
|
|||
|
|
/* Add global variable "session_cfg". */
|
|||
|
|
/* 09/13/99 MDE 07 Added SD_CONST modifiers */
|
|||
|
|
/* 08/13/98 JRB 06 Lint cleanup. */
|
|||
|
|
/* 06/17/98 JRB 05 Allow second call to cosp_bind if SSEL same. */
|
|||
|
|
/* 12/30/97 JRB 04 cosp_bind return same as tp4_bind if it fails*/
|
|||
|
|
/* 07/31/97 JRB 03 cosp_bind & cosp_con_req: set "tp_type" in */
|
|||
|
|
/* tp4_addr. */
|
|||
|
|
/* Don't set NSAP on tp4_bind call (ignored). */
|
|||
|
|
/* 05/27/97 JRB 7.00 MMSEASE 7.0 release. */
|
|||
|
|
/* 03/20/97 EJV 02 Enhanced logging and collision handling. */
|
|||
|
|
/* 02/07/97 EJV 01 Created */
|
|||
|
|
/************************************************************************/
|
|||
|
|
#include "glbtypes.h"
|
|||
|
|
#include "sysincs.h"
|
|||
|
|
|
|||
|
|
#ifdef DEBUG_SISCO
|
|||
|
|
SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; /* Define for SLOG mechanism */
|
|||
|
|
#endif
|
|||
|
|
|
|||
|
|
#include "mem_chk.h"
|
|||
|
|
#include "tp4api.h"
|
|||
|
|
#include "tp4.h" /* need MIN_TP0_CONN_ID definition */
|
|||
|
|
#include "acse2.h"
|
|||
|
|
|
|||
|
|
#include "cosp_log.h"
|
|||
|
|
#include "cosp.h"
|
|||
|
|
#include "cosp_usr.h"
|
|||
|
|
|
|||
|
|
|
|||
|
|
/*======================================================*/
|
|||
|
|
/* */
|
|||
|
|
/* L O C A L V A R I A B L E S */
|
|||
|
|
/* A N D */
|
|||
|
|
/* F U N C T I O N S P R O T O T Y P E S */
|
|||
|
|
/* */
|
|||
|
|
/*======================================================*/
|
|||
|
|
|
|||
|
|
/* define actions to perform after return from one of decode functions */
|
|||
|
|
#define COSP_S_P_ABORT_IND 1
|
|||
|
|
#define COSP_SEND_ABORT_SPDU 2
|
|||
|
|
#define COSP_T_DISCONNECT 4
|
|||
|
|
|
|||
|
|
|
|||
|
|
ST_RET cosp_send_abort (ACSE_CONN *con, ST_INT err_code);
|
|||
|
|
|
|||
|
|
static ST_RET cosp_process_connect (ACSE_CONN *con, ST_UINT spdu_len, char *spdu_buf);
|
|||
|
|
static ST_RET cosp_process_finish (ACSE_CONN *con, ST_UINT spdu_len, char *spdu_buf);
|
|||
|
|
static ST_RET cosp_process_accept (ACSE_CONN *con, ST_UINT spdu_len, char *spdu_buf);
|
|||
|
|
static ST_RET cosp_process_refuse (ACSE_CONN *con, ST_UINT spdu_len, char *spdu_buf);
|
|||
|
|
static ST_RET cosp_process_discon (ACSE_CONN *con, ST_UINT spdu_len, char *spdu_buf);
|
|||
|
|
static ST_RET cosp_process_abort (ACSE_CONN *con, ST_UINT spdu_len, char *spdu_buf);
|
|||
|
|
static ST_RET cosp_process_data (ACSE_CONN *con, ST_UINT spdu_len, char *spdu_buf);
|
|||
|
|
|
|||
|
|
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* Global and static variables. */
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* flag below prevents calling acse_free_con twice (if we are in func */
|
|||
|
|
/* tp4_connect and tp4_disconnect_ind is called) */
|
|||
|
|
|
|||
|
|
static ST_BOOLEAN cosp_in_tp4_func;
|
|||
|
|
|
|||
|
|
static ST_BOOLEAN cosp_bind_called; /* only 1 binding allowed */
|
|||
|
|
|
|||
|
|
ST_UCHAR cosp_only_ssel [1+MAX_SSEL_LEN];
|
|||
|
|
SESSION_CFG session_cfg; /* Session layer configuration */
|
|||
|
|
|
|||
|
|
/*======================================================*/
|
|||
|
|
/* */
|
|||
|
|
/* B I N D I N G F U N C T I O N S */
|
|||
|
|
/* */
|
|||
|
|
/*======================================================*/
|
|||
|
|
|
|||
|
|
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* cosp_bind */
|
|||
|
|
/*----------------------------------------------------------------------*/
|
|||
|
|
/* Function called by SS-user to bind to local Session Address. */
|
|||
|
|
/* The SS-user should implement the u_cosp_bind_cnf function. */
|
|||
|
|
/* */
|
|||
|
|
/* Parameters: */
|
|||
|
|
/* ST_LONG cosp_user_bind_id COSP User's id for this binding.*/
|
|||
|
|
/* PRES_ADDR *loc_addr Local Address to bind to */
|
|||
|
|
/* ST_INT sharable Ignored, (for compatibility with*/
|
|||
|
|
/* ST_INT max_conns Ignored, previous versions) */
|
|||
|
|
/* */
|
|||
|
|
/* Return: */
|
|||
|
|
/* SD_SUCCESS (0) if bind successful */
|
|||
|
|
/* error code otherwise */
|
|||
|
|
/************************************************************************/
|
|||
|
|
ST_RET cosp_bind (ST_LONG cosp_user_bind_id, PRES_ADDR *loc_addr,
|
|||
|
|
ST_INT sharable, ST_INT max_conns)
|
|||
|
|
{
|
|||
|
|
ST_INT ret;
|
|||
|
|
TP4_ADDR tp4_addr;
|
|||
|
|
ST_LONG user_bind_id; /* TP4 user bind id */
|
|||
|
|
|
|||
|
|
COSP_LOG_ENC1 ("S-BIND.req: cosp_user_bind_id =0x%08X", cosp_user_bind_id);
|
|||
|
|
|
|||
|
|
ret = SD_SUCCESS;
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
/* Check SSEL. If OK, save it. */
|
|||
|
|
if (!cosp_bind_called)
|
|||
|
|
{
|
|||
|
|
/* If local SSEL len is legal, save SSEL. */
|
|||
|
|
if (loc_addr->ssel_len <= MAX_SSEL_LEN)
|
|||
|
|
{
|
|||
|
|
if ((cosp_only_ssel [0] = (ST_UCHAR) loc_addr->ssel_len) > 0)
|
|||
|
|
memcpy (&cosp_only_ssel [1], loc_addr->ssel, loc_addr->ssel_len);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
ret = COSP_ERR_INV_SSEL; /* invalid loc SSEL */
|
|||
|
|
COSP_LOG_ERR1 ("COSP-ERROR: S-BIND.req: Invalid length=%d of SSEL.",
|
|||
|
|
loc_addr->ssel_len);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{ /* Second Bind. Only allow it if the SSEL is the same. */
|
|||
|
|
if (cosp_only_ssel [0] != (ST_UCHAR) loc_addr->ssel_len ||
|
|||
|
|
(loc_addr->ssel_len != 0 &&
|
|||
|
|
memcmp (&cosp_only_ssel [1], loc_addr->ssel, loc_addr->ssel_len)))
|
|||
|
|
{
|
|||
|
|
COSP_LOG_ERR0 ("COSP-ERROR: Cannot BIND to different SSEL");
|
|||
|
|
ret = COSP_ERR_INV_SSEL;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
/* Bind to Transport. */
|
|||
|
|
if (ret == SD_SUCCESS)
|
|||
|
|
{
|
|||
|
|
/* Copy tsel from pres_addr to tp4_addr struct. Don't copy nsap */
|
|||
|
|
/* because tp4_bind ignores it anyway. */
|
|||
|
|
if (loc_addr->tsel_len <= sizeof (tp4_addr.tp4_sel))
|
|||
|
|
{
|
|||
|
|
tp4_addr.tp4_sel_len = loc_addr->tsel_len;
|
|||
|
|
memcpy (tp4_addr.tp4_sel, loc_addr->tsel, loc_addr->tsel_len);
|
|||
|
|
tp4_addr.tp_type = loc_addr->tp_type; /* TP4 or TCP? */
|
|||
|
|
|
|||
|
|
user_bind_id = cosp_user_bind_id; /* pass bind id down */
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
if ((ret = tp4_bind (user_bind_id, &tp4_addr, sharable, max_conns))
|
|||
|
|
!= SD_SUCCESS)
|
|||
|
|
{
|
|||
|
|
COSP_LOG_ERR0 ("COSP-ERROR: S-BIND.req: T-BIND.req failed.");
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
ret = COSP_ERR_INV_TP4_ADDR; /* TP4 bind failed */
|
|||
|
|
COSP_LOG_ERR2 ("COSP-ERROR: S-BIND.req: Invalid TSEL length=%d or NSAP length=%d.",
|
|||
|
|
loc_addr->tsel_len, loc_addr->nsap_len);
|
|||
|
|
}
|
|||
|
|
} /* end Transport binding section */
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
/* If successful, set called flag. Otherwise, treat next bind like first.*/
|
|||
|
|
if (ret == SD_SUCCESS)
|
|||
|
|
cosp_bind_called = SD_TRUE;
|
|||
|
|
|
|||
|
|
return (ret);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* tp4_bind_cnf */
|
|||
|
|
/*----------------------------------------------------------------------*/
|
|||
|
|
/* This function is called by the TP-provider to indicate the result of */
|
|||
|
|
/* the bind operation (see cosp_bind func). */
|
|||
|
|
/* */
|
|||
|
|
/* Parameters: */
|
|||
|
|
/* ST_LONG user_bind_id User's id (COSP id) for this binding. */
|
|||
|
|
/* ST_LONG tp4_bind_id TP4 assigned ID for this binding. */
|
|||
|
|
/* ST_INT result Indicates if the bind was successful: */
|
|||
|
|
/* = 0 Success */
|
|||
|
|
/* <> 0 Error code */
|
|||
|
|
/* */
|
|||
|
|
/* Return: */
|
|||
|
|
/* ST_VOID */
|
|||
|
|
/************************************************************************/
|
|||
|
|
ST_VOID tp4_bind_cnf (ST_LONG user_bind_id, ST_LONG tp4_bind_id, ST_RET result)
|
|||
|
|
{
|
|||
|
|
ST_LONG cosp_user_bind_id;
|
|||
|
|
ST_LONG cosp_bind_id;
|
|||
|
|
|
|||
|
|
cosp_user_bind_id = user_bind_id; /* we passing same bind id up */
|
|||
|
|
cosp_bind_id = tp4_bind_id; /* COSP bind id same as TP4 */
|
|||
|
|
|
|||
|
|
COSP_LOG_DEC3 ("S-BIND.cnf: cosp_user_bind_id =0x%08X cosp_bind_id =%9ld result =%d",
|
|||
|
|
cosp_user_bind_id, cosp_bind_id, result);
|
|||
|
|
|
|||
|
|
u_cosp_bind_cnf (cosp_user_bind_id, cosp_bind_id, result);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* cosp_unbind */
|
|||
|
|
/*----------------------------------------------------------------------*/
|
|||
|
|
/* Function called by SS-user to unbind from local Session Address. */
|
|||
|
|
/* The SS-user should implement the u_cosp_unbind_cnf function. */
|
|||
|
|
/* */
|
|||
|
|
/* Parameters: */
|
|||
|
|
/* ST_LONG cosp_bind_id COSP's id to unbind. */
|
|||
|
|
/* */
|
|||
|
|
/* Return: */
|
|||
|
|
/* SD_SUCCESS (0) if unbind successful */
|
|||
|
|
/* error code otherwise */
|
|||
|
|
/************************************************************************/
|
|||
|
|
ST_RET cosp_unbind (ST_LONG cosp_bind_id)
|
|||
|
|
{
|
|||
|
|
ST_LONG tp4_bind_id;
|
|||
|
|
|
|||
|
|
COSP_LOG_ENC1 ("S-UNBIND.req: cosp_bind_id =%9ld", cosp_bind_id);
|
|||
|
|
|
|||
|
|
tp4_bind_id = cosp_bind_id;
|
|||
|
|
|
|||
|
|
/* unbind the transport */
|
|||
|
|
if (tp4_unbind (tp4_bind_id) != SD_SUCCESS)
|
|||
|
|
{
|
|||
|
|
COSP_LOG_ERR0 ("COSP-ERROR: S-UNBIND.req: T-UNBIND.req failed.");
|
|||
|
|
return (COSP_ERR_TP4_RET);
|
|||
|
|
}
|
|||
|
|
return (SD_SUCCESS);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* tp4_unbind_cnf */
|
|||
|
|
/*----------------------------------------------------------------------*/
|
|||
|
|
/* This function is called by the TP4-provider to indicate that the */
|
|||
|
|
/* unbind operation completed. */
|
|||
|
|
/* */
|
|||
|
|
/* Parameters: */
|
|||
|
|
/* ST_LONG user_bind_id User's id for this binding. */
|
|||
|
|
/* */
|
|||
|
|
/* Return: */
|
|||
|
|
/* ST_VOID */
|
|||
|
|
/************************************************************************/
|
|||
|
|
ST_VOID tp4_unbind_cnf (ST_LONG user_bind_id)
|
|||
|
|
{
|
|||
|
|
ST_LONG cosp_user_bind_id;
|
|||
|
|
|
|||
|
|
cosp_user_bind_id = user_bind_id;
|
|||
|
|
|
|||
|
|
COSP_LOG_DEC1 ("S-UNBIND.cnf: cosp_user_bind_id =0x%08X", cosp_user_bind_id);
|
|||
|
|
|
|||
|
|
u_cosp_unbind_cnf (cosp_user_bind_id);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* acse_free_con */
|
|||
|
|
/*----------------------------------------------------------------------*/
|
|||
|
|
/* This function will free the pointer to connection info. */
|
|||
|
|
/* In most cases the COSP engine is responsible for releasing the con */
|
|||
|
|
/* pointer. */
|
|||
|
|
/* */
|
|||
|
|
/* Parameters: */
|
|||
|
|
/* ACSE_CONN *con Pointer to connection info struct */
|
|||
|
|
/* */
|
|||
|
|
/* Return: */
|
|||
|
|
/* ST_VOID none */
|
|||
|
|
/************************************************************************/
|
|||
|
|
ST_VOID acse_free_con (ACSE_CONN *con)
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
|
|||
|
|
if (con)
|
|||
|
|
{
|
|||
|
|
/* free partner Authentication Info */
|
|||
|
|
|
|||
|
|
a_free_part_security_info ((ST_LONG) con);
|
|||
|
|
|
|||
|
|
if (con->cosp_cn_ptr)
|
|||
|
|
M_FREE (MSMEM_COSP_CN, con->cosp_cn_ptr); /* free saved encoded CN SPDU */
|
|||
|
|
|
|||
|
|
M_FREE (MSMEM_ACSE_CONN, con);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/*======================================================*/
|
|||
|
|
/* */
|
|||
|
|
/* C O N N E C T (CALLED SIDE) F U N C T I O N S */
|
|||
|
|
/* */
|
|||
|
|
/*======================================================*/
|
|||
|
|
|
|||
|
|
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* tp4_connect_ind */
|
|||
|
|
/*----------------------------------------------------------------------*/
|
|||
|
|
/* This function is called by the TP4-provider to indicate that a */
|
|||
|
|
/* remote node wishes to establish a connection. */
|
|||
|
|
/* */
|
|||
|
|
/* Parameters: */
|
|||
|
|
/* ST_LONG user_bind_id User's id for this binding. */
|
|||
|
|
/* ST_LONG tp4_conn_id COSP connection id for this connect. */
|
|||
|
|
/* ST_UCHAR *loc_tsel Local (called) TSEL. */
|
|||
|
|
/* ST_UCHAR *rem_tsel Remote (calling) TSEL. */
|
|||
|
|
/* ST_UCHAR *rem_nsap Remote (calling) NSAP (TP4) or */
|
|||
|
|
/* ST_ULONG rem_ip Remote (calling) IP addr(TP0) */
|
|||
|
|
/* ST_INT conndata_len Length of opt connect data <= 32 bytes */
|
|||
|
|
/* char *conndata Pointer to opt connect data. */
|
|||
|
|
/* */
|
|||
|
|
/* Return: */
|
|||
|
|
/* ST_VOID */
|
|||
|
|
/************************************************************************/
|
|||
|
|
ST_VOID tp4_connect_ind (ST_LONG user_bind_id, ST_LONG tp4_conn_id,
|
|||
|
|
ST_UCHAR *loc_tsel, ST_UCHAR *rem_tsel,
|
|||
|
|
ST_UCHAR *rem_nsap, ST_ULONG rem_ip,
|
|||
|
|
ST_INT conndata_len, char *conndata)
|
|||
|
|
{
|
|||
|
|
ACSE_CONN *con;
|
|||
|
|
|
|||
|
|
tp4_reldata (conndata); /* !!! we ignoring conndata */
|
|||
|
|
|
|||
|
|
con = (ACSE_CONN *) M_CALLOC (MSMEM_ACSE_CONN, 1, sizeof (ACSE_CONN));
|
|||
|
|
|
|||
|
|
/* accept incomming transport connection */
|
|||
|
|
if (tp4_accept (tp4_conn_id, (ST_LONG) con, 0, NULL) == SD_SUCCESS)
|
|||
|
|
{
|
|||
|
|
con->cosp_state = COSP_CSTATE_IDLE_TCON;
|
|||
|
|
con->cosp_bind_id = user_bind_id; /* save the id to pass to COPP */
|
|||
|
|
con->cosp_vtca = SD_TRUE; /* transport conn acceptor */
|
|||
|
|
con->tp4_conn_id = tp4_conn_id;
|
|||
|
|
/* Save TSELs, NSAP in ACSE_CONN struct. */
|
|||
|
|
memcpy (con->loc_tsel, loc_tsel, loc_tsel [0]+1);
|
|||
|
|
memcpy (con->rem_tsel, rem_tsel, rem_tsel [0]+1);
|
|||
|
|
if (tp4_conn_id >= MIN_TP0_CONN_ID) /* This is TP0 conn. Save IP addr*/
|
|||
|
|
{
|
|||
|
|
con->remNetAddr.ip = rem_ip;
|
|||
|
|
#if defined (TP0_ENABLED)
|
|||
|
|
/* If connection is TP0, save encrypt_ctrl. */
|
|||
|
|
if (tp4_conn_id >= MIN_TP0_CONN_ID)
|
|||
|
|
{ /* this is TP0 connection */
|
|||
|
|
TP0_CONN *tp0_conn = &tp0_conn_arr [tp4_conn_id-MIN_TP0_CONN_ID];
|
|||
|
|
/* save the encryption info in ACSE_CONN */
|
|||
|
|
con->encrypt_ctrl = tp0_conn->sock_info->encrypt_ctrl;
|
|||
|
|
}
|
|||
|
|
#endif
|
|||
|
|
}
|
|||
|
|
else /* This is TP4 conn. Save NSAP */
|
|||
|
|
memcpy (con->remNetAddr.nsap, rem_nsap, rem_nsap [0]+1);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
COSP_LOG_ERR0 ("COSP-ERROR: T-CONNECT.ind: T-ACCEPT.req connection failed.");
|
|||
|
|
|
|||
|
|
M_FREE (MSMEM_STARTUP, con);
|
|||
|
|
|
|||
|
|
/* reject incomming transport connection, accept failed */
|
|||
|
|
tp4_disconnect (tp4_conn_id, 0, NULL);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* cosp_con_rsp_pos */
|
|||
|
|
/*----------------------------------------------------------------------*/
|
|||
|
|
/* Function called by SS-user to Accept an incomming connection. */
|
|||
|
|
/* */
|
|||
|
|
/* Parameters: */
|
|||
|
|
/* ACSE_CONN *con Pointer to con info struct */
|
|||
|
|
/* */
|
|||
|
|
/* Return: */
|
|||
|
|
/* SD_SUCCESS (0) if successful */
|
|||
|
|
/* error code otherwise */
|
|||
|
|
/************************************************************************/
|
|||
|
|
ST_RET cosp_con_rsp_pos (ACSE_CONN *con)
|
|||
|
|
{
|
|||
|
|
ST_INT ret;
|
|||
|
|
ST_UINT spdu_len;
|
|||
|
|
char *spdu_ptr;
|
|||
|
|
|
|||
|
|
COSP_LOG_ENC2 ("S-CONNECT.rsp+: acse_conn_id =0x%08X user_conn_id =%4ld",
|
|||
|
|
con, con->user_conn_id);
|
|||
|
|
COSP_LOG_ENCC1 ("User data length: %d", con->ppdu_len);
|
|||
|
|
COSP_LOG_ENCH (con->ppdu_len, con->ppdu_ptr);
|
|||
|
|
|
|||
|
|
ret = SD_SUCCESS;
|
|||
|
|
|
|||
|
|
if (con->cosp_state == COSP_CSTATE_WAIT_CON_RSP)
|
|||
|
|
{
|
|||
|
|
/* encode ACCEPT SPDU */
|
|||
|
|
ret = cosp_enc_cn_ac (con, NULL, &spdu_ptr, &spdu_len, COSP_SI_ACCEPT);
|
|||
|
|
if (ret == SD_SUCCESS)
|
|||
|
|
{
|
|||
|
|
if (tp4_data (con->tp4_conn_id, SD_TRUE, spdu_len, spdu_ptr) == SD_SUCCESS)
|
|||
|
|
{
|
|||
|
|
con->cosp_state = COSP_CSTATE_DATA_XFER;
|
|||
|
|
con->cosp_vcoll = SD_FALSE;
|
|||
|
|
con->cosp_vdnr = SD_FALSE;
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
ret = COSP_ERR_TP4_RET;
|
|||
|
|
COSP_LOG_ERR1 ("COSP-ERROR: S-CONNECT.rsp+ acse_conn_id=0x%08X: T-DATA.req failed.",
|
|||
|
|
con);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
COSP_LOG_ERR1 ("COSP-ERROR: S-CONNECT.rsp+ acse_conn_id=0x%08X: Encoding ACCEPT SPDU failed.",
|
|||
|
|
con);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
ret = COSP_ERR_INV_CON_STATE;
|
|||
|
|
COSP_LOG_ERR2 ("COSP-ERROR: S-CONNECT.rsp+ acse_conn_id=0x%08X: Invalid state=%d.",
|
|||
|
|
con, con->cosp_state);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return (ret);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* cosp_con_rsp_neg */
|
|||
|
|
/*----------------------------------------------------------------------*/
|
|||
|
|
/* Function called by SS-user to Reject an incomming connection. */
|
|||
|
|
/* */
|
|||
|
|
/* Parameters: */
|
|||
|
|
/* ACSE_CONN *con Pointer to con info struct */
|
|||
|
|
/* ST_INT reason Reason for reject COSP_CON_RSP_U_... */
|
|||
|
|
/* */
|
|||
|
|
/* Return: */
|
|||
|
|
/* SD_SUCCESS (0) if successful */
|
|||
|
|
/* error code otherwise */
|
|||
|
|
/************************************************************************/
|
|||
|
|
ST_RET cosp_con_rsp_neg (ACSE_CONN *con, ST_INT reason)
|
|||
|
|
{
|
|||
|
|
ST_INT ret;
|
|||
|
|
ST_UINT spdu_len;
|
|||
|
|
char *spdu_ptr;
|
|||
|
|
ST_UCHAR reason_code;
|
|||
|
|
|
|||
|
|
COSP_LOG_ENC3 ("S-CONNECT.rsp-: acse_conn_id =0x%08X user_conn_id =%4ld reason =%d",
|
|||
|
|
con, con->user_conn_id, reason);
|
|||
|
|
COSP_LOG_ENCC1 ("User data length: %d", con->ppdu_len);
|
|||
|
|
COSP_LOG_ENCH (con->ppdu_len, con->ppdu_ptr);
|
|||
|
|
|
|||
|
|
ret = SD_SUCCESS;
|
|||
|
|
|
|||
|
|
if (con->cosp_state == COSP_CSTATE_WAIT_CON_RSP)
|
|||
|
|
{
|
|||
|
|
/* encode REFUSE SPDU */
|
|||
|
|
switch (reason)
|
|||
|
|
{
|
|||
|
|
case COSP_CON_RSP_U_CONGESTION:
|
|||
|
|
reason_code = COSP_RF_REASON_U_CONGESTION;
|
|||
|
|
break;
|
|||
|
|
|
|||
|
|
case COSP_CON_RSP_U_IN_UDATA:
|
|||
|
|
reason_code = COSP_RF_REASON_U_REJECT;
|
|||
|
|
/* SS-user data should be present in this case */
|
|||
|
|
break;
|
|||
|
|
|
|||
|
|
case COSP_CON_RSP_U_NOT_SPECIFIED:
|
|||
|
|
default:
|
|||
|
|
reason_code = COSP_RF_REASON_U_NOT_SPECIFIED;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* check if user data present */
|
|||
|
|
if (reason == COSP_CON_RSP_U_IN_UDATA)
|
|||
|
|
{
|
|||
|
|
/* SS-user data should be present in this case */
|
|||
|
|
if (con->ppdu_len == 0)
|
|||
|
|
ret = COSP_ERR_INV_UDATA_LEN;
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
/* SS-user data should NOT be present in this case */
|
|||
|
|
if (con->ppdu_len != 0)
|
|||
|
|
ret = COSP_ERR_INV_UDATA_LEN;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (ret == SD_SUCCESS)
|
|||
|
|
{
|
|||
|
|
ret = cosp_enc_rf (con, &spdu_ptr, &spdu_len, reason_code);
|
|||
|
|
if (ret == SD_SUCCESS)
|
|||
|
|
{
|
|||
|
|
if (tp4_data (con->tp4_conn_id, SD_TRUE, spdu_len, spdu_ptr) == SD_SUCCESS)
|
|||
|
|
{
|
|||
|
|
con->cosp_state = COSP_CSTATE_WAIT_TDISCON_IND;
|
|||
|
|
tp4_session_timer (con->tp4_conn_id, SD_TRUE); /* start timer */
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
ret = COSP_ERR_TP4_RET;
|
|||
|
|
COSP_LOG_ERR1 ("COSP-ERROR: S-CONNECT.rsp- acse_conn_id=0x%08X: T-DATA.req failed.",
|
|||
|
|
con);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
COSP_LOG_ERR1 ("COSP-ERROR: S-CONNECT.rsp- acse_conn_id=0x%08X: Encoding REFUSE SPDU failed.",
|
|||
|
|
con);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
COSP_LOG_ERR3 ("COSP-ERROR: S-CONNECT.rsp- acse_conn_id=0x%08X: Invalid SS-UserData length=%u for Reason=%d.",
|
|||
|
|
con, con->ppdu_len, reason);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
ret = COSP_ERR_INV_CON_STATE;
|
|||
|
|
COSP_LOG_ERR2 ("COSP-ERROR: S-CONNECT.rsp- acse_conn_id=0x%08X: Invalid state=%d.",
|
|||
|
|
con, con->cosp_state);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return (ret);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/*======================================================*/
|
|||
|
|
/* */
|
|||
|
|
/* C O N N E C T (CALLING SIDE) F U N C T I O N S */
|
|||
|
|
/* */
|
|||
|
|
/*======================================================*/
|
|||
|
|
|
|||
|
|
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* cosp_con_req */
|
|||
|
|
/*----------------------------------------------------------------------*/
|
|||
|
|
/* Function called by SS-user to establish Session Layer connection. */
|
|||
|
|
/* SS-user should implement the u_cosp_con_cnf_pos & u_cosp_con_cnf_neg */
|
|||
|
|
/* functions to receive confirm for this request. */
|
|||
|
|
/* If this function returns value other then SD_SUCCESS then the function */
|
|||
|
|
/* u_cosp_con_cnf_xxx will not be called. */
|
|||
|
|
/* */
|
|||
|
|
/* Parameters: */
|
|||
|
|
/* ST_LONG cosp_bind_id COSP bind id */
|
|||
|
|
/* PRES_ADDR *rem_addr Remote Address */
|
|||
|
|
/* ACSE_CONN *con Pointer to connection info */
|
|||
|
|
/* */
|
|||
|
|
/* Return: */
|
|||
|
|
/* SD_SUCCESS (0) if successful */
|
|||
|
|
/* error code otherwise */
|
|||
|
|
/************************************************************************/
|
|||
|
|
ST_RET cosp_con_req (ST_LONG cosp_bind_id, PRES_ADDR *rem_addr, ACSE_CONN *con)
|
|||
|
|
{
|
|||
|
|
ST_RET ret;
|
|||
|
|
TP4_ADDR tp4_addr;
|
|||
|
|
ST_UINT spdu_len;
|
|||
|
|
char *spdu_ptr;
|
|||
|
|
ST_LONG tp4_user_bind_id;
|
|||
|
|
|
|||
|
|
COSP_LOG_ENC3 ("S-CONNECT.req: acse_conn_id =0x%08X user_conn_id =%4ld cosp_bind_id =%9ld",
|
|||
|
|
con, con->user_conn_id, cosp_bind_id);
|
|||
|
|
COSP_LOG_ENCC1 ("User data length: %d", con->ppdu_len);
|
|||
|
|
COSP_LOG_ENCH (con->ppdu_len, con->ppdu_ptr);
|
|||
|
|
|
|||
|
|
if (con->cosp_state != COSP_CSTATE_IDLE)
|
|||
|
|
{
|
|||
|
|
ret = COSP_ERR_INV_CON_STATE; /* invalid connect state*/
|
|||
|
|
COSP_LOG_ERR2 ("COSP-ERROR: S-CONNECT.req acse_conn_id=0x%08X: Invalid state=%d.",
|
|||
|
|
con, con->cosp_state);
|
|||
|
|
return (ret);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
tp4_user_bind_id = cosp_bind_id; /* we using only one id */
|
|||
|
|
|
|||
|
|
/* Check "Called" SSEL. May be NULL (i.e. length=0) */
|
|||
|
|
if (rem_addr->ssel_len <= MAX_SSEL_LEN)
|
|||
|
|
{
|
|||
|
|
/* Save SSEL in ACSE_CONN struct. */
|
|||
|
|
con->rem_ssel[0] = rem_addr->ssel_len; /* first byte is len */
|
|||
|
|
memcpy (&con->rem_ssel[1], rem_addr->ssel, rem_addr->ssel_len);
|
|||
|
|
|
|||
|
|
ret = cosp_enc_cn_ac (con, rem_addr, &spdu_ptr, &spdu_len, COSP_SI_CONNECT);
|
|||
|
|
if (ret == SD_SUCCESS)
|
|||
|
|
{
|
|||
|
|
/* we always will initiate new transport connection for every new */
|
|||
|
|
/* session connection, so find empty spot for con info */
|
|||
|
|
|
|||
|
|
/* Copy tsel and nsap from pres_addr to tp4_addr struct */
|
|||
|
|
tp4_addr.tp4_sel_len = rem_addr->tsel_len;
|
|||
|
|
memcpy (tp4_addr.tp4_sel, rem_addr->tsel, rem_addr->tsel_len);
|
|||
|
|
tp4_addr.tp_type = rem_addr->tp_type;
|
|||
|
|
if (rem_addr->tp_type == TP_TYPE_TP4)
|
|||
|
|
{
|
|||
|
|
tp4_addr.net_addr_len = rem_addr->nsap_len;
|
|||
|
|
memcpy (tp4_addr.netAddr.nsap, rem_addr->netAddr.nsap, rem_addr->nsap_len);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
tp4_addr.netAddr.ip = rem_addr->netAddr.ip; /* IP Addr */
|
|||
|
|
tp4_addr.port = rem_addr->port;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* Note: !!! the tp4_disconnect_ind may be called before the */
|
|||
|
|
/* tp4_connect function returns (SD_FAILURE), we want to log the err */
|
|||
|
|
/* only in one place (here) */
|
|||
|
|
cosp_in_tp4_func = SD_TRUE; /* prevents logging err */
|
|||
|
|
|
|||
|
|
/* request transport connection (no connect data) */
|
|||
|
|
if ((con->tp4_conn_id = tp4_connect (tp4_user_bind_id, (ST_LONG) con, &tp4_addr, 0, NULL,
|
|||
|
|
&con->encrypt_ctrl)) >= 0)
|
|||
|
|
{
|
|||
|
|
/* save the encoded CN until T-CONNECT.cnf received */
|
|||
|
|
con->cosp_state = COSP_CSTATE_WAIT_TCON_CNF;
|
|||
|
|
con->cosp_cn_len = spdu_len;
|
|||
|
|
con->cosp_cn_ptr = (ST_CHAR *) M_MALLOC (MSMEM_COSP_CN, spdu_len);
|
|||
|
|
memcpy (con->cosp_cn_ptr, spdu_ptr, spdu_len);
|
|||
|
|
con->cosp_vtca = SD_FALSE; /* transport conn initiator */
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
ret = COSP_ERR_TP4_RET;
|
|||
|
|
COSP_LOG_ENC1 ("COSP-ERROR: S-CONNECT.req acse_conn_id=0x%08X: T-CONNECT.req failed.",
|
|||
|
|
con);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
cosp_in_tp4_func = SD_FALSE; /* turn off the flag */
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
COSP_LOG_ERR1 ("COSP-ERROR: S-CONNECT.req acse_conn_id=0x%08X: Encoding CONNECT SPDU failed.",
|
|||
|
|
con);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
ret = COSP_ERR_INV_SSEL; /* invalid SSEL (length) */
|
|||
|
|
COSP_LOG_ERR2 ("COSP-ERROR: S-CONNECT.req acse_conn_id=0x%08X: Invalid remote SSEL length=%d.",
|
|||
|
|
con, rem_addr->ssel_len);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return (ret);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* tp4_connect_cnf */
|
|||
|
|
/*----------------------------------------------------------------------*/
|
|||
|
|
/* This function is called by the TP4-provider to indicate that the */
|
|||
|
|
/* transport connection has been established. */
|
|||
|
|
/* NOTE: cosp_con_req saved the TP4 connection ID in con->tp4_conn_id. */
|
|||
|
|
/* It should match the tp4_conn_id passed to this function. */
|
|||
|
|
/* */
|
|||
|
|
/* Parameters: */
|
|||
|
|
/* ST_LONG user_conn_id User's connection id for this connect. */
|
|||
|
|
/* ST_LONG tp4_conn_id TP4 connection id for this connect. */
|
|||
|
|
/* ST_INT conndata_len Length of optional connect data. */
|
|||
|
|
/* char *conndata Pointer to optional connect data. */
|
|||
|
|
/* */
|
|||
|
|
/* Return: */
|
|||
|
|
/* ST_VOID */
|
|||
|
|
/************************************************************************/
|
|||
|
|
ST_VOID tp4_connect_cnf (ST_LONG user_conn_id, ST_LONG tp4_conn_id,
|
|||
|
|
ST_INT conndata_len, char *conndata)
|
|||
|
|
{
|
|||
|
|
ACSE_CONN *con;
|
|||
|
|
|
|||
|
|
tp4_reldata (conndata); /* !!! we ignoring conndata */
|
|||
|
|
|
|||
|
|
con = (ACSE_CONN *) user_conn_id;
|
|||
|
|
|
|||
|
|
if (con->cosp_state == COSP_CSTATE_WAIT_TCON_CNF)
|
|||
|
|
{
|
|||
|
|
#if defined (TP0_ENABLED)
|
|||
|
|
/* If connection is TP0, save encrypt_ctrl. */
|
|||
|
|
if (tp4_conn_id >= MIN_TP0_CONN_ID)
|
|||
|
|
{ /* this is TP0 connection */
|
|||
|
|
TP0_CONN *tp0_conn = &tp0_conn_arr [tp4_conn_id-MIN_TP0_CONN_ID];
|
|||
|
|
/* save the encryption info in ACSE_CONN */
|
|||
|
|
con->encrypt_ctrl = tp0_conn->sock_info->encrypt_ctrl;
|
|||
|
|
}
|
|||
|
|
#endif
|
|||
|
|
|
|||
|
|
/* send the CN (already encoded) on the established transport connection */
|
|||
|
|
if (tp4_data (tp4_conn_id, SD_TRUE, con->cosp_cn_len, con->cosp_cn_ptr)
|
|||
|
|
== SD_SUCCESS)
|
|||
|
|
{
|
|||
|
|
con->cosp_state = COSP_CSTATE_WAIT_AC; /* wait AC or RF */
|
|||
|
|
|
|||
|
|
/* we are done with the encoding buffer for CN */
|
|||
|
|
if (con->cosp_cn_ptr)
|
|||
|
|
{
|
|||
|
|
M_FREE (MSMEM_COSP_CN, con->cosp_cn_ptr);
|
|||
|
|
con->cosp_cn_len = 0;
|
|||
|
|
con->cosp_cn_ptr = NULL;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
COSP_LOG_ERR1 ("COSP-ERROR: T-CONNECT.cnf acse_conn_id=0x%08X: T-DATA.req failed",
|
|||
|
|
con);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
COSP_LOG_ERR2 ("COSP-ERROR: T-CONNECT.cnf acse_conn_id=0x%08X: Invalid state=%d.",
|
|||
|
|
con, con->cosp_state);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/*======================================================*/
|
|||
|
|
/* */
|
|||
|
|
/* C O N N E C T I O N R E L E A S E (CALLED SIDE) */
|
|||
|
|
/* */
|
|||
|
|
/*======================================================*/
|
|||
|
|
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* cosp_rel_rsp_pos */
|
|||
|
|
/*----------------------------------------------------------------------*/
|
|||
|
|
/* Function called by SS-user to Accept a release of connection. */
|
|||
|
|
/* */
|
|||
|
|
/* Parameters: */
|
|||
|
|
/* ACSE_CONN *con Pointer to connection info */
|
|||
|
|
/* */
|
|||
|
|
/* Return: */
|
|||
|
|
/* SD_SUCCESS (0) if successful */
|
|||
|
|
/* error code otherwise */
|
|||
|
|
/************************************************************************/
|
|||
|
|
ST_RET cosp_rel_rsp_pos (ACSE_CONN *con)
|
|||
|
|
{
|
|||
|
|
ST_INT ret;
|
|||
|
|
ST_UINT spdu_len;
|
|||
|
|
char *spdu_ptr;
|
|||
|
|
|
|||
|
|
COSP_LOG_ENC2 ("S-RELEASE.rsp+: acse_conn_id =0x%08X user_conn_id =%4ld",
|
|||
|
|
con, con->user_conn_id);
|
|||
|
|
COSP_LOG_ENCC1 ("User data length: %d", con->ppdu_len);
|
|||
|
|
COSP_LOG_ENCH (con->ppdu_len, con->ppdu_ptr);
|
|||
|
|
|
|||
|
|
if (con->cosp_state == COSP_CSTATE_WAIT_REL_RSP)
|
|||
|
|
{
|
|||
|
|
/* some additional predicates must be also true */
|
|||
|
|
if (!con->cosp_vcoll ||
|
|||
|
|
(con->cosp_vcoll && con->cosp_vdnr) || /* collision but DN received */
|
|||
|
|
(con->cosp_vcoll && !con->cosp_vtca)) /* collision and we are con initiator */
|
|||
|
|
{
|
|||
|
|
/* connection released confirmed by COPP, encode and send DISCONNECT SPDU */
|
|||
|
|
/* Transport connections are not reused. */
|
|||
|
|
ret = cosp_enc_fn_dn (con, &spdu_ptr, &spdu_len, COSP_SI_DISCON);
|
|||
|
|
if (ret == SD_SUCCESS)
|
|||
|
|
{
|
|||
|
|
if (tp4_data (con->tp4_conn_id, SD_TRUE, spdu_len, spdu_ptr) == SD_SUCCESS)
|
|||
|
|
{
|
|||
|
|
if (!con->cosp_vcoll ||
|
|||
|
|
(con->cosp_vcoll && con->cosp_vdnr)) /* collision but DN received */
|
|||
|
|
{
|
|||
|
|
con->cosp_state = COSP_CSTATE_WAIT_TDISCON_IND;
|
|||
|
|
tp4_session_timer (con->tp4_conn_id, SD_TRUE); /* start timer */
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
/* collision and we are the con initiator */
|
|||
|
|
con->cosp_state = COSP_CSTATE_WAIT_DN;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
ret = COSP_ERR_TP4_RET;
|
|||
|
|
COSP_LOG_ERR1 ("COSP-ERROR: S-RELEASE.rsp+ acse_conn_id=0x%08X: T-DATA.req failed.",
|
|||
|
|
con);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
COSP_LOG_ERR1 ("COSP-ERROR: S-RELEASE.rsp+ acse_conn_id=0x%08X: Encoding DISCONNECT SPDU failed.",
|
|||
|
|
con);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
ret = COSP_ERR_INV_CON_STATE;
|
|||
|
|
COSP_LOG_ERR1 ("COSP-ERROR: S-RELEASE.rsp+ acse_conn_id=0x%08X: Connection Release Collision\n"
|
|||
|
|
" (DN not received or not a connection initiator).",
|
|||
|
|
con);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
ret = COSP_ERR_INV_CON_STATE;
|
|||
|
|
COSP_LOG_ERR2 ("COSP-ERROR: S-RELEASE.rsp+ acse_conn_id=0x%08X: Invalid state=%d.",
|
|||
|
|
con, con->cosp_state);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return (ret);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
/*======================================================*/
|
|||
|
|
/* */
|
|||
|
|
/* C O N N E C T I O N R E L E A S E (CALLING SIDE)*/
|
|||
|
|
/* */
|
|||
|
|
/*======================================================*/
|
|||
|
|
|
|||
|
|
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* cosp_rel_req */
|
|||
|
|
/*----------------------------------------------------------------------*/
|
|||
|
|
/* Function called by SS-user to release a Session connection. */
|
|||
|
|
/* SS-user should implement the u_cosp_rel_cnf_pos function to receive */
|
|||
|
|
/* confirm for this request. Negative confirm is not implemented. */
|
|||
|
|
/* If this function returns value other then SD_SUCCESS then the function */
|
|||
|
|
/* u_cosp_rel_cnf_pos will not be called. */
|
|||
|
|
/* */
|
|||
|
|
/* Parameters: */
|
|||
|
|
/* ACSE_CONN *con Pointer to connection info */
|
|||
|
|
/* */
|
|||
|
|
/* Return: */
|
|||
|
|
/* SD_SUCCESS (0) if successful */
|
|||
|
|
/* error code otherwise */
|
|||
|
|
/************************************************************************/
|
|||
|
|
ST_RET cosp_rel_req (ACSE_CONN *con)
|
|||
|
|
{
|
|||
|
|
ST_INT ret;
|
|||
|
|
ST_UINT spdu_len;
|
|||
|
|
char *spdu_ptr;
|
|||
|
|
|
|||
|
|
COSP_LOG_ENC2 ("S-RELEASE.req: acse_conn_id =0x%08X user_conn_id =%4ld",
|
|||
|
|
con, con->user_conn_id);
|
|||
|
|
COSP_LOG_ENCC1 ("User data length: %d", con->ppdu_len);
|
|||
|
|
COSP_LOG_ENCH (con->ppdu_len, con->ppdu_ptr);
|
|||
|
|
|
|||
|
|
ret = SD_SUCCESS;
|
|||
|
|
|
|||
|
|
if (con->cosp_state == COSP_CSTATE_WAIT_REL_RSP ||
|
|||
|
|
con->cosp_state == COSP_CSTATE_DATA_XFER)
|
|||
|
|
{
|
|||
|
|
/* connection is beeing released, encode and send FINISH SPDU */
|
|||
|
|
ret = cosp_enc_fn_dn (con, &spdu_ptr, &spdu_len, COSP_SI_FINISH);
|
|||
|
|
if (ret == SD_SUCCESS)
|
|||
|
|
{
|
|||
|
|
if (tp4_data (con->tp4_conn_id, SD_TRUE, spdu_len, spdu_ptr) == SD_SUCCESS)
|
|||
|
|
{
|
|||
|
|
if (con->cosp_state == COSP_CSTATE_WAIT_REL_RSP)
|
|||
|
|
{
|
|||
|
|
/* collision occurred, request to release con while waiting */
|
|||
|
|
/* for resp to S-RELEASE.ind */
|
|||
|
|
con->cosp_vcoll = SD_TRUE;
|
|||
|
|
/* remain in the same state */
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
con->cosp_state = COSP_CSTATE_WAIT_DN;
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
ret = COSP_ERR_TP4_RET;
|
|||
|
|
COSP_LOG_ERR1 ("COSP-ERROR: S-RELEASE.req acse_conn_id=0x%08X: T-DATA.req failed.",
|
|||
|
|
con);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
COSP_LOG_ERR1 ("COSP-ERROR: S-RELEASE.req acse_conn_id=0x%08X: Encoding FINISH SPDU failed.",
|
|||
|
|
con);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
ret = COSP_ERR_INV_CON_STATE;
|
|||
|
|
COSP_LOG_ERR2 ("COSP-ERROR: S-RELEASE.req acse_conn_id=0x%08X: Invalid state=%d.",
|
|||
|
|
con, con->cosp_state);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return (ret);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* tp4_disconnect_ind */
|
|||
|
|
/*----------------------------------------------------------------------*/
|
|||
|
|
/* This function is called by the TP4-provider to indicate that a */
|
|||
|
|
/* transport connection is beeing released. */
|
|||
|
|
/* */
|
|||
|
|
/* Parameters: */
|
|||
|
|
/* ST_LONG user_conn_id User's connection id for this connect. */
|
|||
|
|
/* ST_INT reason Reason for disconnect */
|
|||
|
|
/* ST_INT conndata_len Length of opt connect data <= 32 bytes */
|
|||
|
|
/* char *conndata Pointer to opt connect data. */
|
|||
|
|
/* */
|
|||
|
|
/* Return: */
|
|||
|
|
/* ST_VOID */
|
|||
|
|
/************************************************************************/
|
|||
|
|
ST_VOID tp4_disconnect_ind (ST_LONG user_conn_id, ST_INT reason,
|
|||
|
|
ST_INT conndata_len, char *conndata)
|
|||
|
|
{
|
|||
|
|
ACSE_CONN *con;
|
|||
|
|
|
|||
|
|
tp4_reldata (conndata); /* !!! we ignoring conndata */
|
|||
|
|
|
|||
|
|
con = (ACSE_CONN *) user_conn_id;
|
|||
|
|
|
|||
|
|
switch (con->cosp_state)
|
|||
|
|
{
|
|||
|
|
case COSP_CSTATE_IDLE:
|
|||
|
|
/* ignore this tp4_disconnect_ind if in tp4_connect (returns SD_FAILURE) */
|
|||
|
|
if (!cosp_in_tp4_func)
|
|||
|
|
{
|
|||
|
|
COSP_LOG_ERR2 ("COSP-ERROR: T-DISCONNECT.ind acse_conn_id=0x%08X: Invalid state=%d.",
|
|||
|
|
con, con->cosp_state);
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
|
|||
|
|
case COSP_CSTATE_IDLE_TCON:
|
|||
|
|
/* disconnected before a CN has been received (COPP has no */
|
|||
|
|
/* knowledge about this connection at this point). */
|
|||
|
|
acse_free_con (con);
|
|||
|
|
break;
|
|||
|
|
|
|||
|
|
case COSP_CSTATE_WAIT_TCON_CNF:
|
|||
|
|
case COSP_CSTATE_WAIT_AC:
|
|||
|
|
case COSP_CSTATE_WAIT_DN:
|
|||
|
|
case COSP_CSTATE_WAIT_CON_RSP:
|
|||
|
|
case COSP_CSTATE_WAIT_REL_RSP:
|
|||
|
|
case COSP_CSTATE_DATA_XFER:
|
|||
|
|
|
|||
|
|
/* issue S-P-ABORT.ind to local SS-user (use code from cosp_usr.h)*/
|
|||
|
|
COSP_LOG_DEC4 ("S-P-ABORT.ind: acse_conn_id =0x%08X user_conn_id =%4ld reason =%d (TP4 reason=0x%02x)",
|
|||
|
|
con, con->user_conn_id, (ST_INT) COSP_P_AB_IND_TP_DISCON, reason);
|
|||
|
|
|
|||
|
|
u_cosp_p_abort_ind (con, COSP_P_AB_IND_TP_DISCON);
|
|||
|
|
acse_free_con (con);
|
|||
|
|
break;
|
|||
|
|
|
|||
|
|
case COSP_CSTATE_WAIT_TDISCON_IND:
|
|||
|
|
tp4_session_timer (con->tp4_conn_id, SD_FALSE); /* stop timer */
|
|||
|
|
acse_free_con (con);
|
|||
|
|
break;
|
|||
|
|
|
|||
|
|
default:
|
|||
|
|
COSP_LOG_ERR2 ("COSP-ERROR: T-DISCONNECT.ind acse_conn_id=0x%08X: Invalid state=%d.",
|
|||
|
|
con, con->cosp_state);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* tp4_session_timer_expired */
|
|||
|
|
/*----------------------------------------------------------------------*/
|
|||
|
|
/* This function is called by TP4 when the session_timer expire. */
|
|||
|
|
/* */
|
|||
|
|
/* Parameters: */
|
|||
|
|
/* ST_LONG user_conn_id COSP connection id for this connect. */
|
|||
|
|
/* */
|
|||
|
|
/* Return: */
|
|||
|
|
/* ST_VOID */
|
|||
|
|
/************************************************************************/
|
|||
|
|
ST_VOID tp4_session_timer_expired (ST_LONG user_conn_id)
|
|||
|
|
{
|
|||
|
|
ACSE_CONN *con;
|
|||
|
|
|
|||
|
|
con = (ACSE_CONN *) user_conn_id;
|
|||
|
|
|
|||
|
|
if (con->cosp_state == COSP_CSTATE_WAIT_TDISCON_IND)
|
|||
|
|
{
|
|||
|
|
tp4_disconnect (con->tp4_conn_id, 0, NULL);
|
|||
|
|
acse_free_con (con);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
COSP_LOG_ERR2 ("COSP-ERROR: S-TIMER.expired acse_conn_id=0x%08X: Invalid state=%d.",
|
|||
|
|
con, con->cosp_state);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
/*======================================================*/
|
|||
|
|
/* */
|
|||
|
|
/* A B O R T F U N C T I O N S */
|
|||
|
|
/* */
|
|||
|
|
/*======================================================*/
|
|||
|
|
|
|||
|
|
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* cosp_u_abort_req */
|
|||
|
|
/*----------------------------------------------------------------------*/
|
|||
|
|
/* Function called by SS-user to Abort a connection (S-U-ABORT) */
|
|||
|
|
/* */
|
|||
|
|
/* Parameters: */
|
|||
|
|
/* ACSE_CONN *con Pointer to connection info */
|
|||
|
|
/* */
|
|||
|
|
/* Return: */
|
|||
|
|
/* SD_SUCCESS (0) if successful */
|
|||
|
|
/* error code otherwise */
|
|||
|
|
/* CRITICAL: this function may free the ACSE_CONN struct so the struct */
|
|||
|
|
/* MUST NOT be accessed after calling this function. */
|
|||
|
|
/************************************************************************/
|
|||
|
|
ST_RET cosp_u_abort_req (ACSE_CONN *con)
|
|||
|
|
{
|
|||
|
|
ST_INT ret;
|
|||
|
|
|
|||
|
|
COSP_LOG_ENC2 ("S-U-ABORT.req: acse_conn_id =0x%08X user_conn_id =%4ld",
|
|||
|
|
con, con->user_conn_id);
|
|||
|
|
COSP_LOG_ENCC1 ("User data length: %d", con->ppdu_len);
|
|||
|
|
COSP_LOG_ENCH (con->ppdu_len, con->ppdu_ptr);
|
|||
|
|
|
|||
|
|
ret = SD_SUCCESS;
|
|||
|
|
|
|||
|
|
switch (con->cosp_state)
|
|||
|
|
{
|
|||
|
|
case COSP_CSTATE_WAIT_TCON_CNF:
|
|||
|
|
tp4_disconnect (con->tp4_conn_id, 0, NULL);
|
|||
|
|
acse_free_con (con); /* done with this connection */
|
|||
|
|
break;
|
|||
|
|
|
|||
|
|
case COSP_CSTATE_WAIT_AC:
|
|||
|
|
case COSP_CSTATE_WAIT_DN:
|
|||
|
|
case COSP_CSTATE_WAIT_CON_RSP:
|
|||
|
|
case COSP_CSTATE_WAIT_REL_RSP:
|
|||
|
|
case COSP_CSTATE_DATA_XFER:
|
|||
|
|
/* send ABORT SPDU and wait for T-DISCONNECT.ind */
|
|||
|
|
if ((ret = cosp_send_abort (con, 0)) == SD_SUCCESS)
|
|||
|
|
{
|
|||
|
|
con->cosp_state = COSP_CSTATE_WAIT_TDISCON_IND;
|
|||
|
|
tp4_session_timer (con->tp4_conn_id, SD_TRUE); /* start timer */
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
|
|||
|
|
default:
|
|||
|
|
ret = COSP_ERR_INV_CON_STATE;
|
|||
|
|
COSP_LOG_ERR2 ("COSP-ERROR: S-U-ABORT.req acse_conn_id=0x%08X: Invalid state=%d.",
|
|||
|
|
con, con->cosp_state);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (ret != SD_SUCCESS)
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
|
|||
|
|
/* disconnect if we couldn't send abort */
|
|||
|
|
tp4_disconnect (con->tp4_conn_id, 0, NULL);
|
|||
|
|
acse_free_con (con);
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* we always will return success */
|
|||
|
|
return (SD_SUCCESS);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* cosp_send_abort */
|
|||
|
|
/*----------------------------------------------------------------------*/
|
|||
|
|
/* Function to sends ABORT SPDU to remote SS-user. */
|
|||
|
|
/* */
|
|||
|
|
/* Parameters: */
|
|||
|
|
/* ACSE_CONN *con Pointer to conn info struct */
|
|||
|
|
/* ST_INT err_code Error code (defined by COSP) */
|
|||
|
|
/* If =0 then S-U-ABORT sent */
|
|||
|
|
/* If !=0 then S-P-ABORT sent */
|
|||
|
|
/* Return: */
|
|||
|
|
/* SD_SUCCESS (0) if abort successful */
|
|||
|
|
/* error code otherwise */
|
|||
|
|
/************************************************************************/
|
|||
|
|
ST_RET cosp_send_abort (ACSE_CONN *con, ST_INT err_code)
|
|||
|
|
{
|
|||
|
|
ST_RET ret;
|
|||
|
|
char spdu_buf [COSP_P_AB_SPDU_LEN];
|
|||
|
|
ST_UINT spdu_len;
|
|||
|
|
char *spdu_ptr;
|
|||
|
|
|
|||
|
|
if (err_code != 0)
|
|||
|
|
{
|
|||
|
|
/* encode S-P-ABORT (error code will be encoded and we supply encoding buffer) */
|
|||
|
|
spdu_len = sizeof (spdu_buf);
|
|||
|
|
spdu_ptr = spdu_buf;
|
|||
|
|
if ((ret = cosp_enc_p_ab (spdu_ptr, err_code)) == SD_SUCCESS)
|
|||
|
|
{
|
|||
|
|
if (tp4_data (con->tp4_conn_id, SD_TRUE, spdu_len, spdu_ptr) != SD_SUCCESS)
|
|||
|
|
{
|
|||
|
|
ret = COSP_ERR_TP4_RET;
|
|||
|
|
COSP_LOG_ERR1 ("COSP-ERROR: S-P-ABORT acse_conn_id=0x%08X: T-DATA.req failed.",
|
|||
|
|
con);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
COSP_LOG_ERR1 ("COSP-ERROR: S-P-ABORT acse_conn_id=0x%08X: Encoding of P-ABORT SPDU failed.",
|
|||
|
|
con);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
/* encode S-U-ABORT (user data should be already encoded) */
|
|||
|
|
if ((ret = cosp_enc_u_ab (con, &spdu_ptr, &spdu_len)) == SD_SUCCESS)
|
|||
|
|
{
|
|||
|
|
if (tp4_data (con->tp4_conn_id, SD_TRUE, spdu_len, spdu_ptr) != SD_SUCCESS)
|
|||
|
|
{
|
|||
|
|
ret = COSP_ERR_TP4_RET;
|
|||
|
|
COSP_LOG_ERR1 ("COSP-ERROR: S-U-ABORT.req acse_conn_id=0x%08X: T-DATA.req failed.",
|
|||
|
|
con);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
COSP_LOG_ERR1 ("COSP-ERROR: S-U-ABORT.req acse_conn_id=0x%08X: Encoding of U-ABORT SPDU failed.",
|
|||
|
|
con);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return (ret);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
/*======================================================*/
|
|||
|
|
/* */
|
|||
|
|
/* D A T A F U N C T I O N S */
|
|||
|
|
/* */
|
|||
|
|
/*======================================================*/
|
|||
|
|
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* tp4_data_ind */
|
|||
|
|
/*----------------------------------------------------------------------*/
|
|||
|
|
/* Function to process data indication. */
|
|||
|
|
/* Note that the tp4_data_ind is called when complete SPDU has been */
|
|||
|
|
/* received, so the eot flag is always SD_TRUE. */
|
|||
|
|
/* */
|
|||
|
|
/* Parameters: */
|
|||
|
|
/* ST_LONG user_conn_id User's connection id for this connect. */
|
|||
|
|
/* ST_INT eot Indicates if last part of SPDU received.*/
|
|||
|
|
/* ST_UINT data_len Length of data. */
|
|||
|
|
/* char *data Pointer to data buffer. */
|
|||
|
|
/* */
|
|||
|
|
/* Return: */
|
|||
|
|
/* ST_VOID */
|
|||
|
|
/************************************************************************/
|
|||
|
|
//void called_conn_disconnect(ACSE_CONN *con);//lnk编译删除,原前置程序未使用
|
|||
|
|
ST_VOID tp4_data_ind (ST_LONG user_conn_id, ST_INT eot,
|
|||
|
|
ST_UINT data_len, char *data)
|
|||
|
|
{
|
|||
|
|
ST_INT ret;
|
|||
|
|
ST_UINT action;
|
|||
|
|
ACSE_CONN *con;
|
|||
|
|
|
|||
|
|
ret = SD_SUCCESS;
|
|||
|
|
action = 0;
|
|||
|
|
con = (ACSE_CONN *) user_conn_id;
|
|||
|
|
|
|||
|
|
/* Note: the protocol requires following steps to be taken for invalid*/
|
|||
|
|
/* incomming-event/state intersection (default: in switch) or */
|
|||
|
|
/* if the incomming SPDU can't be correctly process: */
|
|||
|
|
/* - issue S-P-ABORT */
|
|||
|
|
/* - send an ABORT SPDU */
|
|||
|
|
/* - start timer */
|
|||
|
|
/* - wait for T-DISCONNECT or ABORT ACCEPT SPDU */
|
|||
|
|
|
|||
|
|
switch (data [0]) /* First byte is SPDU Session Identifier */
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
case COSP_SI_CONNECT:
|
|||
|
|
switch (con->cosp_state)
|
|||
|
|
{
|
|||
|
|
case COSP_CSTATE_IDLE_TCON:
|
|||
|
|
/* if we are the transport connection acceptor, process CN */
|
|||
|
|
if (con->cosp_vtca)
|
|||
|
|
ret = cosp_process_connect (con, data_len, data);
|
|||
|
|
else
|
|||
|
|
action = COSP_T_DISCONNECT;
|
|||
|
|
break;
|
|||
|
|
|
|||
|
|
case COSP_CSTATE_WAIT_TDISCON_IND:
|
|||
|
|
tp4_session_timer (con->tp4_conn_id, SD_FALSE); /* stop timer */
|
|||
|
|
action = COSP_T_DISCONNECT;
|
|||
|
|
break;
|
|||
|
|
|
|||
|
|
default: /* in invalid state */
|
|||
|
|
ret = COSP_ERR_INV_CON_STATE;
|
|||
|
|
COSP_LOG_ERR2 ("COSP-ERROR: T-DATA.ind acse_conn_id=0x%08X: Invalid state=%d (for CONNECT SPDU).",
|
|||
|
|
con, con->cosp_state);
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
|
|||
|
|
case COSP_SI_FINISH:
|
|||
|
|
switch (con->cosp_state)
|
|||
|
|
{
|
|||
|
|
case COSP_CSTATE_IDLE_TCON:
|
|||
|
|
action = COSP_T_DISCONNECT;
|
|||
|
|
break;
|
|||
|
|
|
|||
|
|
case COSP_CSTATE_WAIT_DN: /* collision of conn releases */
|
|||
|
|
con->cosp_vcoll = SD_TRUE;
|
|||
|
|
/* go to next case */
|
|||
|
|
case COSP_CSTATE_DATA_XFER:
|
|||
|
|
ret = cosp_process_finish (con, data_len, data);
|
|||
|
|
break;
|
|||
|
|
|
|||
|
|
case COSP_CSTATE_WAIT_TDISCON_IND:
|
|||
|
|
/* we ignore the FINISH SPDU and remain in the same state */
|
|||
|
|
break;
|
|||
|
|
|
|||
|
|
default: /* in invalid state */
|
|||
|
|
ret = COSP_ERR_INV_CON_STATE;
|
|||
|
|
COSP_LOG_ERR2 ("COSP-ERROR: T-DATA.ind acse_conn_id=0x%08X: Invalid state=%d (for FINISH SPDU).",
|
|||
|
|
con, con->cosp_state);
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
|
|||
|
|
case COSP_SI_ACCEPT:
|
|||
|
|
switch (con->cosp_state)
|
|||
|
|
{
|
|||
|
|
case COSP_CSTATE_IDLE_TCON:
|
|||
|
|
action = COSP_T_DISCONNECT;
|
|||
|
|
break;
|
|||
|
|
|
|||
|
|
case COSP_CSTATE_WAIT_AC:
|
|||
|
|
con->cosp_vcoll = SD_FALSE;
|
|||
|
|
con->cosp_vdnr = SD_FALSE;
|
|||
|
|
ret = cosp_process_accept (con, data_len, data);
|
|||
|
|
break;
|
|||
|
|
|
|||
|
|
case COSP_CSTATE_WAIT_TDISCON_IND:
|
|||
|
|
/* we ignore the ACCEPT SPDU and remain in the same state */
|
|||
|
|
break;
|
|||
|
|
|
|||
|
|
default: /* in invalid state */
|
|||
|
|
ret = COSP_ERR_INV_CON_STATE;
|
|||
|
|
COSP_LOG_ERR2 ("COSP-ERROR: T-DATA.ind acse_conn_id=0x%08X: Invalid state=%d (for ACCEPT SPDU).",
|
|||
|
|
con, con->cosp_state);
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
|
|||
|
|
case COSP_SI_REFUSE:
|
|||
|
|
switch (con->cosp_state)
|
|||
|
|
{
|
|||
|
|
case COSP_CSTATE_IDLE_TCON:
|
|||
|
|
action = COSP_T_DISCONNECT;
|
|||
|
|
break;
|
|||
|
|
|
|||
|
|
case COSP_CSTATE_WAIT_AC:
|
|||
|
|
if ((ret = cosp_process_refuse (con, data_len, data)) == SD_SUCCESS)
|
|||
|
|
action = COSP_T_DISCONNECT;
|
|||
|
|
break;
|
|||
|
|
|
|||
|
|
case COSP_CSTATE_WAIT_TDISCON_IND:
|
|||
|
|
/* we ignore the REFUSE SPDU and remain in the same state */
|
|||
|
|
break;
|
|||
|
|
|
|||
|
|
default: /* in invalid state */
|
|||
|
|
ret = COSP_ERR_INV_CON_STATE;
|
|||
|
|
COSP_LOG_ERR2 ("COSP-ERROR: T-DATA.ind acse_conn_id=0x%08X: Invalid state=%d (for REFUSE SPDU).",
|
|||
|
|
con, con->cosp_state);
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
|
|||
|
|
case COSP_SI_DISCON:
|
|||
|
|
switch (con->cosp_state)
|
|||
|
|
{
|
|||
|
|
case COSP_CSTATE_IDLE_TCON:
|
|||
|
|
action = COSP_T_DISCONNECT;
|
|||
|
|
break;
|
|||
|
|
|
|||
|
|
case COSP_CSTATE_WAIT_DN:
|
|||
|
|
if ((ret = cosp_process_discon (con, data_len, data)) == SD_SUCCESS)
|
|||
|
|
action = COSP_T_DISCONNECT;
|
|||
|
|
break;
|
|||
|
|
|
|||
|
|
case COSP_CSTATE_WAIT_REL_RSP: /* collision */
|
|||
|
|
if (con->cosp_vcoll && con->cosp_vtca)
|
|||
|
|
{
|
|||
|
|
con->cosp_vdnr = SD_TRUE;
|
|||
|
|
ret = cosp_process_discon (con, data_len, data);
|
|||
|
|
/* remain in the same state */
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
ret = COSP_ERR_INV_CON_STATE;
|
|||
|
|
COSP_LOG_ERR1 ("COSP-ERROR: T-DATA.ind acse_conn_id=0x%08X: Collision flag not set or not a connection acceptor.",
|
|||
|
|
con);
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
|
|||
|
|
case COSP_CSTATE_WAIT_TDISCON_IND:
|
|||
|
|
/* we ignore the DN SPDU and remain in the same state */
|
|||
|
|
break;
|
|||
|
|
|
|||
|
|
default: /* in invalid state */
|
|||
|
|
ret = COSP_ERR_INV_CON_STATE;
|
|||
|
|
COSP_LOG_ERR2 ("COSP-ERROR: T-DATA.ind acse_conn_id=0x%08X: Invalid state=%d (for DISCONNECT SPDU).",
|
|||
|
|
con, con->cosp_state);
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
|
|||
|
|
case COSP_SI_ABORT: /* !always! disconnect transport */
|
|||
|
|
/* otherwise we may loop sending ABORTs */
|
|||
|
|
action = COSP_T_DISCONNECT;
|
|||
|
|
|
|||
|
|
switch (con->cosp_state)
|
|||
|
|
{
|
|||
|
|
case COSP_CSTATE_IDLE_TCON:
|
|||
|
|
break;
|
|||
|
|
|
|||
|
|
case COSP_CSTATE_WAIT_AC:
|
|||
|
|
case COSP_CSTATE_WAIT_DN:
|
|||
|
|
case COSP_CSTATE_WAIT_CON_RSP:
|
|||
|
|
case COSP_CSTATE_WAIT_REL_RSP:
|
|||
|
|
case COSP_CSTATE_DATA_XFER:
|
|||
|
|
if ((ret = cosp_process_abort (con, data_len, data)) != SD_SUCCESS)
|
|||
|
|
{
|
|||
|
|
/* even if we failed to decode abort we still will generate S-P-ABORT */
|
|||
|
|
action |= COSP_S_P_ABORT_IND;
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
|
|||
|
|
case COSP_CSTATE_WAIT_TDISCON_IND:
|
|||
|
|
tp4_session_timer (con->tp4_conn_id, SD_FALSE); /* stop timer */
|
|||
|
|
break;
|
|||
|
|
|
|||
|
|
default: /* in invalid state */
|
|||
|
|
ret = COSP_ERR_INV_CON_STATE;
|
|||
|
|
COSP_LOG_ERR2 ("COSP-ERROR: T-DATA.ind acse_conn_id=0x%08X: Invalid state=%d (for ABORT SPDU).",
|
|||
|
|
con, con->cosp_state);
|
|||
|
|
action |= COSP_S_P_ABORT_IND;
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
|
|||
|
|
case COSP_SI_AB_ACCEPT:
|
|||
|
|
/* this SPDU may be sent by remote COSP engine even if the */
|
|||
|
|
/* transport connection is not to be kept */
|
|||
|
|
|
|||
|
|
action = COSP_T_DISCONNECT; /* !always! disconnect transport */
|
|||
|
|
|
|||
|
|
switch (con->cosp_state)
|
|||
|
|
{
|
|||
|
|
case COSP_CSTATE_IDLE_TCON:
|
|||
|
|
break;
|
|||
|
|
|
|||
|
|
case COSP_CSTATE_WAIT_TDISCON_IND:
|
|||
|
|
tp4_session_timer (con->tp4_conn_id, SD_FALSE); /* stop timer */
|
|||
|
|
break;
|
|||
|
|
|
|||
|
|
default: /* in invalid state */
|
|||
|
|
ret = COSP_ERR_INV_CON_STATE;
|
|||
|
|
COSP_LOG_ERR2 ("COSP-ERROR: T-DATA.ind acse_conn_id=0x%08X: Invalid state=%d (for ABORT ACCEPT SPDU).",
|
|||
|
|
con, con->cosp_state);
|
|||
|
|
/* ABORT ACCEPT can be received only in response to already */
|
|||
|
|
/* sent ABORT, so we will not send another one here */
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
|
|||
|
|
/* case COSP_SI_GIVE_TOKEN: !!! GIVE-TOKEN is concatinated with DATA*/
|
|||
|
|
case COSP_SI_DATA: /* SPDU and both have the same code=1 */
|
|||
|
|
switch (con->cosp_state)
|
|||
|
|
{
|
|||
|
|
case COSP_CSTATE_IDLE_TCON:
|
|||
|
|
action = COSP_T_DISCONNECT;
|
|||
|
|
break;
|
|||
|
|
|
|||
|
|
case COSP_CSTATE_WAIT_DN:
|
|||
|
|
if (con->cosp_vcoll)
|
|||
|
|
{
|
|||
|
|
ret = COSP_ERR_INV_CON_STATE;
|
|||
|
|
COSP_LOG_ERR2 ("COSP-ERROR: T-DATA.ind acse_conn_id=0x%08X: Invalid state=%d (for DATA SPDU).",
|
|||
|
|
con, con->cosp_state);
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
/* process the received DATA SPDU and remain in the same state */
|
|||
|
|
/* go to next case */
|
|||
|
|
case COSP_CSTATE_DATA_XFER:
|
|||
|
|
ret = cosp_process_data (con, data_len, data);
|
|||
|
|
break;
|
|||
|
|
|
|||
|
|
case COSP_CSTATE_WAIT_TDISCON_IND:
|
|||
|
|
/* we ignore the DATA SPDU and remain in the same state */
|
|||
|
|
break;
|
|||
|
|
|
|||
|
|
default: /* in invalid state */
|
|||
|
|
ret = COSP_ERR_INV_CON_STATE;
|
|||
|
|
COSP_LOG_ERR2 ("COSP-ERROR: T-DATA.ind acse_conn_id=0x%08X: Invalid state=%d (for DATA SPDU).",
|
|||
|
|
con, con->cosp_state);
|
|||
|
|
}
|
|||
|
|
break;
|
|||
|
|
|
|||
|
|
default:
|
|||
|
|
ret = COSP_ERR_DEC_INV_SPDU;
|
|||
|
|
COSP_LOG_ERR2 ("COSP-ERROR: T-DATA.ind acse_conn_id=0x%08X: Unsupported SPDU SI code=%d received.",
|
|||
|
|
con, (ST_INT)(data [0]));
|
|||
|
|
action = COSP_S_P_ABORT_IND | COSP_SEND_ABORT_SPDU;
|
|||
|
|
} /* end of switch */
|
|||
|
|
|
|||
|
|
tp4_reldata (data); /* we are done with the TP4 data buffer */
|
|||
|
|
|
|||
|
|
if (ret != SD_SUCCESS)
|
|||
|
|
{
|
|||
|
|
/* if error occurred and SPDU other then an ABORT or ABORT ACCEPT */
|
|||
|
|
/* received then issue S-P-ABORT and SEND an ABORT SPDU. */
|
|||
|
|
|
|||
|
|
if ((data [0] != COSP_SI_ABORT) && (data [0] != COSP_SI_AB_ACCEPT))
|
|||
|
|
action = COSP_S_P_ABORT_IND | COSP_SEND_ABORT_SPDU;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/*--------------------------------------------------------------------*/
|
|||
|
|
/* abort/disconnect if processing of received SPDU failed or this is */
|
|||
|
|
/* the protocol specification */
|
|||
|
|
/*--------------------------------------------------------------------*/
|
|||
|
|
|
|||
|
|
if (action & COSP_SEND_ABORT_SPDU)
|
|||
|
|
{
|
|||
|
|
/* encode and send ABORT SPDU to remote SS-user, ret is the error code */
|
|||
|
|
if (cosp_send_abort (con, ret) == SD_SUCCESS)
|
|||
|
|
{
|
|||
|
|
con->cosp_state = COSP_CSTATE_WAIT_TDISCON_IND;
|
|||
|
|
tp4_session_timer (con->tp4_conn_id, SD_TRUE); /* start timer */
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
con->cosp_state = COSP_CSTATE_IDLE;
|
|||
|
|
action |= COSP_T_DISCONNECT; /* disconnect if we can't abort */
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (action & COSP_S_P_ABORT_IND)
|
|||
|
|
{
|
|||
|
|
/* issue S-P-ABORT.ind to local SS-user (use code from cosp_usr.h) */
|
|||
|
|
|
|||
|
|
COSP_LOG_DEC3 ("S-P-ABORT.ind: acse_conn_id =0x%08X user_conn_id =%4ld reason =%d",
|
|||
|
|
con, con->user_conn_id, (ST_INT) COSP_P_AB_IND_PROT_ERR);
|
|||
|
|
|
|||
|
|
u_cosp_p_abort_ind (con, COSP_P_AB_IND_PROT_ERR);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (action & COSP_T_DISCONNECT)
|
|||
|
|
{
|
|||
|
|
tp4_disconnect (con->tp4_conn_id, 0, NULL);
|
|||
|
|
/*renxiaobao20220831 °²È«¼ì²â*/
|
|||
|
|
//called_conn_disconnect(con);//lnk编译删除,原前置程序未使用
|
|||
|
|
|
|||
|
|
acse_free_con (con); /* we are disconnected, free con struct */
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* tp4_expdata_ind */
|
|||
|
|
/*----------------------------------------------------------------------*/
|
|||
|
|
/* Function to process a expedited S-DATA.ind. */
|
|||
|
|
/* */
|
|||
|
|
/* Parameters: */
|
|||
|
|
/* ST_LONG user_conn_id User's connection id for this connect. */
|
|||
|
|
/* ST_UINT data_len Length of data. */
|
|||
|
|
/* char *data Pointer to data buffer. */
|
|||
|
|
/* */
|
|||
|
|
/* Return: */
|
|||
|
|
/* ST_VOID */
|
|||
|
|
/************************************************************************/
|
|||
|
|
ST_VOID tp4_expdata_ind (ST_LONG user_conn_id, ST_UINT data_len, char *data)
|
|||
|
|
{
|
|||
|
|
/* Treat like normal data. Assume "eot" = 1 */
|
|||
|
|
tp4_data_ind (user_conn_id, 1, data_len, data);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* cosp_data_req */
|
|||
|
|
/*----------------------------------------------------------------------*/
|
|||
|
|
/* Function called by SS-user to transfer normal data on a previously */
|
|||
|
|
/* established connection. */
|
|||
|
|
/* */
|
|||
|
|
/* Parameters: */
|
|||
|
|
/* ACSE_CONN *con Pointer to connection info */
|
|||
|
|
/* */
|
|||
|
|
/* Return: */
|
|||
|
|
/* SD_SUCCESS (0) if successful */
|
|||
|
|
/* error code otherwise */
|
|||
|
|
/************************************************************************/
|
|||
|
|
ST_RET cosp_data_req (ACSE_CONN *con)
|
|||
|
|
{
|
|||
|
|
ST_INT ret;
|
|||
|
|
ST_UINT spdu_len;
|
|||
|
|
char *spdu_ptr;
|
|||
|
|
|
|||
|
|
COSP_LOG_ENC2 ("S-DATA.req: acse_conn_id =0x%08X user_conn_id =%4ld",
|
|||
|
|
con, con->user_conn_id);
|
|||
|
|
COSP_LOG_ENCC1 ("User data length: %d", con->ppdu_len);
|
|||
|
|
COSP_LOG_ENCH (con->ppdu_len, con->ppdu_ptr);
|
|||
|
|
|
|||
|
|
ret = SD_SUCCESS;
|
|||
|
|
|
|||
|
|
if ((con->cosp_state == COSP_CSTATE_DATA_XFER) ||
|
|||
|
|
(con->cosp_state == COSP_CSTATE_WAIT_REL_RSP && !con->cosp_vcoll))
|
|||
|
|
{
|
|||
|
|
if ((ret = cosp_enc_dt (con, &spdu_ptr, &spdu_len)) == SD_SUCCESS)
|
|||
|
|
{
|
|||
|
|
if (tp4_data (con->tp4_conn_id, SD_TRUE, spdu_len, spdu_ptr) != SD_SUCCESS)
|
|||
|
|
{
|
|||
|
|
ret = COSP_ERR_TP4_RET;
|
|||
|
|
COSP_LOG_ERR0 ("COSP-ERROR: S-DATA.req acse_conn_id=0x%08X: T-DATA.req failed.");
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
COSP_LOG_ERR1 ("COSP-ERROR: S-DATA.req acse_conn_id=0x%08X: Encoding of DATA SPDU failed.",
|
|||
|
|
con);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
ret = COSP_ERR_INV_CON_STATE;
|
|||
|
|
COSP_LOG_ERR2 ("COSP-ERROR: S-DATA.req acse_conn_id=0x%08X: Invalid state=%d (or collision flag set).",
|
|||
|
|
con, con->cosp_state);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return (ret);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
/*======================================================*/
|
|||
|
|
/* */
|
|||
|
|
/* L O C A L S P D U P R O C E S S I N G F U N C */
|
|||
|
|
/* */
|
|||
|
|
/*======================================================*/
|
|||
|
|
|
|||
|
|
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* cosp_process_connect */
|
|||
|
|
/*----------------------------------------------------------------------*/
|
|||
|
|
/* This function will decode the CONNECT SPDU and call SS-user's funct */
|
|||
|
|
/* u_cosp_con_ind to indicate to the SS-user incomming connection req. */
|
|||
|
|
/* */
|
|||
|
|
/* Parameters: */
|
|||
|
|
/* ACSE_CONN *con Pointer to con info struct */
|
|||
|
|
/* ST_UINT spdu_len Length of SPDU */
|
|||
|
|
/* char *spdu_buf Pointer to SPDU buffer */
|
|||
|
|
/* */
|
|||
|
|
/* Return: */
|
|||
|
|
/* SD_SUCCESS (0) if successful */
|
|||
|
|
/* error code otherwise */
|
|||
|
|
/************************************************************************/
|
|||
|
|
static ST_RET cosp_process_connect (ACSE_CONN *con, ST_UINT spdu_len,
|
|||
|
|
char *spdu_buf)
|
|||
|
|
{
|
|||
|
|
ST_INT ret;
|
|||
|
|
COSP_CN_AC dec_par; /* decoded connection params */
|
|||
|
|
ST_LONG cosp_user_bind_id;
|
|||
|
|
|
|||
|
|
/*----------------------------*/
|
|||
|
|
/* decode the CONNECT SPDU */
|
|||
|
|
/*----------------------------*/
|
|||
|
|
|
|||
|
|
ret = cosp_dec_cn_ac (&dec_par, spdu_buf, spdu_len, COSP_SI_CONNECT);
|
|||
|
|
if (ret == SD_SUCCESS)
|
|||
|
|
{
|
|||
|
|
/* Save SSELs in ACSE_CONN struct. */
|
|||
|
|
memcpy (con->loc_ssel, dec_par.loc_ssel, dec_par.loc_ssel [0]+1);
|
|||
|
|
memcpy (con->rem_ssel, dec_par.rem_ssel, dec_par.rem_ssel [0]+1);
|
|||
|
|
|
|||
|
|
/* generate S-CONNECT.ind to the SS-user */
|
|||
|
|
|
|||
|
|
con->cosp_state = COSP_CSTATE_WAIT_CON_RSP;
|
|||
|
|
con->ppdu_len = dec_par.udata_len;
|
|||
|
|
con->ppdu_ptr = dec_par.udata_ptr;
|
|||
|
|
|
|||
|
|
/* user_conn_id (created by ACSE-user) is invalid at this point, */
|
|||
|
|
/* we probably should set it to -1 (an invalid value). Note that 0 */
|
|||
|
|
/* is a valid id. */
|
|||
|
|
con->user_conn_id = -1L;
|
|||
|
|
|
|||
|
|
cosp_user_bind_id = con->cosp_bind_id; /* COSP id = COSP User's bind id */
|
|||
|
|
|
|||
|
|
COSP_LOG_DEC1 ("S-CONNECT.ind: acse_conn_id =0x%08X", con);
|
|||
|
|
COSP_LOG_DECC1 ("User data length: %d", con->ppdu_len);
|
|||
|
|
COSP_LOG_DECH (con->ppdu_len, con->ppdu_ptr);
|
|||
|
|
|
|||
|
|
u_cosp_con_ind (cosp_user_bind_id, con);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
COSP_LOG_ERR1 ("COSP-ERROR: T-DATA.ind acse_conn_id=0x%08X: Decoding of CONNECT SPDU failed.",
|
|||
|
|
con);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return (ret);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* cosp_process_finish */
|
|||
|
|
/*----------------------------------------------------------------------*/
|
|||
|
|
/* This function will decode the FINISH SPDU and call SS-user's function*/
|
|||
|
|
/* u_cosp_rel_ind to indicate to the SS-user that the remote wants to */
|
|||
|
|
/* release connection. */
|
|||
|
|
/* */
|
|||
|
|
/* Parameters: */
|
|||
|
|
/* ACSE_CONN *con Pointer to con info struct */
|
|||
|
|
/* ST_UINT spdu_len Length of SPDU */
|
|||
|
|
/* char *spdu_buf Pointer to SPDU buffer */
|
|||
|
|
/* */
|
|||
|
|
/* Return: */
|
|||
|
|
/* SD_SUCCESS (0) if successful */
|
|||
|
|
/* error code otherwise */
|
|||
|
|
/************************************************************************/
|
|||
|
|
static ST_RET cosp_process_finish (ACSE_CONN *con, ST_UINT spdu_len,
|
|||
|
|
char *spdu_buf)
|
|||
|
|
{
|
|||
|
|
ST_INT ret;
|
|||
|
|
COSP_FN_DN dec_par; /* decoded con rel params */
|
|||
|
|
|
|||
|
|
/*------------------------------------*/
|
|||
|
|
/* decode and check the FINISH SPDU */
|
|||
|
|
/*------------------------------------*/
|
|||
|
|
|
|||
|
|
ret = cosp_dec_fn_dn (&dec_par, spdu_buf, spdu_len, COSP_SI_FINISH);
|
|||
|
|
if (ret == SD_SUCCESS)
|
|||
|
|
{
|
|||
|
|
/* generate S-RELEASE.ind */
|
|||
|
|
|
|||
|
|
con->cosp_state = COSP_CSTATE_WAIT_REL_RSP;
|
|||
|
|
con->ppdu_len = dec_par.udata_len;
|
|||
|
|
con->ppdu_ptr = dec_par.udata_ptr;
|
|||
|
|
|
|||
|
|
COSP_LOG_DEC2 ("S-RELEASE.ind: acse_conn_id =0x%08X user_conn_id =%4ld",
|
|||
|
|
con, con->user_conn_id);
|
|||
|
|
COSP_LOG_DECC1 ("User data length: %d", con->ppdu_len);
|
|||
|
|
COSP_LOG_DECH (con->ppdu_len, con->ppdu_ptr);
|
|||
|
|
|
|||
|
|
u_cosp_rel_ind (con);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
COSP_LOG_ERR1 ("COSP-ERROR: T-DATA.ind acse_conn_id=0x%08X: Decoding of FINISH SPDU failed.",
|
|||
|
|
con);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return (ret);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* cosp_process_accept */
|
|||
|
|
/*----------------------------------------------------------------------*/
|
|||
|
|
/* This function will decode the ACCEPT SPDU and call SS-user's funct */
|
|||
|
|
/* u_cosp_con_cnf_pos to indicate to the SS-user that the connection has*/
|
|||
|
|
/* been established. */
|
|||
|
|
/* */
|
|||
|
|
/* Parameters: */
|
|||
|
|
/* ACSE_CONN *con Pointer to con info struct */
|
|||
|
|
/* ST_UINT spdu_len Length of SPDU */
|
|||
|
|
/* char *spdu_buf Pointer to SPDU buffer */
|
|||
|
|
/* */
|
|||
|
|
/* Return: */
|
|||
|
|
/* SD_SUCCESS (0) if successful */
|
|||
|
|
/* error code otherwise */
|
|||
|
|
/************************************************************************/
|
|||
|
|
static ST_RET cosp_process_accept (ACSE_CONN *con, ST_UINT spdu_len,
|
|||
|
|
char *spdu_buf)
|
|||
|
|
{
|
|||
|
|
ST_INT ret;
|
|||
|
|
COSP_CN_AC dec_par; /* decoded accept params */
|
|||
|
|
|
|||
|
|
/*----------------------------------*/
|
|||
|
|
/* decode and check the ACCEPT SPDU */
|
|||
|
|
/*----------------------------------*/
|
|||
|
|
|
|||
|
|
ret = cosp_dec_cn_ac (&dec_par, spdu_buf, spdu_len, COSP_SI_ACCEPT);
|
|||
|
|
if (ret == SD_SUCCESS)
|
|||
|
|
{
|
|||
|
|
/* generate S-CONNECT.cnf+ */
|
|||
|
|
|
|||
|
|
con->cosp_state = COSP_CSTATE_DATA_XFER;
|
|||
|
|
con->ppdu_len = dec_par.udata_len;
|
|||
|
|
con->ppdu_ptr = dec_par.udata_ptr;
|
|||
|
|
|
|||
|
|
COSP_LOG_DEC2 ("S-CONNECT.cnf+: acse_conn_id =0x%08X user_conn_id =%4ld",
|
|||
|
|
con, con->user_conn_id);
|
|||
|
|
COSP_LOG_DECC1 ("User data length: %d", con->ppdu_len);
|
|||
|
|
COSP_LOG_DECH (con->ppdu_len, con->ppdu_ptr);
|
|||
|
|
|
|||
|
|
u_cosp_con_cnf_pos (con);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
COSP_LOG_ERR1 ("COSP-ERROR: T-DATA.ind acse_conn_id=0x%08X: Decoding of ACCEPT SPDU failed.",
|
|||
|
|
con);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return (ret);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* cosp_process_refuse */
|
|||
|
|
/*----------------------------------------------------------------------*/
|
|||
|
|
/* This function will decode the REFUSE SPDU and call SS-user's function*/
|
|||
|
|
/* u_cosp_con_cnf_neg to indicate to the SS-user that the establishment */
|
|||
|
|
/* of connection failed. */
|
|||
|
|
/* Note that this implementation will not reuse the transport connection*/
|
|||
|
|
/* for another session connect (transport will be disconnected). */
|
|||
|
|
/* */
|
|||
|
|
/* Parameters: */
|
|||
|
|
/* ACSE_CONN *con Pointer to con info struct */
|
|||
|
|
/* ST_UINT spdu_len Length of SPDU */
|
|||
|
|
/* char *spdu_buf Pointer to SPDU buffer */
|
|||
|
|
/* */
|
|||
|
|
/* Return: */
|
|||
|
|
/* SD_SUCCESS (0) if successful */
|
|||
|
|
/* error code otherwise */
|
|||
|
|
/************************************************************************/
|
|||
|
|
static ST_RET cosp_process_refuse (ACSE_CONN *con, ST_UINT spdu_len,
|
|||
|
|
char *spdu_buf)
|
|||
|
|
{
|
|||
|
|
ST_INT ret;
|
|||
|
|
COSP_RF dec_par; /* decoded refuse connection params */
|
|||
|
|
ST_INT result;
|
|||
|
|
ST_INT reason;
|
|||
|
|
|
|||
|
|
/*----------------------------------*/
|
|||
|
|
/* decode and check the REFUSE SPDU */
|
|||
|
|
/*----------------------------------*/
|
|||
|
|
|
|||
|
|
ret = cosp_dec_rf (&dec_par, spdu_buf, spdu_len);
|
|||
|
|
if (ret == SD_SUCCESS)
|
|||
|
|
{
|
|||
|
|
con->cosp_state = COSP_CSTATE_IDLE;
|
|||
|
|
|
|||
|
|
/* generate S-CONNECT.cnf- */
|
|||
|
|
|
|||
|
|
if (dec_par.reason <= 2)
|
|||
|
|
result = COSP_CON_CNF_U_REJECT; /* remote SS-user reject */
|
|||
|
|
else
|
|||
|
|
result = COSP_CON_CNF_P_REJECT; /* remote SS-provider reject */
|
|||
|
|
|
|||
|
|
/* convert the reason code from SPDU to reason codes in cosp_usr.h */
|
|||
|
|
switch ((ST_UINT) dec_par.reason)
|
|||
|
|
{
|
|||
|
|
case 0: /* rejection by called SS-user??, reason not specified */
|
|||
|
|
reason = COSP_CON_CNF_U_NOT_SPECIFIED;
|
|||
|
|
break;
|
|||
|
|
|
|||
|
|
case 1: /* rejection by called SS-user, tmp congestion */
|
|||
|
|
reason = COSP_CON_CNF_U_CONGESTION;
|
|||
|
|
break;
|
|||
|
|
|
|||
|
|
case 2: /* rejection by called SS-user, user data may follow */
|
|||
|
|
reason = COSP_CON_CNF_U_IN_UDATA;
|
|||
|
|
con->ppdu_len = dec_par.udata_len;
|
|||
|
|
con->ppdu_ptr = dec_par.udata_ptr;
|
|||
|
|
break;
|
|||
|
|
|
|||
|
|
case 128+1: /* rejection by called SS-prov, SSEL unknown */
|
|||
|
|
reason = COSP_CON_CNF_P_INV_SSEL;
|
|||
|
|
break;
|
|||
|
|
|
|||
|
|
case 128+2: /* rejection by called SS-prov, SS-user not attached */
|
|||
|
|
reason = COSP_CON_CNF_P_NOT_ATTACHED;
|
|||
|
|
break;
|
|||
|
|
|
|||
|
|
case 128+3: /* rejection by called SS-prov, congestion */
|
|||
|
|
reason = COSP_CON_CNF_P_CONGESTION;
|
|||
|
|
break;
|
|||
|
|
|
|||
|
|
case 128+4: /* rejection by called SS-prov, prot version not supported */
|
|||
|
|
case 128+5: /* rejection by called SS-prov, reason not specified */
|
|||
|
|
case 128+6: /* rejection by called SS-prov, implementation restriction stated in PICS */
|
|||
|
|
default:
|
|||
|
|
reason = COSP_CON_CNF_P_NOT_SPECIFIED;
|
|||
|
|
} /* end of switch */
|
|||
|
|
|
|||
|
|
COSP_LOG_DEC4 ("S-CONNECT.cnf-: acse_conn_id =0x%08X user_conn_id =%4ld result =%d reason =%d",
|
|||
|
|
con, con->user_conn_id, result, reason);
|
|||
|
|
COSP_LOG_DECC1 ("User data length: %d", con->ppdu_len);
|
|||
|
|
COSP_LOG_DECH (con->ppdu_len, con->ppdu_ptr);
|
|||
|
|
|
|||
|
|
/* S-CONNECT.cnf- */
|
|||
|
|
u_cosp_con_cnf_neg (con, result, reason);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
COSP_LOG_ERR1 ("COSP-ERROR: T-DATA.ind acse_conn_id=0x%08X: Decoding of REFUSE SPDU failed.",
|
|||
|
|
con);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return (ret);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* cosp_process_discon */
|
|||
|
|
/*----------------------------------------------------------------------*/
|
|||
|
|
/* This function will decode the DN SPDU and call SS-user's function */
|
|||
|
|
/* u_cosp_rel_cnf_pos to indicate to the SS-user the result of session */
|
|||
|
|
/* release request. */
|
|||
|
|
/* */
|
|||
|
|
/* Parameters: */
|
|||
|
|
/* ACSE_CONN *con Pointer to con info struct */
|
|||
|
|
/* ST_UINT spdu_len Length of SPDU */
|
|||
|
|
/* char *spdu_buf Pointer to SPDU buffer */
|
|||
|
|
/* */
|
|||
|
|
/* Return: */
|
|||
|
|
/* SD_SUCCESS (0) if successful */
|
|||
|
|
/* error code otherwise */
|
|||
|
|
/************************************************************************/
|
|||
|
|
static ST_RET cosp_process_discon (ACSE_CONN *con, ST_UINT spdu_len,
|
|||
|
|
char *spdu_buf)
|
|||
|
|
{
|
|||
|
|
ST_INT ret;
|
|||
|
|
COSP_FN_DN dec_par; /* decoded con rel params */
|
|||
|
|
|
|||
|
|
/*------------------------------------*/
|
|||
|
|
/* decode and check the DN SPDU */
|
|||
|
|
/*------------------------------------*/
|
|||
|
|
|
|||
|
|
ret = cosp_dec_fn_dn (&dec_par, spdu_buf, spdu_len, COSP_SI_DISCON);
|
|||
|
|
if (ret == SD_SUCCESS)
|
|||
|
|
{
|
|||
|
|
/* do not change here the state, new state depends on previous */
|
|||
|
|
/* state and if collision of S-RELEASEs occurred. */
|
|||
|
|
|
|||
|
|
/* generate S-RELEASE.cnf+ */
|
|||
|
|
|
|||
|
|
con->ppdu_len = dec_par.udata_len;
|
|||
|
|
con->ppdu_ptr = dec_par.udata_ptr;
|
|||
|
|
|
|||
|
|
COSP_LOG_DEC2 ("S-RELEASE.cnf+: acse_conn_id =0x%08X user_conn_id =%4ld",
|
|||
|
|
con, con->user_conn_id);
|
|||
|
|
COSP_LOG_DECC1 ("User data length: %d", con->ppdu_len);
|
|||
|
|
COSP_LOG_DECH (con->ppdu_len, con->ppdu_ptr);
|
|||
|
|
|
|||
|
|
u_cosp_rel_cnf_pos (con); /* currently only positive cnf possible */
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
COSP_LOG_ERR1 ("COSP-ERROR: T-DATA.ind acse_conn_id=0x%08X: Decoding of DISCONNECT SPDU failed.",
|
|||
|
|
con);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return (ret);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* cosp_process_abort */
|
|||
|
|
/*----------------------------------------------------------------------*/
|
|||
|
|
/* This function will decode the ABORT SPDU and call SS-user's function */
|
|||
|
|
/* u_cosp_abort_ind to indicate to the SS-user that the session */
|
|||
|
|
/* connection has been aborted by remote. */
|
|||
|
|
/* Note that this implementation will not reuse the transport connection*/
|
|||
|
|
/* for another session connect (transport will be disconnected). */
|
|||
|
|
/* */
|
|||
|
|
/* Parameters: */
|
|||
|
|
/* ACSE_CONN *con Pointer to con info struct */
|
|||
|
|
/* ST_UINT spdu_len Length of SPDU */
|
|||
|
|
/* char *spdu_buf Pointer to SPDU buffer */
|
|||
|
|
/* */
|
|||
|
|
/* Return: */
|
|||
|
|
/* SD_SUCCESS (0) if successful */
|
|||
|
|
/* error code otherwise */
|
|||
|
|
/************************************************************************/
|
|||
|
|
static ST_RET cosp_process_abort (ACSE_CONN *con, ST_UINT spdu_len,
|
|||
|
|
char *spdu_buf)
|
|||
|
|
{
|
|||
|
|
ST_INT ret;
|
|||
|
|
COSP_AB dec_par; /* decoded abort connection params */
|
|||
|
|
ST_INT reason;
|
|||
|
|
ST_INT err_code;
|
|||
|
|
|
|||
|
|
/*------------------------------------*/
|
|||
|
|
/* decode and check the ABORT SPDU */
|
|||
|
|
/*------------------------------------*/
|
|||
|
|
|
|||
|
|
ret = cosp_dec_ab (&dec_par, spdu_buf, spdu_len);
|
|||
|
|
if (ret == SD_SUCCESS)
|
|||
|
|
{
|
|||
|
|
con->cosp_state = COSP_CSTATE_IDLE;
|
|||
|
|
|
|||
|
|
/* generate S-U-ABORT.ind or S-P-ABORT.ind */
|
|||
|
|
|
|||
|
|
if (dec_par.reason & COSP_AB_REASON_USER_ABORT)
|
|||
|
|
{
|
|||
|
|
/* remote SS-user abort */
|
|||
|
|
con->ppdu_len = dec_par.udata_len;
|
|||
|
|
con->ppdu_ptr = dec_par.udata_ptr;
|
|||
|
|
|
|||
|
|
COSP_LOG_DEC2 ("S-U-ABORT.ind: acse_conn_id =0x%08X user_conn_id =%4ld",
|
|||
|
|
con, con->user_conn_id);
|
|||
|
|
COSP_LOG_DECC1 ("User data length: %d", con->ppdu_len);
|
|||
|
|
COSP_LOG_DECH (con->ppdu_len, con->ppdu_ptr);
|
|||
|
|
|
|||
|
|
u_cosp_u_abort_ind (con);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
/* SS-provider abort */
|
|||
|
|
if (dec_par.reason & COSP_AB_REASON_PROT_ERROR)
|
|||
|
|
{
|
|||
|
|
reason = COSP_P_AB_IND_PROT_ERR;
|
|||
|
|
err_code = 0;
|
|||
|
|
|
|||
|
|
/* Log the ABORT error code */
|
|||
|
|
if (dec_par.reflect_par_len == 2)
|
|||
|
|
err_code = ((ST_UINT16) dec_par.reflect_par [0] << 8)
|
|||
|
|
+ (ST_UINT16) dec_par.reflect_par [1];
|
|||
|
|
|
|||
|
|
COSP_LOG_DEC4 ("S-P-ABORT.ind: acse_conn_id =0x%08X user_conn_id =%4ld reason =%d err_code =0x%04X",
|
|||
|
|
con, con->user_conn_id, reason, err_code);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
reason = COSP_P_AB_IND_UNDEFINED;
|
|||
|
|
|
|||
|
|
COSP_LOG_DEC3 ("S-P-ABORT.ind: acse_conn_id =0x%08X user_conn_id =%4ld reason =%d",
|
|||
|
|
con, con->user_conn_id, reason);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
u_cosp_p_abort_ind (con, reason);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
COSP_LOG_ERR1 ("COSP-ERROR: T-DATA.ind acse_conn_id=0x%08X: Decoding of ABORT SPDU failed.",
|
|||
|
|
con);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return (ret);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
/************************************************************************/
|
|||
|
|
/* cosp_process_data */
|
|||
|
|
/*----------------------------------------------------------------------*/
|
|||
|
|
/* This function will decode a DATA SPDU and generate a S-DATA.ind. */
|
|||
|
|
/* */
|
|||
|
|
/* Parameters: */
|
|||
|
|
/* ACSE_CONN *con Pointer to con info struct */
|
|||
|
|
/* ST_UINT spdu_len Length of SPDU */
|
|||
|
|
/* char *spdu_buf Pointer to SPDU buffer */
|
|||
|
|
/* */
|
|||
|
|
/* Return: */
|
|||
|
|
/* SD_SUCCESS (0) if successful */
|
|||
|
|
/* error code otherwise */
|
|||
|
|
/************************************************************************/
|
|||
|
|
static ST_RET cosp_process_data (ACSE_CONN *con, ST_UINT spdu_len,
|
|||
|
|
char *spdu_buf)
|
|||
|
|
{
|
|||
|
|
ST_INT ret;
|
|||
|
|
COSP_DT dec_par; /* decoded refuse connection params */
|
|||
|
|
|
|||
|
|
/*------------------------------------*/
|
|||
|
|
/* decode and check the DATA SPDU */
|
|||
|
|
/*------------------------------------*/
|
|||
|
|
ret = cosp_dec_dt (&dec_par, spdu_buf, spdu_len);
|
|||
|
|
if (ret == SD_SUCCESS)
|
|||
|
|
{
|
|||
|
|
/* generate S-DATA.ind */
|
|||
|
|
con->ppdu_len = dec_par.udata_len;
|
|||
|
|
con->ppdu_ptr = dec_par.udata_ptr;
|
|||
|
|
|
|||
|
|
COSP_LOG_DEC2 ("S-DATA.ind: acse_conn_id =0x%08X user_conn_id =%4ld",
|
|||
|
|
con, con->user_conn_id);
|
|||
|
|
COSP_LOG_DECC1 ("User data length: %d", con->ppdu_len);
|
|||
|
|
COSP_LOG_DECH (con->ppdu_len, con->ppdu_ptr);
|
|||
|
|
|
|||
|
|
u_cosp_data_ind (con);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
COSP_LOG_ERR1 ("COSP-ERROR: T-DATA.ind acse_conn_id=0x%08X: Decoding of DATA SPDU failed.",
|
|||
|
|
con);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return (ret);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
|