/*!
  @file           vos963.c
  @author         RaymondR
  @brief          Xserver - support for 6.1 applications
  @see            

\if EMIT_LICENCE

    ========== licence begin  GPL
    Copyright (c) 2000-2005 SAP AG

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

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

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



\endif
*/




/*===========================================================================*
 *  INCLUDES                                                                 *
 *===========================================================================*/
#define RTE_USE_SOCK

#include          <winerror.h>

#include         "heo46.h"
#include	     "geo007_1.h"
#include		 "geo43_0.h"
#include         "hos42.h"
#include		 "gos96.h"
#include		 "gos963.h"

/*===========================================================================*
 *  DEFINES                                                                  *
 *===========================================================================*/

#ifdef NO_INLINES
# define _INLINE
#else
# define _INLINE	__inline
#endif


#define MOD__  "VOS963.C : "
#define MF__   MOD__"UNDEFINED"

#define MAXTCPIPCONNECTIONS       2000
#define MIN_PACKET_SIZE           (2 * sizeof(OLD_SQL_PACKET_REC))
#define MIN_PACKET_DATA_LEN       (2 * sizeof(OLD_SQL_PACKET_REC) - \
                                   2 * OLD_RTE_HEADER_SIZE )

/*===========================================================================*
 *  MACROS                                                                   *
 *===========================================================================*/



/*===========================================================================*
 *  LOCAL CLASSES, STRUCTURES, TYPES, UNIONS ...                             *
 *===========================================================================*/

typedef struct sockaddr          sockaddr_type;


/*===========================================================================*
 *  GLOBAL VARIABLES                                                         *
 *===========================================================================*/

extern  GLOBAL_XSERVER_REC   gxr;


/*===========================================================================*
 *  LOCAL VARIABLES                                                          *
 *===========================================================================*/



/*===========================================================================*
 *  STATIC/INLINE FUNCTIONS (PROTOTYPES)                                     *
 *===========================================================================*/

ULONG        sql96o_open_lis_socket   ( VOID );
VOID _System sql96o_TCPIP_serv_thread ( ULONG                            ulConnInfoHandle );
ULONG        sql96o_request           ( POLD_TCPIP_SERV_CONNECT_INFO_REC pConnInfo );
ULONG        sql96o_cancel_dump       ( ULONG                            ulServerRef,
                                        PSZ                              pszServerDB,
                                        ULONG                            ulReqType );
ULONG        sql96o_transfer_new_db   ( POLD_TCPIP_SERV_CONNECT_INFO_REC pConnInfo );
ULONG        sql96o_transfer_old_db   ( POLD_TCPIP_SERV_CONNECT_INFO_REC pConnInfo );
ULONG        sql96o_set_sock_buf_sizes( teo00_Socket                     sd,
                                        ULONG                            ulMinSegmentSize,
                                        PULONG                           pulMaxSegmentSize );
ULONG   sql33o_connect     ( POLD_SHM_INFO_REC               pConnInfo,
                             ULONG                           ulApplicRef,
                             ULONG                           ulService,
                             PSZ                             pszServerDB,
                             PSECURITY_ATTRIBUTES            pWorldSA,
                             PSECURITY_ATTRIBUTES            pLockSA,
                             PULONG                          pulKernelRef,
                             PVOID                           *ppSQLPacket,
                             tsp00_ErrTextc                  pErrText,
                             ULONG                           ulTimeOut );
ULONG  sql33o_request      ( POLD_SHM_INFO_REC               pConnInfo,
                             tsp00_ErrTextc                  pErrText );
ULONG  sql33o_receive      ( POLD_SHM_INFO_REC               pConnInfo,
                             tsp00_ErrTextc                  pErrText );
ULONG  sql33o_cancel       ( POLD_SHM_INFO_REC               pConnInfo,
                             tsp00_ErrTextc                  pErrText );
ULONG  sql33o_release      ( POLD_SHM_INFO_REC               pConnInfo,
                             tsp00_ErrTextc                  pErrText );
ULONG  sql42o_send_conpkt  ( teo00_Socket                    sd,
                             ULONG                           ulMessClass,
                             ULONG                           ulMyRef,
                             ULONG                           ulPeerRef,
                             ULONG                           ulService,
                             ULONG                           ulMaxSegmentSize,
                             SQL_DBNAMEC                     szMyServerDB,
                             SQL_DBNAMEC                     szPeerServerDB,
                             USHORT                          usServicePort,
                             ULONG                           ulCommState,
                             tsp00_ErrTextc                  pErrText );
ULONG  sql42o_recv_conpkt  ( teo00_Socket                    sd,
                             PULONG                          pulMessClass,
                             PULONG                          pulMyRef,
                             PULONG                          pulPeerRef,
                             PULONG                          pulService,
                             PULONG                          pulMaxSegmentSize,
                             PULONG                          pulSwapType,
                             SQL_DBNAMEC                     szMyServerDB,
                             SQL_DBNAMEC                     szPeerServerDB,
                             PID                             *pPID,
                             PUSHORT                         pusServicePort,
                             tsp00_ErrTextc                  pErrText );
ULONG  sql42o_send_packet  ( teo00_Socket                    sd,
                             POLD_SQL_PACKET_REC             pSQLPacket,
                             ULONG                           ulMaxSegmentSize,
                             ULONG                           ulCommState,
                             tsp00_ErrTextc                  pErrText );
ULONG  sql42o_recv_packet  ( teo00_Socket                    sd,
                             POLD_SQL_PACKET_REC             pSQLPacket,
                             ULONG                           ulSwapType,
                             ULONG                           ulMaxSegmentSize,
                             tsp00_ErrTextc                  pErrText );


/*===========================================================================*
 *  PUBLIC FUNCTIONS (CODE)                                                  *
 *===========================================================================*/

