.ad 8
.bm 8
.fm 4
.bt $Copyright by   Software AG, 1993$$Page %$
.tm 12
.hm 6
.hs 3
.tt 1 $NME$Project Distributed Database System$vos42oc$
.tt 2 $$$
.tt 3 $R.Roedling$create/extract/read/write remote sql_packets$1996-03-13$
***********************************************************
.nf


    ========== licence begin LGPL
    Copyright (C) 2002 SAP AG

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    ========== licence end

.fo
.nf
.sp
Module  : create/extract/read/write_remote_sql_packets
=========
.sp
Purpose :
.CM *-END-* purpose -------------------------------------
.sp
.cp 3
Define  :

.CM *-END-* define --------------------------------------
.sp;.cp 3
Use     :

.CM *-END-* use -----------------------------------------
.sp;.cp 3
Synonym :

.CM *-END-* synonym -------------------------------------
.sp;.cp 3
Author  : R.Roedling
.sp
.cp 3
Created : 23.3.93
.sp
.cp 3
Version :
.sp
.cp 3
Release :  6.2 	 Date : 1996-03-13
.br
.sp
***********************************************************
.sp
.cp 10
.fo
.oc _/1
Specification:

.CM *-END-* specification -------------------------------
.sp 2
***********************************************************
.sp
.cp 10
.fo
.oc _/1
Description:

.CM *-END-* description ---------------------------------
.sp 2
***********************************************************
.sp
.cp 10
.nf
.oc _/1
Structure:

.CM *-END-* structure -----------------------------------
.sp 2
**********************************************************
.sp
.cp 10
.nf
.oc _/1
.CM -lll-
Code    :
/*PRETTY*/

/*
 * INCLUDE FILES
 */


/*
 *  DEFINES
 */
#define MOD__  "VOS42OC : "
#define MF__   MOD__"UNDEFINED"

#define ARGID_PORT_NO           ('P')
#define ARGID_REM_PID           ('I')
#define ARGID_NODE              ('N')


/*
 *  MACROS
 */


/*
 *  LOCAL TYPE AND STRUCT DEFINITIONS
 */

typedef struct  old_rte_conn_packet_record
  {
  C2                              sMessCode;
  INT2                            ConnectLength;
  INT1                            ServiceType;
  INT1                            OSType;
  INT2                            MaxPacketSize;
  C8                              ServerDB;
  C8                              ClientDB;
  C256                            VarPart;
  } OLD_RTE_CONN_PACKET_REC;

typedef OLD_RTE_CONN_PACKET_REC   *POLD_RTE_CONN_PACKET_REC;


/*
 * EXTERNAL VARIABLES
 */


/*
 *  EXPORTED VARIABLES
 */


/*
 * LOCAL VARIABLES
 */


/*
 * LOCAL FUNCTION PROTOTYPES
 */
_INLINE ULONG  __sql42o_sndpkt         ( INT                  sd,
                                         POLD_RTE_HEADER_REC  pHeader,
                                         PCHAR                pPacket,
                                         ERRORTEXT            pErrText );

_INLINE ULONG  __sql42o_rcvpkt         ( INT                  sd,
                                         POLD_RTE_HEADER_REC  pHeader,
                                         PCHAR                pPacket,
                                         INT                  SwapType,
                                         INT                  MaxSegmentSize,
                                         ERRORTEXT            pErrText );

_INLINE ULONG  __sql42o_create_conpkt  ( PUCHAR               pucPacket,
                                         INT                  MessClass,
                                         INT4                 MyRef,
                                         INT4                 PeerRef,
                                         ULONG                ulCommState,
                                         SQL_SERVICE          Service,
                                         INT2                 MaxSegmentSize,
                                         SQL_DBNAMEC          szMyServerDB,
                                         SQL_DBNAMEC          szPeerServerDB,
                                         USHORT               usServicePort );

_INLINE ULONG  __sql42o_extract_conpkt ( PUCHAR               pucPacket,
                                         PINT                 pMessClass,
                                         PINT4                pMyRef,
                                         PINT4                pPeerRef,
                                         PSQL_SERVICE         pService,
                                         PINT2                pMaxSegmentSize,
                                         PINT                 pSwapType,
                                         SQL_DBNAMEC          szMyServerDB,
                                         SQL_DBNAMEC          szPeerServerDB,
                                         PID                  *pPID,
                                         PUSHORT              pusServicePort,
                                         ERRORTEXT            pErrText );


_INLINE VOID __sql42o_put_port_no   ( POLD_RTE_HEADER_REC      pRTEHeader,
                                      POLD_RTE_CONN_PACKET_REC pConnectPacket,
                                      USHORT                   usServicePort );
_INLINE VOID __sql42o_put_rem_pid   ( POLD_RTE_HEADER_REC      pRTEHeader,
                                      POLD_RTE_CONN_PACKET_REC pConnectPacket,
                                      PID                      pid );
