/************************************************************************/
/* SISCO SOFTWARE MODULE HEADER *****************************************/
/************************************************************************/
/*	(c) Copyright Systems Integration Specialists Company, Inc.,	*/
/*	1997, All Rights Reserved					*/
/*									*/
/*			PROPRIETARY AND CONFIDENTIAL			*/
/*									*/
/* MODULE NAME : cosp_enc.c						*/
/* PRODUCT(S)  : MOSI Stack (over TP4)					*/
/*									*/
/* MODULE DESCRIPTION : 						*/
/*		This file implements the encoding of COSP SPDUs.	*/
/*									*/
/* NOTE: Implementation restrictions:					*/
/*		Non-segmenting COSP,					*/
/*		Transport connections are not reused.			*/
/*									*/
/*  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_envelope_len 				*/
/*			cosp_enc_cn_ac					*/
/*			cosp_enc_rf					*/
/*			cosp_enc_fn_dn					*/
/*			cosp_enc_ab					*/
/*			cosp_enc_dt					*/
/*									*/
/* MODIFICATION LOG :							*/
/*  Date     Who   Rev			Comments			*/
/* --------  ---  ------   -------------------------------------------	*/
/* 06/02/04  JRB    10     cosp_enc_dt: do NOT restrict user data len.	*/
/* 07/16/02  JRB    09     Clean up & fix comments in cosp_enc_cn_ac.	*/
/* 06/05/02  JRB    08     Send Calling SSEL on connect request.	*/
/* 09/12/01  JRB    07     Reverse last change (not needed).		*/
/* 08/01/01  JRB    06     Del rem_addr arg from cosp_enc_cn_ac.	*/
/* 04/12/00  JRB    05     Lint cleanup.				*/
/* 09/13/99  MDE    04     Added SD_CONST modifiers			*/
/* 08/13/98  JRB    03     Lint cleanup.				*/
/* 05/27/97  JRB   7.00    MMSEASE 7.0 release.				*/
/* 03/20/97  EJV    02     Enhanced logging.				*/
/* 01/17/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 "acse2.h"

#include "cosp_log.h"
#include "cosp.h"
#include "cosp_usr.h"


	/*----------------------------------------------*/
	/* Fixed encoding for CONNECT / ACCEPT SPDU:	*/
	/* Connect/Accept PGI:		    		*/
	/*	- extended concatination not supported,	*/
	/*	- COSP Version2 supported		*/
	/* Session User Requirements PI: 		*/
	/*	- duplex functional unit (FU) supported	*/
	/*----------------------------------------------*/

static ST_UCHAR cosp_cn_ac_fixed [12] = {
	5,		/*   CN-AC PGI code				*/
	6,		/*   CN-AC PGI len				*/
			/* Protocol Option PI:				*/
	19,		/*   PI code					*/
	1,		/*   PI len					*/
	0,		/*   0 if rcv extended concatinat. not supported*/
			/* Version Number PI:				*/
	22,		/*   PI code					*/
	1,		/*   PI len					*/
	COSP_VER2,	/*   we supporting Version2			*/
			/* Session User Requirements PI:		*/
	20,		/*   PI code					*/
	2,		/*   PI len					*/
	0,		/*   bits 9-16 are 0				*/
	2};		/*   bits 1-8 (only bit2=1 duplex FU supported)	*/



	/*----------------------------------------------*/
	/* Fixed encoding for REFUSE SPDU:		*/
	/* Session User Requirements PI:	 	*/
	/*	- duplex functional unit (FU) supported	*/
	/* COSP Version PI:				*/
	/*	- Version2 supported			*/
	/*----------------------------------------------*/

static ST_UCHAR cosp_rf_fixed [7] = {
			/* Session User Requirements PI:		*/
	20,		/*   PI code					*/
	2,		/*   PI len					*/
	0,		/*   bits 9-16 are 0				*/
	2,		/*   bits 1-8 (only bit2=1 duplex FU supported)	*/
			/* Version Number PI:				*/
	22,		/*   PI code					*/
	1,		/*   PI len					*/
	COSP_VER2};	/*   we supporting Version2			*/


static ST_UINT cosp_enc_len (ST_UINT16 len, ST_UCHAR *buf);