VOID _System sql96o_TCPIP_coordinator ( VOID )
  {
  #undef  MF__
  #define MF__ MOD__"sql96o_serv_loop"
  sockaddr_type                      SockAddr;
  SQL_NODEIDC                        szSenderNodeID;
  ULONG                              ulConnInfoHandle;
  APIRET                             rc        = NO_ERROR;
  ULONG                              ulErrCnt  = 0;
  INT                                AddrLen   = sizeof(SockAddr);
  teo00_Socket                       sd        = UNDEF;
  POLD_TCPIP_SERV_CONNECT_INFO_REC   pConnInfo = NULL;

  DBGIN;

    __try 
    {
    // --- set thread control info
    gxr.OldTCPIPCoord.ThrdCtrlHeader.ulStartTime = time (NULL);
  
    //
    //
    // --- set the thread priority
    //
    //
    rc = SET_THREAD_PRIO ( gxr.OldTCPIPCoord.ThrdCtrlHeader.lThrdPrio,
                           gxr.OldTCPIPCoord.ThrdCtrlHeader.Tid,
                           gxr.OldTCPIPCoord.ThrdCtrlHeader.hThrd );
  
    if ( rc != NO_ERROR )
      {
      MSGALL (( ERR_XSER_SET_THRD_PRIO_ERROR,
                gxr.OldTCPIPCoord.ThrdCtrlHeader.Tid, rc ));
      gxr.OldTCPIPCoord.ThrdCtrlHeader.ThrdState = THRD_TERMINATED;
      gxr.ulCrashRc                              = rc;
      ABORT();
      }
  
    if( !sql09c_init_handle_dir( &gxr.OldTCPIPCoord.pHandles,
                                 MAXTCPIPCONNECTIONS ))
      {
      MSGALL (( ERR_RESERVE_HANDLE_VALUES ));
      gxr.OldTCPIPCoord.ThrdCtrlHeader.ThrdState = THRD_TERMINATED;
      gxr.ulCrashRc                              = ERROR_INVALID_HANDLE;
      ABORT();
      }

    rc = sql96o_open_lis_socket ();
  
    if ( rc != NO_ERROR )
      {
      gxr.OldTCPIPCoord.ThrdCtrlHeader.ThrdState = THRD_TERMINATED;
      gxr.ulCrashRc                              = rc;
      ABORT();
      }
  
  
    for (;;)
    {
      MSG6 (( INFO_XSER_ACCEPTING ));

      gxr.OldTCPIPCoord.ThrdCtrlHeader.ThrdState = THRD_SLEEPING;
  
      rc = sql40c_accept_conn_request ( gxr.OldTCPIPCoord.sd, &sd,
                                        &SockAddr, &AddrLen );

      gxr.OldTCPIPCoord.ThrdCtrlHeader.ThrdState = THRD_RUNNING;
  
  
      if ( (rc != NO_ERROR) || (sd == INVALID_SOCKET) )
        {
        if ( rc == SOCEINTR ) continue;

        MSGALL (( ERR_XSER_ACCEPT_ERROR, rc ));
  
        if ( ( (++ulErrCnt) > 9 ) || ( rc == SOCENOTSOCK ) )
          {
          //
          // --- try to reopen the listen socket
          //
          sql40c_socket_close ( gxr.OldTCPIPCoord.sd );
          gxr.OldTCPIPCoord.sd = INVALID_SOCKET;
          ulErrCnt             = 0;
          AddrLen              = sizeof(SockAddr);

          SLEEP( 30000 );

          rc = sql96o_open_lis_socket ();
  
          if ( rc != NO_ERROR )
            break;
          }
        continue;
        }
      else
        ulErrCnt = 0;
  
      if ( gxr.fNoDNSReverseLookup == FALSE )
        {
        sql43_get_host_by_address ( (PUCHAR)&SockAddr.sa_data[2],
                                     szSenderNodeID, sizeof(szSenderNodeID));
        }
      else
        {
        char* ptr = (char*) &SockAddr.sa_data[2];

        _snprintf ( szSenderNodeID, sizeof(szSenderNodeID), "%d.%d.%d.%d" ,
                    ptr[0]&0xff , ptr[1]&0xff , ptr[2]&0xff , ptr[3]&0xff );
        }

      MSG7 (( INFO_XSER_ACCEPT_CONNECTION_FROM_CLIENT, sd, szSenderNodeID ));

      SetHandleInformation ( (HANDLE)sd, HANDLE_FLAG_INHERIT, 0 );

      rc =  sql40c_keep_alive ( sd );
  
      if ( rc != NO_ERROR )
        MSGCD (( ERR_XSER_KEEP_ALIV_ERROR, rc ))
  
  
      // --- allocate space for the internal communication structure
      rc = ALLOC_MEM((PPVOID)&pConnInfo, sizeof(OLD_TCPIP_SERV_CONNECT_INFO_REC));
  
      if ( rc != NO_ERROR )
        {
        sql40c_socket_close ( sd );
        continue;
        }
  
      // --- Get a new handle and combine it with the pointer to the
      //     internal communication structure.
      //
      if ( !sql09c_reserve_handle ( gxr.OldTCPIPCoord.pHandles, &ulConnInfoHandle) )
        {
        MSGALL (( ERR_XSER_MAX_CONNECTIONS ));
        sql40c_socket_close ( sd );
        FREE_MEM ( pConnInfo );
        continue;
        }
  
      if ( !sql09c_put_handle_data( gxr.OldTCPIPCoord.pHandles, ulConnInfoHandle,
                                    pConnInfo, (ULONG)UNDEF, (ULONG)UNDEF))
        {
        MSGALL (( ERR_XSER_GET_SET_HANDLE_DATA ));
        gxr.ulCrashRc  = ERROR_INVALID_HANDLE;
        ABORT();
        }
  
      pConnInfo->ThrdCtrlHeader.Tid         = (TID)UNDEF;
      pConnInfo->ThrdCtrlHeader.hThrd       = (HANDLE)INVALID_HANDLE_VALUE;
      pConnInfo->ThrdCtrlHeader.lThrdPrio   = SERVER_THRD_PRIO;
      pConnInfo->ThrdCtrlHeader.ThrdState   = THRD_INITIALIZED;
      pConnInfo->ThrdCtrlHeader.ulStartTime = (ULONG)UNDEF;
  
      pConnInfo->ulConnInfoHandle           = ulConnInfoHandle;
      pConnInfo->sd                         = sd;
      strcpy ( pConnInfo->szSenderNodeID, szSenderNodeID );
  
      pConnInfo->ulConnStatus               = CON_INITIALIZED;
      pConnInfo->ulServerRef                = (ULONG)UNDEF;
      pConnInfo->pPacket                    = NULL;
  
      pConnInfo->ulSwapType                 = (ULONG)UNDEF;
      pConnInfo->ulMaxSegmentSize           = gxr.OldTCPIPCoord.ulMaxSegmentSize;

      pConnInfo->fNewPackets                = FALSE;
  
      #if defined(_WIN32)
       pConnInfo->pWorldSA                  = &gxr.WorldSA;
       pConnInfo->pLockSA                   = &gxr.LockSA;
      #endif
  
      rc = CREATE_THREAD( &pConnInfo->ThrdCtrlHeader.Tid,
                          &pConnInfo->ThrdCtrlHeader.hThrd,
                          sql96o_TCPIP_serv_thread,
                          (tsp00_Longuint)ulConnInfoHandle,
                          CREATE_THRD_SUSPENDED,
                          OLD_SERVER_STACK_SIZE);
  
      if (rc != NO_ERROR)
        {
        MSGALL (( ERR_XSER_CREATING_THREAD, "SERVER", rc));
  
        sql40c_socket_close ( sd );
        sql09c_free_handle  ( gxr.OldTCPIPCoord.pHandles, ulConnInfoHandle );
        FREE_MEM ( pConnInfo );
        }
      else
        {
        rc = RESUME_THREAD(pConnInfo->ThrdCtrlHeader.Tid,
                           pConnInfo->ThrdCtrlHeader.hThrd);
  
        if (rc != NO_ERROR)
        {
          MSGALL (( ERR_XSER_RESUMING_THREAD, "SERVER", rc));
  
          KILL_THREAD (pConnInfo->ThrdCtrlHeader.Tid,
                       pConnInfo->ThrdCtrlHeader.hThrd);
          sql40c_socket_close ( sd );
          sql09c_free_handle  ( gxr.OldTCPIPCoord.pHandles, ulConnInfoHandle );
          FREE_MEM ( pConnInfo );
          }
        }
      }
  
    gxr.OldTCPIPCoord.ThrdCtrlHeader.ThrdState = THRD_TERMINATED;
    gxr.ulCrashRc                              = rc;
    ABORT();
  } 
  __except( os968ExceptionHandler(GetExceptionInformation()) ){;}

  DBGOUT;
  EXITTHREAD( rc, gxr.OldTCPIPCoord.ThrdCtrlHeader.hThrd );
  return;
  }

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