_INLINE ULONG  __sql42o_get_rem_pid ( POLD_RTE_CONN_PACKET_REC pConnectPacket,
                                      PID                      *pPID );
_INLINE ULONG  __sql42o_get_port_no ( POLD_RTE_CONN_PACKET_REC pConnectPacket,
                                      PUSHORT                  pusServicePort );

/*
 * ========================== GLOBAL FUNCTIONS ================================
 */

ULONG  sql42o_send_conpkt ( INT                             sd,
                            ULONG                           ulMessClass,
                            ULONG                           ulMyRef,
                            ULONG                           ulPeerRef,
                            ULONG                           ulService,
                            ULONG                           ulMaxSegmentSize,
                            SQL_DBNAMEC                     szMyServerDB,
                            SQL_DBNAMEC                     szPeerServerDB,
                            USHORT                          usServicePort,
                            ULONG                           ulCommState,
                            ERRORTEXT                       pErrText )
  {
  #undef  MF__
  #define MF__ MOD__"sql42o_send_conpkt"
  LONG                            rc;
  INT                             BytesSend;
  UCHAR                           ucPacket[sizeof(OLD_RTE_HEADER_REC) +
                                           sizeof(OLD_RTE_CONN_PACKET_REC)];
  POLD_RTE_HEADER_REC             pRTEHeader;

  DBGIN;

  pRTEHeader = (POLD_RTE_HEADER_REC) &ucPacket[0];

  //
  // ---  Create connect packet.
  //
  ulCommState = __sql42o_create_conpkt ( ucPacket,
                                         (INT)ulMessClass,
                                         (INT4)ulMyRef,
                                         (INT4)ulPeerRef,
                                         ulCommState,
                                         (SQL_SERVICE)ulService,
                                         (INT2)ulMaxSegmentSize,
                                         szMyServerDB,
                                         szPeerServerDB,
                                         usServicePort );

  if ( ulCommState != SQLOK )
    return ( ulCommState );

  //
  // --- Send connect packet.
  //
  rc = sql40c_send_packet ( sd, (PCHAR) &ucPacket,
                            pRTEHeader->ActSendLen, &BytesSend );


  if ( rc != NO_ERROR )
    {
    MSGD (( ERR_CANT_SND_TO_SOCKET, rc ))
    sql46c_build_error_string ( pErrText, ERRMSG_COM_CANT_SND_TO_SOCKET, rc );

    DBGOUT;
    return ( SQLNOTOK );
    }


  if ( BytesSend != pRTEHeader->ActSendLen )
    {
    MSGD (( ERR_PACK_SEND_SIZE_ERROR, BytesSend ));
    sql46c_build_error_string ( pErrText, ERRMSG_COM_PACK_SEND_SIZE_ERROR, 0 );

    DBGOUT;
    return ( SQLNOTOK );
    }

  DBGOUT;
  return ( SQLOK );
  }

/*------------------------------*/

ULONG  sql42o_recv_conpkt ( INT                             sd,
                            PULONG                          pulMessClass,
                            PULONG                          pulMyRef,
                            PULONG                          pulPeerRef,
                            PULONG                          pulService,
                            PULONG                          pulMaxSegmentSize,
                            PULONG                          pulSwapType,
                            SQL_DBNAMEC                     szMyServerDB,
                            SQL_DBNAMEC                     szPeerServerDB,
                            PID                             *pPID,
                            PUSHORT                         pusServicePort,
                            ERRORTEXT                       pErrText )
  {
  #undef  MF__
  #define MF__ MOD__"sql42o_recv_conpkt"
  INT                             BytesRec;
  LONG                            rc;
  POLD_RTE_CONN_PACKET_REC        pConnectPacket;
  UCHAR                           ucPacket[sizeof(OLD_RTE_HEADER_REC) +
                                           sizeof(OLD_RTE_CONN_PACKET_REC)];
  ULONG                           ulCommState;

  DBGIN;

  //
  // ---  Receive connect packet.
  //
  rc = sql40c_recv_packet ( sd, ucPacket, sizeof(ucPacket), &BytesRec );

  if ( rc != NO_ERROR )
    {
    MSGD (( ERR_CONN_PACKET_REC_ERR, rc ))
    sql46c_build_error_string ( pErrText, ERRMSG_COM_CONN_PACKET_REC_ERR, rc );

    DBGOUT;
    return ( SQLNOTOK );
    }

  if ( BytesRec == 0 )
    {
    MSGD (( ERR_CONN_SERV_REJECT ))
    sql46c_build_error_string ( pErrText, ERRMSG_COM_CONN_SERV_REJECT, 0 );

    DBGOUT;
    return ( SQLNOTOK );
    }

  pConnectPacket = (POLD_RTE_CONN_PACKET_REC)
                                      &ucPacket[sizeof(OLD_RTE_HEADER_REC)];

  if ( BytesRec <  sizeof (ucPacket) - sizeof (pConnectPacket->VarPart))
    {
    MSGD (( ERR_CONN_PACKET_GARBLED, BytesRec ))
    sql46c_build_error_string ( pErrText, ERRMSG_COM_CONN_PACKET_GARBLED, 0 );

    DBGOUT;
    return ( SQLNOTOK );
    }

  *pulMessClass       = 0;
  *pulMyRef           = 0;
  *pulPeerRef         = 0;
  *pulService         = 0;
  *pulMaxSegmentSize  = 0;
  *pulSwapType        = 0;

  ulCommState = __sql42o_extract_conpkt ( ucPacket,
                                          (PINT)pulMessClass,
                                          (PINT4)pulMyRef,
                                          (PINT4)pulPeerRef,
                                          (PSQL_SERVICE)pulService,
                                          (PINT2)pulMaxSegmentSize,
                                          pulSwapType,
                                          szMyServerDB,
                                          szPeerServerDB,
                                          pPID,
                                          pusServicePort,
                                          pErrText );

  if ( ulCommState != SQLOK )
    return ( ulCommState );

  DBGOUT;
  return ( SQLOK );
  }