/************************************************************************/
/*			cosp_envelope_len 				*/
/*----------------------------------------------------------------------*/
/* Function to compute the number of envelope bytes needed to encode	*/
/* a SPDU. The returned length does not include the SS-user data length.*/
/* 									*/
/* Parameters:								*/
/*  ACSE_CONN   *con		Connection info parameters		*/
/*  ST_UINT      rem_ssel_len 	Remote SSEL length			*/
/*  ST_UCHAR	 spdu_type	One of COSP_SI_... from cosp.h		*/
/*	  								*/
/* Return:								*/
/*  ST_UINT     		Length of SPDU envelope encoding	*/
/************************************************************************/
ST_UINT cosp_envelope_len (ACSE_CONN *con, ST_UINT rem_ssel_len, ST_UCHAR spdu_type)
{
ST_UINT enc_len;
ST_UINT udata_len;

  udata_len = con->ppdu_len;
  enc_len = 0;

  switch (spdu_type)
    {
    case COSP_SI_CONNECT:
      enc_len =
        2+6					/* Connect/Accept PGI	*/
      + 2+2					/* Ses User Requirem. PI*/
      + (cosp_only_ssel[0] != 0 ? 2+cosp_only_ssel[0] : 0)/* Calling SSEL*/
      + (rem_ssel_len != 0 ? 2+rem_ssel_len : 0)/* Called  SSEL		*/
      + (udata_len > 0     ? 2 : 0)		/* 1 PI code, 1 len	*/
      + (udata_len > 254   ? 2 : 0);		/* add 2 bytes for len	*/
    break;

    case COSP_SI_ACCEPT:
      enc_len =
        2+6					/* Connect/Accept PGI	*/
      + 2+2					/* Ses User Requirem. PI*/
      + (udata_len > 0    ? 2 : 0)		/* 1 PI code, 1 len	*/
      + (udata_len > 254  ? 2 : 0);		/* add 2 bytes for len	*/
    break;

    case COSP_SI_REFUSE:
      enc_len = 
        2+2					/* Ses User Requirem. PI*/
      + 2+1					/* Supported Version PI	*/
      + 2+1					/* 1 PI code, 1 len, 1 Reason Code*/
      + (udata_len > 254  ? 2 : 0);		/* add 2 bytes for len */
    break;

    case COSP_SI_FINISH:
    case COSP_SI_DISCON:
      enc_len =
        (udata_len > 0    ? 2 : 0)		/* 1 PI code, 1 len	*/
      + (udata_len > 254  ? 2 : 0);		/* addl 2 bytes for len	*/
    break;

    case COSP_SI_ABORT:
      enc_len =
        2+1					/* TP Disconnect PI	*/
      + (udata_len > 0    ? 2 : 0)		/* 1 PI code, 1 len	*/
      + (udata_len > 254  ? 2 : 0);		/* add 2 bytes for len	*/
    break;

    case COSP_SI_DATA:
      /* We send Give Token SPDU concatinated with the DT (basic concatination)	*/
      enc_len = 2;	/* (SI=01,LI=0) token functionality not used	*/
    break;

    default:
      COSP_LOG_ERR1 ("COSP-ERROR: Encoding: Invalid PDU type = %d", spdu_type);
    break;
    }

  /* add bytes for params len (none in DT) */
  if (spdu_type == COSP_SI_DATA)
    /* in DT we do not send any parameters but we have to send the LI=0	*/
    enc_len += 1;			/* 1 byte for len	*/
  else
    {
    /* all udata is encoded in a parameter */
    if (enc_len + udata_len > 254)
      enc_len += 3;			/* 3 bytes for len	*/
    else
      enc_len += 1;			/* 1 byte for len	*/
    }

  /* add byte for SPDU code */
  enc_len += 1;

  return (enc_len);
}