VOID sql96o_finish ( VOID )
  {
  #undef  MF__
  #define MF__ MOD__"sql96o_finish"
  ULONG                               ulCommState = commErrOk_esp01;
  POLD_TCPIP_SERV_CONNECT_INFO_REC    pConnInfo;
  tsp00_ErrTextc                      pErrText;
  ULONG                               ulTmp;
  ULONG                               ulConnInfoHandle = 0;
  TID                                 tidTID           = THREADID;

  DBGPAS;

  if ( tidTID != gxr.OldTCPIPCoord.ThrdCtrlHeader.Tid)
    {
    KILL_THREAD ( gxr.OldTCPIPCoord.ThrdCtrlHeader.Tid,
                  gxr.OldTCPIPCoord.ThrdCtrlHeader.hThrd );
    }

  while ( sql09c_find_next_handle( gxr.OldTCPIPCoord.pHandles, &ulConnInfoHandle ))
    {
    if ( !sql09c_lock_handle ( gxr.OldTCPIPCoord.pHandles, ulConnInfoHandle ))
      continue;

    if ( sql09c_get_handle_data  ( gxr.OldTCPIPCoord.pHandles,
                                   ulConnInfoHandle,
                                   (PVOID*)&pConnInfo,
                                   &ulTmp, &ulTmp ))
      {
      if ( tidTID != pConnInfo->ThrdCtrlHeader.Tid)
        {
        KILL_THREAD ( pConnInfo->ThrdCtrlHeader.Tid,
                      pConnInfo->ThrdCtrlHeader.hThrd );
        }

      if (( pConnInfo->ulConnStatus != 0               ) &&
          ( pConnInfo->ulConnStatus != CON_INITIALIZED ) &&
          ( pConnInfo->ulConnStatus != CON_CANCELLED   ) &&
          ( pConnInfo->ulConnStatus != CON_RELEASED    ))
        {
        MSGD (( INFO_XSER_CONN_KILLED,
                pConnInfo->szServerDB, pConnInfo->ulServerRef ));

        sql33c_release ( &pConnInfo->Shm, pErrText );
        pConnInfo->ulConnStatus = CON_RELEASED;
        }

      if ( pConnInfo->sd != INVALID_SOCKET )
        {
        sql40c_socket_close ( pConnInfo->sd );
        pConnInfo->sd = INVALID_SOCKET;
        }
      }
    }

  if (gxr.OldTCPIPCoord.sd != INVALID_SOCKET)
    {
//temporary 
    sql40c_socket_close ( gxr.OldTCPIPCoord.sd );
    gxr.OldTCPIPCoord.sd = INVALID_SOCKET;
    }

  return;
  }



/*===========================================================================*
 *  LOCAL/PRIVATE/PROTECTED FUNCTIONS (CODE)                                 *
 *===========================================================================*/