/*------------------------------*/

ULONG  sql42o_send_packet ( INT                             sd,
                            POLD_SQL_PACKET_REC             pSQLPacket,
                            ULONG                           ulMaxSegmentSize,
                            ULONG                           ulCommState,
                            ERRORTEXT                       pErrText )
  {
  #undef  MF__
  #define MF__ MOD__"sql42o_send_packet"
  ULONG                       ulCurrCommState;
  PCHAR                       pSrc;
  LONG                        lRemainingBytes;
  LONG                        lSendLn = 0;
  POLD_RTE_HEADER_REC         pHeader;

  DBGIN;

  pHeader = (POLD_RTE_HEADER_REC)pSQLPacket;

  if ( (ulMaxSegmentSize <= OLD_RTE_HEADER_SIZE) ||
       (ulMaxSegmentSize >  sizeof(OLD_SQL_PACKET_REC)) )
    {
    MSGD (( IERR_ILL_MAXSEGMENTSIZE, ulMaxSegmentSize ))
    sql46c_build_error_string ( pErrText, ERRMSG_COM_ILL_MAXSEGMENTSIZE, 0 );

    DBGOUT;
    return ( SQLNOTOK );
    }

  if ( (pHeader->MaxSendLen < OLD_RTE_HEADER_SIZE) ||
       (pHeader->MaxSendLen > sizeof(OLD_SQL_PACKET_REC)) )
    {
    MSGD (( IERR_ILL_PACK_SIZE, pHeader->MaxSendLen ))
    sql46c_build_error_string ( pErrText, ERRMSG_COM_ILL_PACKET_SIZE, 0 );

    DBGOUT;
    return ( SQLNOTOK );
    }

  //
  // --- Update RTE header.
  //
  pHeader->ProtocolID       = RSQL_RTE_PROT_TCP;
  pHeader->Filler           = 0;
  pHeader->RTEReturnCode    = (USHORT)ulCommState;

  if ( (ULONG)pHeader->MaxSendLen <= ulMaxSegmentSize )
    {
    pHeader->ResidualPackets  = 0;
    pHeader->ActSendLen       = pHeader->MaxSendLen;
    ulCurrCommState = __sql42o_sndpkt( sd, pHeader, (PCHAR) pSQLPacket,
                                       pErrText );
    }
  else
    {
    pSrc = ((PCHAR) pSQLPacket) + OLD_RTE_HEADER_SIZE;

    pHeader->ResidualPackets = ( pHeader->MaxSendLen - OLD_RTE_HEADER_SIZE ) /
                               ( ulMaxSegmentSize - OLD_RTE_HEADER_SIZE );


    for ( lRemainingBytes = pHeader->MaxSendLen - OLD_RTE_HEADER_SIZE;
          lRemainingBytes;
          lRemainingBytes -= lSendLn )
      {
      lSendLn             = min ( (LONG)(ulMaxSegmentSize-OLD_RTE_HEADER_SIZE),
                                  lRemainingBytes );
      pHeader->ActSendLen = lSendLn + OLD_RTE_HEADER_SIZE;

      ulCurrCommState = __sql42o_sndpkt ( sd, pHeader, (PCHAR) pSrc,
                                          pErrText );
      if ( ulCurrCommState != SQLOK )
        break;

      pSrc += lSendLn;
      pHeader->ResidualPackets--;
      }
    }

  DBGOUT;
  return ( ulCurrCommState ) ;
  }

/*------------------------------*/

