/* static char szModuleName__ []  = "f:/r3/code/c/unix/nradapi.c"; jmh 29 May 2001 */
/* static char szLastVersion []   = "Version 0.6"; jmh 29 May 2001 */
/* static char szLastSave []      = "1994-07-12*14:05"; jmh 29 May 2001 */
/************************************************************
Abstract
nradapi.c - Nordrad API Access Services

(C) Copyright AU-System Communication AB 1994.

Change activity
970908	    ARG	 Do not modify input parameters
960923	    ARG	 Increased max waittime to 7200 seconds
941107	    ARG	 Some compilation warnings removed,
		 Time supervision for receiveavi
940526      BBN  Foreign.cComment always ended with zero
940202 1.00 BBN  Initial version by Björn Brodin.

Part of  Nordrad.

Description
*************************************************************/
#ifdef VMS
#include <types.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stat.h>
#include <math.h>
#include <netdb.h>
#else
#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <sys/stat.h>
#include <math.h>
#include <netdb.h>
#endif
#include "netdef.h"
#include "api.h"
#include "net.h"
#include "utl.h"
#include "fil.h"
#include "rr_fil.h"
#include "comp.h"
#include "nradutil.h"

/*----------------------------------------------------------
*	Macros
*---------------------------------------------------------*/

/*----------------------------------------------------------
*	Functions
*---------------------------------------------------------*/
INT32  ValidateIpAdr(char  *pIpAddr);
INT32  InsertAdaTypeStr(struct AdaTypeStrStruc *pAdaStr,
                char *pStr,INT32 iMaxLen,INT32 CheckStrNotEmpty);
void ConvToApiProdDescr(struct NetProdDescrStruc *pNetProdDescr,
                        struct ApiProdDescrStruc *pApiProdDescr);
void ConvToNetProdDescr(struct ApiProdDescrStruc *pApiProdDescr,
                          struct NetProdDescrStruc *pNetProdDescr);
INT32 ConvToApiRc(INT32 iRc);
INT32 ValidateIpAdr(char *pIpAddr);
INT32 IsProdDescrOk(struct ApiProdDescrStruc *pProdDescr);
INT32 IsTextStrOk(INT32 *iMaxLen,INT32 iLen,char *pText,INT32 iMaxLimit);
INT32 GetProdDescrSize(INT32 iProdDescr);

/*----------------------------------------------------------
*	Structures
*---------------------------------------------------------*/
#define RESOLUTION_MIN       1
#define RESOLUTION_MAX       65535
#define MAPTYPE_MAX          5
#define MAPGRAPHIC_MAX       1
#define RRMODE_MAX           2  
#define HIGHT_MAX            30000
#define HIGHT_MIN            0    
#define HMI_WALL_MAX         100     /*    ???????????????????????  */
#define SEC_SIZE_MIN         0 
#define SEC_SIZE_MAX         86399   /* Changed by Joe Holmes, 26 Jan 1998, 29 May 2001 */
#define VSI_WALL_MAX         100     /*    ???????????????????????  */
#define MAX_AREA_WALL_VALUE  3

/* Product description Size */
#define PROD_NONE_SIZE       29
#define PROD_FOREIGN_SIZE    64
#define PROD_GEOMAP_SIZE     31
#define PROD_RRSTATUS_SIZE   43
#define PROD_RRPPI_Z_SIZE    30
#define PROD_RRPPI_W_SIZE    30
#define PROD_RRPPI_T_SIZE    30
#define PROD_RRCAPPI_Z_SIZE  32
#define PROD_RRCAPPI_W_SIZE  32
#define PROD_RRCAPPI_T_SIZE  32
#define PROD_RRPSC_Z_SIZE    30
#define PROD_RRPSC_W_SIZE    30
#define PROD_RRPSC_T_SIZE    30
#define PROD_RRETM_Z_SIZE    30
#define PROD_RRVMI_Z_SIZE    30
#define PROD_RRVMI_W_SIZE    30
#define PROD_RRVMI_T_SIZE    30
#define PROD_RRHMI_Z_SIZE    31
#define PROD_RRHMI_W_SIZE    31
#define PROD_RRHMI_T_SIZE    31
#define PROD_RRHMAX_Z_SIZE   30
#define PROD_RRHMAX_W_SIZE   30
#define PROD_RRHMAX_T_SIZE   30
#define PROD_RRVSI_Z_SIZE    65
#define PROD_RRVSI_W_SIZE    65
#define PROD_RRVSI_T_SIZE    65
#define PROD_RRSRT_Z_SIZE    38
#define PROD_DEFAULT_SIZE    4

#define MORE_STAT            1   /* ??????????????????????? */  