static ULONG sql96o_open_lis_socket ( VOID )
  {
  #undef  MF__
  #define MF__ MOD__"sql96o_open_lis_socket"
  LONG                           rc;
  ULONG                          ulMaxSegmentSize;
  ULONG                          ulMinSegmentSize;
  ULONG                          ulCommState = commErrOk_esp01;

  DBGIN;

  gxr.OldTCPIPCoord.sd = INVALID_SOCKET;

  // --- get port number for remote sql service
  rc = sql43_get_service_by_name ( SOCKET_SERVICE_SQL30_EO003,
                                   &gxr.OldTCPIPCoord.usServicePort );

  if ( rc != NO_ERROR )
    {
    MSGALL (( ERR_SERV_BY_NAME_ERROR, SOCKET_SERVICE_SQL30_EO003 ));
    DBGOUT;
    return ( rc );
    }

  MSG6 (( INFO_XSER_SERV_PORT, gxr.OldTCPIPCoord.usServicePort ))

  // --- create server socket as overlapped due to problems at shutdown () otherwise
  rc = sql40c_stream_socket2 ( &gxr.OldTCPIPCoord.sd, WSA_FLAG_OVERLAPPED);

  if ( rc != NO_ERROR )
    {
    MSGALL (( ERR_XSER_LIS_SOCK_OPEN, rc ));
    return ( rc );
    }

  SetHandleInformation ( (HANDLE)gxr.OldTCPIPCoord.sd, HANDLE_FLAG_INHERIT, 0 );

  rc =  sql40c_keep_alive ( gxr.OldTCPIPCoord.sd );

  if ( rc != NO_ERROR )
    MSGCD (( ERR_XSER_KEEP_ALIV_ERROR, rc ))

  MSG6 (( INFO_XSER_OP_LISEN_SOCKET, gxr.OldTCPIPCoord.sd ));


  ulMinSegmentSize = 1024;
  ulMaxSegmentSize = sizeof(OLD_SQL_PACKET_REC);

  ulCommState = sql96o_set_sock_buf_sizes( gxr.OldTCPIPCoord.sd,
                                           ulMinSegmentSize,
                                           &ulMaxSegmentSize );

  if ( ulCommState != commErrOk_esp01 )
    {
    sql40c_socket_close ( gxr.OldTCPIPCoord.sd );
    gxr.OldTCPIPCoord.sd = INVALID_SOCKET;

    DBGOUT;
    return ( ulCommState );
    }

  gxr.OldTCPIPCoord.ulMaxSegmentSize = ulMaxSegmentSize;

  // --- bind the socket to the server address
  rc = sql40c_bind ( gxr.OldTCPIPCoord.sd, gxr.OldTCPIPCoord.usServicePort );

  if ( rc != NO_ERROR )
    {
    if ( rc == SOCEADDRINUSE )
      {
      MSGALL (( ERR_XSER_SOCK_ADDR_IN_USE ));
      }
    else
      MSGALL (( ERR_XSER_BIND_ERROR, rc ));

    sql40c_socket_close ( gxr.OldTCPIPCoord.sd );
    gxr.OldTCPIPCoord.sd = INVALID_SOCKET;

    DBGOUT;
    return ( commErrNotOk_esp01 );
    }

  rc = sql40c_listen ( gxr.OldTCPIPCoord.sd, 10 );

  if ( rc != NO_ERROR )
    {
    MSGALL (( ERR_XSER_LISTEN_ERROR, rc ));

    sql40c_socket_close ( gxr.OldTCPIPCoord.sd );
    gxr.OldTCPIPCoord.sd = INVALID_SOCKET;

    DBGOUT;
    return ( commErrNotOk_esp01 );
    }

  MSG6 (( INFO_XSER_LISTEN_ON_SOCKET, gxr.OldTCPIPCoord.sd ));

  DBGOUT;
  return ( ulCommState );
  }

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

static ULONG sql96o_set_sock_buf_sizes( teo00_Socket    sd,
                                        ULONG			ulMinSegmentSize,
                                        PULONG			pulMaxSegmentSize )
  {
  #undef  MF__
  #define MF__ MOD__"sql96o_set_sock_buf_sizes"
  LONG                           rc;

  DBGIN;

  //
  // --- set send buffer size
  //
  rc = sql40c_set_send_buffer_size ( sd, pulMaxSegmentSize,
                                     ulMinSegmentSize );

  if ( rc != NO_ERROR )
    {
    MSGALL (( ERR_XSER_SET_BUF_SIZE, "SNDBUF", rc ));
    DBGOUT;
    return ( commErrNotOk_esp01 );
    }

  //
  // --- set receive buffer size
  //
  rc = sql40c_set_recv_buffer_size ( sd, pulMaxSegmentSize,
                                     ulMinSegmentSize );

  if ( rc != NO_ERROR )
    {
    MSGALL (( ERR_XSER_SET_BUF_SIZE, "RCVBUF", rc ));
    DBGOUT;
    return ( commErrNotOk_esp01 );
    }

  MSG6 (( INFO_XSER_SEGMENT_SIZES, sd, ulMinSegmentSize, *pulMaxSegmentSize ));

  DBGOUT;
  return ( commErrOk_esp01 );
  }

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