/************************************************************************/
/*			cosp_enc_cn_ac					*/
/*----------------------------------------------------------------------*/
/* Function to encode a CONNECT or ACCEPT SPDU.				*/
/* This function assumed that there is enough place in the enc_buf for	*/
/* the CN or AC SPDU encoding. The function cosp_envelope_len can be	*/
/* used to compute exact envelope encoding length.			*/
/* Note that this function assumes that the SS-user data (CP / CPA PPDU)*/
/* has been already copied into the enc_buf in proper position.		*/
/* 									*/
/* Parameters:								*/
/*  ACSE_CONN	*con		Connection info parameters		*/
/*  PRES_ADDR   *rem_addr	Remote Address (needed only for CN)	*/
/*  char       **spdu_ptr	Pointer where to return pointer to SPDU	*/
/*  ST_UINT	*spdu_len	Pointer where to return the SPDU len	*/
/*  ST_UCHAR 	 spdu_type	COSP_SI_CONNECT or COSP_SI_ACCEPT	*/
/*	  								*/
/* Return:								*/
/*	SD_SUCCESS (0)		if successful				*/
/*	error code		otherwise				*/
/************************************************************************/
ST_RET cosp_enc_cn_ac (ACSE_CONN *con, PRES_ADDR *rem_addr,
			char **spdu_ptr, ST_UINT *spdu_len,
                        ST_UCHAR spdu_type)
{
ST_UINT	envelope_len;
ST_UINT	udata_len;
ST_UINT	udata_max_len;
ST_UCHAR		ssel_len;
ST_UCHAR          *ssel;
ST_UCHAR	       *enc_buf;
ST_UINT	enc_len;
ST_UINT  	idx;

  /*------------------------------------------------------------*/
  /* make sure data len is OK (User Data presence is mandatory)	*/
  /*------------------------------------------------------------*/
  udata_len = con->ppdu_len;
  if (rem_addr)
    envelope_len  = cosp_envelope_len (con, rem_addr->ssel_len, spdu_type);
  else
    envelope_len  = cosp_envelope_len (con, 0, spdu_type);

  if (spdu_type == COSP_SI_CONNECT)
    udata_max_len = COSP_MAX_UDATA_CON;
  else
    udata_max_len = COSP_MAX_UDATA;		/* for ACCEPT SPDU	*/
  if (udata_len == 0 || udata_len > udata_max_len)
    {
    COSP_LOG_ERR2 ("COSP-ERROR: Encoding CN/AC: Invalid User Data length=%u (0<length<=%u).",
      udata_len, udata_max_len);
    return (COSP_ERR_INV_UDATA_LEN);
    }

  /* set the pointer to beginning of encoding in the buffer (global buf)*/
  enc_buf = con->ppdu_ptr - envelope_len;
  if (enc_buf < cosp_buf)
    {
    COSP_LOG_ERR0 ("COSP-ERROR: Encoding CN/AC: Invalid pointer to Global Encoding Buffer.");
    return (COSP_ERR_INV_POINTER);
    }
  idx = 0;

  /*--------------------------------------------*/
  /* Encode CN or AC code and total SPDU len	*/
  /*--------------------------------------------*/
  /* SPDU length to encode does not include 1 byte for SPDU code and	*/
  /* 1 or 3 bytes for total len 					*/

  if (envelope_len-2 + udata_len <= 254)
    enc_len = envelope_len-2 + udata_len;	/* len enc on 1 byte	*/
  else
    enc_len = envelope_len-4 + udata_len;	/* len enc on 3 bytes	*/

  enc_buf [idx++] = spdu_type;
  idx += cosp_enc_len ((ST_UINT16) enc_len, &enc_buf [idx]);

  /*--------------------------------------------*/
  /* no Connection Identifier PGI encoded 	*/
  /*--------------------------------------------*/

  /*--------------------------------------------*/
  /* encode Connect/Accept PGI:			*/
  /*	- extended concatination not supported,	*/
  /*	- COSP Version2 supported		*/
  /* encode Session User Requirements PI: 	*/
  /*	- duplex functional unit (FU) supported	*/
  /*--------------------------------------------*/
  memcpy (&enc_buf [idx], cosp_cn_ac_fixed, sizeof (cosp_cn_ac_fixed));
  idx += sizeof (cosp_cn_ac_fixed);

  /*----------------------------------------------*/
  /* encode Calling SSEL - (CN only)              */
  /*----------------------------------------------*/
  ssel_len = 0;
  ssel = NULL;		/* Just to avoid "uninitialized" warning.	*/
  if (spdu_type == COSP_SI_CONNECT)
    {
    /* Calling SSEL - optional (only if needed)	*/
    ssel_len =  cosp_only_ssel [0];
    ssel     = &cosp_only_ssel [1];
    }
  if (ssel_len > 0)
    {
    enc_buf [idx++] = 51;			/* encode PI code	*/
    enc_buf [idx++] = ssel_len;			/* encode PI len	*/
    memcpy (&enc_buf [idx], ssel, (ST_UINT) ssel_len);
    idx += ssel_len;
    }

  /*------------------------------------*/
  /* encode Called/Responding SSEL (CN only)	*/
  /*------------------------------------*/
  ssel_len = 0;
  ssel = NULL;		/* Just to avoid "uninitialized" warning.	*/
  if (spdu_type == COSP_SI_CONNECT  &&  rem_addr != NULL)
    {
    /* Called SSEL - mandatory */
    ssel_len = (ST_UCHAR)   rem_addr->ssel_len;
    ssel     = (ST_UCHAR *) rem_addr->ssel;
    }
  if (ssel_len > 0)
    {
    enc_buf [idx++] = 52;     			/* PI code	*/
    enc_buf [idx++] = ssel_len;			/* PI len	*/
    memcpy (&enc_buf [idx], ssel, (ST_UINT) ssel_len);
    idx += ssel_len;
    }

  /*--------------------------------------------------------------------*/
  /* encode User Data (length only), SS-user Data should be already	*/
  /* in the enc_buf (in proper position).				*/
  /*--------------------------------------------------------------------*/
  if (spdu_type == COSP_SI_CONNECT)
    {
    if (udata_len <= 512)
      enc_buf [idx++] = 193;		/* encode PGI code		*/
    else
      enc_buf [idx++] = 194;		/* if 512 < udata_len <= 10240)*/
    }
  else
    {
    /* ACCEPT SPDU */
    enc_buf [idx++] = 193;		/* encode PGI code	*/
    }
  idx += cosp_enc_len ((ST_UINT16) udata_len, &enc_buf [idx]);
  /* udata should be already in enc_buf */


  /*-----------------------------------------------*/
  /* set values to be returned to calling function */
  /*-----------------------------------------------*/
  *spdu_len = envelope_len + udata_len;
  *spdu_ptr = (char *) enc_buf;

  return (SD_SUCCESS);
}