/*----------------------------------------------------------
*  API call GetProduct - Fetch a product from Nordrad node
*---------------------------------------------------------*/
void       GetProduct(char                     *pAccessCtrl,
                      char                     *pHostName,
                      struct ApiAviStruc       *pApiAvi, 
                      char                     *pDestFile,
                      INT32                    iWaitTime,
                      INT32                    *piStatus)    
  {

char szDestFile [MAX_FILE_NAME_SIZE+1];
char szHostName [MAX_HOSTNAME_SIZE+1];
char szAccessCtrl [MAX_ACCESSCTRL_SIZE+1];

      INT32     iSendSize = 0;
      INT32     iRc = OK;
      INT32     Sockh = -1;
	  struct NetAviStruc  NetAvi;

  if (strlen (pAccessCtrl) > MAX_ACCESSCTRL_SIZE)
     {
	*piStatus = APIILLPAR;
	return;
     }

  strcpy (szAccessCtrl, pAccessCtrl);

  if (strlen (pDestFile) > MAX_FILE_NAME_SIZE)
     {
	*piStatus = APIILLPAR;
	return;
     }

  strcpy (szDestFile, pDestFile);

  if (strlen (pHostName) > MAX_HOSTNAME_SIZE)
     {
	*piStatus = APIILLPAR;
	return;
     }

  strcpy (szHostName, pHostName);

  if (iWaitTime > 7200 )
	{
	*piStatus = APIILLPAR;
	return;
	}
  UtlInitTimeoutHandler();
  if ( IsProdDescrOk(&pApiAvi->ApiProdDescr) )
    {
    if ( UtlStripStr(szDestFile,
      		     (INT32) strlen(szDestFile),
		     (INT32) CHECK_NOT_EMPTY,
		     (INT32) UNCHANGED) == NOK)
      { 
      *piStatus = APINODEST;
      return;
      }
  
    if ( UtlStripStr(szHostName,
      		     (INT32) (strlen(szHostName)+1),
		     (INT32) CHECK_NOT_EMPTY,
		     (INT32) UNCHANGED) == NOK)
      {    
      *piStatus = APIILLPAR; 
      return;
      } 
    if ( UtlStripStr(szAccessCtrl,
      		     (INT32) (strlen(szAccessCtrl)+1),
		     (INT32) CHECK_NOT_EMPTY,
		     (INT32) TO_UPPER) == NOK)
      { 
      *piStatus = APIILLPAR; 
      return;
      }
    if ((strlen(pApiAvi->cNodeName)+1) > sizeof(pApiAvi->cNodeName))
      {
      *piStatus = APIILLPAR; 
      return;
      }
      
    if ( UtlStripStr(pApiAvi->cNodeName,
      		     (INT32) sizeof(pApiAvi->cNodeName),
		     (INT32) CHECK_NOT_EMPTY,
		     (INT32) TO_UPPER) == NOK)
      {  
      *piStatus = APINONODE;
      return;
      } 
    strcpy(NetAvi.cNodeName,pApiAvi->cNodeName);

    ConvToNetProdDescr(&pApiAvi->ApiProdDescr,
                      &NetAvi.NetProdDescr);

    *piStatus = ValidateIpAdr(szHostName);
    if (*piStatus != OK)
      return;     

    *piStatus = UtlStartTimeout( iWaitTime);
    if (*piStatus != OK)
      return;     

    Sockh = NetOpenClient(GATE_GET_PROD,szHostName,piStatus);
    if (Sockh < 0)
      {
      NetClose(Sockh);
      return;
      }
      
    NetValidateAccess(Sockh,szAccessCtrl,piStatus );
    if (*piStatus != OK)  /* ACESS VALIDATED  */
      {
      iRc = UtlCancelTimeout();
      NetClose(Sockh);
      *piStatus = ConvToApiRc(*piStatus);
      return;
      }

    iSendSize = sizeof(NetAvi);
    
    NetWriteBuff(Sockh,(char *)&NetAvi,iSendSize,piStatus);
    if (*piStatus == OK)
      {
      NetReadInt(Sockh,piStatus,&iRc);      

	  if (iRc == OK)
        {
        if (*piStatus == OK) 
          NetGetFile(Sockh,szDestFile,piStatus);  
        }
      else
        *piStatus = iRc;
        
      }
    else
      *piStatus = APIDESTFIL;

    iRc = UtlCancelTimeout (); 
    }    /*   if ( IsProdDescrOk(&pApiProdDescr) )  */
  else 
    *piStatus = APIILLPAR;
  
  NetClose(Sockh);
  *piStatus = ConvToApiRc(*piStatus);
  }




/*----------------------------------------------------------
*  API call StoreProduct - Save a product in a Nordrad node
*---------------------------------------------------------*/
void       StoreProduct(char                     *pAccessCtrl,
                        char                     *pHostName,
                        struct ApiProdDescrStruc *pApiProdDescr,
                        char                     *pFileName,
                        INT32                    iWaitTime,
                        INT32                    *piStatus)    
  {
char szFileName [MAX_FILE_NAME_SIZE+1];
char szHostName [MAX_HOSTNAME_SIZE+1];
char szAccessCtrl [MAX_ACCESSCTRL_SIZE+1];


      INT32     iRc = OK;   
      INT32     Sockh = -1;
      INT32     iSendSize = 0;
	  struct NetProdDescrStruc NetProdDescr;

  if (strlen (pAccessCtrl) > MAX_ACCESSCTRL_SIZE)
     {
	*piStatus = APIILLPAR;
	return;
     }

  strcpy (szAccessCtrl, pAccessCtrl);

  if (strlen (pFileName) > MAX_FILE_NAME_SIZE)
     {
	*piStatus = APIILLPAR;
	return;
     }

  strcpy (szFileName, pFileName);

  if (strlen (pHostName) > MAX_HOSTNAME_SIZE)
     {
	*piStatus = APIILLPAR;
	return;
     }

  strcpy (szHostName, pHostName);



  if (iWaitTime > 7200 )
	{
	*piStatus = APIILLPAR;
	return;
	}
  UtlInitTimeoutHandler();
  if ( IsProdDescrOk(pApiProdDescr) )
	{
	if (UtlStripStr(szHostName,
	  		(INT32) strlen(szHostName),
			(INT32) CHECK_NOT_EMPTY,
			(INT32) UNCHANGED ) == NOK)
	  {
      *piStatus = APIILLPAR; 
      return;
      }
    if (UtlStripStr(szFileName,
      		    (INT32)strlen(szFileName),
		    (INT32) CHECK_NOT_EMPTY,
		    (INT32) UNCHANGED ) == NOK)
      {
      *piStatus = APINOSOURCE; 
      return;
      }

    ConvToNetProdDescr(pApiProdDescr,&NetProdDescr);

    if (UtlStripStr(szAccessCtrl,
      		    (INT32) strlen(szAccessCtrl),
		    (INT32) CHECK_NOT_EMPTY,
		    (INT32) TO_UPPER) == NOK)
      {  
      *piStatus = APIILLPAR;  
      return;
      }
    *piStatus = ValidateIpAdr(szHostName);
    if (*piStatus != OK)
      {
      *piStatus = ConvToApiRc(*piStatus);     
      return;
      }

    *piStatus = UtlStartTimeout ( iWaitTime);
    if (*piStatus != OK)
      return;     

    Sockh = NetOpenClient(GATE_STORE_PROD,szHostName,piStatus);
    if (Sockh < 0)
      {
      NetClose(Sockh);
      return;
      }

    NetValidateAccess(Sockh,szAccessCtrl,piStatus);
    if (*piStatus != ACCESS_VALIDATED)
      {
      iRc = UtlCancelTimeout();
      NetClose(Sockh);
      *piStatus = ConvToApiRc(*piStatus);
      return;
      }

    iSendSize = sizeof(struct NetProdDescrStruc);

    NetSendReqData(Sockh,(char *) &NetProdDescr,iSendSize,piStatus);
    if (*piStatus == OK)
      {
      NetReadInt(Sockh,piStatus,&iRc);      
      if (iRc == OK)
		{
        if (*piStatus == OK)
          NetPutFile(Sockh,szFileName,piStatus);  
        }
      else
        *piStatus = iRc;
 
      if (*piStatus == OK)
	{
        NetReadInt(Sockh,piStatus,&iRc);      
	if (iRc != OK)
	   *piStatus = iRc;
	}
  }
    iRc = UtlCancelTimeout (); 
    }
  else   /*   if ( IsProdDescrOk(pApiProdDescr) )  */
    *piStatus = APIILLPAR;
    
  NetClose(Sockh);
  *piStatus = ConvToApiRc(*piStatus);
  }