static VOID _System sql96o_TCPIP_serv_thread ( ULONG ulConnInfoHandle )
  {
  #undef  MF__
  #define MF__ MOD__"sql96o_TCPIP_serv_thread"
  POLD_TCPIP_SERV_CONNECT_INFO_REC   pConnInfo = NULL;
  ULONG                              ulCommState;
  HANDLE                             hServerThread;
  ULONG                              ulTmp;
  tsp00_ErrTextc                     pErrText;
  LONG                               rc;

  DBGIN;

  __try
  {
    if ( !sql09c_get_handle_data  ( gxr.OldTCPIPCoord.pHandles,
                                    ulConnInfoHandle,
                                    (PVOID*)&pConnInfo,
                                    &ulTmp, &ulTmp ))
      {
      MSGALL (( ERR_XSER_GET_SET_HANDLE_DATA ));
      gxr.ulCrashRc  = ERROR_INVALID_HANDLE;
      ABORT();
      return;
      }

    // --- set thread control info
    pConnInfo->ThrdCtrlHeader.ulStartTime = time (NULL);

    //
    //
    // --- set the thread priority
    //
    //
    rc = SET_THREAD_PRIO ( pConnInfo->ThrdCtrlHeader.lThrdPrio,
                           pConnInfo->ThrdCtrlHeader.Tid,
                           pConnInfo->ThrdCtrlHeader.hThrd );

    if ( rc != NO_ERROR )
      {
      MSGALL (( ERR_XSER_SET_THRD_PRIO_ERROR,
                pConnInfo->ThrdCtrlHeader.Tid, rc ));
      gxr.ulCrashRc  = rc;
      ABORT();
      return;
      }

    MSG4 (( INFO_XSER_SERVER_STARTED, pConnInfo->ThrdCtrlHeader.Tid ))

    pConnInfo->ThrdCtrlHeader.ThrdState = THRD_RUNNING;

    ulCommState = sql96o_request ( pConnInfo );

    if ( pConnInfo->ulConnStatus == CON_CONNECTED )
      {
      if ( ulCommState == commErrOk_esp01 )
        {
        MSGD (( INFO_XSER_APPL_CONNECTED,
                pConnInfo->szSenderNodeID,
                pConnInfo->szServerDB,
                pConnInfo->ulServerRef ));
        MSG3 (( INFO_XSER_ENTER_DATA_TRANS,
                pConnInfo->ThrdCtrlHeader.Tid ));

        if ( pConnInfo->fNewPackets )
          sql96o_transfer_new_db ( pConnInfo );
        else
          sql96o_transfer_old_db ( pConnInfo );

        MSG3 (( INFO_XSER_END_OF_DATA_TRANS,
                pConnInfo->ThrdCtrlHeader.Tid ));
        MSGD (( INFO_XSER_APPL_DISCONNECT,
                pConnInfo->szSenderNodeID,
                pConnInfo->szServerDB,
                pConnInfo->ulServerRef ));
        }

      if ( pConnInfo->fNewPackets )
        sql33c_release ( &pConnInfo->Shm, pErrText );
      else
        sql33o_release ( &pConnInfo->OldShm, pErrText );

      pConnInfo->ulConnStatus = CON_RELEASED;
      }


    MSG4 (( INFO_XSER_SERVER_EXITING, pConnInfo->ThrdCtrlHeader.Tid ));

    if ( pConnInfo->sd != INVALID_SOCKET )
      {
      sql40c_socket_close ( pConnInfo->sd );
      pConnInfo->sd = INVALID_SOCKET;
      }

    sql09c_free_handle  ( gxr.OldTCPIPCoord.pHandles, ulConnInfoHandle );

    pConnInfo->ThrdCtrlHeader.ThrdState = THRD_TERMINATED;
    hServerThread                       = pConnInfo->ThrdCtrlHeader.hThrd;
    FREE_MEM ( pConnInfo );
  } 
  __except( os968ExceptionHandler(GetExceptionInformation()) ){;}


  DBGOUT;
  EXITTHREAD( ulCommState, hServerThread );
  return;
  }

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