ULONG  sql42o_recv_packet ( INT                             sd,
                            POLD_SQL_PACKET_REC             pSQLPacket,
                            ULONG                           ulSwapType,
                            ULONG                           ulMaxSegmentSize,
                            ERRORTEXT                       pErrText )
  {
  #undef  MF__
  #define MF__ MOD__"sql42o_recv_packet"
  ULONG                       ulCommState;
  PCHAR                       pDst;
  LONG                        lRemainingBytes;
  LONG                        lRecLn;
  LONG                        lMaxLen;
  POLD_RTE_HEADER_REC         pHeader;

  DBGIN;

  pHeader = (POLD_RTE_HEADER_REC)pSQLPacket;

  if ( (ulMaxSegmentSize <= OLD_RTE_HEADER_SIZE) ||
       (ulMaxSegmentSize >  sizeof(OLD_SQL_PACKET_REC)) )
    {
    MSGD (( IERR_ILL_MAXSEGMENTSIZE, ulMaxSegmentSize ))
    sql46c_build_error_string ( pErrText, ERRMSG_COM_ILL_MAXSEGMENTSIZE, 0 );

    DBGOUT;
    return ( SQLNOTOK );
    }

  ulCommState = __sql42o_rcvpkt ( sd, pHeader, (PCHAR) pSQLPacket,
                                  ulSwapType, (INT)ulMaxSegmentSize,
                                  pErrText );

  if ( ulCommState != SQLOK )
    return ( ulCommState );

  if ( (pHeader->MaxSendLen < OLD_RTE_HEADER_SIZE) ||
       (pHeader->MaxSendLen > sizeof(OLD_SQL_PACKET_REC)) )
    {
    MSGD (( ERR_PACKET_GARBLED, pHeader->MaxSendLen ))
    sql46c_build_error_string ( pErrText, ERRMSG_COM_PACKET_GARBLED, 0 );

    DBGOUT;
    return ( SQLNOTOK );
    }

  if ( pHeader->ResidualPackets )
    {
    pDst             = ((PCHAR) pSQLPacket) + OLD_RTE_HEADER_SIZE;
    pDst            += pHeader->ActSendLen - OLD_RTE_HEADER_SIZE;
    lMaxLen          = pHeader->MaxSendLen;
    lRemainingBytes  = lMaxLen - pHeader->ActSendLen;

    for ( ; pHeader->ResidualPackets > 0; )
      {
      lRecLn = min ( (LONG)(lRemainingBytes + OLD_RTE_HEADER_SIZE),
                     (LONG)ulMaxSegmentSize );

      ulCommState = __sql42o_rcvpkt ( sd, pHeader, pDst, (INT)ulSwapType,
                                      lRecLn, pErrText );

      if ( ulCommState != SQLOK )
        break;

      if ( pHeader->MaxSendLen != lMaxLen )
        break;

      lRecLn           = pHeader->ActSendLen - OLD_RTE_HEADER_SIZE;
      pDst            += lRecLn;
      lRemainingBytes -= lRecLn;
      }

    if ( ulCommState == SQLOK )
      {
      if ( pHeader->MaxSendLen != lMaxLen )
        {
        MSGD (( ERR_REC_NEW_MAXSENDLEN ))
        sql46c_build_error_string ( pErrText,  ERRMSG_COM_PACKET_GARBLED, 0 );

        DBGOUT;
        return ( SQLNOTOK );
        }

      if ( lRemainingBytes )
        {
        MSGD (( ERR_REC_MISSING_BYTES, lRemainingBytes ))
        sql46c_build_error_string ( pErrText,  ERRMSG_COM_PACKET_GARBLED, 0 );

        DBGOUT;
        return ( SQLNOTOK );
        }
      }

    pHeader->ActSendLen = pHeader->MaxSendLen;
    }

  DBGOUT;
  return ( SQLOK );
  }


/*------------------------------*/

ULONG  sql42o_unpack_int2 ( INT                             SwapTyp,
                            INT2                            Src,
                            INT2                            *pDst,
                            ERRORTEXT                       pErrText )
  {
  #undef  MF__
  #define MF__ MOD__"sql42o_unpack_int2"
  register PUCHAR puc;

  DBGPAS;

  puc = (PUCHAR) &Src;

  switch ( SwapTyp )
    {
    case 1:
          // --- no swap: hi-lo
          *pDst = ( puc[ 0 ] << 8 ) | ( puc[ 1 ] << 0 );
          break;
    case 2:
          // --- full swap: lo-hi
    case 3:
          // --- half swap: lo-hi
          *pDst = ( puc[ 0 ] << 0 ) | ( puc[ 1 ] << 8 );
          break;
    default:
          MSGD (( IERR_ILL_SWAP_TYPE, SwapTyp ));
          sql46c_build_error_string ( pErrText, ERRMSG_ILL_SWAP_TYPE, 0 );
          *pDst = 0;
          return ( SQLNOTOK );
    }

  return ( SQLOK );
  }



/*
 * ========================== LOCAL FUNCTIONS =================================
 */