/************************************************************************/
/*			cosp_enc_rf					*/
/*----------------------------------------------------------------------*/
/* Function to encode a REFUSE SPDU.					*/
/* This function assumed that there is enough place in the enc_buf for	*/
/* the RF SPDU encoding. The function cosp_envelope_len can be used	*/
/* to compute exact envelope encoding length.				*/
/* Note that this function assumes that the SS-user data (refuse reason)*/
/* has been already copied into the enc_buf in proper position.		*/
/* 									*/
/* Parameters:								*/
/*  ACSE_CONN	*con		Connection info parameters		*/
/*  charE      **spdu_ptr	Pointer where to return pointer to SPDU	*/
/*  ST_UINT	*spdu_len	Pointer where to return the SPDU len	*/
/*  ST_UCHAR	 reason		Reason  code for refuse			*/
/*	  								*/
/* Return:								*/
/*	SD_SUCCESS (0)		if successful				*/
/*	error code		otherwise				*/
/************************************************************************/
ST_RET cosp_enc_rf (ACSE_CONN *con, char **spdu_ptr, ST_UINT *spdu_len,
                     ST_UCHAR reason)
{
ST_UINT	envelope_len;
ST_UINT	udata_len;
ST_UCHAR	       *enc_buf;
ST_UINT	enc_len;
ST_UINT  	idx;

  /*--------------------------------------------*/
  /* make sure data len is OK			*/
  /*--------------------------------------------*/
  udata_len = con->ppdu_len;
  envelope_len  = cosp_envelope_len (con, 0, COSP_SI_REFUSE);

  if (udata_len > COSP_MAX_UDATA)
    {
    COSP_LOG_ERR2 ("COSP-ERROR: Encoding RF: Invalid User Data length=%u (length<=%u).",
      udata_len, COSP_MAX_UDATA);
    return (COSP_ERR_INV_UDATA_LEN);
    }
  /* set the pointer to beginning of encoding in the buffer (global buf)*/
  enc_buf = con->ppdu_ptr - envelope_len;
  if (enc_buf < cosp_buf)
    {
    COSP_LOG_ERR0 ("COSP-ERROR: Encoding RF: Invalid pointer to Global Encoding Buffer.");
    return (COSP_ERR_INV_POINTER);
    }

  idx = 0;

  /*------------------------------------*/
  /* Encode RF code and total SPDU len	*/
  /*------------------------------------*/
  /* SPDU length to encode does not include 1 byte for SPDU code and	*/
  /* 1 or 3 bytes for total len 					*/

  if (envelope_len-2 + udata_len <= 254)
    enc_len = envelope_len-2 + udata_len;	/* len enc on 1 byte	*/
  else
    enc_len = envelope_len-4 + udata_len;	/* len enc on 3 bytes	*/

  enc_buf [idx++] = COSP_SI_REFUSE;
  idx += cosp_enc_len ((ST_UINT16) enc_len, &enc_buf [idx]);

  /*--------------------------------------------*/
  /* no Connection Identifier PGI encoded 	*/
  /*--------------------------------------------*/

  /*--------------------------------------------*/
  /* encode Session User Requirements PI: 	*/
  /*	- duplex functional unit (FU) supported	*/
  /* encode COSP Version PI:			*/
  /*	- Version2 supported			*/
  /*--------------------------------------------*/
  memcpy (&enc_buf [idx], cosp_rf_fixed, sizeof (cosp_rf_fixed));
  idx += sizeof (cosp_rf_fixed);

  /*--------------------------------------------------------------------*/
  /* encode Reason Code. SS-user Data (if any) should be already in the	*/
  /* enc_buf (in proper position).					*/
  /*--------------------------------------------------------------------*/
  enc_buf [idx++] = 50;					/* PI code	*/
  idx += cosp_enc_len ((ST_UINT16) (udata_len+1), &enc_buf [idx]);	/* len	*/
  enc_buf [idx++] = reason;				/* Reason code	*/
  /* udata may follow if reason=COSP_RF_REASON_U_REJECT	*/

  /*-----------------------------------------------*/
  /* set values to be returned to calling function */
  /*-----------------------------------------------*/
  *spdu_len = envelope_len + udata_len;
  *spdu_ptr = (char *) enc_buf;

  return (SD_SUCCESS);
}