static ULONG sql96o_request ( POLD_TCPIP_SERV_CONNECT_INFO_REC pConnInfo )
  {
  #undef  MF__
  #define MF__ MOD__"sql96o_request"
  CONNECT_PARAM_REC               LocConnParam;
  ULONG                           ulCommState;
  tsp00_ErrTextc                  pErrText;
  ULONG                           ulMaxSegmentSize;
  ULONG                           ulSenderRef;
  ULONG                           ulReceiverRef;
  ULONG                           ulServiceType;
  SQL_DBNAMEC                     szSenderServerDB;
  SQL_DBNAMEC                     szReceiverServerDB;
  PID                             pidSenderPid;
  USHORT                          usServicePort;
  ULONG                           ulSwapType;
  ULONG                           ulMessClass;
  ULONG                           ulMinReplySize;
  ULONG                           ulPacketSize;
  ULONG                           ulMaxDataLen;
  ULONG                           ulLocalHeaderSize;

  DBGIN;


  //
  // ---  receive server reply
  //
  ulCommState = sql42o_recv_conpkt ( pConnInfo->sd,
                                     &ulMessClass,
                                     &ulReceiverRef,
                                     &ulSenderRef,
                                     &ulServiceType,
                                     &ulMaxSegmentSize,
                                     &ulSwapType,
                                     szReceiverServerDB,
                                     szSenderServerDB,
                                     &pidSenderPid,
                                     &usServicePort,
                                     pErrText );

  if ( ulCommState != commErrOk_esp01 )
    {
    MSGD (( ERR_XSER_REC_REQ_PACKET_ERR ));
    return ( ulCommState );
    }

  MSG2 (( INFO_XSER_REC_REQ_PACKET,
          ulMessClass,
          ulReceiverRef,
          ulSenderRef,
          ulServiceType,
          szReceiverServerDB,
          szSenderServerDB ));

  switch ( ulMessClass )
    {
    case RSQL_RTE_ADDRESS_REQUEST_EO003 :
      usServicePort          = gxr.OldTCPIPCoord.usServicePort;
      ulMessClass            = RSQL_RTE_ADDRESS_REPLY_EO003;
      break;

    case RSQL_RTE_REQUEST_CONN_EO003 :
    case RSQL_RTE_OPEN_SESSION_EO003 :

      ulPacketSize  = MIN_PACKET_SIZE;
      ulMaxDataLen  = MIN_PACKET_SIZE;

      ulCommState = sql33c_info_request( szReceiverServerDB,
                                         ulServiceType,
                                         1,
                                         &ulPacketSize,
                                         &ulMaxDataLen,
                                         &ulMinReplySize,
                                         pErrText );


      if ( ulCommState == commErrOk_esp01 )
        {
        MSG8 (( INFO_XSER_REC_CONN_REQ, szReceiverServerDB,
                ulSenderRef, (ULONG)UNDEF, (ULONG)UNDEF ));

        ulLocalHeaderSize = ulPacketSize - ulMaxDataLen;
        ulPacketSize      = MIN_PACKET_SIZE + ulLocalHeaderSize;
        ulMaxDataLen      = MIN_PACKET_DATA_LEN  + ulLocalHeaderSize;

        memset ( &LocConnParam, 0, sizeof(LocConnParam) );
        LocConnParam.ulPacketCnt       = 1;
        LocConnParam.ulClientRef       = ulSenderRef;
        LocConnParam.ulServiceType     = ulServiceType;
        LocConnParam.pWorldSA          = pConnInfo->pWorldSA;
        LocConnParam.pLockSA           = pConnInfo->pLockSA;
        LocConnParam.ulConnTimeout     = LOCAL_CONN_TIMEOUT;
        LocConnParam.pszServerDB       = szReceiverServerDB;
        LocConnParam.pszClientNode     = pConnInfo->szSenderNodeID;
        LocConnParam.ulPacketSize      = ulPacketSize;
        LocConnParam.ulMaxDataLen      = ulMaxDataLen;
        LocConnParam.ulMinReplySize    = ulMinReplySize;
        LocConnParam.pidClientPID      = pidSenderPid;
        LocConnParam.ulCommFlagNo      = (ULONG)UNDEF;
        LocConnParam.ulServerRef       = (ULONG)UNDEF;

        ulCommState = sql33c_connect( &LocConnParam, &pConnInfo->Shm,
                                      pErrText );

        if ( ulCommState != commErrOk_esp01 )
          {
          MSGD (( ERR_XSER_CONN_REQ, pErrText ))
          }
        else
          {
          pConnInfo->ulConnStatus = CON_CONNECTED;
          pConnInfo->fNewPackets  = TRUE;

          if (( LocConnParam.ulPacketSize < MIN_PACKET_SIZE ) ||
              ( LocConnParam.ulMaxDataLen < MIN_PACKET_DATA_LEN ))
            {
            MSGALL(( ERR_XSER_WRONG_PACKET_SIZE, szReceiverServerDB,
                     ALIGN (MIN_PACKET_SIZE, 4096) ));
            ulCommState = commErrNotOk_esp01;
            }
          else
            {
            pConnInfo->ulServerRef      = LocConnParam.ulServerRef;
            pConnInfo->pPacket          = (PVOID)LocConnParam.pCommPacketList[0];
            pConnInfo->ulMaxSegmentSize = ulMaxSegmentSize;
            pConnInfo->ulSwapType       = ulSwapType;
            pConnInfo->ulSenderRef      = ulSenderRef;
            strcpy ( pConnInfo->szServerDB, szReceiverServerDB );

            // - store server reference
            if ( !sql09c_put_handle_data ( gxr.OldTCPIPCoord.pHandles,
                                           pConnInfo->ulConnInfoHandle,
                                           pConnInfo,
                                           (ULONG)UNDEF,
                                           pConnInfo->ulServerRef ))
              {
              MSGALL (( ERR_XSER_GET_SET_HANDLE_DATA ));
              gxr.ulCrashRc = ERROR_INVALID_HANDLE;
              ABORT();
              }

            MSG8 (( INFO_XSER_CONN_REQ,
                    szReceiverServerDB,
                    pConnInfo->ulServerRef,
                    LocConnParam.ulMaxDataLen -
                    ulMinReplySize,
                    pConnInfo->ulConnInfoHandle ));
            }
          }
        }
      else
        {
        ulCommState = sql33o_connect ( &pConnInfo->OldShm,
                                       ulSenderRef,
                                       ulServiceType,
                                       szReceiverServerDB,
                                       pConnInfo->pWorldSA,
                                       pConnInfo->pLockSA,
                                       &pConnInfo->ulServerRef,
                                       &pConnInfo->pPacket,
                                       pErrText,
                                       LOCAL_CONN_TIMEOUT );

        if ( ulCommState != commErrOk_esp01 )
          {
          if ( ulCommState != commErrStartRequired_esp01 )
            {
            MSGD (( ERR_XSER_CONN_REQ, pErrText ))
            }
          }
        else
          {
          pConnInfo->ulConnStatus     = CON_CONNECTED;
          pConnInfo->fNewPackets      = FALSE;

          pConnInfo->ulMaxSegmentSize = ulMaxSegmentSize;
          pConnInfo->ulSwapType       = ulSwapType;
          pConnInfo->ulSenderRef      = ulSenderRef;
          strcpy ( pConnInfo->szServerDB, szReceiverServerDB );

          // - store server reference
          if ( !sql09c_put_handle_data ( gxr.OldTCPIPCoord.pHandles,
                                         pConnInfo->ulConnInfoHandle,
                                         pConnInfo,
                                         (ULONG)UNDEF,
                                         pConnInfo->ulServerRef ))
            {
            MSGALL (( ERR_XSER_GET_SET_HANDLE_DATA ));
            gxr.ulCrashRc = ERROR_INVALID_HANDLE;
            ABORT();
            }
          }
        }

      if ( ulMessClass == RSQL_RTE_REQUEST_CONN_EO003 )
        ulMessClass = RSQL_RTE_REPLY_CONN_EO003;
      else
        ulMessClass = RSQL_RTE_OPEN_SESSION_REPLY_EO003;

      break;

    case RSQL_RTE_CANCEL_EO003 :
      MSG5 (( INFO_XSER_CANCEL_REQUESTED, ulReceiverRef  ));

      ulCommState = sql96o_cancel_dump ( ulReceiverRef,
                                         szReceiverServerDB,
                                         SQL_RTE_CANCEL );

      if ( ulCommState == commErrOk_esp01 )
        pConnInfo->ulConnStatus = CON_CANCELLED;

      return ( ulCommState );

    case RSQL_RTE_DUMP_EO003 :
      ulCommState = sql96o_cancel_dump ( ulReceiverRef,
                                         szReceiverServerDB,
                                         SQL_RTE_DUMP );

      if ( ulCommState == commErrOk_esp01 )
        pConnInfo->ulConnStatus = CON_CANCELLED;

      return ( ulCommState );

    default :
      MSGALL (( ERR_XSER_ILL_FRST_MESS_CLASS, ulMessClass ));
      return ( commErrNotOk_esp01 );
    }


  if ( ulMaxSegmentSize < pConnInfo->ulMaxSegmentSize )
    pConnInfo->ulMaxSegmentSize = ulMaxSegmentSize;

  if ( ulCommState != commErrOk_esp01 )            // - do not overwrite 'ulCommState'
    {
    sql42o_send_conpkt ( pConnInfo->sd,
                         ulMessClass,
                         pConnInfo->ulServerRef,
                         ulSenderRef,
                         ulServiceType,
                         pConnInfo->ulMaxSegmentSize,
                         szReceiverServerDB,
                         szSenderServerDB,
                         usServicePort,
                         ulCommState,
                         pErrText );
    }
  else
    {
    ulCommState = sql42o_send_conpkt ( pConnInfo->sd,
                                       ulMessClass,
                                       pConnInfo->ulServerRef,
                                       ulSenderRef,
                                       ulServiceType,
                                       pConnInfo->ulMaxSegmentSize,
                                       szReceiverServerDB,
                                       szSenderServerDB,
                                       usServicePort,
                                       ulCommState,
                                       pErrText );

    if ( ulCommState != commErrOk_esp01 )
      MSGD (( ERR_XSER_SEND_REQ_PACKET_ERR ));
    }

  DBGOUT;
  return ( ulCommState );
  }

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