_INLINE ULONG  __sql42o_sndpkt ( INT                   sd,
                                 POLD_RTE_HEADER_REC  pHeader,
                                 PCHAR                pPacket,
                                 ERRORTEXT            pErrText )
  {
  #undef  MF__
  #define MF__ MOD__"__sql42o_sndpkt"
  LONG                            rc;
  INT                             BytesSend;
  INT                             Len;
  PCHAR                           pData;
  OLD_SQL_PACKET_REC              SQLPacket;

  DBGIN;

  if ( (pPacket != (PCHAR) pHeader + OLD_RTE_HEADER_SIZE) &&
       (pPacket != (PCHAR) pHeader) )
    {
    // --- concatenate header and data
    memcpy ( (PCHAR) &SQLPacket, pHeader, OLD_RTE_HEADER_SIZE );
    memcpy ( (PCHAR) &SQLPacket + OLD_RTE_HEADER_SIZE,
            pPacket, pHeader->ActSendLen - OLD_RTE_HEADER_SIZE );

    pData = (PCHAR) &SQLPacket;
    Len   = SQLPacket.ActSendLen;
    }
  else
    {
    pData = (PCHAR) pHeader;
    Len   = pHeader->ActSendLen;
    }


  for (BytesSend = 0; Len > 0; pData += BytesSend, Len -= BytesSend )
    {
    rc = sql40c_send_packet ( sd, pData, (INT2)Len, &BytesSend );

    if ( rc != NO_ERROR )
      {
      MSGD (( ERR_SOCKET_SND_ERR, rc ));
      sql46c_build_error_string ( pErrText, ERRMSG_COM_SOCKET_SND_ERROR, rc );

      // --- assuming TIMEOUT
      DBGOUT;
      return ( SQLTIMEOUT );
      }
    }

  DBGOUT;
  return ( SQLOK );
  }

/*------------------------------*/

_INLINE ULONG  __sql42o_rcvpkt ( INT                  sd,
                                 POLD_RTE_HEADER_REC  pHeader,
                                 PCHAR                pPacket,
                                 INT                  SwapType,
                                 INT                  MaxSegmentSize,
                                 ERRORTEXT            pErrText )
  {
  #undef  MF__
  #define MF__ MOD__"__sql42o_rcvpkt"
  LONG                            rc;
  INT                             BytesRec;
  INT                             Len;
  INT                             sLen;
  PCHAR                           pData;
  OLD_SQL_PACKET_REC              SQLPacket;

  DBGIN;

  pData = (PCHAR) &SQLPacket;
  sLen  = 0;
  Len   = MaxSegmentSize;

  for (BytesRec = 0; Len > 0; pData += BytesRec, Len -= BytesRec )
    {
    rc = sql40c_recv_packet ( sd, pData,
                              (INT2)(sLen ? Len :OLD_RTE_HEADER_SIZE - MaxSegmentSize + Len),&BytesRec );

    if ( rc != NO_ERROR )
      {
      MSGD (( ERR_SOCKET_REC_ERR, rc ));
      sql46c_build_error_string ( pErrText, ERRMSG_COM_SOCKET_REC_ERROR, rc );

      DBGOUT;
      return ( SQLNOTOK );
      }

    if ( BytesRec == 0 )
      {
      if ( (sLen != 0) || (Len != MaxSegmentSize) )
        {
        sql46c_build_error_string ( pErrText, ERRMSG_COM_CONN_BROCKEN, 0 );
        MSGD (( ERR_CONN_BROCKEN ));
        }
      else
        {
        sql46c_build_error_string ( pErrText,
                                    ERRMSG_COM_CONN_CLOSED_BY_COM_PART, 0 );
        DBGOUT;
        return ( SQLRELEASED );
        }

      DBGOUT;
      return ( SQLNOTOK );
      }

    //
    //  After the rte header is complete,
    //  we know exactly which size to receive.
    //
    if ( (sLen           == 0) &&
         (Len - BytesRec <= MaxSegmentSize - (INT)OLD_RTE_HEADER_SIZE) )
      {
      sql42o_unpack_int2 ( SwapType, SQLPacket.ActSendLen,
                           (PINT2) &sLen, pErrText );

      if ( sLen > MaxSegmentSize ) break;

      Len -= MaxSegmentSize - sLen;
      }
    }

  if ( sLen > MaxSegmentSize )
    {
    MSGD (( ERR_ILL_PACKET_SIZE, SQLPacket.ActSendLen ));
    sql46c_build_error_string ( pErrText, ERRMSG_COM_PACKET_GARBLED, 0 );
    return ( SQLNOTOK );
    }

  sql42o_unpack_int2 ( SwapType, SQLPacket.ActSendLen,
                       &SQLPacket.ActSendLen, pErrText );

  sql42o_unpack_int2 ( SwapType, SQLPacket.MaxSendLen,
                       &SQLPacket.MaxSendLen, pErrText );

  sql42o_unpack_int2 ( SwapType, SQLPacket.RTEReturnCode,
                       &SQLPacket.RTEReturnCode, pErrText );


  if ( (pPacket != (PCHAR) pHeader + OLD_RTE_HEADER_SIZE) &&
       (pPacket != (PCHAR) pHeader) )
    {
    memcpy ( pHeader, (PCHAR) &SQLPacket, OLD_RTE_HEADER_SIZE );
    memcpy ( pPacket, (PCHAR) &SQLPacket + OLD_RTE_HEADER_SIZE,
             SQLPacket.ActSendLen - OLD_RTE_HEADER_SIZE );
    }
  else
    memcpy ( pHeader, (PCHAR) &SQLPacket, SQLPacket.ActSendLen );


  DBGOUT;
  return ( pHeader->RTEReturnCode );
  }