/************************************************************************/
/*			cosp_enc_fn_dn					*/
/*----------------------------------------------------------------------*/
/* Function to encode a FINISH or DISCONNECT SPDU.			*/
/* This function assumed that there is enough place in the enc_buf for	*/
/* the FN or DN SPDU encoding. The function cosp_envelope_len can be	*/
/* used to compute exact envelope encoding length.			*/
/* Note that this function assumes that the SS-user data (RLRQ or RLRE	*/
/* APDU) have been already copied into the enc_buf in proper position.	*/
/* 									*/
/* Parameters:								*/
/*  ACSE_CONN	*con		Connection info parameters		*/
/*  char       **spdu_ptr	Pointer where to return pointer to SPDU	*/
/*  ST_UINT	*spdu_len	Pointer where to return the SPDU len	*/
/*  ST_UCHAR	 spdu_type	COSP_SI_FINISH or COSP_SI_DISCON	*/
/*	  								*/
/* Return:								*/
/*	SD_SUCCESS (0)		if successful				*/
/*	error code		otherwise				*/
/************************************************************************/
ST_RET cosp_enc_fn_dn (ACSE_CONN *con, char **spdu_ptr, ST_UINT *spdu_len,
			ST_UCHAR spdu_type)
{
ST_UINT	envelope_len;
ST_UINT	udata_len;
ST_UCHAR	       *enc_buf;
ST_UINT	enc_len;
ST_UINT  	idx;

  /*------------------------------------------------------------*/
  /* make sure data len is OK (User Data mandatory)		*/
  /*------------------------------------------------------------*/
  udata_len = con->ppdu_len;
  envelope_len  = cosp_envelope_len (con, 0, spdu_type);

  if (udata_len == 0 || udata_len > COSP_MAX_UDATA)
    {
    COSP_LOG_ERR2 ("COSP-ERROR: Encoding FN/DN: Invalid User Data length=%u (0<length<=%u).",
      udata_len, COSP_MAX_UDATA);
    return (COSP_ERR_INV_UDATA_LEN);
    }

  /* set the pointer to beginning of encoding in the buffer (global buf)*/
  enc_buf = con->ppdu_ptr - envelope_len;
  if (enc_buf < cosp_buf)
    {
    COSP_LOG_ERR0 ("COSP-ERROR: Encoding FN/DN: Invalid pointer to Global Encoding Buffer.");
    return (COSP_ERR_INV_POINTER);
    }

  idx = 0;

  /*------------------------------------------*/
  /* Encode FN or DN code and total SPDU len  */
  /*------------------------------------------*/
  /* SPDU length to encode does not include 1 byte for FN or DN code	*/
  /* and 1 or 3 bytes for total len 					*/

  if (envelope_len-2 + udata_len <= 254)
    enc_len = envelope_len-2 + udata_len;	/* len enc on 1 byte	*/
  else
    enc_len = envelope_len-4 + udata_len;	/* len enc on 3 bytes	*/

  enc_buf [idx++] = spdu_type;
  idx += cosp_enc_len ((ST_UINT16) enc_len, &enc_buf [idx]);

  /*--------------------------------------------------------------------*/
  /* encode User Data (length only), SS-user Data should be already in	*/
  /* the enc_buf (in proper position).					*/
  /*--------------------------------------------------------------------*/
   enc_buf [idx++] = 193;				/* PI code	*/
   idx += cosp_enc_len ((ST_UINT16) udata_len, &enc_buf [idx]);

  /*-----------------------------------------------*/
  /* set values to be returned to calling function */
  /*-----------------------------------------------*/
  *spdu_len = envelope_len + udata_len;
  *spdu_ptr = (char *) enc_buf;

  return (SD_SUCCESS);
}