/*----------------------------------------------------------
*  API call SearchProduct - Search for products in a Nordrad node
*---------------------------------------------------------*/
void  SearchProduct(char                     *pAccessCtrl,
                    char                     *pHostName,
                    struct ApiProdDescrStruc *pApiProdDescr,
                    struct SearchCritStruc   *pSearchCrit,
                    char                     *pSearchLimFile,
                    char                     *pDestFileName,
                    INT32                    iWaitTime,
                    INT32                    *piStatus)    
  {
      INT32     iRc = 0;
      INT32     Sockh = -1;
      INT32     iSendSize = 0;
      INT32     iTransSize = 0;
      INT32     iRecSize = FILE_BUFF_SIZE;
      INT32     iAckRecSize = 0;
      INT32     iSearchStatus = APISEARCHOK;
      INT32     *piStatusBuff;      
      char      GetBuff[FILE_BUFF_SIZE];      
      char      *pGetBuff;      
      FILE      *pDestFile = NULL; 
      struct    NetProdDescrStruc NetProdDescr;
      struct    NetProdDescrStruc *pNetProdDescr;
      struct    NetAviStruc  NetAvi;
      struct    ApiAviStruc  ApiAvi;
      INT32     iIncompleteFound = FALSE;

char szSearchLimFile [MAX_FILE_NAME_SIZE+1];
char szDestFileName  [MAX_FILE_NAME_SIZE+1];
char szHostName      [MAX_HOSTNAME_SIZE+1];
char szAccessCtrl    [MAX_ACCESSCTRL_SIZE+1];

  if (strlen (pAccessCtrl) > MAX_ACCESSCTRL_SIZE)
     {
	*piStatus = APIILLPAR;
	return;
     }

  strcpy (szAccessCtrl, pAccessCtrl);

  if (strlen (pDestFileName) > MAX_FILE_NAME_SIZE)
     {
	*piStatus = APIILLPAR;
	return;
     }

  strcpy (szDestFileName, pDestFileName);

  if (strlen (pSearchLimFile) > MAX_FILE_NAME_SIZE)
     {
	*piStatus = APIILLPAR;
	return;
     }

  strcpy (szSearchLimFile, pSearchLimFile);

  if (strlen (pHostName) > MAX_HOSTNAME_SIZE)
     {
	*piStatus = APIILLPAR;
	return;
     }

  strcpy (szHostName, pHostName);

  if (iWaitTime > 7200 )
    {
    *piStatus = APIILLPAR;
    return;
    }     
  UtlInitTimeoutHandler();
  pGetBuff = GetBuff;
  piStatusBuff = &iSearchStatus;
  pNetProdDescr = &NetProdDescr;

  if ( IsProdDescrOk(pApiProdDescr) )
    {
    if ( UtlStripStr(szHostName,
      		     (INT32) strlen(szHostName),
		     (INT32) CHECK_NOT_EMPTY,
		     (INT32) UNCHANGED ) == NOK)
      {
      *piStatus = APIILLPAR; 
      return;
      }

    if ( UtlStripStr(szDestFileName,
      		     (INT32) strlen(szDestFileName),
		     (INT32) CHECK_NOT_EMPTY,
		     (INT32) UNCHANGED ) == NOK)
      {
      *piStatus = APINODEST; 
      return;
      }

    ConvToNetProdDescr(pApiProdDescr,&NetProdDescr);
    if (*piStatus != OK)
      return;

    if (UtlStripStr(szAccessCtrl,
      		    (INT32) strlen(szAccessCtrl),
		    (INT32) CHECK_NOT_EMPTY,
		    (INT32) TO_UPPER) == NOK)
      {
      *piStatus  = APIILLPAR;
      return;
      }

    if (UtlStripStr(szSearchLimFile,
      		    (INT32) strlen(szSearchLimFile),
		    (INT32) CHECK_NOT_EMPTY,
		    (INT32) UNCHANGED ) == NOK)
      {
      *piStatus = APINOSEALIM; 
      return;
      } 

    *piStatus =  ValidateIpAdr(szHostName);
    if (*piStatus != OK)
      {
      *piStatus = ConvToApiRc(*piStatus);     
      return;
      }
   
    *piStatus = UtlStartTimeout ( iWaitTime);
    if (*piStatus != OK)
      return;     

    Sockh = NetOpenClient(GATE_SEARCH_PROD,szHostName,piStatus);
    if (Sockh < 0)
      {
      *piStatus = UtlCancelTimeout();
      NetClose(Sockh);
      return;
      }

    NetValidateAccess(Sockh,szAccessCtrl,piStatus);
    if (*piStatus != ACCESS_VALIDATED)
      {
      iRc = UtlCancelTimeout();
      NetClose(Sockh);
      *piStatus = ConvToApiRc(*piStatus);
      return;
      }

    iSendSize = strlen(szSearchLimFile);
    NetSendReqData(Sockh,szSearchLimFile,iSendSize,piStatus);    
    if (*piStatus == OK)
      {
      iSendSize = sizeof(struct NetProdDescrStruc);
      NetSendReqData(Sockh,(char *) pNetProdDescr,iSendSize,piStatus);
      if (*piStatus == OK)
        {
        iSendSize = sizeof(struct SearchCritStruc);
        NetWriteBuff(Sockh,(char *) pSearchCrit,iSendSize,piStatus);
        if (*piStatus == OK)
          {
          NetReadInt(Sockh,piStatusBuff,&iRc); 
	  if (iRc != OK)     
			 {
             *piStatus = iRc;   
             return;
             } 
          }
        }
      }

    /* skip this one and continue with next but */
    /* remember for final return state          */
    if (iSearchStatus == APISEAINCMPL)
      iIncompleteFound = TRUE;
    else if (iSearchStatus != APISEARCHOK)
      {
      *piStatus = iSearchStatus;
      return;
      }
    pDestFile = fopen(szDestFileName,"wb");
    if (pDestFile == NULL)
       {
       *piStatus = APIDESTFIL;
       return;
       }

    while ((*piStatus == OK) && 
           ((iSearchStatus == APISEAINCMPL) ||
            (iSearchStatus == APISEARCHOK)))
      {
     
      NetReadInt(Sockh,&iTransSize,piStatus);      
      if ((iTransSize > 0) && (*piStatus == OK))
        {    
        iAckRecSize = 0; 
        while (iAckRecSize < iTransSize)
           {
           if ( iTransSize - iAckRecSize < FILE_BUFF_SIZE)
             iRecSize = iTransSize - iAckRecSize;
 
           NetReadBuff(Sockh, pGetBuff,iRecSize,piStatus);
           if (*piStatus == OK)
             iAckRecSize += iRecSize;

           if ((*piStatus == OK ) && (iSearchStatus != APISEAINCMPL))
             {   
             memcpy(&NetAvi,pGetBuff,sizeof(NetAvi)); 

             memcpy(ApiAvi.cNodeName,NetAvi.cNodeName,
                    sizeof(ApiAvi.cNodeName));
             ConvToApiProdDescr(&NetAvi.NetProdDescr,
                                &ApiAvi.ApiProdDescr);
 
             if (fwrite(&ApiAvi,sizeof(char),sizeof(ApiAvi),pDestFile) != sizeof(ApiAvi))
               { 
               *piStatus = APIDESTFIL;
               fclose(pDestFile); 
               return;
               }
             } 
           }
        } 

      if (*piStatus == OK)
        {
	NetReadInt(Sockh,piStatusBuff,&iRc); 
	if (iRc != OK)     
		  *piStatus = iRc;

        if (iSearchStatus == APISEAINCMPL)
          {
          /* skip this one and continue with next but */
          /* remember for final return state          */
          iIncompleteFound = TRUE;
          }
        }   
      }    /* END   while ((*piStatus == OK) ... )   */

    iRc = UtlCancelTimeout (); 
    if (pDestFile != NULL)
      fclose(pDestFile); 
    }   
  else   /*   if ( IsProdDescrOk(pProdDescr) )  */
    *piStatus = APIILLPAR;

  /* if some of the fetched product descriptions were */
  /* incomplete set return state accordingly          */
  if ((iIncompleteFound == TRUE) && 
      ((iSearchStatus == OK) || 
       (iSearchStatus == APIOK) || 
       (iSearchStatus == APISEAINCMPL)))
    *piStatus = APISEAINCMPL;      

  NetClose(Sockh);
  *piStatus = ConvToApiRc(*piStatus);

  }