/*------------------------------*/

_INLINE ULONG  __sql42o_create_conpkt ( PUCHAR              pucPacket,
                                        INT                 MessClass,
                                        INT4                MyRef,
                                        INT4                PeerRef,
                                        ULONG               ulCommState,
                                        SQL_SERVICE         Service,
                                        INT2                MaxSegmentSize,
                                        SQL_DBNAMEC         szMyServerDB,
                                        SQL_DBNAMEC         szPeerServerDB,
                                        USHORT              usServicePort )
  {
  #undef  MF__
  #define MF__ MOD__"__sql42o_create_conpkt"
  INT                             i;
  union map_check_i4_b4           MapCheck;
  POLD_RTE_HEADER_REC             pRTEHeader;
  POLD_RTE_CONN_PACKET_REC        pConnectPacket;
  static PID                      Pid            = (PID)UNDEF;


  DBGIN;

  if ( Pid == (PID)UNDEF )
    GETPROCESSID (&Pid);

  pRTEHeader     = (POLD_RTE_HEADER_REC) &pucPacket[0];
  pConnectPacket = (POLD_RTE_CONN_PACKET_REC)
                                        &pucPacket[sizeof(OLD_RTE_HEADER_REC)];

  /*
   *  Create connect packet header.
   */
  pRTEHeader->ActSendLen       = sizeof(OLD_RTE_HEADER_REC) +
                                 sizeof(OLD_RTE_CONN_PACKET_REC) -
                                 sizeof (pConnectPacket->VarPart);
  pRTEHeader->MaxSendLen       = pRTEHeader->ActSendLen;
  pRTEHeader->ProtocolID       = RSQL_RTE_PROT_TCP;
  pRTEHeader->MessClass        = MessClass;
  pRTEHeader->RTEFlags         = RSQL_NORMAL;
  pRTEHeader->ResidualPackets  = 0;
  pRTEHeader->SenderRefID      = MyRef;
  pRTEHeader->ReceiverRefID    = PeerRef;
  pRTEHeader->RTEReturnCode    = (INT2)ulCommState;
  pRTEHeader->Filler           = 0;

  i = ' ';
  if ( i == 32 )
    pConnectPacket->sMessCode[ 0 ] = 0;
  else
    pConnectPacket->sMessCode[ 0 ] = 1;

  MapCheck.int4 = 65536;
  for ( i = 0; (i < 4) && ( MapCheck.c4[ i ] != 1 ); i++ ) { ; }

  pConnectPacket->sMessCode[ 1 ] = i;
  pConnectPacket->ConnectLength  = sizeof (*pConnectPacket) -
                                   sizeof (pConnectPacket->VarPart);
  pConnectPacket->ServiceType    = Service;
  pConnectPacket->OSType         = RSQL_OS2_OS;
  pConnectPacket->MaxPacketSize  = MaxSegmentSize;

  sql47c_ctop ( pConnectPacket->ServerDB, szPeerServerDB,
                sizeof(pConnectPacket->ServerDB) );
  sql47c_ctop ( pConnectPacket->ClientDB, szMyServerDB,
                sizeof(pConnectPacket->ClientDB) );

   __sql42o_put_rem_pid ( pRTEHeader, pConnectPacket, Pid );
   __sql42o_put_port_no ( pRTEHeader, pConnectPacket, usServicePort );

  DBGOUT;
  return ( SQLOK );
  }

/*------------------------------*/