/************************************************************************/
/*			cosp_enc_u_ab					*/
/*----------------------------------------------------------------------*/
/* Function to encode a SS-user generated  ABORT SPDU			*/
/* This function assumed that there is enough place in the enc_buf for	*/
/* the AB SPDU encoding. The function cosp_envelope_len can be used	*/
/* to compute exact envelope encoding length.				*/
/* Note that this function assumes that the SS-user data (ARP /ATU PPDU)*/
/* has been already copied into the enc_buf in proper position.		*/
/* 									*/
/* Parameters:								*/
/*  ACSE_CON	*con		Connection info parameters		*/
/*  char      **spdu_ptr	Pointer where to return pointer to SPDU	*/
/*  ST_UINT	*spdu_len	Pointer where to return the SPDU len	*/
/*	  								*/
/* Return:								*/
/*	SD_SUCCESS (0)		if successful				*/
/*	error code		otherwise				*/
/************************************************************************/
ST_RET cosp_enc_u_ab (ACSE_CONN *con, char **spdu_ptr, ST_UINT *spdu_len)
{
ST_UINT	envelope_len;
ST_UINT	udata_len;
ST_UCHAR	       *enc_buf;
ST_UINT	enc_len;
ST_UINT  	idx;

  /*------------------------------------------------------------*/
  /* make sure data len is OK (depending on the reason the User	*/
  /* Data or the Reflect Parameter presence is mandatory)	*/
  /*------------------------------------------------------------*/
  udata_len = con->ppdu_len;
  envelope_len  = cosp_envelope_len (con, 0, COSP_SI_ABORT);

//envelope_len  = cosp_envelope_len (con, 0, COSP_SI_AB_ACCEPT);  //renxiaobao2022 mod

  

  if (udata_len == 0 || udata_len > COSP_MAX_UDATA)
    {
    COSP_LOG_ERR2 ("COSP-ERROR: Encoding U-AB: Invalid User Data length=%u (0<length<=%u).",
      udata_len, COSP_MAX_UDATA);
    return (COSP_ERR_INV_UDATA_LEN);
    }

  /* set the pointer to beginning of encoding in the buffer (global buf)*/
  enc_buf = con->ppdu_ptr - envelope_len;
  if (enc_buf < cosp_buf)
    {
    COSP_LOG_ERR0 ("COSP-ERROR: Encoding U-AB: Invalid pointer to Global Encoding Buffer.");
    return (COSP_ERR_INV_POINTER);
    }

  idx = 0;

  /*------------------------------------*/
  /* Encode AB code and total SPDU len  */
  /*------------------------------------*/
  /* SPDU length to encode does not include 1 byte for AB code and	*/
  /* 1 or 3 bytes for total len 					*/

  if (envelope_len-2 + udata_len <= 254)
    enc_len = envelope_len-2 + udata_len;	/* len enc on 1 byte	*/
  else
    enc_len = envelope_len-4 + udata_len;	/* len enc on 3 bytes	*/

    enc_buf [idx++] = COSP_SI_ABORT;

   //enc_buf [idx++] = COSP_SI_AB_ACCEPT;;  //renxiaobao2022 mod



  idx += cosp_enc_len ((ST_UINT16) enc_len, &enc_buf [idx]);

  /*----------------------------------------------------*/
  /* Encode Transport Disonnect PI (release TP conn)	*/
  /*----------------------------------------------------*/
  enc_buf [idx++] = 17;					/* PI code	*/
  enc_buf [idx++] = 1;					/* PI len	*/
  enc_buf [idx++] = COSP_TCONN_RELEASE | COSP_AB_REASON_USER_ABORT;

  /*--------------------------------------------------------------------*/
  /* encode User Data (length only), SS-user Data should be already	*/
  /* in the enc_buf (in proper position).				*/
  /*--------------------------------------------------------------------*/
  if (udata_len > 0)
    {
    /* encode User Data	*/
    enc_buf [idx++] = 193;				/* PGI code	*/
    idx += cosp_enc_len ((ST_UINT16) udata_len, &enc_buf [idx]);
    /* udata should be already in enc_buf */
    }

  /*-----------------------------------------------*/
  /* set values to be returned to calling function */
  /*-----------------------------------------------*/
  *spdu_len = envelope_len + udata_len;
  *spdu_ptr = (char *) enc_buf;

  return (SD_SUCCESS);
}