static ULONG sql96o_transfer_old_db (POLD_TCPIP_SERV_CONNECT_INFO_REC pConnInfo)
  {
  #undef  MF__
  #define MF__ MOD__"sql96o_transfer_old_db"
  ULONG                           ulCommState;
  tsp00_ErrTextc                  pErrText;
  POLD_SQL_PACKET_REC             pSQLPacket;

  for (;;)
    {
    pConnInfo->ThrdCtrlHeader.ThrdState = THRD_COMMAND_WAIT;

    pSQLPacket = (POLD_SQL_PACKET_REC)pConnInfo->pPacket;

    ulCommState =  sql42o_recv_packet ( pConnInfo->sd,
                                        pSQLPacket,
                                        pConnInfo->ulSwapType,
                                        pConnInfo->ulMaxSegmentSize,
                                        pErrText );

    if ( ulCommState != commErrOk_esp01 )
      {
      if ( ulCommState == commErrReleased_esp01 )
        break;

      MSGD (( ERR_XSER_RECV_PACKET, pConnInfo->ulServerRef, pErrText ));
      break;
      }

    if ( (pSQLPacket->ActSendLen < OLD_RTE_HEADER_SIZE) ||
         (pSQLPacket->ActSendLen > sizeof(OLD_SQL_PACKET_REC)) )
      {
      MSGD (( ERR_XSER_ILL_PACKET_SIZE,
              pSQLPacket->ActSendLen, pConnInfo->ulServerRef ));
      ulCommState = commErrNotOk_esp01;
      break;
      }
    MSG8 (( INFO_XSER_READ_REQ_PACKET,
            pSQLPacket->ActSendLen, pConnInfo->ulServerRef ));

    pConnInfo->ThrdCtrlHeader.ThrdState = THRD_COMMAND_SEND;

    ulCommState = sql33o_request( &pConnInfo->OldShm, pErrText );

    if ( ulCommState != commErrOk_esp01 )
      {
      MSGD (( ERR_XSER_REQUEST, pConnInfo->ulServerRef, pErrText ));
      break;
      }

    MSG8 (( INFO_XSER_REQUEST_RETURNED, pConnInfo->ulServerRef, ulCommState ));

    pConnInfo->ThrdCtrlHeader.ThrdState = THRD_DATA_RECEIVE;

    ulCommState = sql33o_receive( &pConnInfo->OldShm, pErrText );

    if ( ulCommState != commErrOk_esp01 )
      {
      MSGD (( ERR_XSER_RECEIVE, pConnInfo->ulServerRef, pErrText ));
      break;
      }

    MSG8 (( INFO_XSER_RECEIVE_RETURNED, pConnInfo->ulServerRef, ulCommState ));

    pConnInfo->ThrdCtrlHeader.ThrdState = THRD_DATA_SEND;

    ulCommState = sql42o_send_packet ( pConnInfo->sd,
                                       pSQLPacket,
                                       pConnInfo->ulMaxSegmentSize,
                                       commErrOk_esp01, pErrText );

    if ( ulCommState != commErrOk_esp01 )
      {
      MSGD (( ERR_XSER_SEND_PACKET, pConnInfo->ulServerRef, pErrText ));
      break;
      }
    MSG8 (( INFO_XSER_SEND_REPLY_PACKET,
            pSQLPacket->ActSendLen, pConnInfo->ulServerRef ));
    }

  pConnInfo->ThrdCtrlHeader.ThrdState = THRD_RUNNING;

  DBGOUT;
  return ( ulCommState );
  }

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