/*----------------------------------------------------------
*  API call SubscribeAvi - Anounce intersest of receiving info
*                          about products currently stored and
*                          arriving in server.
*---------------------------------------------------------*/
void  SubscribeAvi(char                     *pAccessCtrl,
                   char                     *pHostName,
                   char                     *pReceiverId,
                   INT32                    iWaitTime,
                   INT32                    *pSubscrSock,
                   INT32                    *piStatus)    
  {
      INT32     iRc = OK; 
      INT32     Sockh = -1;
      INT32     iSendSize = 0;

char szHostName [MAX_HOSTNAME_SIZE+1];
char szReceiverId [MAX_RECEIVERID_SIZE+1];
char szAccessCtrl [MAX_ACCESSCTRL_SIZE+1];

  if (strlen (pAccessCtrl) > MAX_ACCESSCTRL_SIZE)
     {
	*piStatus = APIILLPAR;
	return;
     }

  strcpy (szAccessCtrl, pAccessCtrl);

  if (strlen (pReceiverId) > MAX_RECEIVERID_SIZE)
     {
	*piStatus = APIILLPAR;
	return;
     }

  strcpy (szReceiverId, pReceiverId);

  if (strlen (pHostName) > MAX_HOSTNAME_SIZE)
     {
	*piStatus = APIILLPAR;
	return;
     }

  strcpy (szHostName, pHostName);


  if (iWaitTime > 7200 )
	{
	*piStatus = APIILLPAR;
	return;
	}
  UtlInitTimeoutHandler();
  *pSubscrSock = -1;

  if (UtlStripStr(szAccessCtrl,
    		  (INT32) strlen(szAccessCtrl),
		  (INT32) CHECK_NOT_EMPTY,
		  (INT32) TO_UPPER) == NOK)
    {
    *piStatus = APIILLPAR; 
    return;
    }

  if ( UtlStripStr(szHostName,
    		   (INT32) strlen(szHostName),
		   (INT32) CHECK_NOT_EMPTY,
		   (INT32) UNCHANGED ) == NOK)
    {
    *piStatus = APIILLPAR;
    return;
    }

  if ( UtlStripStr(szReceiverId,
    		   (INT32) strlen(szReceiverId),
		   (INT32) CHECK_NOT_EMPTY,
		   (INT32) TO_UPPER) == NOK)
    { 
    *piStatus = APINORECID;
    return;
    }

  *piStatus = UtlStartTimeout( iWaitTime);
  if (*piStatus != OK)
     return;     

  *piStatus = ValidateIpAdr(szHostName);
  if (*piStatus != OK)
    return;     

  Sockh = NetOpenClient(GATE_SUBSCR_AVI,szHostName,piStatus);
  if (Sockh < 0)
    {
    NetClose(Sockh);
    return;
    }

  NetValidateAccess(Sockh,szAccessCtrl,piStatus);
  if (*piStatus != ACCESS_VALIDATED)
    {
    iRc = UtlCancelTimeout();
    NetClose(Sockh);
    *piStatus = ConvToApiRc(*piStatus); 
    return; 
    }

  iSendSize = strlen(szReceiverId);
  NetSendReqData(Sockh,szReceiverId,iSendSize,piStatus);    
  if (*piStatus == OK)
    {
    NetReadInt(Sockh,piStatus,&iRc);      
    if (iRc != OK)
	  *piStatus = iRc;
    }
  if (*piStatus != OK)   
    NetClose(Sockh);

  iRc = UtlCancelTimeout (); 

  *pSubscrSock = Sockh;

  *piStatus = ConvToApiRc(*piStatus);  
  return; 
  }