_INLINE ULONG  __sql42o_extract_conpkt ( PUCHAR              pucPacket,
                                         PINT                pMessClass,
                                         PINT4               pMyRef,
                                         PINT4               pPeerRef,
                                         PSQL_SERVICE        pService,
                                         PINT2               pMaxSegmentSize,
                                         PINT                pSwapType,
                                         SQL_DBNAMEC         szMyServerDB,
                                         SQL_DBNAMEC         szPeerServerDB,
                                         PID                 *pPID,
                                         PUSHORT             pusServicePort,
                                         ERRORTEXT           pErrText )
  {
  #undef  MF__
  #define MF__ MOD__"__sql42o_extract_conpkt"
  ULONG                           ulCommState = SQLOK;
  POLD_RTE_HEADER_REC             pRTEHeader;
  POLD_RTE_CONN_PACKET_REC        pConnectPacket;

  DBGPAS;

  pRTEHeader     = (POLD_RTE_HEADER_REC) &pucPacket[0];
  pConnectPacket = (POLD_RTE_CONN_PACKET_REC)
                                        &pucPacket[sizeof(OLD_RTE_HEADER_REC)];

  *pSwapType  = pConnectPacket->sMessCode[ 1 ];

  if ( sql42o_unpack_int2 ( *pSwapType, pRTEHeader->ActSendLen,
                            &pRTEHeader->ActSendLen,
                            pErrText ) != SQLOK )
    return ( SQLNOTOK );

  if ( sql42o_unpack_int2 ( *pSwapType, pRTEHeader->MaxSendLen,
                            &pRTEHeader->MaxSendLen,
                            pErrText ) != SQLOK )
    return ( SQLNOTOK );

  if ( sql42o_unpack_int2 ( *pSwapType, pRTEHeader->RTEReturnCode,
                            &pRTEHeader->RTEReturnCode,
                            pErrText ) != SQLOK )
    return ( SQLNOTOK );

  if ( sql42o_unpack_int2 ( *pSwapType, pConnectPacket->ConnectLength,
                            &pConnectPacket->ConnectLength,
                            pErrText ) != SQLOK )
    return ( SQLNOTOK );

  if ( sql42o_unpack_int2 ( *pSwapType, pConnectPacket->MaxPacketSize,
                            &pConnectPacket->MaxPacketSize,
                            pErrText ) != SQLOK )
    return ( SQLNOTOK );

  *pMessClass      = pRTEHeader->MessClass;
  *pMyRef          = pRTEHeader->ReceiverRefID;
  *pPeerRef        = pRTEHeader->SenderRefID;
  ulCommState      = (ULONG)pRTEHeader->RTEReturnCode;

  *pService        = pConnectPacket->ServiceType;
  *pMaxSegmentSize = pConnectPacket->MaxPacketSize;

  sql47c_ptoc ( szMyServerDB  , pConnectPacket->ServerDB,
                sizeof(pConnectPacket->ServerDB) );
  sql47c_ptoc ( szPeerServerDB, pConnectPacket->ClientDB,
                sizeof(pConnectPacket->ClientDB) );

  __sql42o_get_rem_pid ( pConnectPacket, pPID );
  __sql42o_get_port_no ( pConnectPacket, pusServicePort );


  return ( ulCommState );
  }

/*------------------------------*/

/*
 *  Here, we have some functions which use the var_part of the connect
 *  packet. The var_part can contain several information and is
 *  structured as follows:
 *
 *  var_part: [argument][argument]...
 *
 *  Each argument is structured as follows:
 *
 *  argument: |length|id|information|
 *
 *            'length'      is a one byte integer.
 *                          It includes the length and id-bytes.
 *            'id'          is a one byte character
 *            'information' is coded argument dependent
 *
 *  Example:
 *
 *      var_part: 04 50 1b 58 06 49 31 32 33 00 (hexadecimal)
 *                ^  ^  ^     ^  ^  ^
 *                |  |  |     |  |  |
 *                |  |  |     |  |  NUL terminated string ("123")
 *                |  |  |     |  Argument id 'I' for remote pid
 *                |  |  |     Argument length (6 bytes: length,id,string,\0)
 *                |  |  |
 *                |  |  TCP/IP port number (0x1b58)
 *                |  Argument id 'P' for TCP/IP port number
 *                Argument length (4 bytes: length,id,port number)
 *
 *  There is no terminator for the VarPart since the length of the
 *  connect packet includes the VarPart and thus specifies its length.
 */

_INLINE ULONG  __sql42o_get_port_no( POLD_RTE_CONN_PACKET_REC pConnectPacket,
                                     PUSHORT                     pusServicePort )
  {
  #undef  MF__
  #define MF__ MOD__"__sql42o_get_port_no"
  ULONG           ulLength;
  ULONG           ulPos;

  DBGIN;

  ulLength = pConnectPacket->ConnectLength  -
             ( sizeof (*pConnectPacket) - sizeof (pConnectPacket->VarPart) );

  ulLength = min ( ulLength, sizeof (pConnectPacket->VarPart) );

  for ( ulPos =  0;
        ulPos <  ulLength;
        ulPos += pConnectPacket->VarPart[ulPos] & 0xff )
    {
    if ( ( pConnectPacket->VarPart[ulPos] & 0xff ) < 2 )
      {
      DBGOUT;
      return ( SQLNOTOK );
      }

    if ( pConnectPacket->VarPart[ulPos + 1] == ARGID_PORT_NO )
      {
      if ( ( pConnectPacket->VarPart[ulPos] & 0xff ) != 4 )
        {
        MSGD (( WRN_ILL_ARG_LENGTH, pConnectPacket->VarPart[ulPos] & 0xff ));
        DBGOUT;
        return ( SQLNOTOK );
        }
      break;
      }
    }

  if ( ulPos >= ulLength )
    {
    // --- no port number found!
    DBGOUT;
    return ( SQLNOTOK );
    }

  *pusServicePort  = (USHORT)(pConnectPacket->VarPart[ulPos + 2] & 0xff) << 8;
  *pusServicePort |= (USHORT)(pConnectPacket->VarPart[ulPos + 3] & 0xff);

  DBGOUT;
  return ( SQLOK );
  }

