Files
microser/mmslib/ositcps/cosp_enc.c

813 lines
28 KiB
C
Raw Normal View History

2026-06-15 15:48:16 +08:00
/************************************************************************/
/* 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);
}