/*----------------------------------------------------------
*  API call ReceiveAvi - Receive product from 'mailbox' in 
*                        nordrad node if any stored. 
*---------------------------------------------------------*/
void	ReceiveAvi(INT32                      SubscrSockh,
                   struct ApiAviStruc         *pApiAvi,
                   INT32                      iWaitTime,
                   INT32                      *piStatus)    
  {
      INT32     iRc = OK;
      INT32     iSendSize = 0;
      INT32     iTransSize=0;
      INT32     iInternWaitTime = 0;
      struct    NetAviStruc  NetAvi;
      
  
  if ((SubscrSockh <= 0) || (iWaitTime > 7200))     
   {
   *piStatus = APIILLPAR; 
   return; 
   }

  if (iWaitTime > 0)
     iInternWaitTime = iWaitTime + 5;	/* We would like the other */
					/* side to signal the	   */
					/* timeout, but if it dis- */
					/* appears we'll supervise */
					/* it on this side as well */

  *piStatus = UtlStartTimeout( iInternWaitTime);
  if (*piStatus != OK)
     return;     

 
  iSendSize = sizeof(iInternWaitTime);

  iInternWaitTime = UtlIntToNet(iWaitTime);

  NetWriteBuff(SubscrSockh,(char *) &iInternWaitTime,iSendSize,piStatus);
  if (*piStatus == OK)
    {
    NetReadInt(SubscrSockh,piStatus,&iRc);      
    if (iRc != OK)
	   *piStatus = iRc;
    if (*piStatus == OK)   
      {
      NetReadInt(SubscrSockh,&iTransSize,piStatus);      
      if ((iTransSize > 0) && (*piStatus == OK))
        NetReadBuff(SubscrSockh, (char *) &NetAvi,iTransSize,piStatus);
      } 
    }

  iRc = UtlCancelTimeout();

  if (*piStatus == OK)
    {
    memcpy(pApiAvi->cNodeName,NetAvi.cNodeName,
           sizeof(pApiAvi->cNodeName));
    ConvToApiProdDescr(&NetAvi.NetProdDescr,
                       &pApiAvi->ApiProdDescr);
    }

  *piStatus = ConvToApiRc(*piStatus);
  }    




/*----------------------------------------------------------
*  API call CancelAvi - Release subscription by Disconnecting 
*                       connection to nordrad node.
*---------------------------------------------------------*/
void	CancelAvi(INT32 SubscrSockh)
  {
  NetClose(SubscrSockh);
  }

  
/*----------------------------------------------------------
*  API call Pack - Compress a nordrad product
*---------------------------------------------------------*/
void	Pack(char *pSourceFile,char *pDestFile,
             unsigned char bPackAlg,INT32 *piStatus)
  {
char szDestFile [MAX_FILE_NAME_SIZE+1];
char szSourceFile [MAX_FILE_NAME_SIZE+1];

     INT32 iErr = OK;
     
  if (strlen (pDestFile) > MAX_FILE_NAME_SIZE)
     {
	*piStatus = APIILLPAR;
	return;
     }

  strcpy (szDestFile, pDestFile);

  if (strlen (pSourceFile) > MAX_FILE_NAME_SIZE)
     {
	*piStatus = APIILLPAR;
	return;
     }

  strcpy (szSourceFile, pSourceFile);



  if (bPackAlg > 1 )
    {
    *piStatus = APIILLPAR;
    return;
    }
    
  if ( UtlStripStr(szSourceFile,
    		   (INT32) strlen(szSourceFile),
		   (INT32) CHECK_NOT_EMPTY,
		   (INT32) UNCHANGED ) == NOK)
    {
    *piStatus = APINOSOURCE;
    return;
    }
  if ( UtlStripStr(szDestFile,
    		   (INT32) strlen(szDestFile),
		   (INT32) CHECK_NOT_EMPTY,
		   (INT32) UNCHANGED ) == NOK)
    {
    *piStatus = APINODEST;
    return;
    }

  if (bPackAlg == RLE)  
	iErr = pckCompressNradProd(szSourceFile,szDestFile);

  *piStatus = ConvToApiRc(iErr);  

  }

  
/*----------------------------------------------------------
*  API call UnPack - UnCompress a nordrad product
*---------------------------------------------------------*/
void	UnPack(char *pSourceFile,char *pDestFile,
			   unsigned char bPackAlg,INT32 *piStatus)
  {
char szDestFile [MAX_FILE_NAME_SIZE+1];
char szSourceFile [MAX_FILE_NAME_SIZE+1];

     INT32 iErr = OK;
     
  if (strlen (pDestFile) > MAX_FILE_NAME_SIZE)
     {
	*piStatus = APIILLPAR;
	return;
     }

  strcpy (szDestFile, pDestFile);

  if (strlen (pSourceFile) > MAX_FILE_NAME_SIZE)
     {
	*piStatus = APIILLPAR;
	return;
     }

  strcpy (szSourceFile, pSourceFile);
    
  if (bPackAlg > 1 )
    {
    *piStatus = APIILLPAR;
    return;
    }
    
  if ( UtlStripStr(szSourceFile,
    		   (INT32) strlen(szSourceFile),
		   (INT32) CHECK_NOT_EMPTY,
		   (INT32) UNCHANGED ) == NOK)
    {
    *piStatus = APINOSOURCE;
    return;
    }
  if ( UtlStripStr(szDestFile,
    		   (INT32) strlen(szDestFile),
		   (INT32) CHECK_NOT_EMPTY,
		   (INT32) UNCHANGED ) == NOK)
    {
    *piStatus = APINODEST;
    return;
    }

  if (bPackAlg == RLE)  
    iErr = pckExpandNradProd(szSourceFile,szDestFile);

  *piStatus = ConvToApiRc(iErr);      
  }




/*----------------------------------------------------------
*  ConvToApiRc - Convert to correct API error codes on known
*                Net error codes and internal error, let 
*                everything else pass. 
*---------------------------------------------------------*/
INT32 ConvToApiRc(INT32 iRc)
  {
  switch(iRc)
    {
    case OK:
      return APIOK;
    default: 
      return iRc;
    }         
  }


/*----------------------------------------------------------
*  ValidateIpAdr - Validate given node name is in IP address
*                  format or convert if in Symbolic name format
*     returns    - Pointer to Ip address string or NULL if error               
*---------------------------------------------------------*/
INT32 ValidateIpAdr(char *pIpAddr)
  {
  struct hostent *pHostAdrData;
  INT32            iLoopInd = 0;
  INT32            iLen = 0;
  struct in_addr *pListIpAddr;

  iLen = strlen(pIpAddr);
  if (iLen <= 0)
    return APIILLPAR;

  while (iLoopInd < iLen)
    {    
    if (isdigit(*(pIpAddr+iLoopInd)) == FALSE)
      {
      if (*(pIpAddr+iLoopInd) != '.')
        {
        if ((pHostAdrData = gethostbyname(pIpAddr)) == NULL)
          return NET_ILLEGAL_HOST_NAME;
        else
          {
          pListIpAddr = (struct in_addr *) *pHostAdrData->h_addr_list;
          strcpy(pIpAddr,(char *)inet_ntoa(*pListIpAddr));
          return OK;   
          } 
        }
      }
    iLoopInd++;  
    }
  return OK;  
  }  