static ULONG sql96o_transfer_new_db (POLD_TCPIP_SERV_CONNECT_INFO_REC pConnInfo)
  {
  #undef  MF__
  #define MF__ MOD__"sql96o_transfer_new_db"
  ULONG                           ulCommState;
  tsp00_ErrTextc                  pErrText;
  PCOMM_PACKET_REC                pCommPacket;
  ULONG                           ulResDataLen;
  PCOMM_PACKET_REC                pResCommPacket;
  POLD_SQL_PACKET_REC             pSQLComPacket;
  POLD_SQL_PACKET_REC             pSQLResPacket;

  if ( RTE_HEADER_SIZE  < OLD_RTE_HEADER_SIZE )
    {
    MSGALL(( ERR_XSER_SURPRISING_HEADER ));
    ABORT();
    }

  pCommPacket    = (PCOMM_PACKET_REC)pConnInfo->pPacket;
  pSQLComPacket  = (POLD_SQL_PACKET_REC)((PCHAR)pCommPacket->pDataPart - OLD_RTE_HEADER_SIZE);

  for (;;)
    {
    pConnInfo->ThrdCtrlHeader.ThrdState = THRD_COMMAND_WAIT;

    ulCommState =  sql42o_recv_packet ( pConnInfo->sd,
                                        pSQLComPacket,
                                        pConnInfo->ulSwapType,
                                        pConnInfo->ulMaxSegmentSize,
                                        pErrText );

    if ( ulCommState != commErrOk_esp01 )
      {
      if ( ulCommState == commErrReleased_esp01 )
        break;

      MSGD (( ERR_XSER_RECV_PACKET, pConnInfo->ulServerRef, pErrText ));
      break;
      }

    MSG8 (( INFO_XSER_READ_REQ_PACKET,
            pSQLComPacket->ActSendLen, pConnInfo->ulServerRef ));

    pConnInfo->ThrdCtrlHeader.ThrdState = THRD_COMMAND_SEND;

    ulCommState = sql33c_request( &pConnInfo->Shm, 0, pSQLComPacket->ActSendLen, pErrText );

    if ( ulCommState != commErrOk_esp01 )
      {
      MSGD (( ERR_XSER_REQUEST, pConnInfo->ulServerRef, pErrText ));
      break;
      }

    MSG8 (( INFO_XSER_REQUEST_RETURNED, pConnInfo->ulServerRef, ulCommState ));

    pConnInfo->ThrdCtrlHeader.ThrdState = THRD_DATA_RECEIVE;


    ulCommState = sql33c_receive( &pConnInfo->Shm, &pResCommPacket, &ulResDataLen, pErrText );

    if ( ulCommState != commErrOk_esp01 )
      {
      MSGD (( ERR_XSER_RECEIVE, pConnInfo->ulServerRef, pErrText ));
      break;
      }

    if ( (ulResDataLen + OLD_RTE_HEADER_SIZE) > sizeof(OLD_SQL_PACKET_REC))
      {
      MSGD (( ERR_INVALID_REPL_SIZE, ulResDataLen  ));
      ulCommState = commErrNotOk_esp01;
      break;
      }

    pSQLResPacket  = (POLD_SQL_PACKET_REC)
                       ((PCHAR)pResCommPacket->pDataPart - OLD_RTE_HEADER_SIZE);

    pSQLResPacket->ActSendLen       = (INT2)ulResDataLen + OLD_RTE_HEADER_SIZE;
    pSQLResPacket->MaxSendLen       = (INT2)ulResDataLen + OLD_RTE_HEADER_SIZE;
    pSQLResPacket->ProtocolID       = RSQL_RTE_PROT_LOCAL_EO003;
    pSQLResPacket->MessClass        = RSQL_RTE_REPLY_USER_EO003;
    pSQLResPacket->RTEFlags         = RSQL_NORMAL_EO003;
    pSQLResPacket->ResidualPackets  = 0;
    pSQLResPacket->ReceiverRefID    = pSQLResPacket->SenderRefID;
    pSQLResPacket->SenderRefID      = (INT4)pConnInfo->ulServerRef;
    pSQLResPacket->RTEReturnCode    = commErrOk_esp01;
    pSQLResPacket->Filler           = 0;

    MSG8 (( INFO_XSER_RECEIVE_RETURNED, pConnInfo->ulServerRef, ulCommState ));

    pConnInfo->ThrdCtrlHeader.ThrdState = THRD_DATA_SEND;

    ulCommState = sql42o_send_packet ( pConnInfo->sd,
                                       pSQLResPacket,
                                       pConnInfo->ulMaxSegmentSize,
                                       commErrOk_esp01, pErrText );

    if ( ulCommState != commErrOk_esp01 )
      {
      MSGD (( ERR_XSER_SEND_PACKET, pConnInfo->ulServerRef, pErrText ));
      break;
      }

    MSG8 (( INFO_XSER_SEND_REPLY_PACKET,
            pSQLResPacket->ActSendLen, pConnInfo->ulServerRef ));
    }

  pConnInfo->ThrdCtrlHeader.ThrdState = THRD_RUNNING;

  DBGOUT;
  return ( ulCommState );
  }

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

static ULONG sql96o_cancel_dump ( ULONG                        ulServerRef,
                                  PSZ                          pszServerDB,
                                  ULONG                        ulReqType )
  {
  #undef  MF__
  #define MF__ MOD__"sql96o_cancel_dump"
  ULONG                               ulCommState = commErrOk_esp01;
  POLD_TCPIP_SERV_CONNECT_INFO_REC    pConnInfo;
  tsp00_ErrTextc                      pErrText;
  ULONG                               ulTmp;
  ULONG                               ulConnInfoHandle = 0;


  DBGPAS;

  // --- Find the connect info handle of the command to be cancelled and try
  //     to lock it.
  //
  for ( ;; )
    {
    if (( !sql09c_find_handle_by_id ( gxr.OldTCPIPCoord.pHandles,
                                      ulServerRef, &ulConnInfoHandle )) ||
        ( !sql09c_lock_handle ( gxr.OldTCPIPCoord.pHandles, ulConnInfoHandle )) )
      {
      return ( commErrOk_esp01 );
      }

    if ( sql09c_get_handle_data  ( gxr.OldTCPIPCoord.pHandles,
                                  ulConnInfoHandle,
                                  (PVOID*)&pConnInfo,
                                  &ulTmp, &ulTmp ))
      {
      if ( strcmp (pConnInfo->szServerDB, pszServerDB) )
        continue;

      if ( pConnInfo->fNewPackets )
        ulCommState = sql33c_cancel_dump ( &pConnInfo->Shm, ulReqType, pErrText );
      else if ( ulReqType == SQL_RTE_CANCEL )
        ulCommState = sql33o_cancel ( &pConnInfo->OldShm, pErrText );
      }

    if ( !sql09c_unlock_handle ( gxr.OldTCPIPCoord.pHandles, ulConnInfoHandle ))
      {
      MSGALL (( ERR_XSER_LOCK_UNLOCK_HANDLE ));
      gxr.ulCrashRc = ERROR_INVALID_HANDLE;
      ABORT();
      }
    break;
    }


  MSG5 (( INFO_XSER_CANCEL_RETURNING, ulCommState ))

  return ( ulCommState );
  }

/*===========================================================================*
 *  END OF CODE                                                              *
 *===========================================================================*/