/************************************************************************/
/*			cosp_enc_p_ab					*/
/*----------------------------------------------------------------------*/
/* Function to encode a SS-provider generated  ABORT SPDU		*/
/* This function assumed that there is enough place in the enc_buf for	*/
/* the AB SPDU encoding (COSP_P_AB_LEN bytes).				*/
/* 									*/
/* Parameters:								*/
/*  char       *spdu_ptr	Pointer to encode buffer for SPDU	*/
/*  ST_INT	err_code	This value will be passed for AB reason	*/
/*	  								*/
/* Return:								*/
/*	SD_SUCCESS (0)		if successful				*/
/*	error code		otherwise				*/
/************************************************************************/
ST_RET cosp_enc_p_ab (char *spdu_ptr, ST_INT err_code)
{

  /*------------------------------------*/
  /* Encode AB code and total SPDU len  */
  /*------------------------------------*/




  spdu_ptr [0] = COSP_SI_ABORT;
  spdu_ptr [1] = 3 + 4;

  


  /*----------------------------------------------------*/
  /* Encode Transport Disonnect PI (release TP conn)	*/
  /*----------------------------------------------------*/
  spdu_ptr [2] = 17;					/* PI code	*/
  spdu_ptr [3] = 1;					/* PI len	*/
  spdu_ptr [4] = COSP_TCONN_RELEASE | COSP_AB_REASON_PROT_ERROR;

  /* encode the Reflect Parameter PI */
  spdu_ptr [5] = 49;					/* PI code	*/
  spdu_ptr [6] = (ST_UCHAR) 2;				/* PI len (0-9)	*/
  spdu_ptr [7] = (ST_UCHAR) ((err_code >> 8) & 0x00FF);
  spdu_ptr [8] = (ST_UCHAR)  (err_code       & 0x00FF);

  /* !!! if number of encoded bytes changes make sure that the define	*/
  /* !!! COSP_P_AB_SPDU_LEN is changed accordingly.			*/

  return (SD_SUCCESS);
}