/*----------------------------------------------------------
*  IsProdDescrOk - Validate fields in product description
*                  for range and max lengths.
*     returns    - TRUE if no errors found, FALSE otherwise
*---------------------------------------------------------*/
INT32  IsProdDescrOk(struct ApiProdDescrStruc *pProdDescr)
  {
	float fTmpStartLat;
    float fTmpStartLong; 
    float fTmpEndLat;
    float fTmpEndLong;
    INT32 iInd = 0;

  if (pProdDescr->bProd > PROD_MAXVALUE)
    return FALSE;

  if ((strlen(pProdDescr->cTimeStr)+1) > sizeof(pProdDescr->cTimeStr))
    return FALSE;

  if ( UtlStripStr(pProdDescr->cTimeStr,
    		   (INT32) strlen(pProdDescr->cTimeStr),
                   (INT32) NO_CHECK,
		   (INT32) UNCHANGED) == NOK)
    return FALSE;


  if ((strlen(pProdDescr->cArea)+1) > MAX_AREANAME_SIZE )
    return FALSE;

  if ( UtlStripStr(pProdDescr->cArea,
    		   (INT32) strlen(pProdDescr->cArea),
                   (INT32) NO_CHECK,
		   (INT32) TO_UPPER) == NOK)
    return FALSE;

  if ((pProdDescr->iResolution < RESOLUTION_MIN) ||
      (pProdDescr->iResolution > RESOLUTION_MAX))
    return FALSE;

  if (pProdDescr->bProd  == PROD_FOREIGN)
    {
    if (strlen(pProdDescr->uData.Foreign.cComment) >
                                       MAX_COMMENT_SIZE) 
      return FALSE;
    if (strlen(pProdDescr->uData.Foreign.cComment) > 0)
      {
      for (iInd=0; iInd<strlen(pProdDescr->uData.Foreign.cComment); iInd++)
        if ((pProdDescr->uData.Foreign.cComment[iInd] > 0x7D) ||
            (pProdDescr->uData.Foreign.cComment[iInd] < 0x20))
          return FALSE;
      }
    }
    
  if (pProdDescr->bProd  == PROD_GEOMAP)
    {
	if (pProdDescr->uData.GeoMap.bMapType > MAPTYPE_MAX)
      return FALSE;
    if (pProdDescr->uData.GeoMap.bMapGraphic > MAPGRAPHIC_MAX)
      return FALSE;
    }

  if (pProdDescr->bProd  == PROD_RRSTATUS)
    {
    if (strlen(pProdDescr->uData.RrStatus.cStatusNode) >
                                       MAX_NODENAME_SIZE)
      return FALSE;                      
    }
        
  if ((pProdDescr->bProd  >= PROD_RRPPI_Z) &&
      (pProdDescr->bProd  <= PROD_RRSRT_Z))
    {
    if ((pProdDescr->uData.RrType.bRrMode < 1) ||
        (pProdDescr->uData.RrType.bRrMode > RRMODE_MAX))  
      return FALSE;
    }
        
  if ((pProdDescr->bProd  >= PROD_RRCAPPI_Z) &&
      (pProdDescr->bProd  <= PROD_RRCAPPI_T))
    {
    if ((pProdDescr->uData.RrType.uRr.RrCappi.iHeight < HIGHT_MIN) ||
        (pProdDescr->uData.RrType.uRr.RrCappi.iHeight > HIGHT_MAX))  
      return FALSE;
    }
    
  if ((pProdDescr->bProd  >= PROD_RRHMI_Z) &&
      (pProdDescr->bProd  <= PROD_RRHMI_T))
    {
    if (pProdDescr->uData.RrType.uRr.RrHmi.bHmiWall > MAX_AREA_WALL_VALUE)
      return FALSE;
    }

  if ((pProdDescr->bProd  >= PROD_RRVSI_Z) &&
      (pProdDescr->bProd  <= PROD_RRVSI_T))
    {
	if (pProdDescr->uData.RrType.uRr.RrVsi.bVsiWall > VSI_WALL_MAX)
      return FALSE;

    fTmpStartLat = atof(pProdDescr->uData.RrType.uRr.RrVsi.cStartLat);
    if ((fTmpStartLat  < -90.0) || (fTmpStartLat  > 90.0))  
      return FALSE;
    fTmpStartLong = atof(pProdDescr->uData.RrType.uRr.RrVsi.cStartLong);
    if ((fTmpStartLong < -180.0) || (fTmpStartLong > 180.0))  
      return FALSE;
    fTmpEndLat = atof(pProdDescr->uData.RrType.uRr.RrVsi.cEndLat);
    if ((fTmpEndLat < -90.0) || (fTmpEndLat > 90.0))  
      return FALSE;
    fTmpEndLong = atof(pProdDescr->uData.RrType.uRr.RrVsi.cEndLong);
    if ((fTmpEndLong < -180.0) || (fTmpEndLong > 180.0))  
      return FALSE;

    if (strlen(pProdDescr->uData.RrType.uRr.RrVsi.cVsiName) >
                                       MAX_VSINAME_SIZE) 
      return FALSE;                      
    }
    
  if (pProdDescr->bProd  == PROD_RRSRT_Z)
    if ((pProdDescr->uData.RrType.uRr.Duration.iSecs <
                                                  SEC_SIZE_MIN) ||
        (pProdDescr->uData.RrType.uRr.Duration.iSecs >
                                                  SEC_SIZE_MAX))
      return FALSE;

      
  return TRUE;  
  }  


/*----------------------------------------------------------
*  IsTextStrOk - Validate a string in 'ADA format' for 
*                  for range and max lengths.
*     returns  - TRUE if no errors found, FALSE otherwise
*---------------------------------------------------------*/
INT32 IsTextStrOk(INT32 *iMaxLen,INT32 iLen,char *pText,INT32 iMaxLimit)
  {
  *iMaxLen = iMaxLimit;  
  if ((iLen > *iMaxLen) || (iLen < 0))
    return FALSE;  
  if (strlen(pText) > *iMaxLen)
    return FALSE;
  return TRUE;  
  }