/*------------------------------*/

_INLINE ULONG  __sql42o_get_rem_pid( POLD_RTE_CONN_PACKET_REC pConnectPacket,
                                     PID                         *pPID )
  {
  #undef  MF__
  #define MF__ MOD__"__sql42o_get_rem_pid"
  ULONG           ulLength;
  ULONG           ulPos;
  ULONG           ulStrLen;

  DBGIN;

  ulLength = pConnectPacket->ConnectLength  -
             ( sizeof (*pConnectPacket) - sizeof (pConnectPacket->VarPart) );

  ulLength = min ( ulLength, sizeof (pConnectPacket->VarPart) );

  for ( ulPos =  0;
        ulPos <  ulLength;
        ulPos += pConnectPacket->VarPart[ulPos] & 0xff )
    {
    if ( ( pConnectPacket->VarPart[ulPos] & 0xff ) < 2 )
      {
      DBGOUT;
      return ( SQLNOTOK );
      }

    if ( pConnectPacket->VarPart[ulPos + 1] == ARGID_REM_PID )
      {
      ulStrLen = pConnectPacket->VarPart[ulPos] & 0xff;

      if ( ( ulStrLen < 4 ) ||
           ( pConnectPacket->VarPart[ulPos + ulStrLen - 1 ] != '\0' ))
        {
        MSGD (( WRN_ILL_ARG_LENGTH, pConnectPacket->VarPart[ulPos] & 0xff ));
        DBGOUT;
        return ( SQLNOTOK );
        }
      break;
      }
    }

  if ( ulPos >= ulLength )
    {
    // --- no pid found!
    DBGOUT;
    return ( SQLNOTOK );
    }

  *pPID = (PID)atol( pConnectPacket->VarPart + ulPos + 2 );

  DBGOUT;
  return ( SQLOK );
  }

/*------------------------------*/

_INLINE VOID __sql42o_put_port_no ( POLD_RTE_HEADER_REC         pRTEHeader,
                                    POLD_RTE_CONN_PACKET_REC pConnectPacket,
                                    USHORT                      usServicePort )
  {
  #undef  MF__
  #define MF__ MOD__"__sql42o_put_port_no"
  ULONG           ulPos;

  DBGIN;

  ulPos  = pConnectPacket->ConnectLength  -
           ( sizeof (*pConnectPacket) - sizeof (pConnectPacket->VarPart) );

  pConnectPacket->VarPart[ulPos]     = 4;
  pConnectPacket->VarPart[ulPos + 1] = ARGID_PORT_NO;
  pConnectPacket->VarPart[ulPos + 2] = ( usServicePort >> 8 & 0xFF ); // - high byte
  pConnectPacket->VarPart[ulPos + 3] = ( usServicePort      & 0xFF ); // - low  byte

  pConnectPacket->ConnectLength  += 4;
  pRTEHeader->ActSendLen         += 4;
  pRTEHeader->MaxSendLen         += 4;

  DBGOUT;
  return;
  }

/*------------------------------*/

_INLINE VOID __sql42o_put_rem_pid ( POLD_RTE_HEADER_REC         pRTEHeader,
                                    POLD_RTE_CONN_PACKET_REC pConnectPacket,
                                    PID                         pid )
  {
  #undef  MF__
  #define MF__ MOD__"__sql42o_put_rem_pid"
  USHORT          usLength;
  ULONG           ulPos;

  DBGIN;

  ulPos  = pConnectPacket->ConnectLength  -
           ( sizeof (*pConnectPacket) - sizeof (pConnectPacket->VarPart) );

  _ultoa ( pid, (PSZ)pConnectPacket->VarPart + ulPos + 2, 10 );
  usLength = (USHORT)strlen ( (PSZ)pConnectPacket->VarPart + ulPos + 2 ) + 3;

  pConnectPacket->VarPart[ulPos]      = (UCHAR)usLength;
  pConnectPacket->VarPart[ulPos + 1]  = ARGID_REM_PID;

  pConnectPacket->ConnectLength  += usLength;
  pRTEHeader->ActSendLen         += usLength;
  pRTEHeader->MaxSendLen         += usLength;

  DBGOUT;
  return;
  }

/*
 * =============================== END ========================================
 */
.CM *-END-* code ----------------------------------------
.SP 2
***********************************************************