/************************************************************************/
/*			cosp_enc_dt					*/
/*----------------------------------------------------------------------*/
/* Function to encode a DATA SPDU					*/
/* This function assumed that there is enough place in the enc_buf for	*/
/* the GIVE-TOKEN ans DT SPDU encoding.					*/
/* The function cosp_envelope_len can be used to compute exact envelope	*/
/* encoding length.							*/
/* Note that this function assumes that the SS-user data have been	*/
/* already copied into the enc_buf in proper position.			*/
/* 									*/
/* Parameters:								*/
/*  ACSE_CON	*con		Connection info parameters		*/
/*  char       **spdu_ptr	Pointer where to return pointer to SPDU	*/
/*  ST_UINT	*spdu_len	Pointer where to return the SPDU len	*/
/*	  								*/
/* Return:								*/
/*	SD_SUCCESS (0)		if successful				*/
/*	error code		otherwise				*/
/************************************************************************/
ST_RET cosp_enc_dt (ACSE_CONN *con, char **spdu_ptr, ST_UINT *spdu_len)
{
ST_UINT	envelope_len;
ST_UINT	udata_len;
ST_UCHAR	       *enc_buf;
ST_UINT  	idx;

  /*------------------------------------------------------------*/
  /* make sure data len is OK 					*/
  /*------------------------------------------------------------*/
  udata_len     = con->ppdu_len;
  envelope_len  = cosp_envelope_len (con, 0, COSP_SI_DATA);

  if (udata_len == 0)
    {
    COSP_LOG_ERR2 ("COSP-ERROR: Encoding DT: Invalid User Data length=%u (0<length<=%u).",
      udata_len, COSP_MAX_UDATA);
    return (COSP_ERR_INV_UDATA_LEN);
    }

  /* set the pointer to beginning of encoding in the buffer (global buf)*/
  enc_buf = con->ppdu_ptr - envelope_len;
  if (enc_buf < cosp_buf)
    {
    COSP_LOG_ERR0 ("COSP-ERROR: Encoding DT: Invalid pointer to Global Encoding Buffer.");
    return (COSP_ERR_INV_POINTER);
    }

  idx = 0;

  /*--------------------------------------------*/
  /* Encode GIVE-TOKEN code and params len LI=0	*/
  /*--------------------------------------------*/

  enc_buf [idx++] = COSP_SI_GIVE_TOKEN;
  enc_buf [idx++] = 0;			/* no parameters present LI=0	*/

  /*------------------------------------*/
  /* Encode DT code and params len LI=0	*/
  /*------------------------------------*/

  enc_buf [idx++] = COSP_SI_DATA;
  enc_buf [idx++] = 0;			/* no parameters present LI=0	*/
  /* udata should be already in enc_buf */

  /*-----------------------------------------------*/
  /* set values to be returned to calling function */
  /*-----------------------------------------------*/
  *spdu_len = envelope_len + udata_len;
  *spdu_ptr = (char *) enc_buf;

  return (SD_SUCCESS);
}


/************************************************************************/
/*			cosp_enc_len					*/
/*----------------------------------------------------------------------*/
/* Function to encode a parameter's len. If len<=254 then 1 byte	*/
/* will be used to encode the length. If len>254 then 3 bytes will	*/
/* be used to encode the length.					*/
/* 									*/
/* Parameters:								*/
/*  ST_UINT16	  len		Parameter's length to encode		*/
/*  ST_UCHAR        *buf		Pointer where to encode the len		*/
/* 									*/
/* Return:								*/
/*  ST_UINT		Number of bytes used in encoding of len		*/
/************************************************************************/
static ST_UINT cosp_enc_len (ST_UINT16 len, ST_UCHAR *buf)
{
ST_UINT bytes;

  if (len <= 254)
    {
    buf [0] = (ST_UCHAR) len;
    bytes = 1;
    }
  else
    {
    buf [0] = (ST_UCHAR) 0xFF;			/* indicates len>254	*/
    buf [1] = (ST_UCHAR)((len >> 8) & 0x00FF);	/* high order byte	*/
    buf [2] = (ST_UCHAR) (len       & 0x00FF);	/* low order byte	*/
    bytes = 3;
    }

  return (bytes);
}