/*----------------------------------------------------------
*  GetProdDescrSize - Select correct size depending on product
*  returns          - Size of given product
*---------------------------------------------------------*/
INT32 GetProdDescrSize(INT32 iProdDescr)
  {
     INT32 iSize=0;

  switch(iProdDescr)
    {
    case PROD_FOREIGN:
      iSize = PROD_FOREIGN_SIZE;
      break;
    case PROD_GEOMAP:
      iSize = PROD_GEOMAP_SIZE;
      break;
    case PROD_RRSTATUS:
      iSize = PROD_RRSTATUS_SIZE;
      break;
    case PROD_RRPPI_Z:
      iSize = PROD_RRPPI_Z_SIZE;
      break;
    case PROD_RRPPI_W:
      iSize = PROD_RRPPI_W_SIZE;    
      break;
    case PROD_RRPPI_T:
      iSize = PROD_RRPPI_T_SIZE;
      break;
    case PROD_RRCAPPI_Z:
      iSize = PROD_RRCAPPI_Z_SIZE;
      break;
    case PROD_RRCAPPI_W: 
      iSize = PROD_RRCAPPI_W_SIZE;
      break;
    case PROD_RRCAPPI_T:
      iSize = PROD_RRCAPPI_T_SIZE;
      break;
    case PROD_RRPSC_Z:  
      iSize = PROD_RRPSC_Z_SIZE;
      break;
    case PROD_RRPSC_W: 
      iSize = PROD_RRPSC_W_SIZE;
      break;
    case PROD_RRPSC_T_SIZE:
      iSize = PROD_RRPSC_T_SIZE;
      break;
    case PROD_RRETM_Z:
      iSize = PROD_RRETM_Z_SIZE;
      break;
    case PROD_RRVMI_Z:
      iSize = PROD_RRVMI_Z_SIZE; 
      break;
    case PROD_RRVMI_W:
      iSize = PROD_RRVMI_W_SIZE;
      break;
    case PROD_RRVMI_T:
      iSize = PROD_RRVMI_T_SIZE;
      break;
    case PROD_RRHMI_Z:
      iSize = PROD_RRHMI_Z_SIZE;
      break;    
    case PROD_RRHMI_W:
      iSize = PROD_RRHMI_W_SIZE;
      break; 
    case PROD_RRHMI_T_SIZE:
      iSize = PROD_RRHMI_T_SIZE;
      break;
    case PROD_RRHMAX_Z:
      iSize = PROD_RRHMAX_Z_SIZE; 
      break;
    case PROD_RRHMAX_W:
      iSize = PROD_RRHMAX_W_SIZE;
      break;
    case PROD_RRHMAX_T:
      iSize = PROD_RRHMAX_T_SIZE;
      break;
    case PROD_RRVSI_Z:
      iSize = PROD_RRVSI_Z_SIZE;
      break;
    case PROD_RRVSI_W:
      iSize = PROD_RRVSI_W_SIZE; 
      break;
    case PROD_RRVSI_T:
      iSize = PROD_RRVSI_T_SIZE; 
      break;
    case PROD_RRSRT_Z:
      iSize = PROD_RRSRT_Z_SIZE; 
      break;
    default:
      iSize = PROD_DEFAULT_SIZE;
      break;
    } 
  return iSize;
  }  



/*-----------------------------------------------------------------
*  ConvToApiProdDescr - Convert to API format
*     returns         -
*-----------------------------------------------------------------*/
void ConvToApiProdDescr(struct NetProdDescrStruc *pNetProdDescr,
						struct ApiProdDescrStruc *pApiProdDescr)
  {

  memset(pApiProdDescr,0,sizeof(struct ApiProdDescrStruc));
  pApiProdDescr->bProd = pNetProdDescr->bProd;
  memcpy(pApiProdDescr->cTimeStr,pNetProdDescr->cTimeStr,
		 sizeof(pApiProdDescr->cTimeStr));
  strncpy(pApiProdDescr->cArea,pNetProdDescr->cArea,
		  MAX_AREANAME_SIZE);

  pApiProdDescr->iResolution = atoi(pNetProdDescr->cResolution);

  if (pApiProdDescr->bProd  == PROD_FOREIGN)
	{
	memset(pApiProdDescr->uData.Foreign.cComment,0,        /* guarantee of ending */
		   sizeof(pApiProdDescr->uData.Foreign.cComment));
	strncpy(pApiProdDescr->uData.Foreign.cComment,
			pNetProdDescr->uData.Foreign.cComment,
			sizeof(pApiProdDescr->uData.Foreign.cComment)-1);  /* zero BBN 940526 */
	}

  if (pApiProdDescr->bProd  == PROD_GEOMAP)
	{
	pApiProdDescr->uData.GeoMap.bMapType =
		pNetProdDescr->uData.GeoMap.bMapType;
	pApiProdDescr->uData.GeoMap.bMapGraphic =
		pNetProdDescr->uData.GeoMap.bMapGraphic;
	}

  if (pApiProdDescr->bProd  == PROD_RRSTATUS)
	{
	strncpy(pApiProdDescr->uData.RrStatus.cStatusNode,
			pNetProdDescr->uData.RrStatus.cStatusNode,
			MAX_NODENAME_SIZE);
	}

  if ((pApiProdDescr->bProd  >= PROD_RRPPI_Z) &&
	  (pApiProdDescr->bProd  <= PROD_RRSRT_Z))
	{
	pApiProdDescr->uData.RrType.bRrMode =
	   pNetProdDescr->uData.RrType.bRrMode;
	}

  if ((pApiProdDescr->bProd  >= PROD_RRCAPPI_Z) &&
	  (pApiProdDescr->bProd  <= PROD_RRCAPPI_T))
	{
	pApiProdDescr->uData.RrType.uRr.RrCappi.iHeight =
		   atoi(pNetProdDescr->uData.RrType.uRr.RrCappi.cHeight);
	}

  if ((pApiProdDescr->bProd  >= PROD_RRHMI_Z) &&
	  (pApiProdDescr->bProd  <= PROD_RRHMI_T))
	{
	pApiProdDescr->uData.RrType.uRr.RrHmi.bHmiWall =
		pNetProdDescr->uData.RrType.uRr.RrHmi.bHmiWall;
	}


  if ((pApiProdDescr->bProd  >= PROD_RRVSI_Z) &&
	  (pApiProdDescr->bProd  <= PROD_RRVSI_T))
	{
	memset(&pApiProdDescr->uData.RrType.uRr.RrVsi,0,
		   sizeof(pApiProdDescr->uData.RrType.uRr.RrVsi));

	pApiProdDescr->uData.RrType.uRr.RrVsi.bVsiWall =
	   pNetProdDescr->uData.RrType.uRr.RrVsi.bVsiWall;

	strncpy(pApiProdDescr->uData.RrType.uRr.RrVsi.cStartLat,
	   pNetProdDescr->uData.RrType.uRr.RrVsi.cStartLat,POS_SIZE-1);

	strncpy(pApiProdDescr->uData.RrType.uRr.RrVsi.cStartLong,
		pNetProdDescr->uData.RrType.uRr.RrVsi.cStartLong,POS_SIZE-1);

	strncpy(pApiProdDescr->uData.RrType.uRr.RrVsi.cEndLat,
		pNetProdDescr->uData.RrType.uRr.RrVsi.cEndLat,POS_SIZE-1);

	strncpy(pApiProdDescr->uData.RrType.uRr.RrVsi.cEndLong,
		pNetProdDescr->uData.RrType.uRr.RrVsi.cEndLong,POS_SIZE-1);

	strncpy(pApiProdDescr->uData.RrType.uRr.RrVsi.cVsiName,
		   pNetProdDescr->uData.RrType.uRr.RrVsi.cVsiName,
					 MAX_VSINAME_SIZE);
	}

  if (pApiProdDescr->bProd  == PROD_RRSRT_Z)
	{
	pApiProdDescr->uData.RrType.uRr.Duration.iSecs =
		   atoi(pNetProdDescr->uData.RrType.uRr.Duration.cSecs);
	pApiProdDescr->uData.RrType.uRr.Duration.iDays =
		   atoi(pNetProdDescr->uData.RrType.uRr.Duration.cDays);
	}

  }


/*-----------------------------------------------------------------
*  ConvToNetProdDescr - Convert to NET send format
*     returns         -
*-----------------------------------------------------------------*/
void ConvToNetProdDescr(struct ApiProdDescrStruc *pApiProdDescr,
						  struct NetProdDescrStruc *pNetProdDescr)
  {

  memset(pNetProdDescr,0,sizeof(struct NetProdDescrStruc));
  pNetProdDescr->bProd = pApiProdDescr->bProd;
  memcpy(pNetProdDescr->cTimeStr,pApiProdDescr->cTimeStr,
         sizeof(pNetProdDescr->cTimeStr));
  strncpy(pNetProdDescr->cArea,pApiProdDescr->cArea,
          MAX_AREANAME_SIZE);
  sprintf(pNetProdDescr->cResolution,"%d",
          pApiProdDescr->iResolution);
		   
  if (pNetProdDescr->bProd  == PROD_FOREIGN)
    {
    memset(pNetProdDescr->uData.Foreign.cComment,0x20,
           sizeof(pNetProdDescr->uData.Foreign.cComment));
    memcpy(pNetProdDescr->uData.Foreign.cComment,
           pApiProdDescr->uData.Foreign.cComment,
           strlen(pApiProdDescr->uData.Foreign.cComment));
    
    }
    
  if (pNetProdDescr->bProd  == PROD_GEOMAP)
    {
    pNetProdDescr->uData.GeoMap.bMapType =
        pApiProdDescr->uData.GeoMap.bMapType;
    pNetProdDescr->uData.GeoMap.bMapGraphic =
        pApiProdDescr->uData.GeoMap.bMapGraphic;
    }

  if (pNetProdDescr->bProd  == PROD_RRSTATUS)
    {
    strncpy(pNetProdDescr->uData.RrStatus.cStatusNode,
            pApiProdDescr->uData.RrStatus.cStatusNode,
            MAX_NODENAME_SIZE);		   
    }    

  if ((pNetProdDescr->bProd  >= PROD_RRPPI_Z) &&
      (pNetProdDescr->bProd  <= PROD_RRSRT_Z))
    {
    pNetProdDescr->uData.RrType.bRrMode =
       pApiProdDescr->uData.RrType.bRrMode;
    }
        
  if ((pNetProdDescr->bProd  >= PROD_RRCAPPI_Z) &&
      (pNetProdDescr->bProd  <= PROD_RRCAPPI_T))
    {
    sprintf(pNetProdDescr->uData.RrType.uRr.RrCappi.cHeight,
            "%d",
            pApiProdDescr->uData.RrType.uRr.RrCappi.iHeight);
    }
    
  if ((pNetProdDescr->bProd  >= PROD_RRHMI_Z) &&
      (pNetProdDescr->bProd  <= PROD_RRHMI_T))
    {
    pNetProdDescr->uData.RrType.uRr.RrHmi.bHmiWall =
        pApiProdDescr->uData.RrType.uRr.RrHmi.bHmiWall;
    }


  if ((pNetProdDescr->bProd  >= PROD_RRVSI_Z) &&
      (pNetProdDescr->bProd  <= PROD_RRVSI_T))
    {
    pNetProdDescr->uData.RrType.uRr.RrVsi.bVsiWall =
       pApiProdDescr->uData.RrType.uRr.RrVsi.bVsiWall;

    strcpy(pNetProdDescr->uData.RrType.uRr.RrVsi.cStartLat, 
       pApiProdDescr->uData.RrType.uRr.RrVsi.cStartLat);

    strcpy(pNetProdDescr->uData.RrType.uRr.RrVsi.cStartLong,
        pApiProdDescr->uData.RrType.uRr.RrVsi.cStartLong);

    strcpy(pNetProdDescr->uData.RrType.uRr.RrVsi.cEndLat,
        pApiProdDescr->uData.RrType.uRr.RrVsi.cEndLat);

    strcpy(pNetProdDescr->uData.RrType.uRr.RrVsi.cEndLong,
        pApiProdDescr->uData.RrType.uRr.RrVsi.cEndLong);

    strncpy(pNetProdDescr->uData.RrType.uRr.RrVsi.cVsiName,
           pApiProdDescr->uData.RrType.uRr.RrVsi.cVsiName,
                     MAX_VSINAME_SIZE);		   
    }

  if (pNetProdDescr->bProd  == PROD_RRSRT_Z)
    {
    sprintf(pNetProdDescr->uData.RrType.uRr.Duration.cSecs, 
            "%d.0",
            pApiProdDescr->uData.RrType.uRr.Duration.iSecs);
    sprintf(pNetProdDescr->uData.RrType.uRr.Duration.cDays, 
            "%d",
            pApiProdDescr->uData.RrType.uRr.Duration.iDays);
    }

  }

